00001 #include "mux.h"
00002 #include "file.h"
00003 #include "parser.h"
00004 #include "port.h"
00005 #include "main.h"
00006
00007 #define ALARMTIMEOUT 60
00008
00009 jabconn jab_c = NULL;
00010 jwgconn jwg_c = NULL;
00011 time_t jab_connect_time = 0;
00012 int jwgc_register = 0;
00013 int jab_reauth = 0;
00014
00015 char *whoami = NULL;
00016 char *progname = NULL;
00017 char *description_filename_override = NULL;
00018 struct _Node *program = NULL;
00019
00020 char *current_presence = "available";
00021
00022 char *barebones_desc = "\
00023 fields body\n\
00024 print \"@b(Description file is broken! This is a barebones config.)\\n\"\n\
00025 print \"Date: \"+$date+\"\\n\"\n\
00026 print \"Time: \"+$time+\"\\n\"\n\
00027 print \"From: \"+$from+\"\\n\"\n\
00028 print \"Status: \"+$status+\"\\n\"\n\
00029 print \"Show: \"+$show+\"\\n\"\n\
00030 print \"Type: \"+$type+\"\\n\"\n\
00031 print \"Subtype: \"+$subtype+\"\\n\"\n\
00032 print \"Body:\\n\"+$body+\"\\n\"\n\
00033 put\n\
00034 exit\n\
00035 ";
00036
00037 void
00038 usage()
00039 {
00040 fprintf(stderr, "\
00041 Usage: %s [-h] [-f <filename>]\n\
00042 [-u <username>] [-p <password>]\n\
00043 [-r <resource>] [-s <server>] [-j <jid>]\n\
00044 [-port <port>] [-priority <priority>]\n\
00045 [-ttymode] [-nofork] [-register]\n\
00046 [-default <driver>] {-disable <driver>}*\n\
00047 [output driver options]\n\
00048 ", whoami);
00049 #ifdef USE_GPGME
00050 fprintf(stderr, "\
00051 [-gpg] [-nogpg] [-gpgpass <password>]\n\
00052 ");
00053 #endif
00054 #ifdef USE_SSL
00055 fprintf(stderr, "\
00056 [-ssl] [-nossl]\n\
00057 ");
00058 #endif
00059 #ifndef NODEBUG
00060 fprintf(stderr, "\
00061 [-debug <flags>]\n\
00062 ");
00063 #endif
00064 exit(1);
00065 }
00066
00067 void
00068 fake_startup_packet()
00069 {
00070 xode fake;
00071
00072 fake = jabutil_msgnew("internal",
00073 (char *)jVars_get(jVarJID),
00074 "startup",
00075 "Jabber Windowgram Client Started...",
00076 NULL);
00077 jab_send(jab_c, fake);
00078 xode_free(fake);
00079 }
00080
00081 int
00082 read_in_description_file()
00083 {
00084 FILE *input_file;
00085 char *defdesc;
00086
00087 defdesc = (char *)malloc(sizeof(char) * (strlen(DATADIR) + 1 +
00088 strlen(DEFDESC) + 1));
00089
00090 sprintf(defdesc, "%s/%s", DATADIR, DEFDESC);
00091 input_file = (FILE *) locate_file(description_filename_override,
00092 USRDESC, defdesc);
00093 free(defdesc);
00094 if (input_file)
00095 program = (struct _Node *) parse_file(input_file);
00096 else
00097 program = NULL;
00098
00099 if (program == NULL)
00100 program = (struct _Node *) parse_buffer(barebones_desc);
00101
00102 if (program != NULL) {
00103 fake_startup_packet();
00104 return 1;
00105 }
00106 else {
00107 return 0;
00108 }
00109 }
00110
00111 void
00112 check_live_jwgc_on_event_handler(jwgconn conn, jwgpacket packet)
00113 {
00114 fprintf(stderr, "There is already an active jwgc running! Exiting...\n");
00115 exit(0);
00116 }
00117
00118 void
00119 check_live_jwgc()
00120 {
00121 jwgconn checkjwg;
00122 xode x;
00123
00124 checkjwg = jwg_new();
00125 if (!checkjwg) {
00126 dprintf(dExecution, "check_live_jwgc: failed to initialize jwgc connection\n");
00127 return;
00128 }
00129
00130 jwg_event_handler(checkjwg, check_live_jwgc_on_event_handler);
00131 jwg_start(checkjwg);
00132 if (jwg_getfd(checkjwg) < 0) {
00133 dprintf(dExecution, "check_live_jwgc: failed to create jwgc connection\n");
00134 return;
00135 }
00136
00137 x = xode_new("check");
00138 jwg_send(checkjwg, x);
00139 xode_free(x);
00140
00141 jwg_poll(checkjwg, -1);
00142 jwg_stop(checkjwg);
00143 }
00144
00145 void
00146 jwgc_init()
00147 {
00148 jwg_c = jwg_server();
00149 if (!jwg_c) {
00150 fprintf(stderr, "jwgc: unable to initialize jwgc connection.\n");
00151 exit(1);
00152 }
00153 jwg_event_handler(jwg_c, jwg_on_event_handler);
00154 jwg_servstart(jwg_c);
00155 if (jwg_getfd(jwg_c) < 0) {
00156 fprintf(stderr, "jwgc: unable to create jwgc connection.\n");
00157 exit(1);
00158 }
00159 mux_add_input_source(jwg_getfd(jwg_c), jwg_servrecv, jwg_c);
00160 }
00161
00162 void
00163 jabber_init()
00164 {
00165 jab_reauth = 0;
00166 jab_c = jab_new((char *)jVars_get(jVarJID), (char *)jVars_get(jVarPassword));
00167 if (!jab_c) {
00168 fprintf(stderr, "jwgc: unable to create jabber connection.\n");
00169 exit(1);
00170 }
00171 jab_c->port = *(int *)jVars_get(jVarPort);
00172 jab_packet_handler(jab_c, jab_on_packet_handler);
00173 jab_state_handler(jab_c, jab_on_state_handler);
00174 jab_start(jab_c,
00175 #ifdef USE_SSL
00176 *(int *) jVars_get(jVarUseSSL)
00177 #else
00178 0
00179 #endif
00180 );
00181 if (jwgc_register) {
00182 dprintf(dExecution, "Registering user...\n");
00183 jab_reg(jab_c);
00184 jwgc_register = 0;
00185 }
00186 jab_auth(jab_c);
00187 if (jab_c->state == JABCONN_STATE_OFF) {
00188 fprintf(stderr, "Unable to connect to jabber server. Retrying in %d seconds.\n", ALARMTIMEOUT);
00189 jab_reauth = 1;
00190 return;
00191 }
00192 mux_add_input_source(jab_getfd(jab_c), jab_recv, jab_c);
00193
00194 jab_startup(jab_c);
00195 jab_connect_time = time(0);
00196 }
00197
00198 void
00199 jabber_finalize()
00200 {
00201 jab_stop(jab_c);
00202 jwg_stop(jwg_c);
00203 JCleanupSocket();
00204 }
00205
00206 void
00207 run_initprogs()
00208 {
00209 int status;
00210 char *progname = (char *)jVars_get(jVarInitProgs);
00211
00212 if (!progname)
00213 return;
00214
00215 dprintf(dExecution, "Running init program... %s\n", progname);
00216
00217 status = system(progname);
00218 if (status == 127) {
00219 perror("jwgc initprog exec");
00220 fprintf(stderr, "jwgc initprog of <%s> failed: no shell.\n",
00221 progname);
00222 }
00223 else if (status != -1 && status >> 8) {
00224 perror("jwgc initprog exec");
00225 fprintf(stderr, "jwgc initprog of <%s> failed with status [%d].\n",
00226 progname, status >> 8);
00227 }
00228 }
00229
00230 static RETSIGTYPE
00231 signal_exit()
00232 {
00233 mux_end_loop_p = 1;
00234 }
00235
00236 static RETSIGTYPE
00237 signal_pipe()
00238 {
00239 fprintf(stderr, "Lost connection to server. Retrying in %d seconds...\n", ALARMTIMEOUT);
00240 mux_delete_input_source(jab_getfd(jab_c));
00241 jab_delete(jab_c);
00242 jab_reauth = 1;
00243 }
00244
00245 static RETSIGTYPE
00246 signal_check()
00247 {
00248
00249 xode x, y, z;
00250
00251 dprintf(dExecution, "Checking jabber connection...\n");
00252 if (jab_reauth) {
00253 if (jab_c) { jab_delete(jab_c); }
00254 jabber_init();
00255 }
00256 else if (jab_c->state == JABCONN_STATE_ON) {
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272 jab_send_raw(jab_c, " ");
00273 if (errno == EPIPE) {
00274 fprintf(stderr, "Lost connection to server. Retrying in %d seconds...\n", ALARMTIMEOUT);
00275 mux_delete_input_source(jab_getfd(jab_c));
00276 jab_delete(jab_c);
00277 jab_reauth = 1;
00278 }
00279 }
00280
00281 alarm(ALARMTIMEOUT);
00282 }
00283
00284
00285
00286
00287
00288 static RETSIGTYPE
00289 signal_child()
00290 {
00291 #ifdef HAVE_WAITPID
00292 int status;
00293 #else
00294 union wait status;
00295 #endif
00296 extern int errno;
00297 int pid, old_errno = errno;
00298
00299 do {
00300 #ifdef HAVE_WAITPID
00301 pid = waitpid(-1, &status, WNOHANG);
00302 #else
00303 pid = wait3(&status, WNOHANG, (struct rusage *) 0);
00304 #endif
00305 } while (pid != 0 && pid != -1);
00306 errno = old_errno;
00307 }
00308
00309 static void
00310 setup_signals(dofork)
00311 int dofork;
00312 {
00313 #ifdef _POSIX_VERSION
00314 struct sigaction sa;
00315
00316 sigemptyset(&sa.sa_mask);
00317 sa.sa_flags = 0;
00318
00319 if (dofork) {
00320 sa.sa_handler = SIG_IGN;
00321 sigaction(SIGINT, &sa, (struct sigaction *) 0);
00322 sigaction(SIGTSTP, &sa, (struct sigaction *) 0);
00323 sigaction(SIGQUIT, &sa, (struct sigaction *) 0);
00324 sigaction(SIGTTOU, &sa, (struct sigaction *) 0);
00325 }
00326 else {
00327
00328
00329
00330
00331 sa.sa_handler = signal_exit;
00332 sigaction(SIGINT, &sa, (struct sigaction *) 0);
00333 }
00334
00335
00336 sa.sa_handler = signal_exit;
00337 sigaction(SIGTERM, &sa, (struct sigaction *) 0);
00338 sigaction(SIGHUP, &sa, (struct sigaction *) 0);
00339
00340 sa.sa_handler = SIG_IGN;
00341 sigaction(SIGPIPE, &sa, (struct sigaction *)0);
00342
00343
00344
00345
00346
00347 sa.sa_handler = signal_child;
00348 sigaction(SIGCHLD, &sa, (struct sigaction *) 0);
00349
00350 sa.sa_handler = signal_check;
00351 sigaction(SIGALRM, &sa, (struct sigaction *) 0);
00352
00353 #ifdef _AIX
00354 sa.sa_flags = SA_FULLDUMP;
00355 sa.sa_handler = SIG_DFL;
00356 sigaction(SIGSEGV, &sa, (struct sigaction *) 0);
00357 #endif
00358
00359 #else
00360 if (dofork) {
00361
00362
00363
00364
00365 signal(SIGINT, SIG_IGN);
00366 signal(SIGTSTP, SIG_IGN);
00367 signal(SIGTTOU, SIG_IGN);
00368 signal(SIGQUIT, SIG_IGN);
00369 }
00370 else {
00371
00372
00373
00374
00375 signal(SIGINT, signal_exit);
00376 }
00377
00378
00379 signal(SIGTERM, signal_exit);
00380 signal(SIGHUP, signal_exit);
00381 signal(SIGCHLD, signal_child);
00382 signal(SIGPIPE, SIG_IGN);
00383
00384 signal(SIGALRM, signal_check);
00385 #endif
00386 }
00387
00388 static void
00389 detach()
00390 {
00391
00392 register int i;
00393
00394
00395 #if defined(_POSIX_VERSION) && !defined(ultrix)
00396 (void) setpgid(0, tcgetpgrp(1));
00397 #else
00398 (void) setpgrp(0, getpgrp(getppid()));
00399 #endif
00400
00401
00402 if ((i = fork())) {
00403 if (i < 0) {
00404 perror("jwgc: cannot fork, aborting:");
00405 exit(1);
00406 }
00407 exit(0);
00408 }
00409 }
00410
00411 int
00412 main(argc, argv)
00413 int argc;
00414 char **argv;
00415 {
00416 extern char *optarg;
00417 extern int optind;
00418 char prompt[256];
00419 char **new;
00420 register char **current;
00421 int dofork = 1;
00422 int portset = 0;
00423
00424 whoami = argv[0];
00425 progname = argv[0];
00426 #ifndef NODEBUG
00427 dinit();
00428 for (new = current = argv + 1; *current; current++) {
00429 if (string_Eq(*current, "-debug")) {
00430 argc -= 2;
00431 current++;
00432 if (!*current)
00433 dprinttypes();
00434 dparseflags(*current);
00435 }
00436 }
00437 #endif
00438 jVars_set_defaults_handler(jwg_set_defaults_handler);
00439 jVars_init();
00440
00441 for (new = current = argv + 1; *current; current++) {
00442 if (string_Eq(*current, "-h") ||
00443 string_Eq(*current, "-help")) {
00444 usage();
00445 }
00446 #ifndef NODEBUG
00447 else if (string_Eq(*current, "-debug")) {
00448 argc -= 2;
00449 current++;
00450
00451 }
00452 #endif
00453 else if (string_Eq(*current, "-f") ||
00454 string_Eq(*current, "-descfile")) {
00455 argc -= 2;
00456 current++;
00457 if (!*current)
00458 usage();
00459 description_filename_override = *current;
00460 }
00461 else if (string_Eq(*current, "-j") ||
00462 string_Eq(*current, "-jid")) {
00463 argc -= 2;
00464 current++;
00465 if (!*current)
00466 usage();
00467 jVars_set(jVarJID, *current);
00468 }
00469 else if (string_Eq(*current, "-port")) {
00470 argc -= 2;
00471 current++;
00472 if (!*current)
00473 usage();
00474 jVars_set(jVarPort, *current);
00475 portset = 1;
00476 }
00477 else if (string_Eq(*current, "-priority")) {
00478 argc -= 2;
00479 current++;
00480 if (!*current)
00481 usage();
00482 jVars_set(jVarPriority, *current);
00483 }
00484 else if (string_Eq(*current, "-nofork")) {
00485 argc--;
00486 dofork = 0;
00487 }
00488 else if (string_Eq(*current, "-register")) {
00489 argc--;
00490 jwgc_register = 1;
00491 }
00492 #ifdef USE_SSL
00493 else if (string_Eq(*current, "-ssl")) {
00494 argc--;
00495 jVars_set(jVarUseSSL, "1");
00496 }
00497 else if (string_Eq(*current, "-nossl")) {
00498 argc--;
00499 jVars_set(jVarUseSSL, "0");
00500 }
00501 #endif
00502 #ifdef USE_GPGME
00503 else if (string_Eq(*current, "-gpg")) {
00504 argc--;
00505 jVars_set(jVarUseGPG, "1");
00506 }
00507 else if (string_Eq(*current, "-nogpg")) {
00508 argc--;
00509 jVars_set(jVarUseGPG, "0");
00510 }
00511 else if (string_Eq(*current, "-gpgpass")) {
00512 argc -= 2;
00513 current++;
00514 if (!*current)
00515 usage();
00516 jVars_set(jVarGPGPass, *current);
00517 }
00518 #endif
00519 else if (string_Eq(*current, "-u") ||
00520 string_Eq(*current, "-username")) {
00521 argc -= 2;
00522 current++;
00523 if (!*current)
00524 usage();
00525 jVars_set(jVarUsername, *current);
00526 }
00527 else if (string_Eq(*current, "-s") ||
00528 string_Eq(*current, "-server")) {
00529 argc -= 2;
00530 current++;
00531 if (!*current)
00532 usage();
00533 jVars_set(jVarServer, *current);
00534 }
00535 else if (string_Eq(*current, "-r") ||
00536 string_Eq(*current, "-resource")) {
00537 argc -= 2;
00538 current++;
00539 if (!*current)
00540 usage();
00541 jVars_set(jVarResource, *current);
00542 }
00543 else if (string_Eq(*current, "-p") ||
00544 string_Eq(*current, "-password")) {
00545 argc -= 2;
00546 current++;
00547 if (!*current)
00548 usage();
00549 jVars_set(jVarPassword, *current);
00550 }
00551 else
00552 *(new)++ = *current;
00553 }
00554 *new = *current;
00555
00556 #ifdef USE_SSL
00557 if (!portset && *(int *)jVars_get(jVarUseSSL)) {
00558 jVars_set(jVarPort, DEFSSLPORT);
00559 }
00560 #endif
00561
00562 if (jVars_get(jVarUsername) == NULL) {
00563 if (!jVars_set(jVarUsername, getlogin())) {
00564 printf("No username specified.\n");
00565 exit(0);
00566 }
00567 }
00568
00569 if (jVars_get(jVarPassword) == NULL) {
00570 snprintf(prompt, 255, "Password for %s@%s:",
00571 (char *)jVars_get(jVarUsername),
00572 (char *)jVars_get(jVarServer));
00573 #ifdef HAVE_GETPASSPHRASE
00574 if (!jVars_set(jVarPassword, getpassphrase(prompt))) {
00575 #else
00576 if (!jVars_set(jVarPassword, getpass(prompt))) {
00577 #endif
00578 printf("No password specified.\n");
00579 exit(0);
00580 }
00581 }
00582
00583 mux_init();
00584 var_clear_all_variables();
00585 init_ports();
00586 dprintf(dExecution, "Initializing standard ports...\n");
00587 init_standard_ports(&argc, argv);
00588 if (argc > 1)
00589 usage();
00590 check_live_jwgc();
00591 setup_signals(dofork);
00592
00593 if (!jVars_get(jVarJID)) {
00594 char *jwgcjid;
00595 dprintf(dExecution, "Creating JID...\n");
00596 jwgcjid = (char *) malloc(sizeof(char) *
00597 (strlen((char *)jVars_get(jVarUsername))
00598 + strlen((char *)jVars_get(jVarServer))
00599 + strlen((char *)jVars_get(jVarResource)) + 3));
00600 sprintf(jwgcjid, "%s@%s/%s",
00601 (char *)jVars_get(jVarUsername),
00602 (char *)jVars_get(jVarServer),
00603 (char *)jVars_get(jVarResource));
00604 dprintf(dExecution, "JID = %s\n", jwgcjid ? jwgcjid : "n/a");
00605 jVars_set(jVarJID, jwgcjid);
00606 free(jwgcjid);
00607 }
00608 else {
00609 dprintf(dExecution, "JID already set to %s.\n",
00610 (char *)jVars_get(jVarJID));
00611 }
00612 jwgc_init();
00613 jabber_init();
00614
00615 if (dofork)
00616 detach();
00617
00618 run_initprogs();
00619
00620 read_in_description_file();
00621
00622 alarm(ALARMTIMEOUT);
00623
00624 mux_loop();
00625
00626 jabber_finalize();
00627
00628 exit(0);
00629 }