home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume43 / procmail / part05 < prev    next >
Encoding:
Internet Message Format  |  1994-07-05  |  53.4 KB

  1. From: berg@pool.informatik.rwth-aachen.de (Stephen R. van den Berg)
  2. Newsgroups: comp.sources.misc
  3. Subject: v43i060:  procmail - mail processing package v3.03, Part05/10
  4. Date: 5 Jul 1994 20:50:01 -0500
  5. Organization: Sterling Software
  6. Sender: kent@sparky.sterling.com
  7. Approved: kent@sparky.sterling.com
  8. Message-ID: <2vd2k9$i7u@sparky.sterling.com>
  9. X-Md4-Signature: 4633a686de718684565da3a73f6dd04b
  10.  
  11. Submitted-by: berg@pool.informatik.rwth-aachen.de (Stephen R. van den Berg)
  12. Posting-number: Volume 43, Issue 60
  13. Archive-name: procmail/part05
  14. Environment: sendmail, ZMailer, smail, MMDF, mailsurr, UNIX, POSIX
  15. Supersedes: procmail: Volume 38, Issue 19-31
  16.  
  17. #! /bin/sh
  18. # This is a shell archive.  Remove anything before this line, then feed it
  19. # into a shell via "sh file" or similar.  To overwrite existing files,
  20. # type "sh file -c".
  21. # Contents:  procmail-3.03/config.h procmail-3.03/src/locking.c
  22. #   procmail-3.03/src/mailfold.c procmail-3.03/src/misc.c
  23. # Wrapped by kent@sparky on Tue Jul  5 20:42:13 1994
  24. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin:$PATH ; export PATH
  25. echo If this archive is complete, you will see the following message:
  26. echo '          "shar: End of archive 5 (of 10)."'
  27. if test -f 'procmail-3.03/config.h' -a "${1}" != "-c" ; then 
  28.   echo shar: Will not clobber existing file \"'procmail-3.03/config.h'\"
  29. else
  30.   echo shar: Extracting \"'procmail-3.03/config.h'\" \(14070 characters\)
  31.   sed "s/^X//" >'procmail-3.03/config.h' <<'END_OF_FILE'
  32. X/*$Id: config.h,v 1.53 1994/06/30 12:01:25 berg Exp $*/
  33. X
  34. X/*#define sMAILBOX_SEPARATOR    "\1\1\1\1\n"    /* sTART- and eNDing separ.  */
  35. X/*#define eMAILBOX_SEPARATOR    "\1\1\1\1\n"    /* uncomment (one or both)
  36. X                           if your mail system uses
  37. X    nonstandard mail separators (non sendmail or smail compatible mailers
  38. X    like MMDF), if yours is even different, uncomment and change the
  39. X    value of course */
  40. X
  41. X/* KEEPENV and PRESTENV should be defined as a comma-separated null-terminated
  42. X   list of strings */
  43. X
  44. X/* every environment variable appearing in KEEPENV will not be thrown away
  45. X * upon startup of procmail, e.g. you could define KEEPENV as follows:
  46. X * #define KEEPENV    {"TZ","LANG",0}
  47. X * environment variables ending in an _ will designate the whole group starting
  48. X * with this prefix (e.g. "LC_").
  49. X */
  50. X#define KEEPENV        {"TZ",0}
  51. X
  52. X/* every environment variable appearing in PRESTENV will be set or wiped
  53. X * out of the environment (variables without an '=' sign will be thrown
  54. X * out), e.g. you could define PRESTENV as follows:
  55. X * #define PRESTENV    {"IFS","ENV","PWD","PATH=$HOME/bin:/bin:/usr/bin",0}
  56. X * any side effects (like setting the umask after an assignment to UMASK) will
  57. X * *not* take place
  58. X */
  59. X#define PRESTENV    {"IFS","ENV","PWD","PATH=$HOME/bin:/bin:/usr/bin", \
  60. X             "USER=$LOGNAME",0}
  61. X
  62. X/************************************************************************
  63. X * Only edit below this line if you have viewed/edited this file before *
  64. X ************************************************************************/
  65. X
  66. X/* every user & group appearing in TRUSTED_IDS is allowed to use the -f option
  67. X   if the list is empty (just a terminating 0), everyone can use it
  68. X   TRUSTED_IDS should be defined as a comma-separated null-terminated
  69. X   list of strings;  if unauthorised users use the -f option, an extra
  70. X   >From_ field will be added in the header */
  71. X
  72. X#define TRUSTED_IDS    {"root","daemon","uucp","mail","x400","network",\
  73. X             "list","lists","news",0}
  74. X
  75. X/*#define NO_USER_TO_LOWERCASE_HACK    /* uncomment if your getpwnam() is
  76. X                       case insensitive or if procmail
  77. X    will always be supplied with the correct case in the explicit
  78. X    delivery mode argument(s) */
  79. X
  80. X/*#define NO_fcntl_LOCK        /* uncomment any of these three if you         */
  81. X/*#define NO_lockf_LOCK        /* definitely do not want procmail to make   */
  82. X/*#define NO_flock_LOCK        /* use of those kernel-locking methods         */
  83. X
  84. X/*#define NO_NFS_ATIME_HACK    /* uncomment if you're definitely not using
  85. X                   NFS mounted filesystems and can't afford
  86. X    procmail to sleep for 1 sec. before writing a mailbox */
  87. X
  88. X/*#define SYSTEM_MBOX    "$HOME/.mail"    /* uncomment and/or change if the
  89. X                       preset default mailbox is *not*
  90. X    suitable or if you want standard mail delivery to take place in a
  91. X    different file from the normal mail-spool-file.
  92. X    (it will supersede the value of SYSTEM_MAILBOX in autoconf.h) */
  93. X
  94. X/*#define DEFsendmail    "/bin/mail"    /* uncomment and/or change if the
  95. X                       autoconfigured default SENDMAIL is
  96. X    not suitable */
  97. X
  98. X#define ETCRC    "/etc/procmailrc"    /* optional global procmailrc startup
  99. X                       file (will only be read if procmail
  100. X    is started with no rcfile on the command line). */
  101. X
  102. X#define ETCRCS    "/etc/procmailrcs/"    /* optional trusted path prefix for
  103. X                       rcfiles which will be executed with
  104. X    the uid of the owner of the rcfile (this only happens if procmail is
  105. X    called with the -m option, without variable assignments on the command
  106. X    line). */
  107. X
  108. X/*#define console    "/dev/console"    /* uncomment if you want procmail to
  109. X                       use the console (or any other
  110. X    terminal or file) to print any error messages that could not be dumped
  111. X    in the "logfile"; only recommended for debugging purposes, if you have
  112. X    trouble creating a "logfile" or suspect that the trouble starts before
  113. X    procmail can interpret any rcfile or arguments. */
  114. X
  115. X/************************************************************************
  116. X * Only edit below this line if you *think* you know what you are doing *
  117. X ************************************************************************/
  118. X
  119. X#define ROOT_uid    0
  120. X
  121. X#define UPDATE_MASK    S_IXOTH       /* bit set on mailboxes when mail arrived */
  122. X#define OVERRIDE_MASK    (S_IXUSR|S_ISUID|S_ISGID|S_ISVTX)    /* if found set */
  123. X            /* the permissions on the mailbox will be left untouched */
  124. X#define INIT_UMASK    (S_IRWXG|S_IRWXO)               /* == 077 */
  125. X#define NORMperm    \
  126. X (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH|UPDATE_MASK)
  127. X         /* == 0667, normal mode bits used to create files, before umask */
  128. X#define READperm    (S_IRUSR|S_IRGRP|S_IROTH)          /* == 0444 */
  129. X#define NORMdirperm    (S_IRWXU|S_IRWXG|S_IRWXO)          /* == 0777 */
  130. X#define LOCKperm    READperm  /* mode bits used while creating lockfiles */
  131. X#define MAX_locksize    16      /* lockfiles are expected not to be longer */
  132. X#ifndef SMALLHEAP
  133. X#define DEFlinebuf    2048         /* default max expanded line length */
  134. X#define BLKSIZ        16384          /* blocksize while reading/writing */
  135. X#define STDBUF        1024             /* blocksize for emulated stdio */
  136. X#else           /* and some lower defaults for the unfortunate amongst us */
  137. X#define DEFlinebuf    512
  138. X#define BLKSIZ        1024
  139. X#define STDBUF        128
  140. X#endif /* SMALLHEAP */
  141. X#define FAKE_FIELD    ">From "
  142. X#define HOSTNAMElen    9      /* determines hostname-ID-len on tempfiles */
  143. X#define BOGUSprefix    "BOGUS."         /* prepended to bogus mailboxes */
  144. X#define PROCMAILRC    ".procmailrc"
  145. X#define DEFsuspend    16         /* multi-purpose 'idle loop' period */
  146. X#define DEFlocksleep    8
  147. X#define TOkey        "^TO"
  148. X#define TOsubstitute    "(^((Original-)?(Resent-)?(To|Cc|Bcc)|\
  149. X(X-Envelope|Apparently(-Resent)?)-To):(.*[^a-zA-Z])?)"
  150. X#define FROMDkey    "^FROM_DAEMON"             /* matches most daemons */
  151. X#define FROMDsubstitute "(^(Precedence:.*(junk|bulk|list)|\
  152. X(((Resent-)?(From|Sender)|X-Envelope-From):|>?From )(.*[^(.%@a-z0-9])?(\
  153. XPost(ma?(st(e?r)?|n)|office)|Mail(er)?|daemon|mmdf|root|uucp|LISTSERV|owner|\
  154. Xrequest|bounce|serv(ices?|er)|Admin(istrator)?)([^).!:a-z0-9].*)?$[^>]))"
  155. X#define FROMMkey    "^FROM_MAILER"          /* matches most mailer-daemons */
  156. X#define FROMMsubstitute "(^(((Resent-)?(From|Sender)|X-Envelope-From):|\
  157. X>?From )(.*[^(.%@a-z0-9])?(Post(ma(st(er)?|n)|office)|Mail(er)?|daemon|mmdf|\
  158. Xroot|uucp|serv(ices?|er)|Admin(istrator)?)([^).!:a-z0-9].*)?$[^>])"
  159. X#define DEFshellmetas    "&|<>~;?*["            /* never put '$' in here */
  160. X#define DEFmaildir    "$HOME"
  161. X#define DEFdefault    "$ORGMAIL"
  162. X#define DEFmsgprefix    "msg."
  163. X#define DEFlockext    ".lock"
  164. X#define DEFshellflags    "-c"
  165. X#define DEFlocktimeout    1024             /* defaults to about 17 minutes */
  166. X#define DEFtimeout    (DEFlocktimeout-64)       /* 64 seconds to clean up */
  167. X#define DEFnoresretry    4      /* default nr of retries if no resources left */
  168. X#define nfsTRY        (7+1) /* nr of times+1 to ignore spurious NFS errors */
  169. X#define DEFlogabstract    -1    /* abstract by default, but don't mail it back */
  170. X#define COMSAThost    "localhost"    /* where the biff/comsat daemon lives */
  171. X#define COMSATservice    "biff"        /* the service name of the comsat daemon */
  172. X#define COMSATprotocol    "udp" /* if you change this, comsat() needs patching */
  173. X#define COMSATxtrsep    ":"         /* mailbox-spec extension separator */
  174. X#define SERV_ADDRsep    '@'          /* when overriding in COMSAT=serv@addr */
  175. X#define DEFcomsat    "no"        /* when an rcfile has been specified */
  176. X
  177. X#define BinSh        "/bin/sh"
  178. X#define RootDir        "/"
  179. X#define DevNull        "/dev/null"
  180. X#define NICE_RANGE    39              /* maximal nice difference */
  181. X#define chCURDIR    '.'                /* the current directory */
  182. X#define chPARDIR    ".."                 /* the parent directory */
  183. X#define DIRSEP        "/"         /* directory separator symbols, the */
  184. X                   /* last one should be the most common one */
  185. X
  186. X#define EOFName        " \t\n#`'\");"
  187. X
  188. X#define HELPOPT1    'h'         /* options to get command line help */
  189. X#define HELPOPT2    '?'
  190. X
  191. X#define VERSIONOPT    'v'            /* option to display version */
  192. X#define PRESERVOPT    'p'                 /* preserve environment */
  193. X#define TEMPFAILOPT    't'              /* return EX_TEMPFAIL on error */
  194. X#define MAILFILTOPT    'm'         /* act as a general purpose mail filter */
  195. X#define FROMWHOPT    'f'               /* set name on From_ line */
  196. X#define REFRESH_TIME    '-'             /* when given as argument to -f */
  197. X#define ALTFROMWHOPT    'r'        /* alternate and obsolete form of -f */
  198. X#define OVERRIDEOPT    'o'             /* do not generate >From_ lines */
  199. X#define ARGUMENTOPT    'a'                       /* set $1 */
  200. X#define DELIVEROPT    'd'          /* deliver mail to named recipient */
  201. X#define PM_USAGE    \
  202. X "Usage: procmail [-vpto] [-f fromwhom] [parameter=value | rcfile] ...\
  203. X\n   Or: procmail [-to] [-f fromwhom] [-a argument] -d recipient ...\
  204. X\n   Or: procmail [-pt] -m [parameter=value] ... rcfile mail_from rcpt_to ...\
  205. X\n"
  206. X#define PM_HELP        \
  207. X "\t-v\t\tdisplay the version number and exit\
  208. X\n\t-p\t\tpreserve (most of) the environment upon startup\
  209. X\n\t-t\t\tfail softly if mail is undeliverable\
  210. X\n\t-f fromwhom\t(re)generate the leading 'From ' line\
  211. X\n\t-o override the leading 'From ' line if necessary\
  212. X\n\t-a argument\twill set $1\
  213. X\n\t-d recipient\texplicit delivery mode\
  214. X\n\t-m\t\tact as a general purpose mail filter\n"
  215. X#define PM_QREFERENCE    \
  216. X "Recipe flag quick reference:\
  217. X\n\tH  egrep header (default)\tB  egrep body\
  218. X\n\tD  distinguish case\
  219. X\n\tA  also execute this recipe if the common condition matched\
  220. X\n\ta  same as 'A', but only if the previous recipe was successful\
  221. X\n\tE  else execute this recipe, if the preceding condition didn't match\
  222. X\n\te  on error execute this recipe, if the previous recipe failed\
  223. X\n\th  deliver header (default)\tb  deliver body (default)\
  224. X\n\tf  filter\t\t\ti  ignore write errors\
  225. X\n\tc  continue with the next recipe in any case\
  226. X\n\tw  wait for a filter or program\
  227. X\n\tW  same as 'w', but suppress 'Program failure' messages\n"
  228. X
  229. X#define MINlinebuf    128    /* minimal LINEBUF length (don't change this) */
  230. X#define FROM_EXPR    "\nFrom "
  231. X#define FROM        "From "
  232. X#define SHFROM        "From"
  233. X#define NSUBJECT    "^Subject:.*$"
  234. X#define MAXSUBJECTSHOW    78
  235. X#define FOLDER        "  Folder: "
  236. X#define LENtSTOP    9 /* tab stop at which message length will be logged */
  237. X
  238. X#define TABCHAR        "\t"
  239. X#define TABWIDTH    8
  240. X
  241. X#define RECFLAGS    "HBDAahbfcwWiEe"
  242. X#define HEAD_GREP     0
  243. X#define BODY_GREP      1
  244. X#define DISTINGUISH_CASE   2
  245. X#define ALSO_NEXT_RECIPE    3
  246. X#define ALSO_N_IF_SUCC         4
  247. X#define PASS_HEAD          5
  248. X#define PASS_BODY           6
  249. X#define FILTER            7
  250. X#define CONTINUE         8
  251. X#define WAIT_EXIT          9
  252. X#define WAIT_EXIT_QUIET           10
  253. X#define IGNORE_WRITERR            11
  254. X#define ELSE_DO                 12
  255. X#define ERROR_DO              13
  256. X
  257. X#define UNIQ_PREFIX    '_'      /* prepended to temporary unique filenames */
  258. X#define ESCAP        ">"
  259. X
  260. X        /* some formail-specific configuration options: */
  261. X
  262. X#define UNKNOWN        "foo@bar"      /* formail default originator name */
  263. X#define OLD_PREFIX    "Old-"             /* formail field-Old-prefix */
  264. X#define BABYL_SEP1    '\037'               /* BABYL format separator one */
  265. X#define BABYL_SEP2    '\f'               /* BABYL format separator two */
  266. X#define DEFfileno    "FILENO=000"        /* split counter for formail */
  267. X#define LEN_FILENO_VAR    7                   /* =strlen("FILENO=") */
  268. X#define CHILD_FACTOR    3/4 /* do not parenthesise; average running children */
  269. X
  270. X#define FM_SKIP        '+'              /* skip the first nnn messages */
  271. X#define FM_TOTAL    '-'        /* only spit out a total of nnn messages */
  272. X#define FM_BOGUS    'b'             /* leave bogus Froms intact */
  273. X#define FM_QPREFIX    'p'              /* define quotation prefix */
  274. X#define FM_CONCATENATE    'c'          /* concatenate continued header-fields */
  275. X#define FM_FORCE    'f'   /* force formail to accept an arbitrary format */
  276. X#define FM_REPLY    'r'            /* generate an auto-reply header */
  277. X#define FM_KEEPB    'k'           /* keep the header, when replying */
  278. X#define FM_TRUST    't'    /* trust the sender to supply a valid header */
  279. X#define FM_LOGSUMMARY    'l'    /* generate a procmail-compatible log summary */
  280. X#define FM_SPLIT    's'                      /* split it up */
  281. X#define FM_NOWAIT    'n'              /* don't wait for the programs */
  282. X#define FM_EVERY    'e'    /* don't require empty lines leading headers */
  283. X#define FM_MINFIELDS    'm'    /* the number of fields that have to be found */
  284. X#define DEFminfields    2        /* before a header is recognised as such */
  285. X#define FM_DIGEST    'd'                 /* split up digests */
  286. X#define FM_BABYL    'B'        /* split up BABYL format rmail files */
  287. X#define FM_QUIET    'q'                     /* be quiet */
  288. X#define FM_DUPLICATE    'D'        /* return success on duplicate mails */
  289. X#define FM_EXTRACT    'x'               /* extract field contents */
  290. X#define FM_EXTRC_KEEP    'X'                    /* extract field */
  291. X#define FM_ADD_IFNOT    'a'         /* add a field if not already there */
  292. X#define FM_ADD_ALWAYS    'A'               /* add this field in any case */
  293. X#define FM_REN_INSERT    'i'            /* rename and insert a field */
  294. X#define FM_DEL_INSERT    'I'            /* delete and insert a field */
  295. X#define FM_FIRST_UNIQ    'u'            /* preserve the first occurrence */
  296. X#define FM_LAST_UNIQ    'U'             /* preserve the last occurrence */
  297. X#define FM_ReNAME    'R'                   /* rename a field */
  298. X#define FM_USAGE    "\
  299. XUsage: formail [-bcfrktq] [-D nnn idcache] [-p prefix] [-l folder]\n\
  300. X\t[-xXaAiIuU field] [-R ofield nfield]\n\
  301. X   Or: formail [+nnn] [-nnn] [-bcfrktnedqB] [-D nnn idcache] [-p prefix]\n\
  302. X\t[-m nnn] [-l folder] [-xXaAiIuU field] [-R ofield nfield]\n\
  303. X\t-s [prg [arg ...]]\n"
  304. X#define FM_HELP        \
  305. X " -b\t\tdon't escape bogus mailbox headers\
  306. X\n -c\t\tconcatenate continued header-fields\
  307. X\n -f\t\tforce formail to pass along any non-mailbox format\
  308. X\n -r\t\tgenerate an auto-reply header, preserve fields with -i\
  309. X\n -k\t\ton auto-reply keep the body, prevent escaping with -b\
  310. X\n -t\t\ttrust the sender for his return address\
  311. X\n -l folder\tgenerate a procmail-compatible log summary\
  312. X\n -D nnn idcache\tdetect duplicates with an idcache of length nnn\
  313. X\n -s prg arg\tsplit the mail, startup prg for every message\
  314. X\n +nnn\t\tskip the first nnn\t-nnn\toutput at most nnn messages\
  315. X\n -n\t\tdon't serialise splits\t-e\tempty lines are optional\
  316. X\n -d\t\taccept digest format\t-B\texpect BABYL rmail format\
  317. X\n -q\t\tbe quiet\t\t-p prefix\tquotation prefix\
  318. X\n -m nnn \tmin fields threshold (default 2) for start of message\
  319. X\n -x field\textract contents\t-X field\textract fully\
  320. X\n -a field\tadd if not present\t-A field\tadd in any case\
  321. X\n -i field\trename and insert\t-I field\tdelete and insert\
  322. X\n -u field\tfirst unique\t\t-U field\tlast unique\
  323. X\n -R oldfield newfield\trename\n"
  324. END_OF_FILE
  325.   if test 14070 -ne `wc -c <'procmail-3.03/config.h'`; then
  326.     echo shar: \"'procmail-3.03/config.h'\" unpacked with wrong size!
  327.   fi
  328.   # end of 'procmail-3.03/config.h'
  329. fi
  330. if test -f 'procmail-3.03/src/locking.c' -a "${1}" != "-c" ; then 
  331.   echo shar: Will not clobber existing file \"'procmail-3.03/src/locking.c'\"
  332. else
  333.   echo shar: Extracting \"'procmail-3.03/src/locking.c'\" \(7423 characters\)
  334.   sed "s/^X//" >'procmail-3.03/src/locking.c' <<'END_OF_FILE'
  335. X/************************************************************************
  336. X *    Whatever is needed for (un)locking files in various ways    *
  337. X *                                    *
  338. X *    Copyright (c) 1990-1994, S.R. van den Berg, The Netherlands    *
  339. X *    #include "../README"                        *
  340. X ************************************************************************/
  341. X#ifdef RCS
  342. Xstatic /*const*/char rcsid[]=
  343. X "$Id: locking.c,v 1.40 1994/06/28 16:56:23 berg Exp $";
  344. X#endif
  345. X#include "procmail.h"
  346. X#include "robust.h"
  347. X#include "shell.h"
  348. X#include "misc.h"
  349. X#include "pipes.h"
  350. X#include "exopen.h"
  351. X#include "locking.h"
  352. X
  353. Xvoid lockit(name,lockp)char*name;char**const lockp;
  354. X{ int permanent=nfsTRY,triedforce=0,locktype=doLOCK;struct stat stbuf;time_t t;
  355. X  zombiecollect();
  356. X  if(*lockp)
  357. X   { if(!strcmp(name,*lockp))    /* compare the previous lockfile to this one */
  358. X    return;             /* they're equal, save yourself some effort */
  359. X     unlock(lockp);               /* unlock any previous lockfile FIRST */
  360. X   }                  /* to prevent deadlocks (I hate deadlocks) */
  361. X  if(!*name)
  362. X     return;
  363. X  if(!strcmp(name,defdeflock))           /* is it the system mailbox lockfile? */
  364. X   { locktype=doCHECK|doLOCK;
  365. X#ifndef fdlock
  366. X     if(!accspooldir)
  367. X      { yell("Bypassed locking",name);
  368. X    return;
  369. X      }
  370. X     else
  371. X#endif
  372. X    setegid(sgid);               /* try and get some extra permissions */
  373. X   }
  374. X  name=tstrdup(name); /* allocate now, so we won't hang on memory *and* lock */
  375. X  for(lcking|=lck_LOCKFILE;;)
  376. X   { yell("Locking",name);        /* in order to cater for clock skew: get */
  377. X     if(!xcreat(name,LOCKperm,&t,locktype))    /* time t from the filesystem */
  378. X      { *lockp=name;                   /* lock acquired, hurray! */
  379. X    break;
  380. X      }
  381. X     switch(errno)
  382. X      { case EEXIST:           /* check if it's time for a lock override */
  383. X       if(!lstat(name,&stbuf)&&stbuf.st_size<=MAX_locksize&&locktimeout
  384. X        &&!lstat(name,&stbuf)&&locktimeout<t-stbuf.st_mtime)
  385. X         /*
  386. X          * stat() till unlink() should be atomic, but can't guarantee that
  387. X          */
  388. X        { if(triedforce)            /* already tried, not trying */
  389. X         goto faillock;                        /* again */
  390. X          if(S_ISDIR(stbuf.st_mode)||unlink(name))
  391. X         triedforce=1,nlog("Forced unlock denied on"),logqnl(name);
  392. X          else
  393. X           { nlog("Forcing lock on");logqnl(name);suspend();
  394. X         goto ce;
  395. X           }
  396. X        }
  397. X       else
  398. X          triedforce=0;         /* legitimate iteration, clear flag */
  399. X       break;
  400. X    case ENOSPC:           /* no space left, treat it as a transient */
  401. X#ifdef EDQUOT                              /* NFS failure */
  402. X    case EDQUOT:              /* maybe it was a short term shortage? */
  403. X#endif
  404. X    case ENOENT:case ENOTDIR:case EIO:case EACCES:
  405. X       if(--permanent)
  406. X          goto ds;
  407. X       goto faillock;
  408. X#ifdef ENAMETOOLONG
  409. X    case ENAMETOOLONG:     /* maybe filename too long, shorten and retry */
  410. X     { int i;
  411. X       if(0<(i=strlen(name)-1)&&!strchr(dirsep,name[i-1]))
  412. X        { nlog("Truncating");logqnl(name);elog(" and retrying lock\n");
  413. X          name[i]='\0';permanent=nfsTRY;
  414. X          goto ce;
  415. X        }
  416. X     }
  417. X#endif
  418. X    default:
  419. Xfaillock:  nlog("Lock failure on");logqnl(name);
  420. X       goto term;
  421. X      }
  422. X     permanent=nfsTRY;
  423. Xds:  ssleep((unsigned)locksleep);
  424. Xce:  if(nextexit)
  425. Xterm: { free(name);                 /* drop the preallocated buffer */
  426. X    break;
  427. X      }
  428. X   }
  429. X  if(rcstate==rc_NORMAL)               /* we already set our ids */
  430. X     setegid(gid);              /* we put back our regular permissions */
  431. X  lcking&=~lck_LOCKFILE;
  432. X  if(nextexit)
  433. X     elog(whilstwfor),elog("lockfile"),logqnl(name),Terminate();
  434. X}
  435. X
  436. Xvoid lcllock P((void))                    /* lock a local lockfile */
  437. X{ char*lckfile;                /* locking /dev/null or | would be silly */
  438. X  if(tolock||strcmp(buf2,devnull)&&strcmp(buf2,"|"))
  439. X   { lckfile=tolock?tolock:strcat(buf2,lockext);
  440. X     if(globlock&&!strcmp(lckfile,globlock))     /* same as global lockfile? */
  441. X    nlog("Deadlock attempted on"),logqnl(lckfile);
  442. X     else
  443. X    lockit(lckfile,&loclock);
  444. X   }
  445. X}
  446. X
  447. Xvoid unlock(lockp)char**const lockp;
  448. X{ lcking|=lck_LOCKFILE;
  449. X  if(*lockp)
  450. X   { if(!strcmp(*lockp,defdeflock))    /* is it the system mailbox lockfile? */
  451. X    setegid(sgid);               /* try and get some extra permissions */
  452. X     yell("Unlocking",*lockp);
  453. X     if(unlink(*lockp))
  454. X    nlog("Couldn't unlock"),logqnl(*lockp);
  455. X     if(rcstate==rc_NORMAL)               /* we already set our ids */
  456. X    setegid(gid);              /* we put back our regular permissions */
  457. X     if(!nextexit)               /* if not inside a signal handler */
  458. X    free(*lockp);
  459. X     *lockp=0;
  460. X   }
  461. X  offguard();
  462. X}
  463. X                    /* an NFS secure exclusive file open */
  464. Xint xcreat(name,mode,tim,chownit)const char*const name;const mode_t mode;
  465. X time_t*const tim;const int chownit;
  466. X{ char*p;int j= -2;size_t i;
  467. X  i=lastdirsep(name)-name;strncpy(p=malloc(i+UNIQnamelen),name,i);
  468. X  if(unique(p,p+i,mode,verbose,chownit)) /* try & rename the unique filename */
  469. X   { if(tim)
  470. X      { struct stat stbuf;     /* return the filesystem time to the caller */
  471. X    stat(p,&stbuf);*tim=stbuf.st_mtime;
  472. X      }
  473. X     j=myrename(p,name);
  474. X   }
  475. X  free(p);
  476. X  return j;
  477. X}
  478. X    /* if you've ever wondered what conditional compilation was good for */
  479. X#ifndef fdlock                        /* watch closely :-) */
  480. X#ifdef USEflock
  481. X#ifndef SYS_FILE_H_MISSING
  482. X#include <sys/file.h>
  483. X#endif
  484. X#define REITflock    1
  485. X#else
  486. X#define REITflock    0
  487. X#endif /* USEflock */
  488. Xstatic oldfdlock= -1;                    /* the fd we locked last */
  489. X#ifndef NOfcntl_lock
  490. Xstatic struct flock flck;        /* why can't it be a local variable? */
  491. X#define REITfcntl    1
  492. X#else
  493. X#define REITfcntl    0
  494. X#endif /* NOfcntl_lock */
  495. X#ifdef USElockf
  496. Xstatic off_t oldlockoffset;
  497. X#define REITlockf    1
  498. X#else
  499. X#define REITlockf    0
  500. X#endif /* USElockf */
  501. X
  502. Xint fdlock(fd)
  503. X{ int ret;
  504. X  if(verbose)
  505. X     nlog("Acquiring kernel-lock\n");
  506. X#if REITfcntl+REITflock+REITlockf>1
  507. X  for(;!toutflag;verbose&&(nlog("Reiterating kernel-lock\n"),0),
  508. X   ssleep((unsigned)locksleep))
  509. X#endif
  510. X   { zombiecollect();
  511. X#ifndef NOfcntl_lock
  512. X     flck.l_type=F_WRLCK;flck.l_whence=SEEK_SET;flck.l_len=0;
  513. X     flck.l_start=tell(fd);
  514. X#endif
  515. X#ifdef USElockf
  516. X     oldlockoffset=tell(fd);
  517. X#endif
  518. X     lcking|=lck_KERNEL;
  519. X#ifndef NOfcntl_lock
  520. X     ret=fcntl(fd,F_SETLKW,&flck);
  521. X#ifdef USElockf
  522. X     if((ret|=lockf(fd,F_TLOCK,(off_t)0))&&(errno==EAGAIN||errno==EACCES||
  523. X      errno==EWOULDBLOCK))
  524. Xufcntl:
  525. X      { flck.l_type=F_UNLCK;fcntl(fd,F_SETLK,&flck);
  526. X    continue;
  527. X      }
  528. X#ifdef USEflock
  529. X     if((ret|=flock(fd,LOCK_EX|LOCK_NB))&&(errno==EAGAIN||errno==EACCES||
  530. X      errno==EWOULDBLOCK))
  531. X      { lockf(fd,F_ULOCK,(off_t)0);
  532. X    goto ufcntl;
  533. X      }
  534. X#endif /* USEflock */
  535. X#else /* USElockf */
  536. X#ifdef USEflock
  537. X     if((ret|=flock(fd,LOCK_EX|LOCK_NB))&&(errno==EAGAIN||errno==EACCES||
  538. X      errno==EWOULDBLOCK))
  539. X      { flck.l_type=F_UNLCK;fcntl(fd,F_SETLK,&flck);
  540. X    continue;
  541. X      }
  542. X#endif /* USEflock */
  543. X#endif /* USElockf */
  544. X#else /* NOfcntl_lock */
  545. X#ifdef USElockf
  546. X     ret=lockf(fd,F_LOCK,(off_t)0);
  547. X#ifdef USEflock
  548. X     if((ret|=flock(fd,LOCK_EX|LOCK_NB))&&(errno==EAGAIN||errno==EACCES||
  549. X      errno==EWOULDBLOCK))
  550. X      { lockf(fd,F_ULOCK,(off_t)0);
  551. X    continue;
  552. X      }
  553. X#endif /* USEflock */
  554. X#else /* USElockf */
  555. X#ifdef USEflock
  556. X     ret=flock(fd,LOCK_EX);
  557. X#endif /* USEflock */
  558. X#endif /* USElockf */
  559. X#endif /* NOfcntl_lock */
  560. X     oldfdlock=fd;lcking&=~lck_KERNEL;
  561. X     return ret;
  562. X   }
  563. X}
  564. X
  565. Xint fdunlock P((void))
  566. X{ int i;
  567. X  if(oldfdlock<0)
  568. X     return -1;
  569. X  i=0;
  570. X#ifdef USEflock
  571. X  i|=flock(oldfdlock,LOCK_UN);
  572. X#endif
  573. X#ifdef USElockf
  574. X  lseek(oldfdlock,oldlockoffset,SEEK_SET);i|=lockf(oldfdlock,F_ULOCK,(off_t)0);
  575. X#endif
  576. X#ifndef NOfcntl_lock
  577. X  flck.l_type=F_UNLCK;i|=fcntl(oldfdlock,F_SETLK,&flck);
  578. X#endif
  579. X  oldfdlock= -1;
  580. X  return i;
  581. X}
  582. X#endif /* fdlock */
  583. END_OF_FILE
  584.   if test 7423 -ne `wc -c <'procmail-3.03/src/locking.c'`; then
  585.     echo shar: \"'procmail-3.03/src/locking.c'\" unpacked with wrong size!
  586.   fi
  587.   # end of 'procmail-3.03/src/locking.c'
  588. fi
  589. if test -f 'procmail-3.03/src/mailfold.c' -a "${1}" != "-c" ; then 
  590.   echo shar: Will not clobber existing file \"'procmail-3.03/src/mailfold.c'\"
  591. else
  592.   echo shar: Extracting \"'procmail-3.03/src/mailfold.c'\" \(14078 characters\)
  593.   sed "s/^X//" >'procmail-3.03/src/mailfold.c' <<'END_OF_FILE'
  594. X/************************************************************************
  595. X *    Routines that deal with the mailfolder(format)            *
  596. X *                                    *
  597. X *    Copyright (c) 1990-1994, S.R. van den Berg, The Netherlands    *
  598. X *    #include "../README"                        *
  599. X ************************************************************************/
  600. X#ifdef RCS
  601. Xstatic /*const*/char rcsid[]=
  602. X "$Id: mailfold.c,v 1.49 1994/06/28 16:56:26 berg Exp $";
  603. X#endif
  604. X#include "procmail.h"
  605. X#include "acommon.h"
  606. X#include "sublib.h"
  607. X#include "robust.h"
  608. X#include "shell.h"
  609. X#include "misc.h"
  610. X#include "pipes.h"
  611. X#include "common.h"
  612. X#include "exopen.h"
  613. X#include "goodies.h"
  614. X#include "locking.h"
  615. X#include "mailfold.h"
  616. X#ifndef NO_COMSAT
  617. X#include "network.h"
  618. X#endif
  619. X
  620. Xint logopened,tofile;
  621. Xoff_t lasttell;
  622. Xstatic long lastdump;
  623. Xstatic volatile mailread;    /* if the mail is completely read in already */
  624. Xstatic struct dyna_long escFrom_,confield;      /* escapes, concatenations */
  625. X                   /* inserts escape characters on outgoing mail */
  626. Xstatic long getchunk(s,fromw,len)const int s;const char*fromw;const long len;
  627. X{ long dist,dif;int i;static const char esc[]=ESCAP;
  628. X  dist=fromw-themail;            /* where are we now in transmitting? */
  629. X  for(dif=len,i=0;i<escFrom_.filled;)        /* let's see if we can find this */
  630. X     if(!(dif=escFrom_.offs[i++]-dist))             /* this exact spot? */
  631. X      { rwrite(s,esc,STRLEN(esc));lastdump++;            /* escape it */
  632. X    if(i>=escFrom_.filled)                      /* last block? */
  633. X       return len;                /* yes, give all what's left */
  634. X    dif=escFrom_.offs[i]-dist;             /* the whole next block */
  635. X    break;
  636. X      }
  637. X     else if(dif>0)                /* passed this spot already? */
  638. X    break;
  639. X  return dif<len?dif:len;
  640. X}
  641. X
  642. Xlong dump(s,source,len)const int s;const char*source;long len;
  643. X{ int i;long part;
  644. X  lasttell=i= -1;
  645. X  if(s>=0)
  646. X   { if(tofile&&(lseek(s,(off_t)0,SEEK_END),fdlock(s)))
  647. X    nlog("Kernel-lock failed\n");
  648. X     lastdump=len;part=tofile==to_FOLDER?getchunk(s,source,len):len;
  649. X     lasttell=lseek(s,(off_t)0,SEEK_END);smboxseparator(s);     /* optional */
  650. X#ifndef NO_NFS_ATIME_HACK                    /* separator */
  651. X     if(part&&tofile)               /* if it is a file, trick NFS into an */
  652. X    len--,part--,rwrite(s,source++,1),ssleep(1);        /* a_time<m_time */
  653. X#endif
  654. X     goto jin;
  655. X     do
  656. X      { part=getchunk(s,source,len);
  657. Xjin:    while(part&&(i=rwrite(s,source,BLKSIZ<part?BLKSIZ:(int)part)))
  658. X     { if(i<0)
  659. X          goto writefin;
  660. X       part-=i;len-=i;source+=i;
  661. X     }
  662. X      }
  663. X     while(len);
  664. X     if(!len&&(lastdump<2||!(source[-1]=='\n'&&source[-2]=='\n')))
  665. X    lastdump++,rwrite(s,newline,1);           /* message always ends with a */
  666. X     emboxseparator(s);         /* newline and an optional custom separator */
  667. Xwritefin:
  668. X     if(tofile&&fdunlock())
  669. X    nlog("Kernel-unlock failed\n");
  670. X     i=rclose(s);
  671. X   }               /* return an error even if nothing was to be sent */
  672. X  tofile=0;
  673. X  return i&&!len?-1:len;
  674. X}
  675. X
  676. Xstatic int dirfile(chp,linkonly)char*const chp;const int linkonly;
  677. X{ const static char lkingto[]="Linking to";
  678. X  if(chp)
  679. X   { long i=0;                 /* first let us try to prime i with the */
  680. X#ifndef NOopendir             /* highest MH folder number we can find */
  681. X     long j;DIR*dirp;struct dirent*dp;char*chp2;
  682. X     if(dirp=opendir(buf))
  683. X      { while(dp=readdir(dirp))        /* there still are directory entries */
  684. X       if((j=strtol(dp->d_name,&chp2,10))>i&&!*chp2)
  685. X          i=j;                /* yep, we found a higher number */
  686. X    closedir(dirp);                     /* aren't we neat today */
  687. X      }
  688. X     else
  689. X    readerr(buf);
  690. X#endif /* NOopendir */
  691. X     ;{ int ok;
  692. X    do ultstr(0,++i,chp);               /* find first empty MH folder */
  693. X    while((ok=linkonly?link(buf2,buf):hlink(buf2,buf))&&errno==EEXIST);
  694. X    if(linkonly)
  695. X     { yell(lkingto,buf);
  696. X       if(ok)
  697. X          goto nolnk;
  698. X       goto ret;
  699. X     }
  700. X      }
  701. X     unlink(buf2);
  702. X     goto opn;
  703. X   }
  704. X  ;{ struct stat stbuf;
  705. X     stat(buf2,&stbuf);
  706. X     ultoan((unsigned long)stbuf.st_ino,      /* filename with i-node number */
  707. X      strchr(strcat(buf,msgprefix),'\0'));
  708. X   }
  709. X  if(linkonly)
  710. X   { yell(lkingto,buf);
  711. X     if(link(buf2,buf))       /* hardlink the new file, it's a directory folder */
  712. Xnolnk:    nlog("Couldn't make link to"),logqnl(buf);
  713. X     goto ret;
  714. X   }
  715. X  if(!rename(buf2,buf))               /* rename it, we need the same i-node */
  716. Xopn: return opena(buf);
  717. Xret:
  718. X  return -1;
  719. X}
  720. X
  721. Xstatic int ismhdir(chp)char*const chp;
  722. X{ if(chp-1>=buf&&chp[-1]==*MCDIRSEP_&&*chp==chCURDIR)
  723. X   { chp[-1]='\0';
  724. X     return 1;
  725. X   }
  726. X  return 0;
  727. X}
  728. X                       /* open file or new file in directory */
  729. Xint deliver(boxname,linkfolder)char*boxname,*linkfolder;
  730. X{ struct stat stbuf;char*chp;int mhdir;mode_t numask;
  731. X  asgnlastf=1;
  732. X  if(*boxname=='|'&&(!linkfolder||linkfolder==Tmnate))
  733. X   { setlastfolder(boxname);
  734. X     return rdup(savstdout);
  735. X   }
  736. X  numask=UPDATE_MASK&~cumask;tofile=to_FILE;
  737. X  if(boxname!=buf)
  738. X     strcpy(buf,boxname);         /* boxname can be found back in buf */
  739. X  if(*(chp=buf))                  /* not null length target? */
  740. X     chp=strchr(buf,'\0')-1;             /* point to just before the end */
  741. X  mhdir=ismhdir(chp);                      /* is it an MH folder? */
  742. X  if(!stat(boxname,&stbuf))                    /* it exists */
  743. X   { if(numask&&!(stbuf.st_mode&UPDATE_MASK))
  744. X    chmod(boxname,stbuf.st_mode|UPDATE_MASK);
  745. X     if(!S_ISDIR(stbuf.st_mode))     /* it exists and is not a directory */
  746. X    goto makefile;                /* no, create a regular file */
  747. X   }
  748. X  else if(!mhdir||mkdir(buf,NORMdirperm))    /* shouldn't it be a directory? */
  749. Xmakefile:
  750. X   { if(linkfolder)      /* any leftovers?  Now is the time to display them */
  751. X    concatenate(linkfolder),skipped(linkfolder);
  752. X     tofile=strcmp(devnull,buf)?to_FOLDER:0;
  753. X     return opena(boxname);
  754. X   }
  755. X  if(linkfolder)            /* any additional directories specified? */
  756. X   { size_t blen;
  757. X     if(blen=Tmnate-linkfolder)               /* copy the names into safety */
  758. X    Tmnate=(linkfolder=tmemmove(malloc(blen),linkfolder,blen))+blen;
  759. X     else
  760. X    linkfolder=0;
  761. X   }
  762. X  if(mhdir)                /* buf should contain directory name */
  763. X     *chp='\0',chp[-1]= *MCDIRSEP_,strcpy(buf2,buf);       /* it ended in /. */
  764. X  else                     /* fixup directory name, append a / */
  765. X     strcat(chp,MCDIRSEP_),strcpy(buf2,buf),chp=0;
  766. X  ;{ int fd= -1;        /* generate the name for the first directory */
  767. X     if(unique(buf2,strchr(buf2,'\0'),NORMperm,verbose,0)&&
  768. X      (fd=dirfile(chp,0))>=0&&linkfolder)     /* save the file descriptor */
  769. X    for(strcpy(buf2,buf),boxname=linkfolder;boxname!=Tmnate;)
  770. X     { strcpy(buf,boxname);        /* go through the list of other dirs */
  771. X       if(*(chp=buf))
  772. X          chp=strchr(buf,'\0')-1;
  773. X       mhdir=ismhdir(chp);                  /* is it an MH folder? */
  774. X       if(stat(boxname,&stbuf))             /* it doesn't exist */
  775. X          mkdir(buf,NORMdirperm);                /* create it */
  776. X       else if(numask&&!(stbuf.st_mode&UPDATE_MASK))
  777. X          chmod(buf,stbuf.st_mode|UPDATE_MASK);
  778. X       if(mhdir)
  779. X          *chp='\0',chp[-1]= *MCDIRSEP_;
  780. X       else                 /* fixup directory name, append a / */
  781. X          strcat(chp,MCDIRSEP_),chp=0;
  782. X       dirfile(chp,1);        /* link it with the original in buf2 */
  783. X       while(*boxname++);          /* skip to the next directory name */
  784. X     }
  785. X     if(linkfolder)                       /* free our cache */
  786. X    free(linkfolder);
  787. X     return fd;                  /* return the file descriptor we saved */
  788. X   }
  789. X}
  790. X
  791. Xvoid logabstract(lstfolder)const char*const lstfolder;
  792. X{ if(lgabstract>0||logopened&&lgabstract)  /* don't mail it back unrequested */
  793. X   { char*chp,*chp2;int i;static const char sfolder[]=FOLDER;
  794. X     if(mailread)              /* is the mail completely read in? */
  795. X      { *thebody='\0';               /* terminate the header, just in case */
  796. X    if(eqFrom_(chp=themail))               /* any "From " header */
  797. X     { if(chp=strchr(themail,'\n'))
  798. X          *chp++='\0';
  799. X       else
  800. X          chp=thebody;              /* preserve mailbox format */
  801. X       elog(themail);elog(newline);                 /* (any length) */
  802. X     }
  803. X    if(!(lcking&lck_ALLOCLIB)&&        /* don't reenter malloc/free */
  804. X     (chp=egrepin(NSUBJECT,chp,(long)(thebody-chp),0)))
  805. X     { for(chp2= --chp;*--chp2!='\n'&&*chp2;);
  806. X       if(chp-++chp2>MAXSUBJECTSHOW)        /* keep it within bounds */
  807. X          chp2[MAXSUBJECTSHOW]='\0';
  808. X       *chp='\0';detab(chp2);elog(" ");elog(chp2);elog(newline);
  809. X     }
  810. X      }
  811. X     elog(sfolder);
  812. X     i=strlen(strncpy(buf,lstfolder,MAXfoldlen))+STRLEN(sfolder);
  813. X     buf[MAXfoldlen]='\0';detab(buf);elog(buf);i-=i%TABWIDTH;    /* last dump */
  814. X     do elog(TABCHAR);
  815. X     while((i+=TABWIDTH)<LENoffset);
  816. X     ultstr(7,lastdump,buf);elog(buf);elog(newline);
  817. X   }
  818. X#ifndef NO_COMSAT
  819. X  ;{ int s;struct sockaddr_in addr;char*chp,*chad;         /* @ seperator? */
  820. X     if(chad=strchr(chp=(char*)scomsat,SERV_ADDRsep))
  821. X    *chad++='\0';              /* split it up in service and hostname */
  822. X     else if(!renvint(-1L,chp))            /* or is it a false boolean? */
  823. X    return;                           /* ok, no comsat then */
  824. X     else
  825. X    chp="";                  /* set to yes, so take the default */
  826. X     if(!chad||!*chad)                          /* no host */
  827. X#ifndef IP_localhost
  828. X    chad=COMSAThost;                      /* use default */
  829. X#else /* IP_localhost */
  830. X      { static const unsigned char ip_localhost[]=IP_localhost;
  831. X    addr.sin_family=AF_INET;
  832. X    tmemmove(&addr.sin_addr,ip_localhost,sizeof ip_localhost);
  833. X      }
  834. X     else
  835. X#endif /* IP_localhost */
  836. X      { const struct hostent*host;          /* what host?  paranoid checks */
  837. X    if(!(host=gethostbyname(chad))||!host->h_0addr_list)
  838. X     { endhostent();             /* host can't be found, too bad */
  839. X       return;
  840. X     }
  841. X    addr.sin_family=host->h_addrtype;         /* address number found */
  842. X    tmemmove(&addr.sin_addr,host->h_0addr_list,host->h_length);
  843. X    endhostent();
  844. X      }
  845. X     if(!*chp)                               /* no service */
  846. X    chp=BIFF_serviceport;                      /* use default */
  847. X     s=strtol(chp,&chad,10);
  848. X     if(chp==chad)                   /* the service is not numeric */
  849. X      { const struct servent*serv;
  850. X    if(!(serv=getservbyname(chp,COMSATprotocol)))       /* so get its no. */
  851. X     { endservent();
  852. X       return;
  853. X     }
  854. X    addr.sin_port=serv->s_port;endservent();
  855. X      }
  856. X     else
  857. X    addr.sin_port=htons((short)s);                /* network order */
  858. X     cat(tgetenv(lgname),"@");             /* should always fit in buf */
  859. X     if(lasttell>=0)                       /* was it a file? */
  860. X    ultstr(0,(unsigned long)lasttell,buf2),catlim(buf2);          /* yep */
  861. X     catlim(COMSATxtrsep);                 /* custom seperator */
  862. X     if(lasttell>=0&&!strchr(dirsep,*lstfolder))       /* relative filename? */
  863. X    catlim(tgetenv(maildir)),catlim(MCDIRSEP_);   /* prepend current dir */
  864. X     catlim(lstfolder);s=socket(AF_INET,SOCK_DGRAM,UDP_protocolno);
  865. X     sendto(s,buf,strlen(buf),0,(const void*)&addr,sizeof(addr));rclose(s);
  866. X     yell("Notified comsat:",buf);
  867. X   }
  868. X#endif /* NO_COMSAT */
  869. X}
  870. X
  871. Xstatic int concnd;                 /* last concatenation value */
  872. X
  873. Xvoid concon(ch)const int ch;   /* flip between concatenated and split fields */
  874. X{ size_t i;
  875. X  if(concnd!=ch)                   /* is this run redundant? */
  876. X   { concnd=ch;                  /* no, but note this one for next time */
  877. X     for(i=confield.filled;i;)           /* step through the saved offsets */
  878. X    themail[confield.offs[--i]]=ch;               /* and flip every one */
  879. X   }
  880. X}
  881. X
  882. Xstatic void ffrom(chp)const char*chp;
  883. X{ while(chp=strstr(chp,FROM_EXPR))
  884. X     app_val(&escFrom_,(off_t)(++chp-themail));           /* bogus From_ found! */
  885. X}
  886. X
  887. Xvoid readmail(rhead,tobesent)const long tobesent;
  888. X{ char*chp,*pastend,*realstart;static size_t contlengthoffset;
  889. X  ;{ long dfilled;
  890. X     if(rhead)                    /* only read in a new header */
  891. X      { dfilled=mailread=0;chp=readdyn(malloc(1),&dfilled);filled-=tobesent;
  892. X    if(tobesent<dfilled)           /* adjust buffer size (grow only) */
  893. X     { realstart=themail;
  894. X       thebody=(themail=realloc(themail,dfilled+filled))+
  895. X        (thebody-realstart);
  896. X     }
  897. X    tmemmove(themail+dfilled,thebody,filled);tmemmove(themail,chp,dfilled);
  898. X    free(chp);themail=realloc(themail,1+(filled+=dfilled));
  899. X      }
  900. X     else
  901. X      { if(!mailread||!filled)
  902. X       rhead=1;     /* yup, we read in a new header as well as new mail */
  903. X    mailread=0;dfilled=thebody-themail;themail=readdyn(themail,&filled);
  904. X      }
  905. X     *(pastend=filled+(thebody=themail))='\0';           /* terminate mail */
  906. X     while(thebody<pastend&&*thebody++=='\n');         /* skip leading garbage */
  907. X     realstart=thebody;
  908. X     if(rhead)                  /* did we read in a new header anyway? */
  909. X      { confield.filled=0;concnd='\n';
  910. X    while(thebody=strchr(thebody,'\n'))
  911. X       switch(*++thebody)              /* mark continuated fields */
  912. X        { case '\t':case ' ':app_val(&confield,(off_t)(thebody-1-themail));
  913. X          default:
  914. X         continue;           /* empty line marks end of header */
  915. X          case '\n':thebody++;
  916. X         goto eofheader;
  917. X        }
  918. X    thebody=pastend;      /* provide a default, in case there is no body */
  919. Xeofheader:
  920. X    contlengthoffset=0;
  921. X    if(chp=egrepin("^Content-Length:",themail,(long)(thebody-themail),0))
  922. X       contlengthoffset=chp-themail;
  923. X      }
  924. X     else                   /* no new header read, keep it simple */
  925. X    thebody=themail+dfilled; /* that means we know where the body starts */
  926. X   }              /* to make sure that the first From_ line is uninjured */
  927. X  escFrom_.filled=0;
  928. X  ;{ int i;                    /* eradicate From_ in the header */
  929. X     i= *thebody;*thebody='\0';ffrom(realstart);*thebody=i;
  930. X   }
  931. X  if((chp=thebody)>themail)
  932. X     chp--;
  933. X  if(contlengthoffset)
  934. X   { unsigned places;long cntlen,actcntlen;        /* minus one, for safety */
  935. X     chp=themail+contlengthoffset;cntlen=filled-(thebody-themail)-1;
  936. X     for(actcntlen=places=0;;
  937. X     *chp++=cntlen>0?(actcntlen=actcntlen*10+9,'9'):' ',places++)
  938. X      { switch(*chp)
  939. X     { default:                    /* fill'r up, please */
  940. X          continue;
  941. X       case '\n':case '\0':;              /* ok, end of the line */
  942. X     }
  943. X    break;
  944. X      }
  945. X     if(cntlen>0)                   /* any Content-Length at all? */
  946. X      { charNUM(num,cntlen);
  947. X    ultstr(places,cntlen,num);               /* our preferred size */
  948. X    if(!num[places])           /* does it fit in the existing space? */
  949. X       tmemmove(chp-places,num,places),actcntlen=cntlen;          /* yup */
  950. X    chp=thebody+actcntlen;          /* skip the actual no we specified */
  951. X      }
  952. X   }
  953. X  ffrom(chp);mailread=1;      /* eradicate From_ in the rest of the body */
  954. X}
  955. X
  956. Xchar*findtstamp(start,end)const char*start,*end;
  957. X{ start=skpspace(start);start+=strcspn(start," \t\n");
  958. X  if(skpspace(start)>=(end-=25))
  959. X     return (char*)start;
  960. X  while(!(end[13]==':'&&end[15]==':')&&--end>start);
  961. X  ;{ int spc=0;
  962. X     while(end-->start)
  963. X      { switch(*end)
  964. X     { case ' ':case '\t':spc=1;
  965. X          continue;
  966. X     }
  967. X    if(!spc)
  968. X       continue;
  969. X    break;
  970. X      }
  971. X     return (char*)end+1;
  972. X   }
  973. X}
  974. END_OF_FILE
  975.   if test 14078 -ne `wc -c <'procmail-3.03/src/mailfold.c'`; then
  976.     echo shar: \"'procmail-3.03/src/mailfold.c'\" unpacked with wrong size!
  977.   fi
  978.   # end of 'procmail-3.03/src/mailfold.c'
  979. fi
  980. if test -f 'procmail-3.03/src/misc.c' -a "${1}" != "-c" ; then 
  981.   echo shar: Will not clobber existing file \"'procmail-3.03/src/misc.c'\"
  982. else
  983.   echo shar: Extracting \"'procmail-3.03/src/misc.c'\" \(14083 characters\)
  984.   sed "s/^X//" >'procmail-3.03/src/misc.c' <<'END_OF_FILE'
  985. X/************************************************************************
  986. X *    Miscellaneous routines used by procmail                *
  987. X *                                    *
  988. X *    Copyright (c) 1990-1994, S.R. van den Berg, The Netherlands    *
  989. X *    #include "../README"                        *
  990. X ************************************************************************/
  991. X#ifdef RCS
  992. Xstatic /*const*/char rcsid[]=
  993. X "$Id: misc.c,v 1.55 1994/06/28 16:56:31 berg Exp $";
  994. X#endif
  995. X#include "procmail.h"
  996. X#include "acommon.h"
  997. X#include "sublib.h"
  998. X#include "robust.h"
  999. X#include "misc.h"
  1000. X#include "pipes.h"
  1001. X#include "common.h"
  1002. X#include "cstdio.h"
  1003. X#include "exopen.h"
  1004. X#include "regexp.h"
  1005. X#include "mcommon.h"
  1006. X#include "goodies.h"
  1007. X#include "locking.h"
  1008. X#include "mailfold.h"
  1009. X
  1010. Xstruct varval strenvvar[]={{"LOCKSLEEP",DEFlocksleep},
  1011. X {"LOCKTIMEOUT",DEFlocktimeout},{"SUSPEND",DEFsuspend},
  1012. X {"NORESRETRY",DEFnoresretry},{"TIMEOUT",DEFtimeout},{"VERBOSE",DEFverbose},
  1013. X {"LOGABSTRACT",DEFlogabstract}};
  1014. Xstruct varstr strenstr[]={{"SHELLMETAS",DEFshellmetas},{"LOCKEXT",DEFlockext},
  1015. X {"MSGPREFIX",DEFmsgprefix},{"COMSAT",""},{"TRAP",""},
  1016. X {"SHELLFLAGS",DEFshellflags},{"DEFAULT",DEFdefault},{"SENDMAIL",DEFsendmail}};
  1017. X
  1018. X#define MAXvarvals     maxindex(strenvvar)
  1019. X#define MAXvarstrs     maxindex(strenstr)
  1020. X
  1021. Xconst char lastfolder[]="LASTFOLDER";
  1022. Xint didchd;
  1023. Xchar*globlock;
  1024. Xstatic time_t oldtime;
  1025. Xstatic int fakedelivery;
  1026. X               /* line buffered to keep concurrent entries untangled */
  1027. Xvoid elog(newt)const char*const newt;
  1028. X{ int lnew;size_t i;static lold;static char*old;char*p;
  1029. X#ifndef O_CREAT
  1030. X  lseek(STDERR,(off_t)0,SEEK_END);      /* locking should be done actually */
  1031. X#endif
  1032. X  if(!(lnew=strlen(newt))||nextexit)                 /* force flush? */
  1033. X     goto flush;
  1034. X  i=lold+lnew;
  1035. X  if(p=lold?realloc(old,i):malloc(i))             /* unshelled malloc */
  1036. X   { memmove((old=p)+lold,newt,(size_t)lnew);               /* append */
  1037. X     if(p[(lold=i)-1]=='\n')                         /* EOL? */
  1038. X    rwrite(STDERR,p,(int)i),lold=0,free(p);        /* flush the line(s) */
  1039. X   }
  1040. X  else                           /* no memory, force flush */
  1041. Xflush:
  1042. X   { if(lold)
  1043. X      { rwrite(STDERR,old,lold);lold=0;
  1044. X    if(!nextexit)
  1045. X       free(old);            /* don't use free in signal handlers */
  1046. X      }
  1047. X     if(lnew)
  1048. X    rwrite(STDERR,newt,lnew);
  1049. X   }
  1050. X}
  1051. X
  1052. X#include "shell.h"
  1053. X
  1054. Xvoid ignoreterm P((void))
  1055. X{ signal(SIGTERM,SIG_IGN);signal(SIGHUP,SIG_IGN);signal(SIGINT,SIG_IGN);
  1056. X  signal(SIGQUIT,SIG_IGN);
  1057. X}
  1058. X
  1059. Xvoid shutdesc P((void))
  1060. X{ rclose(savstdout);closelog();closerc();
  1061. X}
  1062. X
  1063. Xvoid setids P((void))
  1064. X{ if(rcstate!=rc_NORMAL)
  1065. X   { if(setrgid(gid))    /* due to these !@#$%^&*() POSIX semantics, setgid() */
  1066. X    setgid(gid);       /* sets the saved gid as well; we can't use that! */
  1067. X     setruid(uid);setuid(uid);setegid(gid);rcstate=rc_NORMAL;
  1068. X#if !DEFverbose
  1069. X     verbose=0;
  1070. X#endif
  1071. X   }
  1072. X}
  1073. X
  1074. Xvoid writeerr(line)const char*const line;
  1075. X{ nlog(errwwriting);logqnl(line);
  1076. X}
  1077. X
  1078. Xint forkerr(pid,a)const pid_t pid;const char*const a;
  1079. X{ if(pid==-1)
  1080. X   { nlog("Failed forking");logqnl(a);
  1081. X     return 1;
  1082. X   }
  1083. X  return 0;
  1084. X}
  1085. X
  1086. Xvoid progerr(line,xitcode)const char*const line;int xitcode;
  1087. X{ charNUM(num,thepid);
  1088. X  nlog("Program failure (");
  1089. X  if(xitcode<0)
  1090. X     xitcode= -xitcode,elog("-");
  1091. X  ultstr(0,(unsigned long)xitcode,num);elog(num);
  1092. X  elog(") of");logqnl(line);
  1093. X}
  1094. X
  1095. Xvoid chderr(dir)const char*const dir;
  1096. X{ nlog("Couldn't chdir to");logqnl(dir);
  1097. X}
  1098. X
  1099. Xvoid readerr(file)const char*const file;
  1100. X{ nlog("Couldn't read");logqnl(file);
  1101. X}
  1102. X
  1103. Xvoid verboff P((void))
  1104. X{ verbose=0;
  1105. X#ifdef SIGUSR1
  1106. X  qsignal(SIGUSR1,(void(*)())verboff);
  1107. X#endif
  1108. X}
  1109. X
  1110. Xvoid verbon P((void))
  1111. X{ verbose=1;
  1112. X#ifdef SIGUSR2
  1113. X  qsignal(SIGUSR2,(void(*)())verbon);
  1114. X#endif
  1115. X}
  1116. X
  1117. Xvoid yell(a,b)const char*const a,*const b;        /* log if VERBOSE=on */
  1118. X{ if(verbose)
  1119. X     nlog(a),logqnl(b);
  1120. X}
  1121. X
  1122. Xvoid newid P((void))
  1123. X{ thepid=getpid();oldtime=0;
  1124. X}
  1125. X
  1126. Xvoid zombiecollect P((void))
  1127. X{ while(waitpid((pid_t)-1,(int*)0,WNOHANG)>0);          /* collect any zombies */
  1128. X}
  1129. X
  1130. Xvoid nlog(a)const char*const a;
  1131. X{ time_t newtime;
  1132. X  static const char colnsp[]=": ";
  1133. X  elog(procmailn);elog(colnsp);
  1134. X  if(verbose&&oldtime!=(newtime=time((time_t*)0)))
  1135. X   { charNUM(num,thepid);
  1136. X     elog("[");oldtime=newtime;ultstr(0,(unsigned long)thepid,num);elog(num);
  1137. X     elog("] ");elog(ctime(&oldtime));elog(procmailn);elog(colnsp);
  1138. X   }
  1139. X  elog(a);
  1140. X}
  1141. X
  1142. Xvoid logqnl(a)const char*const a;
  1143. X{ elog(oquote);elog(a);elog(cquote);
  1144. X}
  1145. X
  1146. Xvoid skipped(x)const char*const x;
  1147. X{ if(*x)
  1148. X     nlog("Skipped"),logqnl(x);
  1149. X}
  1150. X
  1151. Xint nextrcfile P((void))    /* next rcfile specified on the command line */
  1152. X{ const char*p;int rval=2;
  1153. X  while(p= *gargv)
  1154. X   { gargv++;
  1155. X     if(!strchr(p,'='))
  1156. X      { rcfile=p;
  1157. X    return rval;
  1158. X      }
  1159. X     rval=1;                   /* not the first argument encountered */
  1160. X   }
  1161. X  return 0;
  1162. X}
  1163. X
  1164. Xvoid onguard P((void))
  1165. X{ lcking|=lck_LOCKFILE;
  1166. X}
  1167. X
  1168. Xvoid offguard P((void))
  1169. X{ lcking&=~lck_LOCKFILE;
  1170. X  if(nextexit==1)      /* make sure we are not inside Terminate() already */
  1171. X     elog(newline),Terminate();
  1172. X}
  1173. X
  1174. Xvoid sterminate P((void))
  1175. X{ static const char*const msg[]={"memory","fork",      /* crosscheck with */
  1176. X   "a file descriptor","a kernel-lock"};      /* lck_ defs in procmail.h */
  1177. X  ignoreterm();
  1178. X  if(pidchild>0)        /* don't kill what is not ours, we might be root */
  1179. X     kill(pidchild,SIGTERM);
  1180. X  if(!nextexit)
  1181. X   { nextexit=1;nlog("Terminating prematurely");
  1182. X     if(!(lcking&lck_LOCKFILE))
  1183. X      { register unsigned i,j;
  1184. X    if(i=(lcking&~(lck_ALLOCLIB|lck_LOCKFILE))>>1)
  1185. X     { elog(whilstwfor);
  1186. X       for(j=0;!((i>>=1)&1);j++);
  1187. X       elog(msg[j]);
  1188. X     }
  1189. X    elog(newline);Terminate();
  1190. X      }
  1191. X   }
  1192. X}
  1193. X
  1194. Xvoid Terminate P((void))
  1195. X{ ignoreterm();
  1196. X  if(retvl2!=EX_OK)
  1197. X     fakedelivery=0,retval=retvl2;
  1198. X  if(getpid()==thepid)
  1199. X   { if(retval!=EX_OK)
  1200. X      { tofile=0;lasttell= -1;              /* mark it for logabstract */
  1201. X    logabstract(fakedelivery?"**Lost**":
  1202. X     retval==EX_TEMPFAIL?"**Requeued**":"**Bounced**");
  1203. X      }
  1204. X     else
  1205. X    logabstract(tgetenv(lastfolder));
  1206. X     shutdesc();
  1207. X     if(!(lcking&lck_ALLOCLIB))            /* don't reenter malloc/free */
  1208. X    exectrap(traps);
  1209. X     nextexit=2;unlock(&loclock);unlock(&globlock);fdunlock();
  1210. X   }                    /* flush the logfile & exit procmail */
  1211. X  elog("");exit(fakedelivery==2?EX_OK:retval);
  1212. X}
  1213. X
  1214. Xvoid suspend P((void))
  1215. X{ ssleep((unsigned)suspendv);
  1216. X}
  1217. X
  1218. Xvoid app_val(sp,val)struct dyna_long*const sp;const off_t val;
  1219. X{ if(sp->filled==sp->tspace)                /* growth limit reached? */
  1220. X   { if(!sp->offs)
  1221. X    sp->offs=malloc(1);
  1222. X     sp->offs=realloc(sp->offs,(sp->tspace+=4)*sizeof sp->offs);   /* expand */
  1223. X   }
  1224. X  sp->offs[sp->filled++]=val;                     /* append to it */
  1225. X}
  1226. X
  1227. Xint alphanum(c)const unsigned c;
  1228. X{ return numeric(c)||c-'a'<='z'-'a'||c-'A'<='Z'-'A'||c=='_';
  1229. X}
  1230. X
  1231. Xvoid firstchd P((void))
  1232. X{ if(!didchd)                       /* have we been here already? */
  1233. X   { const char*p;
  1234. X     didchd=1;                  /* no, well, then try an initial chdir */
  1235. X     if(chdir(p=tgetenv(maildir)))
  1236. X      { chderr(p);
  1237. X    if(chdir(p=tgetenv(home)))
  1238. X       chderr(p);
  1239. X      }
  1240. X   }
  1241. X}
  1242. X
  1243. Xvoid srequeue P((void))
  1244. X{ retval=EX_TEMPFAIL;sterminate();
  1245. X}
  1246. X
  1247. Xvoid slose P((void))
  1248. X{ fakedelivery=2;sterminate();
  1249. X}
  1250. X
  1251. Xvoid sbounce P((void))
  1252. X{ retval=EX_CANTCREAT;sterminate();
  1253. X}
  1254. X
  1255. Xvoid catlim(src)register const char*src;
  1256. X{ register char*dest=buf;register size_t lim=linebuf;
  1257. X  while(lim&&*dest)
  1258. X     dest++,lim--;
  1259. X  if(lim)
  1260. X   { while(--lim&&(*dest++= *src++));
  1261. X     *dest='\0';
  1262. X   }
  1263. X}
  1264. X
  1265. Xvoid setdef(name,contents)const char*const name,*const contents;
  1266. X{ strcat(strcat(strcpy((char*)(sgetcp=buf2),name),"="),contents);
  1267. X  readparse(buf,sgetc,2);sputenv(buf);
  1268. X}
  1269. X
  1270. Xvoid metaparse(p)const char*p;                    /* result in buf */
  1271. X{ if(sh=!!strpbrk(p,shellmetas))
  1272. X     strcpy(buf,p);             /* copy literally, shell will parse */
  1273. X  else
  1274. X#ifndef GOT_bin_test
  1275. X   { sgetcp=p=tstrdup(p);
  1276. X     readparse(buf,sgetc,0);                /* parse it yourself */
  1277. X     if(!strcmp(test,buf))
  1278. X    strcpy(buf,p),sh=1;                   /* oops, `test' found */
  1279. X     free((char*)p);
  1280. X   }
  1281. X#else
  1282. X     sgetcp=p,readparse(buf,sgetc,0);
  1283. X#endif
  1284. X}
  1285. X
  1286. Xvoid concatenate(p)register char*p;
  1287. X{ while(p!=Tmnate)              /* concatenate all other arguments */
  1288. X   { while(*p++);
  1289. X     p[-1]=' ';
  1290. X   }
  1291. X  *p=p[-1]='\0';
  1292. X}
  1293. X
  1294. Xchar*lastdirsep(filename)const char*filename;     /* finds the next character */
  1295. X{ const char*p;                    /* following the last DIRSEP */
  1296. X  while(p=strpbrk(filename,dirsep))
  1297. X     filename=p+1;
  1298. X  return (char*)filename;
  1299. X}
  1300. X
  1301. Xchar*cat(a,b)const char*const a,*const b;
  1302. X{ return strcat(strcpy(buf,a),b);
  1303. X}
  1304. X
  1305. Xchar*tstrdup(a)const char*const a;
  1306. X{ int i;
  1307. X  i=strlen(a)+1;
  1308. X  return tmemmove(malloc(i),a,i);
  1309. X}
  1310. X
  1311. Xconst char*tgetenv(a)const char*const a;
  1312. X{ const char*b;
  1313. X  return (b=getenv(a))?b:"";
  1314. X}
  1315. X
  1316. Xchar*cstr(a,b)char*const a;const char*const b;    /* dynamic buffer management */
  1317. X{ if(a)
  1318. X     free(a);
  1319. X  return tstrdup(b);
  1320. X}
  1321. X
  1322. Xvoid setlastfolder(folder)const char*const folder;
  1323. X{ if(asgnlastf)
  1324. X   { char*chp;
  1325. X     asgnlastf=0;
  1326. X     strcpy(chp=malloc(STRLEN(lastfolder)+1+strlen(folder)+1),lastfolder);
  1327. X     chp[STRLEN(lastfolder)]='=';strcpy(chp+STRLEN(lastfolder)+1,folder);
  1328. X     sputenv(chp);free(chp);
  1329. X   }
  1330. X}
  1331. X
  1332. Xchar*gobenv(chp)char*chp;
  1333. X{ int found,i;
  1334. X  found=0;
  1335. X  if(alphanum(i=getb())&&!numeric(i))
  1336. X     for(found=1;*chp++=i,alphanum(i=getb()););
  1337. X  *chp='\0';ungetb(i);
  1338. X  switch(i)
  1339. X   { case ' ':case '\t':case '\n':case '=':
  1340. X    if(found)
  1341. X       return chp;
  1342. X   }
  1343. X  return 0;
  1344. X}
  1345. X
  1346. Xint asenvcpy(src)char*src;
  1347. X{ strcpy(buf,src);
  1348. X  if(src=strchr(buf,'='))                 /* is it an assignment? */
  1349. X   { const char*chp;
  1350. X     strcpy((char*)(sgetcp=buf2),++src);readparse(src,sgetc,2);
  1351. X     chp=sputenv(buf);src[-1]='\0';asenv(chp);
  1352. X     return 1;
  1353. X   }
  1354. X  return 0;
  1355. X}
  1356. X
  1357. Xvoid asenv(chp)const char*const chp;
  1358. X{ static const char slinebuf[]="LINEBUF",logfile[]="LOGFILE",Log[]="LOG",
  1359. X   sdelivered[]="DELIVERED",includerc[]="INCLUDERC",eumask[]="UMASK",
  1360. X   dropprivs[]="DROPPRIVS",shift[]="SHIFT";
  1361. X  if(!strcmp(buf,slinebuf))
  1362. X   { if((linebuf=renvint(0L,chp)+XTRAlinebuf)<MINlinebuf+XTRAlinebuf)
  1363. X    linebuf=MINlinebuf+XTRAlinebuf;               /* check minimum size */
  1364. X     free(buf);free(buf2);buf=malloc(linebuf);buf2=malloc(linebuf);
  1365. X   }
  1366. X  else if(!strcmp(buf,maildir))
  1367. X     if(chdir(chp))
  1368. X    chderr(chp);
  1369. X     else
  1370. X    didchd=1;
  1371. X  else if(!strcmp(buf,logfile))
  1372. X     opnlog(chp);
  1373. X  else if(!strcmp(buf,Log))
  1374. X     elog(chp);
  1375. X  else if(!strcmp(buf,exitcode))
  1376. X     setxit=1;
  1377. X  else if(!strcmp(buf,shift))
  1378. X   { int i;
  1379. X     if((i=renvint(0L,chp))>0)
  1380. X      { if(i>crestarg)
  1381. X       i=crestarg;
  1382. X    crestarg-=i;restargv+=i;             /* shift away arguments */
  1383. X      }
  1384. X   }
  1385. X  else if(!strcmp(buf,dropprivs))              /* drop privileges */
  1386. X   { if(renvint(0L,chp))
  1387. X    setids();
  1388. X   }
  1389. X  else if(!strcmp(buf,sdelivered))                /* fake delivery */
  1390. X   { if(renvint(0L,chp))                    /* is it really? */
  1391. X      { onguard();
  1392. X    if((thepid=sfork())>0)            /* signals may cause trouble */
  1393. X       nextexit=2,lcking&=~lck_LOCKFILE,exit(retvl2);
  1394. X    if(!forkerr(thepid,procmailn))
  1395. X       fakedelivery=1;
  1396. X    newid();offguard();
  1397. X      }
  1398. X   }
  1399. X  else if(!strcmp(buf,lockfile))
  1400. X     lockit((char*)chp,&globlock);
  1401. X  else if(!strcmp(buf,eumask))
  1402. X     doumask((mode_t)strtol(chp,(char**)0,8));
  1403. X  else if(!strcmp(buf,includerc))
  1404. X     pushrc(chp);
  1405. X  else if(!strcmp(buf,host))
  1406. X   { const char*name;
  1407. X     if(strcmp(chp,name=hostname()))
  1408. X      { yell("HOST mismatched",name);
  1409. X    if(rc<0||!nextrcfile())              /* if no rcfile opened yet */
  1410. X       retval=EX_OK,Terminate();          /* exit gracefully as well */
  1411. X    closerc();
  1412. X      }
  1413. X   }
  1414. X  else
  1415. X   { int i=MAXvarvals;
  1416. X     do                          /* several numeric assignments */
  1417. X    if(!strcmp(buf,strenvvar[i].name))
  1418. X       strenvvar[i].val=renvint(strenvvar[i].val,chp);
  1419. X     while(i--);
  1420. X     i=MAXvarstrs;
  1421. X     do                         /* several text assignments */
  1422. X    if(!strcmp(buf,strenstr[i].sname))
  1423. X       strenstr[i].sval=chp;
  1424. X     while(i--);
  1425. X   }
  1426. X}
  1427. X
  1428. Xlong renvint(i,env)const long i;const char*const env;
  1429. X{ const char*p;long t;
  1430. X  t=strtol(env,(char**)&p,10);              /* parse like a decimal nr */
  1431. X  if(p==env)
  1432. X   { for(;;p++)                      /* skip leading whitespace */
  1433. X      { switch(*p)
  1434. X     { case '\t':case ' ':
  1435. X          continue;
  1436. X     }
  1437. X    break;
  1438. X      }
  1439. X     t=i;
  1440. X     if(!strnIcmp(p,"on",(size_t)2)||!strnIcmp(p,"y",(size_t)1)||
  1441. X      !strnIcmp(p,"t",(size_t)1)||!strnIcmp(p,"e",(size_t)1))
  1442. X    t=1;
  1443. X     else if(!strnIcmp(p,"off",(size_t)3)||!strnIcmp(p,"n",(size_t)1)||
  1444. X      !strnIcmp(p,"f",(size_t)1)||!strnIcmp(p,"d",(size_t)1))
  1445. X    t=0;
  1446. X   }
  1447. X  return t;
  1448. X}
  1449. X
  1450. Xvoid squeeze(target)char*target;
  1451. X{ int state;char*src;
  1452. X  for(state=0,src=target;;target++,src++)
  1453. X   { switch(*target= *src)
  1454. X      { case '\n':
  1455. X       if(state==1)
  1456. X          target-=2;                 /* throw out \ \n pairs */
  1457. X       state=2;
  1458. X       continue;
  1459. X    case '\\':state=1;
  1460. X       continue;
  1461. X    case ' ':case '\t':
  1462. X       if(state==2)                         /* skip leading */
  1463. X        { target--;                           /* whitespace */
  1464. X          continue;
  1465. X        }
  1466. X    default:state=0;
  1467. X       continue;
  1468. X    case '\0':;
  1469. X      }
  1470. X     break;
  1471. X   }
  1472. X}
  1473. X
  1474. Xchar*egrepin(expr,source,len,casesens)char*expr;const char*source;
  1475. X const long len;int casesens;
  1476. X{ if(*expr)         /* only do the search if the expression is nonempty */
  1477. X   { source=(const char*)bregexec((struct eps*)(expr=(char*)
  1478. X      bregcomp(expr,!casesens)),(const uchar*)source,(const uchar*)source,
  1479. X      len>0?(size_t)len:(size_t)0,!casesens);
  1480. X     free(expr);
  1481. X   }
  1482. X  return (char*)source;
  1483. X}
  1484. X
  1485. Xconst struct passwd*savepass(spass,uid)struct passwd*const spass;
  1486. X const uid_t uid;
  1487. X{ struct passwd*tpass;
  1488. X  if(spass->pw_name&&spass->pw_uid==uid)
  1489. X     goto ret;
  1490. X  if(tpass=getpwuid(uid))                  /* save by copying */
  1491. X   { spass->pw_uid=tpass->pw_uid;spass->pw_gid=tpass->pw_gid;
  1492. X     spass->pw_name=cstr(spass->pw_name,tpass->pw_name);
  1493. X     spass->pw_dir=cstr(spass->pw_dir,tpass->pw_dir);
  1494. X     spass->pw_shell=cstr(spass->pw_shell,tpass->pw_shell);
  1495. Xret: return spass;
  1496. X   }
  1497. X  return (const struct passwd*)0;
  1498. X}
  1499. X
  1500. Xint enoughprivs(passinvk,euid,egid,uid,gid)const struct passwd*const passinvk;
  1501. X const uid_t euid,uid;const gid_t egid,gid;
  1502. X{ return euid==ROOT_uid||passinvk&&passinvk->pw_uid==uid||euid==uid&&egid==gid;
  1503. X}
  1504. X
  1505. Xvoid initdefenv P((void))
  1506. X{ int i=MAXvarstrs;
  1507. X  do       /* initialise all non-empty string variables into the environment */
  1508. X     if(*strenstr[i].sval)
  1509. X    setdef(strenstr[i].sname,strenstr[i].sval);
  1510. X  while(i--);
  1511. X}
  1512. X
  1513. Xconst char*newdynstring(adrp,chp)struct dynstring**const adrp;
  1514. X const char*const chp;
  1515. X{ struct dynstring*curr;size_t len;
  1516. X  curr=malloc(ioffsetof(struct dynstring,ename[0])+(len=strlen(chp)+1));
  1517. X  tmemmove(curr->ename,chp,len);curr->enext= *adrp;*adrp=curr;
  1518. X  return curr->ename;
  1519. X}
  1520. END_OF_FILE
  1521.   if test 14083 -ne `wc -c <'procmail-3.03/src/misc.c'`; then
  1522.     echo shar: \"'procmail-3.03/src/misc.c'\" unpacked with wrong size!
  1523.   fi
  1524.   # end of 'procmail-3.03/src/misc.c'
  1525. fi
  1526. echo shar: End of archive 5 \(of 10\).
  1527. cp /dev/null ark5isdone
  1528. MISSING=""
  1529. for I in 1 2 3 4 5 6 7 8 9 10 ; do
  1530.     if test ! -f ark${I}isdone ; then
  1531.     MISSING="${MISSING} ${I}"
  1532.     fi
  1533. done
  1534. if test "${MISSING}" = "" ; then
  1535.     echo You have unpacked all 10 archives.
  1536.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1537. else
  1538.     echo You still must unpack the following archives:
  1539.     echo "        " ${MISSING}
  1540. fi
  1541. exit 0
  1542. exit 0 # Just in case...
  1543.