URI: 
       tmix.c - mixmaster - mixmaster 3.0 patched for libressl
  HTML git clone git://parazyd.org/mixmaster.git
   DIR Log
   DIR Files
   DIR Refs
   DIR README
       ---
       tmix.c (33886B)
       ---
            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    Mixmaster initialization, configuration
            9    $Id: mix.c 962 2007-11-19 13:42:41Z zax $ */
           10 
           11 
           12 #include "mix3.h"
           13 #include <stdlib.h>
           14 #include <stdio.h>
           15 #include <string.h>
           16 #include <stdarg.h>
           17 #include <ctype.h>
           18 #include <time.h>
           19 #include <sys/types.h>
           20 #include <sys/stat.h>
           21 #ifdef POSIX
           22 #include <signal.h>
           23 #include <unistd.h>
           24 #include <pwd.h>
           25 #include <sys/utsname.h>
           26 #else /* end of POSIX */
           27 #include <io.h>
           28 #include <direct.h>
           29 #endif /* else if not POSIX */
           30 #ifdef WIN32
           31 #include <windows.h>
           32 #include <shlobj.h>
           33 #include <shlobj.h>
           34 #endif /* WIN32 */
           35 #include <assert.h>
           36 #include "menu.h"
           37 
           38 int buf_vappendf(BUFFER *b, char *fmt, va_list args);
           39 
           40 /** filenames ************************************************************/
           41 char MIXCONF[PATHMAX] = DEFAULT_MIXCONF;
           42 char DISCLAIMFILE[PATHMAX];
           43 char FROMDSCLFILE[PATHMAX];
           44 char MSGFOOTERFILE[PATHMAX];
           45 char POP3CONF[PATHMAX];
           46 char HELPFILE[PATHMAX];
           47 char REQUESTDIR[PATHMAX];
           48 char ABUSEFILE[PATHMAX];
           49 char REPLYFILE[PATHMAX];
           50 char USAGEFILE[PATHMAX];
           51 char USAGELOG[PATHMAX];
           52 char BLOCKFILE[PATHMAX];
           53 char ADMKEYFILE[PATHMAX];
           54 char KEYFILE[PATHMAX];
           55 char PGPKEY[PATHMAX];
           56 char DSAPARAMS[PATHMAX];
           57 char DHPARAMS[PATHMAX];
           58 char MIXRAND[PATHMAX];
           59 char SECRING[PATHMAX];
           60 char PUBRING[PATHMAX];
           61 char IDLOG[PATHMAX];
           62 char STATS[PATHMAX];
           63 char PGPMAXCOUNT[PATHMAX];
           64 char DESTBLOCK[PATHMAX];
           65 char DESTALLOW[PATHMAX];
           66 char DESTALLOW2[PATHMAX];
           67 char SOURCEBLOCK[PATHMAX];
           68 char HDRFILTER[PATHMAX];
           69 char REGULAR[PATHMAX];
           70 char POOL[PATHMAX];
           71 char TYPE1LIST[PATHMAX];
           72 char TYPE2REL[PATHMAX];
           73 char PIDFILE[PATHMAX];
           74 
           75 char PGPREMPUBRING[PATHMAX];
           76 char PGPREMPUBASC[PATHMAX];
           77 char PGPREMSECRING[PATHMAX];
           78 char NYMSECRING[PATHMAX];
           79 char NYMDB[PATHMAX];
           80 char STAREX[PATHMAX];
           81 
           82 /** config ***************************************************************/
           83 
           84 char MIXDIR[PATHMAX];
           85 char POOLDIR[PATHMAX];
           86 
           87 /* programs */
           88 char SENDMAIL[LINELEN];
           89 char SENDANONMAIL[LINELEN];
           90 char NEWS[LINELEN];
           91 char TYPE1[LINELEN];
           92 
           93 /* addresses */
           94 char MAILtoNEWS[LINELEN];
           95 char REMAILERNAME[LINELEN];
           96 char ANONNAME[LINELEN];
           97 char REMAILERADDR[LINELEN];
           98 char ANONADDR[LINELEN];
           99 char COMPLAINTS[LINELEN];
          100 int AUTOREPLY;
          101 char SMTPRELAY[LINELEN];
          102 char SMTPUSERNAME[LINELEN];
          103 char SMTPPASSWORD[LINELEN];
          104 
          105 #ifdef USE_SOCK
          106 char HELONAME[LINELEN];
          107 char ENVFROM[LINELEN];
          108 int POP3DEL;
          109 int POP3SIZELIMIT;
          110 long POP3TIME;
          111 
          112 #endif /* USE_SOCK */
          113 
          114 char SHORTNAME[LINELEN];
          115 char ALLPINGERSURL[BUFSIZE];
          116 char ALLPINGERSFILE[PATHMAX];
          117 char WGET[PATHMAX];
          118 char STATSSRC[PATHMAX];
          119 int  STATSAUTOUPDATE;
          120 long STATSINTERVAL;
          121 
          122 
          123 /* remailer configuration */
          124 int REMAIL;
          125 int MIX;
          126 int PGP;
          127 int UNENCRYPTED;
          128 int REMIX;
          129 int REPGP;
          130 char EXTFLAGS[LINELEN];        /* user-defined capstring flags */
          131 
          132 char PRECEDENCE[LINELEN];        /* default Precedence: header for outgoing mail */
          133 int POOLSIZE;
          134 int RATE;
          135 int INDUMMYP;
          136 int OUTDUMMYP;
          137 int INDUMMYMAXP;
          138 int OUTDUMMYMAXP;
          139 int MIDDLEMAN;
          140 int AUTOBLOCK;
          141 int STATSDETAILS;
          142 char FORWARDTO[LINELEN];
          143 int SIZELIMIT;                /* maximal size of remailed messages */
          144 int INFLATEMAX;                /* maximal size of Inflate: padding */
          145 int MAXRANDHOPS;
          146 int BINFILTER;                /* filter binary attachments? */
          147 int LISTSUPPORTED;        /* list supported remailers in remailer-conf reply? */
          148 long PACKETEXP;                /* Expiration time for old packets */
          149 long IDEXP;                /* 0 = no ID log !! */
          150 long SENDPOOLTIME;        /* frequency for sending pool messages */
          151 long MAILINTIME;        /* frequency for processing MAILIN mail */
          152 
          153 long KEYLIFETIME;
          154 long KEYOVERLAPPERIOD;
          155 long KEYGRACEPERIOD;
          156 
          157 char ERRLOG[LINELEN];
          158 char ADDRESS[LINELEN];
          159 char NAME[LINELEN];
          160 
          161 char ORGANIZATION[LINELEN];
          162 char MID[LINELEN];
          163 
          164 /* client config */
          165 int NUMCOPIES;
          166 char CHAIN[LINELEN];
          167 int VERBOSE;
          168 int DISTANCE;
          169 int MINREL;
          170 int RELFINAL;
          171 long MAXLAT;
          172 long MINLAT;
          173 char PGPPUBRING[PATHMAX];
          174 char PGPSECRING[PATHMAX];
          175 char PASSPHRASE[LINELEN];
          176 char MAILIN[PATHMAX];
          177 char MAILBOX[PATHMAX];
          178 char MAILABUSE[PATHMAX];
          179 char MAILBLOCK[PATHMAX];
          180 char MAILUSAGE[PATHMAX];
          181 char MAILANON[PATHMAX];
          182 char MAILERROR[PATHMAX];
          183 char MAILBOUNCE[PATHMAX];
          184 
          185 int CLIENTAUTOFLUSH;
          186 int MAXRECIPIENTS;
          187 
          188 long TIMESKEW_FORWARD;
          189 long TIMESKEW_BACK;
          190 int TEMP_FAIL;
          191 
          192 char ENTEREDPASSPHRASE[LINELEN] = "";
          193 
          194 static int rereadconfig = 0;
          195 static int terminatedaemon = 0;
          196 
          197 #if defined(S_IFDIR) && !defined(S_ISDIR)
          198 #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
          199 #endif /* defined(S_IFDIR) && !defined(S_ISDIR) */
          200 
          201 static int mixdir(char *d, int create)
          202 {
          203   int err;
          204   struct stat buf;
          205 
          206   if (d != MIXDIR)
          207     strncpy(MIXDIR, d, PATHMAX);
          208   if (MIXDIR[strlen(MIXDIR) - 1] == DIRSEP)
          209     MIXDIR[strlen(MIXDIR) - 1] = '\0';
          210   err = stat(MIXDIR, &buf);
          211   if (err == -1) {
          212     if (create) {
          213 #ifndef POSIX
          214       err = mkdir(MIXDIR);
          215 #else /* end of not POSIX */
          216       err = mkdir(MIXDIR, S_IRWXU);
          217 #endif /* else if POSIX */
          218       if (err == 0)
          219         errlog(NOTICE, "Creating directory %s.\n", MIXDIR);
          220     } else
          221       err = 1;
          222   } else if (!S_ISDIR(buf.st_mode))
          223     err = -1;
          224   if (err == 0)
          225     strcatn(MIXDIR, DIRSEPSTR, PATHMAX);
          226   return (err);
          227 }
          228 
          229 void whoami(char *addr, char *defaultname)
          230 {
          231   char *p = NULL;
          232 
          233 #if defined(HAVE_GETDOMAINNAME) || (defined(HAVE_GETHOSTNAME) && ! defined(HAVE_UNAME))
          234   char line[LINELEN];
          235 
          236 #endif /* defined(HAVE_GETDOMAINNAME) || [...] */
          237 #ifdef HAVE_UNAME
          238   struct utsname uts;
          239 
          240 #endif /* HAVE_UNAME */
          241 #ifdef POSIX
          242   p = getlogin();
          243 #endif /* POSIX */
          244   if (p == NULL)
          245     strcpy(addr, defaultname);
          246   else
          247     strncpy(addr, p, LINELEN);
          248 
          249   strcatn(addr, "@", LINELEN);
          250 #ifdef HAVE_UNAME
          251   if (uname(&uts) != -1)
          252     strcatn(addr, uts.nodename, LINELEN);
          253 #elif defined(HAVE_GETHOSTNAME) /* end of HAVE_UNAME */
          254   if (gethostname(line, LINELEN) == 0)
          255     strcatn(addr, line, LINELEN);
          256 #endif /* defined(HAVE_GETHOSTNAME) */
          257   if (addr[strlen(addr) - 1] == '@')
          258     strcatn(addr, SHORTNAME, LINELEN);
          259 
          260   if (strchr(strchr(addr, '@'), '.') == NULL) {
          261 #ifdef HAVE_GETDOMAINNAME
          262     if (getdomainname(line, LINELEN) == 0 && !streq(line, "(none)")) {
          263       strcatn(addr, ".", LINELEN);
          264       strcatn(addr, line, LINELEN);
          265     }
          266 #endif /* HAVE_GETDOMAINNAME */
          267   }
          268 }
          269 
          270 #define read_conf(t) readconfline(line, #t, sizeof(#t)-1, t)
          271 
          272 static int readconfline(char *line, char *name, int namelen, char *var)
          273 {
          274   if (strncmp(line, name, namelen) == 0 &&
          275       (isspace(line[namelen]) || line[namelen] == '=')) {
          276     line += namelen;
          277     if (*line == '=')
          278       line++;
          279     while (isspace(*line))
          280       line++;
          281     if (line[0] == '\n' || line[0] == '\0')        /* leave default */
          282       return (1);
          283     strncpy(var, line, LINELEN);
          284     if (var[strlen(var) - 1] == '\n')
          285       var[strlen(var) - 1] = '\0';
          286     return (1);
          287   } else
          288     return (0);
          289 }
          290 
          291 #define read_conf_i(t) readiconfline(line, #t, sizeof(#t)-1, &t)
          292 
          293 static int readiconfline(char *line, char *name, int namelen, int *var)
          294 {
          295   if (strncmp(line, name, namelen) == 0 &&
          296       (isspace(line[namelen]) || line[namelen] == '=')) {
          297     line += namelen;
          298     if (*line == '=')
          299       line++;
          300     while (isspace(*line))
          301       line++;
          302     if (line[0] == '\n' || line[0] == '\0')        /* leave default */
          303       return (1);
          304     switch (tolower(line[0])) {
          305     case 'n':
          306       *var = 0;
          307       break;
          308     case 'y':
          309       *var = 1;
          310       break;
          311     case 'x':
          312       *var = 2;
          313       break;
          314     default:
          315       sscanf(line, "%d", var);
          316     }
          317     return (1);
          318   } else
          319     return (0);
          320 }
          321 
          322 #define read_conf_t(t) readtconfline(line, #t, sizeof(#t)-1, &t)
          323 
          324 static int readtconfline(char *line, char *name, int namelen, long *var)
          325 {
          326   char *linenext;
          327   int mod = 0;
          328   long l = 0;
          329   long n;
          330 
          331   if (strncmp(line, name, namelen) == 0 &&
          332       (isspace(line[namelen]) || line[namelen] == '=')) {
          333     line += namelen;
          334     if (*line == '=')
          335       line++;
          336     for (;; line++) {
          337       n = strtol(line, &linenext, 10);
          338       if (linenext == line)
          339         break;
          340       line = linenext;
          341       mod = 1;
          342       assert(line != NULL);
          343       while (isspace(*line))
          344         line++;
          345       switch (tolower(*line)) {
          346       case 'y': /* years */
          347         l += 365 * 24 * 60 * 60 * n;
          348         break;
          349       case 'b': /* months */
          350         l += 30 * 24 * 60 * 60 * n;
          351         break;
          352       case 'w': /* weeks */
          353         l += 7 * 24 * 60 * 60 * n;
          354         break;
          355       case 'd': /* days */
          356         l += 24 * 60 * 60 * n;
          357         break;
          358       case 's': /* seconds */
          359         l += n;
          360         break;
          361       case 'm': /* minutes */
          362         l += 60 * n;
          363         break;
          364       case 'h': /* hours - default */
          365       default:
          366         l += 60 * 60 * n;
          367         break;
          368       }
          369     }
          370     if (mod)
          371       *var = l;
          372     return (1);
          373   } else
          374     return (0);
          375 }
          376 
          377 static void mix_setdefaults()
          378 {
          379 #define strnncpy(a,b) strncpy(a, b, sizeof(a)); a[sizeof(a)-1] = '\0'
          380 
          381         strnncpy(DISCLAIMFILE , DEFAULT_DISCLAIMFILE);
          382         strnncpy(FROMDSCLFILE , DEFAULT_FROMDSCLFILE);
          383         strnncpy(MSGFOOTERFILE, DEFAULT_MSGFOOTERFILE);
          384         strnncpy(POP3CONF     , DEFAULT_POP3CONF);
          385         strnncpy(HELPFILE     , DEFAULT_HELPFILE);
          386         strnncpy(REQUESTDIR   , DEFAULT_REQUESTDIR);
          387         strnncpy(ABUSEFILE    , DEFAULT_ABUSEFILE);
          388         strnncpy(REPLYFILE    , DEFAULT_REPLYFILE);
          389         strnncpy(USAGEFILE    , DEFAULT_USAGEFILE);
          390         strnncpy(USAGELOG     , DEFAULT_USAGELOG);
          391         strnncpy(BLOCKFILE    , DEFAULT_BLOCKFILE);
          392         strnncpy(ADMKEYFILE   , DEFAULT_ADMKEYFILE);
          393         strnncpy(KEYFILE      , DEFAULT_KEYFILE);
          394         strnncpy(PGPKEY       , DEFAULT_PGPKEY);
          395         strnncpy(DSAPARAMS    , DEFAULT_DSAPARAMS);
          396         strnncpy(DHPARAMS     , DEFAULT_DHPARAMS);
          397         strnncpy(MIXRAND      , DEFAULT_MIXRAND);
          398         strnncpy(SECRING      , DEFAULT_SECRING);
          399         strnncpy(PUBRING      , DEFAULT_PUBRING);
          400         strnncpy(IDLOG        , DEFAULT_IDLOG);
          401         strnncpy(STATS        , DEFAULT_STATS);
          402         strnncpy(PGPMAXCOUNT  , DEFAULT_PGPMAXCOUNT);
          403         strnncpy(DESTBLOCK    , DEFAULT_DESTBLOCK);
          404         strnncpy(DESTALLOW    , DEFAULT_DESTALLOW);
          405         strnncpy(DESTALLOW2   , DEFAULT_DESTALLOW2);
          406         strnncpy(SOURCEBLOCK  , DEFAULT_SOURCEBLOCK);
          407         strnncpy(HDRFILTER    , DEFAULT_HDRFILTER);
          408         strnncpy(REGULAR      , DEFAULT_REGULAR);
          409         strnncpy(POOL         , DEFAULT_POOL);
          410         strnncpy(TYPE1LIST    , DEFAULT_TYPE1LIST);
          411         strnncpy(TYPE2REL     , DEFAULT_TYPE2REL);
          412         strnncpy(PIDFILE      , DEFAULT_PIDFILE);
          413 
          414         strnncpy(PGPREMPUBRING, DEFAULT_PGPREMPUBRING);
          415         strnncpy(PGPREMPUBASC , DEFAULT_PGPREMPUBASC);
          416         strnncpy(PGPREMSECRING, DEFAULT_PGPREMSECRING);
          417         strnncpy(NYMSECRING   , DEFAULT_NYMSECRING);
          418         strnncpy(NYMDB        , DEFAULT_NYMDB);
          419         strnncpy(STAREX       , DEFAULT_STAREX);
          420         strnncpy(ALLPINGERSURL, DEFAULT_ALLPINGERSURL);
          421         strnncpy(ALLPINGERSFILE, DEFAULT_ALLPINGERSFILE);
          422         strnncpy(WGET         , DEFAULT_WGET);
          423         strnncpy(STATSSRC     , DEFAULT_STATSSRC);
          424 
          425         strnncpy(MIXDIR       , "");
          426         strnncpy(POOLDIR      , "");
          427 
          428 /* programs */
          429 #ifdef WIN32
          430         strnncpy(SENDMAIL     , "outfile");
          431 #else /* end of WIN32 */
          432         strnncpy(SENDMAIL     , "/usr/lib/sendmail -t");
          433 #endif /* else if not WIN32 */
          434         strnncpy(SENDANONMAIL , "");
          435         strnncpy(NEWS         , "");
          436         strnncpy(TYPE1        , "");
          437 
          438 /* addresses */
          439         strnncpy(MAILtoNEWS   , "mail2news@dizum.com,mail2news@m2n.mixmin.net");
          440         strnncpy(REMAILERNAME , "Anonymous Remailer");
          441         strnncpy(ANONNAME     , "Anonymous");
          442         strnncpy(REMAILERADDR , "");
          443         strnncpy(ANONADDR     , "");
          444         strnncpy(COMPLAINTS   , "");
          445         strnncpy(SMTPRELAY    , "");
          446         AUTOREPLY             = 0;
          447 
          448 #ifdef USE_SOCK
          449           strnncpy(HELONAME     , "");
          450         strnncpy(ENVFROM      , "");
          451         POP3DEL               = 0;
          452         POP3SIZELIMIT         = 0;
          453         POP3TIME              = 60 * 60;
          454 
          455 #endif /* USE_SOCK */
          456 
          457         strnncpy(SHORTNAME    , "");
          458 
          459 /*         configuration */
          460         REMAIL        = 0;
          461         MIX           = 1;
          462         PGP           = 1;
          463         UNENCRYPTED   = 0;
          464         REMIX         = 1;
          465         REPGP         = 1;
          466         STATSAUTOUPDATE = 0;
          467         STATSINTERVAL = 8 * 60 * 60;
          468         strnncpy(EXTFLAGS, "");
          469 
          470     strnncpy(PRECEDENCE, "");
          471         POOLSIZE      = 0;
          472         RATE          = 100;
          473         INDUMMYP      = 3;        /* add dummy messages with probability p for each message added to the pool */
          474         OUTDUMMYP     = 10;        /* add dummy messages with probability p each time we send from the pool */
          475         INDUMMYMAXP   = 84;        /* for both of the above:  while (rnd < p) { senddummy(); }  */
          476         OUTDUMMYMAXP  = 96;     /* set max INDUMMYP and OUTDUMMYP such that 24 and 5.25 dummy messages will */
          477         MIDDLEMAN     = 0;      /* be generated on average. More than this is insane. */
          478         AUTOBLOCK     = 1;
          479         STATSDETAILS  = 1;
          480         strnncpy(FORWARDTO, "*");
          481         SIZELIMIT     = 0;                /* maximal size of remailed messages */
          482         INFLATEMAX    = 50;                /* maximal size of Inflate: padding */
          483         MAXRANDHOPS   = 5;
          484         BINFILTER     = 0;                /* filter binary attachments? */
          485         LISTSUPPORTED = 1;                /* list supported remailers in remailer-conf reply? */
          486         PACKETEXP     = 7 * SECONDSPERDAY;        /* Expiration time for old packets */
          487         IDEXP         = 7 * SECONDSPERDAY;        /* 0 = no ID log !! */
          488         SENDPOOLTIME  = 0;              /* frequency for sending pool messages */
          489         MAILINTIME    = 5 * 60;                /* frequency for processing MAILIN mail */
          490 
          491         KEYLIFETIME      = 13 * 30 * 24 * 60 * 60;        /* validity period for keys. */
          492         KEYOVERLAPPERIOD =  1 * 30 * 24 * 60 * 60;        /* when keys have this amount of time */
          493                                                         /* left before expiration, create  */
          494                                                         /* new ones when ./mix -K is run.*/
          495         KEYGRACEPERIOD   =       7 * 24 * 60 * 60;        /* accept mail to the old key for this */
          496                                                         /* amount of time after it has expired. */
          497 
          498 
          499         strnncpy(ERRLOG      , "");
          500         strnncpy(ADDRESS     , "");
          501         strnncpy(NAME        , "");
          502 
          503         strnncpy(ORGANIZATION, "Anonymous Posting Service");
          504         strnncpy(MID         , "y");
          505 
          506 /* client config */
          507         NUMCOPIES = 1;
          508         strnncpy(CHAIN, "*,*,*,*");
          509         VERBOSE = 2;
          510         DISTANCE = 2;
          511         MINREL = 98;
          512         RELFINAL = 99;
          513         MAXLAT = 36 * 60 * 60;
          514         MINLAT = 5 * 60;
          515         strnncpy(PGPPUBRING, "");
          516         strnncpy(PGPSECRING, "");
          517 #ifdef COMPILEDPASS
          518         strnncpy(PASSPHRASE, COMPILEDPASS);
          519 #else /* end of COMPILEDPASS */
          520         strnncpy(PASSPHRASE, "");
          521 #endif /* else if not COMPILEDPASS */
          522         strnncpy(MAILIN    , "");
          523         strnncpy(MAILBOX   , "mbox");
          524         strnncpy(MAILABUSE , "");
          525         strnncpy(MAILBLOCK , "");
          526 #ifdef WIN32
          527         strnncpy(MAILUSAGE , "nul:");
          528         strnncpy(MAILANON  , "nul:");
          529         strnncpy(MAILERROR , "nul:");
          530 #else /* end of WIN32 */
          531         strnncpy(MAILUSAGE , "/dev/null");
          532         strnncpy(MAILANON  , "/dev/null");
          533         strnncpy(MAILERROR , "/dev/null");
          534 #endif /* else if not WIN32 */
          535         strnncpy(MAILBOUNCE, "");
          536 
          537         CLIENTAUTOFLUSH = 1;
          538         MAXRECIPIENTS   = 5;
          539 
          540         TIMESKEW_FORWARD = 2*7*24*60*60;
          541         TIMESKEW_BACK = 12*60*60;
          542         TEMP_FAIL = 75;
          543 }
          544 
          545 int mix_configline(char *line)
          546 {
          547   return (read_conf(ADDRESS) || read_conf(NAME) ||
          548           read_conf(SHORTNAME) || read_conf(REMAILERADDR) ||
          549           read_conf(ANONADDR) || read_conf(REMAILERNAME) ||
          550           read_conf(ANONNAME) || read_conf(COMPLAINTS) ||
          551           read_conf_i(AUTOREPLY) || read_conf(SMTPRELAY) ||
          552           read_conf(SMTPUSERNAME) || read_conf(SMTPPASSWORD) ||
          553 #ifdef USE_SOCK
          554           read_conf(HELONAME) || read_conf(ENVFROM) ||
          555 #endif /* USE_SOCK */
          556           read_conf(SENDMAIL) || read_conf(SENDANONMAIL) ||
          557           read_conf(PRECEDENCE) ||
          558           read_conf_i(REMAIL) || read_conf_i(MIX) ||
          559           read_conf_i(PGP) || read_conf_i(UNENCRYPTED) ||
          560           read_conf_i(REMIX) || read_conf(NEWS) ||
          561           read_conf_i(REPGP) || read_conf(EXTFLAGS) ||
          562           read_conf(MAILtoNEWS) || read_conf(ERRLOG) ||
          563           read_conf(ORGANIZATION) || read_conf(MID) ||
          564           read_conf(TYPE1) || read_conf_i(POOLSIZE) ||
          565           read_conf_i(RATE) || read_conf_i(MIDDLEMAN) ||
          566           read_conf_i(INDUMMYP) ||
          567           read_conf_i(OUTDUMMYP) ||
          568           read_conf_i(AUTOBLOCK) || read_conf(FORWARDTO) ||
          569           read_conf_i(STATSDETAILS) ||
          570           read_conf_i(SIZELIMIT) || read_conf_i(INFLATEMAX) ||
          571           read_conf_i(MAXRANDHOPS) || read_conf_i(BINFILTER) ||
          572           read_conf_i(LISTSUPPORTED) ||
          573           read_conf_t(PACKETEXP) || read_conf_t(IDEXP) ||
          574           read_conf_t(SENDPOOLTIME) || read_conf_i(NUMCOPIES) ||
          575           read_conf_t(MAILINTIME) ||
          576           read_conf(CHAIN) || read_conf_i(VERBOSE) ||
          577           read_conf_i(DISTANCE) || read_conf_i(MINREL) ||
          578           read_conf_i(RELFINAL) || read_conf_t(MAXLAT) ||
          579           read_conf_t(MINLAT) ||
          580           read_conf(PGPPUBRING) || read_conf(PGPSECRING) ||
          581           read_conf(PASSPHRASE) || read_conf_t(KEYLIFETIME) ||
          582           read_conf_t(KEYGRACEPERIOD) || read_conf_t(KEYOVERLAPPERIOD) ||
          583 #ifdef USE_SOCK
          584           read_conf_i(POP3DEL) || read_conf_i(POP3SIZELIMIT) ||
          585           read_conf_t(POP3TIME) ||
          586 #endif /* USE_SOCK */
          587           read_conf(MAILBOX) || read_conf(MAILABUSE) ||
          588           read_conf(MAILBLOCK) || read_conf(MAILUSAGE) ||
          589           read_conf(MAILANON) || read_conf(MAILERROR) ||
          590           read_conf(MAILBOUNCE) || read_conf(MAILIN) ||
          591 
          592           read_conf(DISCLAIMFILE) || read_conf(FROMDSCLFILE) ||
          593           read_conf(MSGFOOTERFILE) ||
          594           read_conf(POP3CONF) || read_conf(HELPFILE) ||
          595           read_conf(REQUESTDIR)  ||
          596           read_conf(ABUSEFILE) || read_conf(REPLYFILE) ||
          597           read_conf(USAGEFILE) || read_conf(USAGELOG) ||
          598           read_conf(BLOCKFILE) || read_conf(ADMKEYFILE) ||
          599           read_conf(KEYFILE) || read_conf(PGPKEY) ||
          600           read_conf(DSAPARAMS) || read_conf(DHPARAMS) ||
          601           read_conf(MIXRAND) || read_conf(SECRING) ||
          602           read_conf(PUBRING) || read_conf(IDLOG) ||
          603           read_conf(STATS) || read_conf(DESTBLOCK) ||
          604           read_conf(PGPMAXCOUNT) ||
          605           read_conf(DESTALLOW) || read_conf(DESTALLOW2) ||
          606           read_conf(SOURCEBLOCK) ||
          607           read_conf(STAREX) || read_conf(ALLPINGERSURL) ||
          608           read_conf(ALLPINGERSFILE) ||
          609           read_conf(HDRFILTER) || read_conf(REGULAR) ||
          610           read_conf(POOL) || read_conf(TYPE1LIST) ||
          611           read_conf(TYPE2REL) ||
          612           read_conf(PGPREMPUBRING) || read_conf(PGPREMPUBASC) ||
          613           read_conf(PGPREMSECRING) || read_conf(NYMSECRING) ||
          614           read_conf(NYMDB) || read_conf(PIDFILE) ||
          615           read_conf(WGET) || read_conf(STATSSRC) ||
          616           read_conf_i(STATSAUTOUPDATE) || read_conf_t(STATSINTERVAL) ||
          617 
          618           read_conf_i(CLIENTAUTOFLUSH) ||
          619           read_conf_i(MAXRECIPIENTS) ||
          620           
          621           read_conf_t(TIMESKEW_FORWARD) ||
          622           read_conf_t(TIMESKEW_BACK) ||
          623           read_conf_i(TEMP_FAIL) );
          624 }
          625 
          626 int mix_config(void)
          627 {
          628   char *d;
          629   FILE *f;
          630   char line[PATHMAX];
          631   int err = -1;
          632 #ifdef POSIX
          633   struct passwd *pw;
          634 #endif /* POSIX */
          635   struct stat buf;
          636 #ifdef HAVE_UNAME
          637   struct utsname uts;
          638 #endif /* HAVE_UNAME */
          639 #ifdef WIN32
          640   HKEY regsw, reg, regpgp;
          641   DWORD type, len;
          642   int rkey = 0;
          643 #endif /* WIN32 */
          644 
          645   mix_setdefaults();
          646 
          647 #ifdef POSIX
          648   pw = getpwuid(getuid());
          649 #endif /* POSIX */
          650 
          651  /* find our base directory
          652   *
          653   * first match wins.
          654   *
          655   *  - what the MIXPATH environment variable points to, if it is set.
          656   *  - On WIN32, HKEY_CURRENT_USER\Software\Mixmaster\MixDir, if it exists
          657   *  - whatever is compiled in with -DSPOOL
          658   *  - On Win32 %APPDATA%\Mixmaster
          659   *  - on POSIX, ~/Mix  (or ~/<HOMEMIXDIR>)
          660   *  - the current working directory
          661   */
          662 
          663   if (err == -1 && (d = getenv("MIXPATH")) != NULL)
          664     err = mixdir(d, 1);
          665 
          666 #ifdef WIN32
          667   RegOpenKeyEx(HKEY_CURRENT_USER, "Software", 0, KEY_ALL_ACCESS, &regsw);
          668   len=sizeof(line);
          669   if (err == -1 &&
          670       RegOpenKeyEx(regsw, "Mixmaster", 0, KEY_QUERY_VALUE, &reg) == 0) {
          671     if (RegQueryValueEx(reg, "MixDir", 0, &type, line, &len) == 0)
          672       err = mixdir(line, 1);
          673     RegCloseKey(reg);
          674   }
          675 #endif /* WIN32 */
          676 
          677 #ifdef SPOOL
          678   if (err == -1 && strlen(SPOOL) > 0)
          679     err = mixdir(SPOOL, 0);
          680 #endif /* SPOOL */
          681 
          682 #ifdef WIN32
          683     if (err == -1) {
          684       LPMALLOC lpmalloc;
          685       ITEMIDLIST *itemidlist;
          686       if (SUCCEEDED(SHGetMalloc(&lpmalloc)))
          687       {
          688         SHGetSpecialFolderLocation(0,CSIDL_APPDATA,&itemidlist);
          689         SHGetPathFromIDList(itemidlist,line);
          690         lpmalloc->lpVtbl->Free(lpmalloc,&itemidlist);
          691         lpmalloc->lpVtbl->Release(lpmalloc);
          692 
          693         strcatn(line, "\\Mixmaster", PATHMAX);
          694         err = mixdir(line, 1);
          695 
          696       }
          697     }
          698 #endif /* WIN32 */
          699 
          700 #ifdef POSIX
          701   if (err == -1 && pw != NULL) {
          702     strncpy(line, pw->pw_dir, PATHMAX);
          703     line[PATHMAX-1] = '\0';
          704     if (line[strlen(line) - 1] != DIRSEP)
          705       strcatn(line, DIRSEPSTR, PATHMAX);
          706     strcatn(line, HOMEMIXDIR, PATHMAX);
          707     err = mixdir(line, 1);
          708   }
          709 #endif /* POSIX */
          710 
          711   if (err == -1) {
          712     getcwd(MIXDIR, PATHMAX);
          713     mixdir(MIXDIR, 0);
          714   }
          715 
          716 #ifdef GLOBALMIXCONF
          717   f = mix_openfile(GLOBALMIXCONF, "r");
          718   if (f != NULL) {
          719     while (fgets(line, LINELEN, f) != NULL)
          720       if (line[0] > ' ' && line[0] != '#')
          721         mix_configline(line);
          722     fclose(f);
          723   }
          724 #endif /* GLOBALMIXCONF */
          725   f = mix_openfile(MIXCONF, "r");
          726   if (f != NULL) {
          727     while (fgets(line, LINELEN, f) != NULL)
          728       if (line[0] > ' ' && line[0] != '#')
          729         mix_configline(line);
          730     fclose(f);
          731   }
          732 
          733   mixfile(POOLDIR, POOL); /* set POOLDIR after reading POOL from cfg file */
          734   if (POOLDIR[strlen(POOLDIR) - 1] == DIRSEP)
          735     POOLDIR[strlen(POOLDIR) - 1] = '\0';
          736   if (stat(POOLDIR, &buf) != 0)
          737     if
          738 #ifndef POSIX
          739       (mkdir(POOLDIR) != 0)
          740 #else /* end of not POSIX */
          741       (mkdir(POOLDIR, S_IRWXU) == -1)
          742 #endif /* else if POSIX */
          743       strncpy(POOLDIR, MIXDIR, PATHMAX);
          744 
          745   if (IDEXP > 0 && IDEXP < 5 * SECONDSPERDAY)
          746     IDEXP = 5 * SECONDSPERDAY;
          747   if (MAXRANDHOPS > 20)
          748     MAXRANDHOPS = 20;
          749   if (INDUMMYP > INDUMMYMAXP)
          750     INDUMMYP = INDUMMYMAXP;
          751   if (OUTDUMMYP > OUTDUMMYMAXP)
          752     OUTDUMMYP = OUTDUMMYMAXP;
          753 
          754   if (strchr(SHORTNAME, '.'))
          755     *strchr(SHORTNAME, '.') = '\0';
          756   if (strchr(SHORTNAME, ' '))
          757     *strchr(SHORTNAME, ' ') = '\0';
          758 #ifdef HAVE_UNAME
          759   if (SHORTNAME[0] == '\0' && uname(&uts) != -1)
          760     strncpy(SHORTNAME, uts.nodename, LINELEN);
          761 #elif defined(HAVE_GETHOSTNAME) /* end of HAVE_UNAME */
          762   if (SHORTNAME[0] == '\0')
          763     gethostname(SHORTNAME, LINELEN);
          764 #endif /* defined(HAVE_GETHOSTNAME) */
          765   if (SHORTNAME[0] == '\0')
          766     strcpy(SHORTNAME, "unknown");
          767 
          768   if (ADDRESS[0] == '\0')
          769     whoami(ADDRESS, "user");
          770 
          771 #ifdef HAVE_GECOS
          772   if (NAME[0] == '\0' && pw != NULL)
          773     strcatn(NAME, pw->pw_gecos, sizeof(NAME));
          774 #endif /* HAVE_GECOS */
          775 
          776   if (REMAILERADDR[0] == '\0')
          777     strncpy(REMAILERADDR, ADDRESS, LINELEN);
          778 
          779   if (COMPLAINTS[0] == '\0')
          780     strncpy(COMPLAINTS, REMAILERADDR, LINELEN);
          781 
          782   if (strchr(REMAILERNAME, '@') == NULL) {
          783     strcatn(REMAILERNAME, " <", LINELEN);
          784     strcatn(REMAILERNAME, REMAILERADDR, LINELEN);
          785     strcatn(REMAILERNAME, ">", LINELEN);
          786   }
          787   if (strchr(ANONNAME, '@') == NULL && ANONADDR[0] != '\0') {
          788     strcatn(ANONNAME, " <", LINELEN);
          789     strcatn(ANONNAME, ANONADDR, LINELEN);
          790     strcatn(ANONNAME, ">", LINELEN);
          791   }
          792   if (strchr(ANONNAME, '@') == NULL) {
          793     strcatn(ANONNAME, " <", LINELEN);
          794     strcatn(ANONNAME, REMAILERADDR, LINELEN);
          795     strcatn(ANONNAME, ">", LINELEN);
          796   }
          797 #ifndef USE_PGP
          798   if (TYPE1[0] == '\0')
          799     PGP = 0;
          800 #endif /* not USE_PGP */
          801 
          802 #ifdef WIN32
          803   if (RegOpenKeyEx(regsw, "PGP", 0, KEY_ALL_ACCESS, &regpgp) == 0)
          804     rkey++;
          805   if (rkey && RegOpenKeyEx(regpgp, "PGPlib", 0, KEY_QUERY_VALUE, &reg) == 0)
          806     rkey++;
          807   if (PGPPUBRING[0] == '\0' && rkey == 2) {
          808     len = PATHMAX;
          809     RegQueryValueEx(reg, "PubRing", 0, &type, PGPPUBRING, &len);
          810   }
          811   if (PGPSECRING[0] == '\0' && rkey == 2) {
          812     len = PATHMAX;
          813     RegQueryValueEx(reg, "SecRing", 0, &type, PGPSECRING, &len);
          814   }
          815   if (rkey == 2)
          816     RegCloseKey(reg);
          817   if (rkey)
          818     RegCloseKey(regpgp);
          819   RegCloseKey(regsw);
          820 #endif /* WIN32 */
          821 
          822   if (PGPPUBRING[0] == '\0') {
          823     char *d;
          824 
          825     if ((d = getenv("HOME")) != NULL) {
          826       strcpy(PGPPUBRING, d);
          827       strcatn(PGPPUBRING, "/.pgp/", PATHMAX);
          828     }
          829     strcatn(PGPPUBRING, "pubring.pkr", PATHMAX);
          830     if (stat(PGPPUBRING, &buf) == -1)
          831       strcpy(strrchr(PGPPUBRING, '.'), ".pgp");
          832   }
          833   if (PGPSECRING[0] == '\0') {
          834     char *d;
          835 
          836     if ((d = getenv("HOME")) != NULL) {
          837       strcpy(PGPSECRING, d);
          838       strcatn(PGPSECRING, "/.pgp/", PATHMAX);
          839     }
          840     strcatn(PGPSECRING, "secring.skr", PATHMAX);
          841     if (stat(PGPSECRING, &buf) == -1)
          842       strcpy(strrchr(PGPSECRING, '.'), ".pgp");
          843   }
          844   if (streq(NEWS, "mail-to-news"))
          845     strncpy(NEWS, MAILtoNEWS, sizeof(NEWS));
          846 
          847   if (f == NULL) {
          848 #ifndef GLOBALMIXCONF
          849     /* Only write the config file in non systemwide installation */
          850     f = mix_openfile(MIXCONF, "w");
          851     if (f == NULL)
          852       errlog(WARNING, "Can't open %s%s!\n", MIXDIR, MIXCONF);
          853     else {
          854       fprintf(f, "# mix.cfg - mixmaster configuration file\n");
          855       fprintf(f, "NAME                %s\n", NAME);
          856       fprintf(f, "ADDRESS                %s\n", ADDRESS);
          857       fprintf(f, "\n# edit to set up a remailer:\n");
          858       fprintf(f, "REMAIL          n\n");
          859       fprintf(f, "SHORTNAME        %s\n", SHORTNAME);
          860       fprintf(f, "REMAILERADDR        %s\n", REMAILERADDR);
          861       fprintf(f, "COMPLAINTS        %s\n", COMPLAINTS);
          862       fclose(f);
          863     }
          864 #endif /* not GLOBALMIXCONF */
          865     REMAIL = 0;
          866   }
          867 
          868   if (ENTEREDPASSPHRASE[0] != '\0') {
          869     strncpy(PASSPHRASE, ENTEREDPASSPHRASE, LINELEN);
          870     PASSPHRASE[LINELEN-1] = 0;
          871   };
          872 
          873   return (0);
          874 }
          875 
          876 /** Library initialization: ******************************************/
          877 
          878 static int initialized = 0;
          879 
          880 void mix_check_timeskew() {
          881   FILE *f;
          882   long now, tpool = 0, tpop3 = 0, tdaily = 0, tmailin = 0, latest = 0;
          883 
          884   f = mix_openfile(REGULAR, "r+");
          885   if (f != NULL) {
          886     lock(f);
          887     fscanf(f, "%ld %ld %ld %ld", &tpool, &tpop3, &tdaily, &tmailin);
          888     latest = tpool;
          889     latest = latest > tpop3 ? latest : tpop3;
          890     latest = latest > tdaily ? latest : tdaily;
          891     latest = latest > tmailin ? latest : tmailin;
          892     now = time(NULL);
          893 
          894 
          895     if (( (TIMESKEW_BACK    != 0) && (now < latest - TIMESKEW_BACK   )) ||
          896         ( (TIMESKEW_FORWARD != 0) && (now > latest + TIMESKEW_FORWARD)) ) {
          897       /* Possible timeskew */
          898       errlog(ERRORMSG, "Possible timeskew detected.  Check clock and rm %s\n", REGULAR);
          899       exit(TEMP_FAIL);
          900     }
          901     fclose(f);
          902   } else {
          903     /* shrug */
          904   }
          905 }
          906 
          907 int mix_init(char *mixdir)
          908 {
          909   if (!initialized) {
          910     if (mixdir)
          911       strncpy(MIXDIR, mixdir, LINELEN);
          912     mix_config();
          913 #if defined(USE_SOCK) && defined(WIN32)
          914     sock_init();
          915 #endif /* defined(USE_SOCK) && defined(WIN32) */
          916     /* atexit (mix_exit); */
          917     initialized = 1;
          918   }
          919 
          920   if (rnd_init() == -1)
          921     rnd_seed();
          922   return(0);
          923 }
          924 
          925 void mix_exit(void)
          926 {
          927   if (!initialized)
          928     return;
          929   rnd_final();
          930 #if defined(USE_SOCK) && defined(WIN32)
          931   sock_exit();
          932 #endif /* defined(USE_SOCK) && defined(WIN32) */
          933   initialized=0;
          934 }
          935 
          936 void mix_upd_stats(void)
          937 {
          938   FILE *f;
          939   BUFFER *statssrc;
          940   statssrc = buf_new();
          941   buf_clear(statssrc);
          942   f = mix_openfile(STATSSRC, "r");
          943   if (f != NULL) {
          944     buf_read(statssrc, f);
          945     fclose(f);
          946   }
          947   if (statssrc->length > 0)
          948     download_stats(statssrc->data);
          949   buf_free(statssrc);
          950 }
          951 
          952 int mix_regular(int force)
          953 {
          954   FILE *f;
          955   long now, tpool = 0, tpop3 = 0, tdaily = 0, tmailin = 0, tstats = 0;
          956   int ret = 0;
          957 
          958   mix_init(NULL);
          959   now = time(NULL);
          960 
          961   f = mix_openfile(REGULAR, "r+");
          962   if (f != NULL) {
          963     lock(f);
          964     fscanf(f, "%ld %ld %ld %ld %ld", &tpool, &tpop3, &tdaily, &tmailin, &tstats);
          965     if (now - tpool >= SENDPOOLTIME)
          966       force |= FORCE_POOL | FORCE_MAILIN;
          967 #ifdef USE_SOCK
          968     if (now - tpop3 >= POP3TIME)
          969       force |= FORCE_POP3 | FORCE_MAILIN;
          970 #endif /* USE_SOCK */
          971     if (now - tdaily >= SECONDSPERDAY)
          972       force |= FORCE_DAILY;
          973     if (now - tmailin >= MAILINTIME)
          974       force |= FORCE_MAILIN;
          975     if (now - tstats >= STATSINTERVAL)
          976       force |= FORCE_STATS;
          977     if (force & FORCE_POOL)
          978       tpool = now;
          979     if (force & FORCE_POP3)
          980       tpop3 = now;
          981     if (force & FORCE_DAILY)
          982       tdaily = now;
          983     if (force & FORCE_MAILIN)
          984       tmailin = now;
          985     if (force & FORCE_STATS)
          986       tstats = now;
          987     rewind(f);
          988     fprintf(f, "%ld %ld %ld %ld %ld\n", tpool, tpop3, tdaily, tmailin, tstats);
          989     unlock(f);
          990     fclose(f);
          991   } else {
          992     force = FORCE_POOL | FORCE_POP3 | FORCE_DAILY | FORCE_MAILIN | FORCE_STATS;
          993     f = mix_openfile(REGULAR, "w+");
          994     if (f != NULL) {
          995       lock(f);
          996       fprintf(f, "%ld %ld %ld %ld %ld\n", now, now, now, now, now);
          997       unlock(f);
          998       fclose(f);
          999     } else
         1000       errlog(ERRORMSG, "Can't create %s!\n", REGULAR);
         1001   }
         1002 
         1003   if (force & FORCE_DAILY)
         1004     mix_daily(), ret = 1;
         1005 #ifdef USE_SOCK
         1006   if (force & FORCE_POP3)
         1007     pop3get();
         1008 #endif /* USE_SOCK */
         1009   if (force & FORCE_MAILIN)
         1010     ret = process_mailin();
         1011   if (force & FORCE_POOL)
         1012     ret = pool_send();
         1013   if ((force & FORCE_STATS) && (STATSAUTOUPDATE != 0))
         1014     mix_upd_stats();
         1015 
         1016   return (ret);
         1017 }
         1018 
         1019 int mix_daily(void)
         1020 {
         1021   idexp();
         1022   pgpmaxexp();
         1023   pool_packetexp();
         1024   stats(NULL);
         1025   keymgt(0);
         1026   return (0);
         1027 }
         1028 
         1029 /** Handle signals SIGHUP, SIGINT, and SIGTERM
         1030     This signal handler gets called if the daemon
         1031     process receives one of SIGHUP, SIGINT, or SIGTERM.
         1032     It then sets either rereadconfig of terminatedaemon
         1033     to true depending on the signal received.
         1034 
         1035     @author        PP
         1036     @return        nothing
         1037  */
         1038 #ifdef POSIX
         1039 void sighandler(int signal) {
         1040   if (signal == SIGHUP)
         1041     rereadconfig = 1;
         1042   else if (signal == SIGINT || signal == SIGTERM)
         1043     terminatedaemon = 1;
         1044 };
         1045 #endif /* POSIX */
         1046 
         1047 /** Set the signal handler for SIGHUP, SIGINT and SIGTERM
         1048     This function registers signal handlers so that
         1049     we can react on signals send by the user in daemon
         1050     mode. SIGHUP will instruct mixmaster to reload its
         1051     configuration while SIGINT and SIGTERM will instruct
         1052     it to shut down. Mixmaster will finish the current
         1053     pool run before it terminates.
         1054 
         1055     @param restart  Whether or not system calls should be
         1056                     restarted. Usually we want this, the
         1057                     only excetion is the sleep() in the
         1058                     daemon mail loop.
         1059     @author         PP
         1060     @return         -1 if calling sigaction failed, 0 on
         1061                     no error
         1062   */
         1063 int setsignalhandler(int restart)
         1064 {
         1065 #ifdef POSIX
         1066   struct sigaction hdl;
         1067   int err = 0;
         1068 
         1069   memset(&hdl, 0, sizeof(hdl));
         1070   hdl.sa_handler = sighandler;
         1071   hdl.sa_flags = restart ? SA_RESTART : 0;
         1072 
         1073   if (sigaction(SIGHUP, &hdl, NULL))
         1074     err = -1;
         1075   if (sigaction(SIGINT, &hdl, NULL))
         1076     err = -1;
         1077   if (sigaction(SIGTERM, &hdl, NULL))
         1078     err = -1;
         1079   return (err);
         1080 #else /* POSIX */
         1081   return(0);
         1082 #endif /* POSIX */
         1083 }
         1084 
         1085 #ifdef WIN32
         1086 /* Try to detect if we are the service or not...
         1087    seems there is no easy reliable way        */
         1088 int is_nt_service(void)
         1089 {
         1090     static int issvc = -1;
         1091 #ifdef WIN32SERVICE
         1092     STARTUPINFO StartupInfo;
         1093     OSVERSIONINFO VersionInfo;
         1094     DWORD dwsize;
         1095 
         1096     if (issvc != -1)    /* do it only once */
         1097         return issvc;
         1098 
         1099     VersionInfo.dwOSVersionInfoSize = sizeof(VersionInfo);
         1100     if (GetVersionEx(&VersionInfo))
         1101         if (VersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT)
         1102             return issvc = 0; /* not NT - not the service */
         1103 
         1104     GetStartupInfo(&StartupInfo);
         1105     if (StartupInfo.lpDesktop[0] == 0)
         1106         return issvc = 1; /* have no desktop - we are the service probably */
         1107 #endif /* WIN32SERVICE */
         1108 
         1109     return issvc = 0; /* assume not the service */
         1110 } /* is_nt_service */
         1111 
         1112 HANDLE hMustTerminate = NULL;
         1113 void set_nt_exit_event(HANDLE h_svc_exit_event)
         1114 {
         1115     hMustTerminate = h_svc_exit_event;
         1116 } /* set_nt_exit_event */
         1117 
         1118 #endif /* WIN32 */
         1119 
         1120 int mix_daemon(void)
         1121 {
         1122   long t, slept;
         1123   t = SENDPOOLTIME;
         1124   if (MAILINTIME < t && (MAILIN != NULL && MAILIN[0] != '\0'))
         1125     t = MAILINTIME;
         1126 #ifdef USE_SOCK
         1127   if (POP3TIME < t)
         1128     t = POP3TIME;
         1129 #endif /* USE_SOCK */
         1130   if (t < 5)
         1131     t = 5; /* Some kind of safety for broken systems */
         1132   slept = t;
         1133 
         1134   setsignalhandler(1); /* set signal handlers and restart any interrupted system calls */
         1135   for(;;) {
         1136     if (terminatedaemon)
         1137       break;
         1138     if (rereadconfig) {
         1139       rereadconfig = 0;
         1140       mix_config();
         1141       t = SENDPOOLTIME;
         1142       if (MAILINTIME < t && (MAILIN != NULL && MAILIN[0] != '\0'))
         1143         t = MAILINTIME;
         1144 #ifdef USE_SOCK
         1145       if (POP3TIME < t)
         1146         t = POP3TIME;
         1147       if (t < 5)
         1148         t = 5; /* Some kind of safety for broken systems */
         1149 #endif /* USE_SOCK */
         1150     }
         1151     if (slept >= t) {
         1152       mix_regular(0);
         1153       slept = 0;
         1154     }
         1155 
         1156 #ifdef WIN32SERVICE
         1157     if (hMustTerminate) {
         1158       if (WaitForSingleObject(hMustTerminate, t * 1000) == WAIT_OBJECT_0) {
         1159         CloseHandle(hMustTerminate);
         1160         terminatedaemon = 1;
         1161       }
         1162     }
         1163 #endif /* WIN32SERVICE */
         1164 
         1165     if (!terminatedaemon && !rereadconfig) {
         1166       setsignalhandler(0); /* set signal handlers;  don't restart system calls */
         1167 #ifdef WIN32
         1168       sleep(t); /* how to get the real number of seconds slept? */
         1169       slept = t;
         1170 #else /* end of WIN32 */
         1171       slept += (t - slept) - sleep(t - slept);
         1172 #endif /* else if not WIN32 */
         1173       setsignalhandler(1); /* set signal handlers and restart any interrupted system calls */
         1174     }
         1175   }
         1176   return (0);
         1177 }
         1178 
         1179 /** error ***************************************************************/
         1180 
         1181 void errlog(int type, char *fmt,...)
         1182 {
         1183   va_list args;
         1184   BUFFER *msg;
         1185   FILE *e = NULL;
         1186   time_t t;
         1187   struct tm *tc;
         1188   char line[LINELEN];
         1189   int p;
         1190   char err[6][8] =
         1191   {"", "Error", "Warning", "Notice", "Info", "Info"};
         1192 
         1193   if ((VERBOSE == 0 && type != ERRORMSG) || (type == LOG && VERBOSE < 2)
         1194       || (type == DEBUGINFO && VERBOSE < 3))
         1195     return;
         1196 
         1197   t = time(NULL);
         1198   tc = localtime(&t);
         1199   strftime(line, LINELEN, "[%Y-%m-%d %H:%M:%S] ", tc);
         1200 
         1201   msg = buf_new();
         1202   buf_appends(msg, line);
         1203   p = msg->length;
         1204   buf_appendf(msg, "%s: ", err[type]);
         1205   va_start(args, fmt);
         1206   buf_vappendf(msg, fmt, args);
         1207   va_end(args);
         1208 
         1209   if (streq(ERRLOG, "stdout"))
         1210     e = stdout;
         1211   else if (streq(ERRLOG, "stderr"))
         1212     e = stderr;
         1213 
         1214   if (e == NULL && (ERRLOG[0] == '\0' ||
         1215                     (e = mix_openfile(ERRLOG, "a")) == NULL))
         1216     mix_status("%s", msg->data + p);
         1217   else {
         1218     buf_write(msg, e);
         1219     if (e != stderr && e != stdout) {
         1220       fclose(e);
         1221       /* duplicate the error message on screen */
         1222       mix_status("%s", msg->data + p);
         1223     }
         1224   }
         1225   buf_free(msg);
         1226 }
         1227 
         1228 static char statusline[BUFSIZE] = "";
         1229 
         1230 void mix_status(char *fmt,...)
         1231 {
         1232   va_list args;
         1233 
         1234   if (fmt != NULL) {
         1235     va_start(args, fmt);
         1236 #ifdef _MSC
         1237     _vsnprintf(statusline, sizeof(statusline) - 1, fmt, args);
         1238 #else /* end of _MSC */
         1239     vsnprintf(statusline, sizeof(statusline) - 1, fmt, args);
         1240 #endif /* else if not _MSC */
         1241     va_end(args);
         1242   }
         1243 #ifdef USE_NCURSES
         1244   if (menu_initialized) {
         1245     cl(LINES - 2, 10);
         1246     printw("%s", statusline);
         1247     refresh();
         1248   } else
         1249 #endif /* USE_NCURSES */
         1250   {
         1251     fprintf(stderr, "%s", statusline);
         1252   }
         1253 }
         1254 
         1255 void mix_genericerror(void)
         1256 {
         1257   if (streq(statusline, "") || strfind(statusline, "...") ||
         1258       strifind(statusline, "generating"))
         1259     mix_status("Failed!");
         1260   else
         1261     mix_status(NULL);
         1262 }