URI: 
       tmain.c - mixmaster - mixmaster 3.0 patched for libressl
  HTML git clone git://parazyd.org/mixmaster.git
   DIR Log
   DIR Files
   DIR Refs
   DIR README
       ---
       tmain.c (22681B)
       ---
            1 /* Mixmaster version 3.0  --  (C) 1999 - 2006 Anonymizer Inc. and others.
            2 
            3    Mixmaster may be redistributed and modified under certain conditions.
            4    This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
            5    ANY KIND, either express or implied. See the file COPYRIGHT for
            6    details.
            7 
            8    Command-line based frontend
            9    $Id: main.c 937 2006-06-24 15:52:20Z colin $ */
           10 
           11 
           12 #include "mix3.h"
           13 #include "pgp.h"
           14 #include <stdio.h>
           15 #include <string.h>
           16 #include <ctype.h>
           17 #include <stdlib.h>
           18 #ifdef POSIX
           19 #include <unistd.h>
           20 #else /* end of POSIX */
           21 #include <io.h>
           22 #endif /* else if not POSIX */
           23 #include <assert.h>
           24 
           25 static char *largopt(char *p, char *opt, char *name, int *error);
           26 static void noarg(char *name, char p);
           27 static int check_get_pass(int force, int never_ask_for_passphrase);
           28 
           29 /** main *****************************************************************/
           30 
           31 /* Returns:
           32  0 successful operation
           33  1 command line error
           34  2 client error condition */
           35 
           36 #ifdef WIN32SERVICE
           37 int mix_main(int argc, char *argv[])
           38 #else
           39 int main(int argc, char *argv[])
           40 #endif /* WIN32SERVICE */
           41 {
           42   int error = 0, deflt = 1, help = 0, readmail = 0, send = -1, sendpool = 0,
           43   header = 1, maint = 0, keygen = 0, verbose = 0, sign = 0, encrypt = 0,
           44   redirect_mail = 0, about=0, version=0;
           45   int daemon = 0, type_list = 0, nodetach = 0;
           46   int update_stats = 0, update_pingerlist = 0;
           47   int never_ask_for_passphrase = 0;
           48 
           49 #ifdef USE_SOCK
           50   int pop3 = 0;
           51 
           52 #endif /* USE_SOCK */
           53   char *filename = NULL;
           54   int i;
           55   int ret = 0;
           56   char *p, *q;
           57   char chain[1024] = "";
           58   char nym[LINELEN] = "";
           59   BUFFER *nymopt, *pseudonym, *attachments, *statssrc;
           60   int numcopies = 0;                /* default value set in mix.cfg */
           61   BUFFER *msg, *chainlist, *field, *content;
           62   FILE *f;
           63   char pingpath[PATHMAX];
           64 
           65   /* Check if parse_yearmonthday works */
           66   assert(parse_yearmonthday("2003-04-01") == 1049155200);
           67 
           68   mix_init(NULL);
           69 
           70   msg = buf_new();
           71   chainlist = buf_new();
           72   nymopt = buf_new();
           73   pseudonym = buf_new();
           74   attachments = buf_new();
           75   field = buf_new();
           76   content = buf_new();
           77   statssrc = buf_new();
           78 
           79 #ifdef USE_NCURSES
           80   if (argc == 1) {
           81     if (isatty(fileno(stdin)))
           82       menu_main();
           83     else
           84       menu_folder(0, NULL);
           85     goto clientpool;
           86   }
           87 #endif /* USE_NCURSES */
           88   if (argc > 1 && strleft(argv[1], "-f")) {
           89     menu_folder(strlen(argv[1]) > 2 ? argv[1][2] : 0, argc < 3 ? NULL : argv[2]);
           90     goto clientpool;
           91   }
           92   for (i = 1; i < argc; i++) {
           93     p = argv[i];
           94     if (p[0] == '-' && p[1] != '\0') {
           95       if (p[1] == '-') {
           96         p += 2;
           97         if (strieq(p, "help"))
           98           help = 1, deflt = 0;
           99         else if (streq(p, "version"))
          100           version = 1, deflt = 0;
          101         else if (streq(p, "about"))
          102           about = 1, deflt = 0;
          103         else if (streq(p, "verbose"))
          104           verbose = 1;
          105         else if (streq(p, "type-list"))
          106           type_list = 1;
          107         else if (streq(p, "dummy"))
          108           send = MSG_NULL, deflt = 0;
          109         else if (streq(p, "remailer"))
          110           maint = 1, deflt = 0;
          111         else if (streq(p, "generate-key"))
          112           keygen = 2, deflt = 0;
          113         else if (streq(p, "update-keys"))
          114           keygen = 1, deflt = 0;
          115         else if (streq(p, "send"))
          116           sendpool = 1, deflt = 0;
          117         else if (streq(p, "read-mail"))
          118           readmail = 1, deflt = 0;
          119         else if (streq(p, "redirect"))
          120           redirect_mail = 1, deflt = 0;
          121         else if (streq(p, "store-mail"))
          122           readmail = 2, deflt = 0;
          123 #ifdef USE_SOCK
          124         else if (streq(p, "pop-mail"))
          125           pop3 = 1, deflt = 0;
          126 #endif /* USE_SOCK */
          127         else if (streq(p, "daemon"))
          128           daemon = 1, deflt = 0;
          129         else if (streq(p, "no-detach"))
          130           nodetach = 1;
          131         else if (streq(p, "post"))
          132           send = MSG_POST;
          133         else if (streq(p, "mail"))
          134           send = MSG_MAIL;
          135         else if (streq(p, "sign"))
          136           sign = 1;
          137         else if (streq(p, "encrypt"))
          138           encrypt = 1;
          139         else if (streq(p, "no-ask-passphrase"))
          140           never_ask_for_passphrase = 1;
          141         else if (streq(p, "update-pinger-list"))
          142           update_pingerlist = 1;
          143         else if (streq(p, "update-stats")) {
          144           buf_clear(statssrc);
          145           f = mix_openfile(STATSSRC, "r");
          146           if (f != NULL) {
          147             buf_read(statssrc, f);
          148             fclose(f);
          149           }
          150           if (statssrc->length > 0) {
          151             update_stats = 1;
          152           } else {
          153             deflt = 0;
          154             fprintf(stderr, "%s: No current stats source --%s\n", argv[0], p);
          155           }
          156         } else if (strleft(p, "update-stats") && p[strlen("update-stats")] == '=') {
          157           buf_clear(statssrc);
          158           buf_appendf(statssrc, "%s", (p + strlen("update-stats") + 1));
          159           if (statssrc->length > 0) {
          160             update_stats = 1;
          161           } else {
          162             fprintf(stderr, "%s: No stats source specified --%s\n", argv[0], p);
          163           }
          164         } else if ((q = largopt(p, "to", argv[0], &error)) != NULL) {
          165           header = 0;
          166           buf_appendf(msg, "To: %s\n", q);
          167         } else if ((q = largopt(p, "post-to", argv[0], &error)) != NULL) {
          168           send = MSG_POST, header = 0;
          169           buf_appendf(msg, "Newsgroups: %s\n", q);
          170         } else if ((q = largopt(p, "subject", argv[0], &error)) != NULL) {
          171           buf_appendf(msg, "Subject: %s\n", q);
          172         } else if ((q = largopt(p, "header", argv[0], &error)) != NULL) {
          173           buf_appendf(msg, "%s\n", q);
          174         } else if ((q = largopt(p, "chain", argv[0], &error)) != NULL) {
          175           buf_appendf(msg, "Chain: %s\n", q);
          176         }
          177 #ifdef USE_PGP
          178         else if ((q = largopt(p, "reply-chain", argv[0], &error)) != NULL) {
          179           buf_appendf(msg, "Reply-Chain: %s\n", q);
          180         } else if ((q = largopt(p, "latency", argv[0], &error)) != NULL) {
          181           buf_appendf(msg, "Latency: %s\n", q);
          182         } else if ((q = largopt(p, "attachment", argv[0], &error)) != NULL) {
          183           buf_appendf(attachments, "%s\n", q);
          184 #ifdef NYMSUPPORT
          185         } else if ((q = largopt(p, "nym-config", argv[0], &error)) != NULL) {
          186           deflt = 0;
          187           strncpy(nym, q, sizeof(nym));
          188           if (i > argc && strileft(argv[i + 1], "name="))
          189             buf_sets(pseudonym, argv[++i] + 5);
          190           else if (i > argc && strileft(argv[i + 1], "opt="))
          191             buf_appends(nymopt, argv[++i] + 5);
          192         } else if ((q = largopt(p, "nym", argv[0], &error)) != NULL) {
          193           buf_appendf(msg, "Nym: %s\n", q);
          194 #endif /* NYMSUPPORT */
          195         }
          196 #endif /* USE_PGP */
          197         else if ((q = largopt(p, "copies", argv[0], &error)) != NULL) {
          198           sscanf(q, "%d", &numcopies);
          199         } else if ((q = largopt(p, "config", argv[0], &error)) != NULL) {
          200           strncpy(MIXCONF, q, PATHMAX);
          201           MIXCONF[PATHMAX-1] = 0;
          202           mix_config(); /* configuration file changed - reread it */
          203         } else if (error == 0 && mix_configline(p) == 0) {
          204           fprintf(stderr, "%s: Invalid option %s\n", argv[0], argv[i]);
          205           error = 1;
          206         }
          207       } else {
          208         while (*++p) {
          209           switch (*p) {
          210           case 'd':
          211             send = MSG_NULL, deflt = 0;
          212             break;
          213           case 'R':
          214             readmail = 1, deflt = 0;
          215             break;
          216           case 'I':
          217             readmail = 2, deflt = 0;
          218             break;
          219           case 'S':
          220             sendpool = 1, deflt = 0;
          221             break;
          222           case 'M':
          223             maint = 1, deflt = 0;
          224             break;
          225 #ifdef USE_SOCK
          226           case 'P':
          227             pop3 = 1, deflt = 0;
          228             break;
          229 #endif /* USE_SOCK */
          230           case 'D':
          231             daemon = 1, deflt = 0;
          232             break;
          233           case 'G':
          234             keygen = 2, deflt = 0;
          235             break;
          236           case 'K':
          237             keygen = 1, deflt = 0;
          238             break;
          239           case 'L':                /* backwards compatibility */
          240             break;
          241           case 'v':
          242             verbose = 1;
          243             break;
          244           case 'h':
          245             help = 1, deflt = 0;
          246             break;
          247           case 'T':
          248             type_list = 1;
          249             break;
          250           case 'V':
          251             version = 1, deflt = 0;
          252             break;
          253           case 't':
          254             if (*(p + 1) == 'o')
          255               p++;
          256             header = 0;
          257             if (i < argc - 1)
          258               buf_appendf(msg, "To: %s\n", argv[++i]);
          259             else {
          260               fprintf(stderr, "%s: Missing argument for option -to\n", argv[0]);
          261               error = 1;
          262             }
          263             break;
          264           case 's':
          265             if (i < argc - 1)
          266               buf_appendf(msg, "Subject: %s\n", argv[++i]);
          267             else {
          268               noarg(argv[0], *p);
          269               error = 1;
          270             }
          271             break;
          272           case 'l':
          273             if (i < argc - 1)
          274               buf_appendf(msg, "Chain: %s\n", argv[++i]);
          275             else {
          276               noarg(argv[0], *p);
          277               error = 1;
          278             }
          279             break;
          280           case 'r':
          281             if (i < argc - 1)
          282               buf_appendf(msg, "Reply-Chain: %s\n", argv[++i]);
          283             else {
          284               noarg(argv[0], *p);
          285               error = 1;
          286             }
          287             break;
          288 #ifdef USE_PGP
          289           case 'n':
          290             if (i < argc - 1)
          291               buf_appendf(msg, "Nym: %s\n", argv[++i]);
          292             else {
          293               noarg(argv[0], *p);
          294               error = 1;
          295             }
          296             break;
          297 #endif /* USE_PGP */
          298           case 'c':
          299             if (i < argc - 1)
          300               sscanf(argv[++i], "%d", &numcopies);
          301             else {
          302               noarg(argv[0], *p);
          303               error = 1;
          304             }
          305             break;
          306           case 'p':
          307             send = MSG_POST;
          308             break;
          309           case 'g':
          310             if (i < argc - 1) {
          311               send = MSG_POST, header = 0;
          312               buf_appendf(msg, "Newsgroups: %s\n", argv[++i]);
          313             } else {
          314               noarg(argv[0], *p);
          315               error = 1;
          316             }
          317             break;
          318           case 'a':
          319             if (i < argc - 1)
          320               buf_appendf(attachments, "%s\n", argv[++i]);
          321             else {
          322               noarg(argv[0], *p);
          323               error = 1;
          324             }
          325             break;
          326           case 'm':
          327             send = MSG_MAIL;
          328             break;
          329           default:
          330             fprintf(stderr, "%s: Invalid option -%c\n", argv[0], *p);
          331             error = 1;
          332             break;
          333           }
          334         }
          335       }
          336     } else {
          337       if (strchr(argv[i], '@')) {
          338         header = 0;
          339         buf_appendf(msg, "To: %s\n", argv[i]);
          340       } else {
          341         if (filename == NULL)
          342           filename = argv[i];
          343         else {
          344           fprintf(stderr, "%s: Error in command line: %s\n", argv[0], argv[i]);
          345           error = 1;
          346         }
          347       }
          348     }
          349   }
          350 
          351   if (error) {
          352     ret = 1;
          353     goto end;
          354   }
          355 
          356   if (type_list) {
          357     BUFFER *type2list;
          358     type2list = buf_new();
          359     if (prepare_type2list(type2list) < 0) {
          360       fprintf(stderr, "Cannot print type2.list.\n");
          361       ret = 2;
          362     } else {
          363       printf("%s", type2list->data);
          364     };
          365     buf_free(type2list);
          366     goto end;
          367   }
          368 
          369   if (version) {
          370     printf("Mixmaster %s\n", VERSION);
          371     ret = 0;
          372     goto end;
          373   }
          374 
          375   if (update_pingerlist) {
          376     mixfile(pingpath, ALLPINGERSFILE);
          377     if (verbose) printf ("downloading %s...\n", ALLPINGERSURL);
          378     if (url_download(ALLPINGERSURL, pingpath) < 0) {
          379       printf("    Download failed... Try again later.\n");
          380       errlog(ERRORMSG, "All Pingers File Download failed.\n");
          381     } else {
          382       if (verbose) printf("    Done.\n");
          383       errlog(LOG, "All Pingers File Downloaded OK.\n");
          384     }
          385     ret = 0;
          386     goto end;
          387   }
          388   
          389   if (update_stats) {
          390     ret = download_stats(statssrc->data);
          391     if (ret == -3) {
          392       fprintf(stderr, "Stats source does not include all required files.\n");
          393     } else if (ret == -2) {
          394       fprintf(stderr, "Could not open stats source file for writing\n");
          395     } else if (ret == -1) {
          396       fprintf(stderr, "Stats source download failed.\n");
          397     }
          398     ret = 0;
          399     goto end;
          400   }
          401 
          402 #ifdef USE_NCURSES
          403 /* If we get here then it's possible we still want to use the NCURSES interface */
          404     if (deflt && (send == -1) && isatty(fileno(stdin))) {
          405       menu_main();
          406       goto clientpool;
          407     }
          408 #endif /* USE_NCURSES */
          409   
          410   if (help ||about ||(isatty(fileno(stdin)) && isatty(fileno(stdout))))
          411     fprintf(stderr, "Mixmaster %s\n", VERSION);
          412   if (help ||about)
          413     printf("\n\n");
          414   if (about) {
          415     printf("Many people have contributed to the source code for Mixmaster.\n");
          416     printf("These contributors include:\n\n");
          417     printf("Lance Cottrell\n");
          418     printf("Janis Jagars\n");
          419     printf("Ulf Moeller\n");
          420     printf("Peter Palfrader\n");
          421     printf("Len Sassaman\n");
          422     printf("\nand others. For full information on copyright and license issues,\n");
          423     printf("read the bundled file COPYRIGHT.\n\n");
          424     ret = 0;
          425     goto end;
          426   }
          427   
          428   if (help) {
          429     printf("Usage: %s [options] [user@host] [filename]\n\n", argv[0]);
          430     printf("Options:\n\
          431 \n\
          432 -h, --help                        summary of command line options\n\
          433 -V, --version                     print version information\n\
          434     --about                       print authorship information\n\
          435 -T, --type-list                   list available remailers\n\
          436 -t, --to=user@host                the recipient's address(es)\n\
          437 -g, --post-to=newsgroup           newsgroup(s) to post to\n\
          438 -p, --post                        input is a Usenet article\n\
          439 -m, --mail                        input is a mail message\n\
          440 -s, --subject=subject             message subject\n\
          441     --header='header line'        arbitrary message headers\n\
          442 -a, --attachment=file             attach a file\n"
          443 #ifdef USE_PGP
          444 #ifdef NYMSUPPORT
          445            "-n, --nym=yournym                 use pseudonym to send the message\n"
          446 #endif /* NYMSUPPORT */
          447 "    --encrypt                     encrypt the message using the PGP format\n\
          448     --sign                        sign the message using the PGP format\n"
          449 #endif /* USE_PGP */
          450            "-l, --chain=mix1,mix2,mix3,...    specify a remailer chain\n\
          451 -c, --copies=num                  send num copies to increase reliability\n\
          452 -d, --dummy                       generate a dummy message\n\
          453 -S, --send                        send the message(s) in the pool\n"
          454 #ifdef USE_PGP
          455 #ifdef NYMSUPPORT
          456            "    --nym-config=yournym          generate a new pseudonym\n\
          457     --latency=hours               reply chain latency\n\
          458     --reply-chain=rem1,rem2,...   reply chain for the pseudonym\n"
          459 #endif /* NYMSUPPORT */
          460 #endif /* USE_PGP */
          461            "-v, --verbose                     output informational messages\n\
          462 -f [file]                         read a mail folder\n\
          463     --update-pinger-list          Download an updated all pingers list file\n\
          464     --update-stats[=source]       Download updated stats\n"
          465 
          466 #ifndef USE_NCURSES
          467            "\n-fr, -ff, -fg [file]              send reply/followup/group reply to a message\n"
          468 #endif /* USE_NCURSES */
          469            "\nThe input file is expected to contain mail headers if no address is\n\
          470 specified in the command line.\n\
          471 \n\
          472 Remailer:\n\
          473 \n\
          474 -R, --read-mail                   read remailer message from stdin\n\
          475 -I, --store-mail                  read remailer msg from stdin, do not decrypt\n\
          476 -M, --remailer                    process the remailer pool\n\
          477 -D, --daemon                      remailer as background process\n\
          478     --no-detach                   do not detach from terminal as daemon\n"
          479 #ifdef USE_SOCK
          480            "-S, --send                        force sending messages from the pool\n"
          481 #endif /* USE_SOCK */
          482            "-P, --pop-mail                    force getting messages from POP3 servers\n\
          483 -G, --generate-key                generate a new remailer key\n\
          484 -K, --update-keys                 generate remailer keys if necessary\n\
          485     --config=file                 use alternate configuration file\n"
          486 #ifdef WIN32SERVICE
          487            "\n\
          488 WinNT service:\n\
          489 \n\
          490     --install-svc                 install the service\n\
          491     --remove-svc                  remove the service\n\
          492     --run-svc                     run as a service\n"
          493 #endif /* WIN32SERVICE */
          494     );
          495 
          496     ret = 0;
          497     goto end;
          498   }
          499 
          500   if (deflt && send == -1)
          501     send = MSG_MAIL;
          502   if (nym[0] != 0)
          503     send = -1;
          504   if ((send == MSG_MAIL || send == MSG_POST) && filename == NULL &&
          505       header == 1 && isatty(fileno(stdin))) {
          506     /* we don't get here if USE_NCURSES is set */
          507     printf("Run `%s -h' to view a summary of the command line options.\n\nEnter the message, complete with headers.\n",
          508            argv[0]);
          509 #ifdef UNIX
          510     printf("When done, press ^D.\n\n");
          511 #else
          512     printf("When done, press ^Z.\n\n");
          513 #endif /* else not UNIX */
          514   }
          515   if (header == 0)
          516     buf_nl(msg);
          517 
          518   /* timeskew check */
          519   if (REMAIL == 1)
          520     mix_check_timeskew();
          521 
          522   if (readmail || redirect_mail || send == MSG_MAIL || send == MSG_POST) {
          523     if (filename == NULL || streq(filename, "-"))
          524       f = stdin;
          525     else {
          526       f = fopen(filename, "r");
          527       if (f == NULL)
          528         fprintf(stderr, "Can't open %s.\n", filename);
          529     }
          530 
          531     if (f && buf_read(msg, f) != -1) {
          532       if (readmail == 1) {
          533         check_get_pass(1, never_ask_for_passphrase);
          534         mix_decrypt(msg);
          535       } else if (readmail == 2)
          536         pool_add(msg, "inf");
          537       if (send == MSG_MAIL || send == MSG_POST || redirect_mail) {
          538         BUFFER *sendmsg;
          539         int numdest = 0;
          540 
          541         sendmsg = buf_new();
          542 
          543         while (buf_getheader(msg, field, content) == 0) {
          544           if (bufieq(field, "nym")) {
          545             strncpy(nym, content->data, sizeof(nym));
          546           } else if (bufieq(field, "chain"))
          547             if (strchr(content->data, ';')) {
          548               i = strchr(content->data, ';') - (char *)content->data;
          549               strncpy(chain, content->data, i);
          550               if (strstr(content->data + i, "copies=") != NULL) {
          551                 sscanf(strstr(content->data + i, "copies=") +
          552                        sizeof("copies=") - 1, "%d", &numcopies);
          553               }
          554             } else
          555               strncpy(chain, content->data, sizeof(chain));
          556           else {                /* line goes into message */
          557             if (((redirect_mail || send == MSG_MAIL) && bufieq(field, "to"))
          558                 || (send == MSG_POST && bufieq(field, "newsgroups")))
          559               numdest++;
          560             if (bufieq(field, "from") && !redirect_mail)
          561               fprintf(stderr, "Warning: The message has a From: line.\n");
          562             buf_appendheader(sendmsg, field, content);
          563           }
          564         }
          565         buf_nl(sendmsg);
          566         buf_rest(sendmsg, msg);
          567 
          568         while (buf_getline(attachments, field) != -1)
          569           if (attachfile(sendmsg, field) == -1) {
          570             errlog(ERRORMSG, "Can't attach %b!\n", field);
          571             ret = 2;
          572             goto end;
          573           }
          574 
          575 #ifdef USE_PGP
          576         if (nym[0] != 0 && strchr(nym, '@') == NULL)
          577           strcatn(nym, "@", sizeof(nym));
          578         if (sign || encrypt) {
          579           BUFFER *pass;
          580 
          581           pass = buf_new();
          582           user_pass(pass);
          583           if (pgp_mailenc((encrypt ? PGP_ENCRYPT : 0) |
          584                           (nym[0] != 0 && sign ? PGP_SIGN : 0) |
          585                           PGP_TEXT | PGP_REMAIL, sendmsg, nym,
          586                           pass, NULL, NYMSECRING) != 0) {
          587             fprintf(stderr, "Encryption failed: missing key!");
          588             ret = 2;
          589             goto end;
          590           }
          591           buf_free(pass);
          592         }
          593         if (nym[0] != 0) {
          594 #ifdef NYMSUPPORT
          595           if (nym_encrypt(sendmsg, nym, send) == 0)
          596             send = MSG_MAIL;
          597           else
          598 #endif /* NYMSUPPORT */
          599             fprintf(stderr, "Nym error, sending message anonymously.\n");
          600         }
          601 #endif /* USE_PGP */
          602         if (numdest == 0) {
          603           fprintf(stderr, "No destination address given!\n");
          604           ret = 2;
          605         } else if (numcopies < 0 || numcopies > 10) {
          606           fprintf(stderr, "Invalid number of copies!\n");
          607           ret = 2;
          608         } else {
          609           if ( ( redirect_mail ?
          610                 redirect_message(sendmsg, chain, numcopies, chainlist) :
          611                 mix_encrypt(send, sendmsg, chain, numcopies, chainlist)
          612                 ) == -1) {
          613             ret = 2;
          614             if (chainlist->length)
          615               fprintf(stderr, "%s\n", chainlist->data);
          616             else
          617               fprintf(stderr, "Failed!\n");
          618           } else if (verbose) {
          619             fprintf(stderr, "Chain: ");
          620             buf_write(chainlist, stderr);
          621           }
          622         }
          623 
          624         buf_free(sendmsg);
          625       }
          626       if (filename != NULL)
          627         fclose(f);
          628     } else
          629       ret = 2;
          630   }
          631   if (send == MSG_NULL) {
          632     if (msg->length) {
          633       while (buf_getheader(msg, field, content) == 0) {
          634         if (bufieq(field, "chain"))
          635           strncpy(chain, content->data, sizeof(chain));
          636       }
          637     }
          638     if (mix_encrypt(MSG_NULL, NULL, chain, numcopies, chainlist) == -1) {
          639       ret = 2;
          640       if (chainlist->length)
          641         printf("%s\n", chainlist->data);
          642       else
          643         fprintf(stderr, "Failed!\n");
          644     } else if (verbose) {
          645       printf("Chain: ");
          646       buf_write(chainlist, stdout);
          647     }
          648   }
          649 #ifdef USE_PGP
          650 #ifdef NYMSUPPORT
          651   if (nym[0] != 0) {
          652     char nymserver[LINELEN] = "*";
          653     BUFFER *chains;
          654 
          655     chains = buf_new();
          656     if (numcopies < 1 || numcopies > 10)
          657       numcopies = 1;
          658     while (buf_getheader(msg, field, content) != -1) {
          659       if (bufieq(field, "chain"))
          660         strncpy(chain, content->data, sizeof(chain));
          661       else if (bufieq(field, "reply-chain"))
          662         buf_appendf(chains, "Chain: %b\n", content);
          663       else if (field->length)
          664         buf_appendheader(chains, field, content);
          665       else
          666         buf_nl(chains);
          667     }
          668     if (strrchr(nym, '@')) {
          669       strncpy(nymserver, strrchr(nym, '@'), sizeof(nymserver));
          670       *strrchr(nym, '@') = '\0';
          671     }
          672     if (nym_config(NYM_CREATE, nym, nymserver, pseudonym,
          673                    chain, numcopies, chains, nymopt) < 0) {
          674       ret = 2;
          675       fprintf(stderr, "Failed!\n");
          676     }
          677     user_delpass();
          678     buf_free(chains);
          679   }
          680 #endif /* NYMSUPPORT */
          681 #endif /* USE_PGP */
          682 
          683   if (keygen) {
          684     check_get_pass(0, never_ask_for_passphrase);
          685     keymgt(keygen);
          686   }
          687   if (sendpool)
          688     mix_send();
          689 #ifdef USE_SOCK
          690   if (pop3)
          691     pop3get();
          692 #endif /* USE_SOCK */
          693   if (maint) {
          694     check_get_pass(1, never_ask_for_passphrase);
          695     mix_regular(0);
          696   }
          697 
          698 clientpool:
          699   if ((REMAIL == 0) && (CLIENTAUTOFLUSH == 1)) {
          700     SENDPOOLTIME = 0;
          701     RATE = 100;
          702     mix_send();
          703   };
          704 
          705 end:
          706   buf_free(field);
          707   buf_free(content);
          708   buf_free(chainlist);
          709   buf_free(msg);
          710   buf_free(nymopt);
          711   buf_free(pseudonym);
          712   buf_free(attachments);
          713   buf_free(statssrc);
          714 
          715   if (daemon) {
          716     check_get_pass(1, never_ask_for_passphrase);
          717 #ifdef UNIX
          718     if (! nodetach) {
          719       int pid;
          720 
          721       fprintf(stderr, "Detaching.\n");
          722       /* Detach as suggested by the Unix Programming FAQ */
          723       pid = fork();
          724       if (pid > 0)
          725         exit(0);
          726       if (setsid() < 0) {
          727         /* This should never happen. */
          728         fprintf(stderr, "setsid() failed.\n");
          729         exit(1);
          730       };
          731       pid = fork();
          732       if (pid > 0)
          733         exit(0);
          734     };
          735     if (chdir(MIXDIR) < 0) {
          736       if (chdir("/") < 0) {
          737         fprintf(stderr, "Cannot chdir to mixdir or /.\n");
          738         exit(1);
          739       };
          740     };
          741     if (write_pidfile(PIDFILE)) {
          742       fprintf(stderr, "Aborting.\n");
          743       exit(1);
          744     }
          745     if (! nodetach) {
          746       freopen ("/dev/null", "r", stdin);
          747       freopen ("/dev/null", "w", stdout);
          748       freopen ("/dev/null", "w", stderr);
          749     }
          750 #endif /* UNIX */
          751     mix_daemon();
          752 #ifdef UNIX
          753 /* ifdef this one too, so that we do not need to export it from windows dll */
          754     clear_pidfile(PIDFILE);
          755 #endif /* UNIX */
          756   }
          757   mix_exit();
          758   return (ret);
          759 }
          760 
          761 static char *largopt(char *p, char *opt, char *name, int *error)
          762 {
          763   if (streq(p, opt)) {
          764     fprintf(stderr, "%s: Missing argument for option --%s\n", name, p);
          765     *error = 1;
          766   } else if (strleft(p, opt) && p[strlen(opt)] == '=') {
          767     return (p + strlen(opt) + 1);
          768   }
          769   return (NULL);
          770 }
          771 
          772 static void noarg(char *name, char p)
          773 {
          774   fprintf(stderr, "%s: Missing argument for option -%c\n", name, p);
          775 }
          776 
          777 static int check_get_pass(int force, int never_ask_for_passphrase)
          778 /* get a passphrase and check against keys
          779  * if force != 0 passphrase must match with some key */
          780 {
          781     BUFFER *pass, *pass2, *key;
          782     int n = 0;
          783 
          784     if (PASSPHRASE[0] == '\0' && isatty(fileno(stdin)) && ! never_ask_for_passphrase) {
          785       pass = buf_new();
          786       pass2 = buf_new();
          787       key = buf_new();
          788       buf_sets(pass, PASSPHRASE);
          789       while (
          790 #ifdef USE_PGP
          791              pgpdb_getkey(PK_DECRYPT, PGP_ES_RSA, NULL, NULL, NULL, NULL, NULL,
          792                            NULL, NULL, NULL, pass) < 0 &&
          793              pgpdb_getkey(PK_DECRYPT, PGP_E_ELG,  NULL, NULL, NULL, NULL, NULL,
          794                            NULL, NULL, NULL, pass) < 0 &&
          795 #endif /* USE_PGP */
          796              getv2seckey(NULL, key) < 0)
          797       {
          798         user_delpass();
          799         if (n)
          800           fprintf(stderr, "re-");
          801         user_pass(pass);
          802         strncpy(PASSPHRASE, pass->data, LINELEN);
          803         PASSPHRASE[LINELEN-1] = 0;
          804         if (!force) {
          805           if (n && buf_eq(pass, pass2))
          806             break;
          807           buf_set(pass2, pass);
          808         }
          809         n=1;
          810       }
          811       user_delpass();
          812       buf_free(pass);
          813       buf_free(pass2);
          814       buf_free(key);
          815 
          816       strncpy(ENTEREDPASSPHRASE, PASSPHRASE, LINELEN);
          817       ENTEREDPASSPHRASE[LINELEN-1] = 0;
          818     }
          819     return 1;
          820 }