home *** CD-ROM | disk | FTP | other *** search
- From: berg@pool.informatik.rwth-aachen.de (Stephen R. van den Berg)
- Newsgroups: comp.sources.misc
- Subject: v43i060: procmail - mail processing package v3.03, Part05/10
- Date: 5 Jul 1994 20:50:01 -0500
- Organization: Sterling Software
- Sender: kent@sparky.sterling.com
- Approved: kent@sparky.sterling.com
- Message-ID: <2vd2k9$i7u@sparky.sterling.com>
- X-Md4-Signature: 4633a686de718684565da3a73f6dd04b
-
- Submitted-by: berg@pool.informatik.rwth-aachen.de (Stephen R. van den Berg)
- Posting-number: Volume 43, Issue 60
- Archive-name: procmail/part05
- Environment: sendmail, ZMailer, smail, MMDF, mailsurr, UNIX, POSIX
- Supersedes: procmail: Volume 38, Issue 19-31
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then feed it
- # into a shell via "sh file" or similar. To overwrite existing files,
- # type "sh file -c".
- # Contents: procmail-3.03/config.h procmail-3.03/src/locking.c
- # procmail-3.03/src/mailfold.c procmail-3.03/src/misc.c
- # Wrapped by kent@sparky on Tue Jul 5 20:42:13 1994
- PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin:$PATH ; export PATH
- echo If this archive is complete, you will see the following message:
- echo ' "shar: End of archive 5 (of 10)."'
- if test -f 'procmail-3.03/config.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'procmail-3.03/config.h'\"
- else
- echo shar: Extracting \"'procmail-3.03/config.h'\" \(14070 characters\)
- sed "s/^X//" >'procmail-3.03/config.h' <<'END_OF_FILE'
- X/*$Id: config.h,v 1.53 1994/06/30 12:01:25 berg Exp $*/
- X
- X/*#define sMAILBOX_SEPARATOR "\1\1\1\1\n" /* sTART- and eNDing separ. */
- X/*#define eMAILBOX_SEPARATOR "\1\1\1\1\n" /* uncomment (one or both)
- X if your mail system uses
- X nonstandard mail separators (non sendmail or smail compatible mailers
- X like MMDF), if yours is even different, uncomment and change the
- X value of course */
- X
- X/* KEEPENV and PRESTENV should be defined as a comma-separated null-terminated
- X list of strings */
- X
- X/* every environment variable appearing in KEEPENV will not be thrown away
- X * upon startup of procmail, e.g. you could define KEEPENV as follows:
- X * #define KEEPENV {"TZ","LANG",0}
- X * environment variables ending in an _ will designate the whole group starting
- X * with this prefix (e.g. "LC_").
- X */
- X#define KEEPENV {"TZ",0}
- X
- X/* every environment variable appearing in PRESTENV will be set or wiped
- X * out of the environment (variables without an '=' sign will be thrown
- X * out), e.g. you could define PRESTENV as follows:
- X * #define PRESTENV {"IFS","ENV","PWD","PATH=$HOME/bin:/bin:/usr/bin",0}
- X * any side effects (like setting the umask after an assignment to UMASK) will
- X * *not* take place
- X */
- X#define PRESTENV {"IFS","ENV","PWD","PATH=$HOME/bin:/bin:/usr/bin", \
- X "USER=$LOGNAME",0}
- X
- X/************************************************************************
- X * Only edit below this line if you have viewed/edited this file before *
- X ************************************************************************/
- X
- X/* every user & group appearing in TRUSTED_IDS is allowed to use the -f option
- X if the list is empty (just a terminating 0), everyone can use it
- X TRUSTED_IDS should be defined as a comma-separated null-terminated
- X list of strings; if unauthorised users use the -f option, an extra
- X >From_ field will be added in the header */
- X
- X#define TRUSTED_IDS {"root","daemon","uucp","mail","x400","network",\
- X "list","lists","news",0}
- X
- X/*#define NO_USER_TO_LOWERCASE_HACK /* uncomment if your getpwnam() is
- X case insensitive or if procmail
- X will always be supplied with the correct case in the explicit
- X delivery mode argument(s) */
- X
- X/*#define NO_fcntl_LOCK /* uncomment any of these three if you */
- X/*#define NO_lockf_LOCK /* definitely do not want procmail to make */
- X/*#define NO_flock_LOCK /* use of those kernel-locking methods */
- X
- X/*#define NO_NFS_ATIME_HACK /* uncomment if you're definitely not using
- X NFS mounted filesystems and can't afford
- X procmail to sleep for 1 sec. before writing a mailbox */
- X
- X/*#define SYSTEM_MBOX "$HOME/.mail" /* uncomment and/or change if the
- X preset default mailbox is *not*
- X suitable or if you want standard mail delivery to take place in a
- X different file from the normal mail-spool-file.
- X (it will supersede the value of SYSTEM_MAILBOX in autoconf.h) */
- X
- X/*#define DEFsendmail "/bin/mail" /* uncomment and/or change if the
- X autoconfigured default SENDMAIL is
- X not suitable */
- X
- X#define ETCRC "/etc/procmailrc" /* optional global procmailrc startup
- X file (will only be read if procmail
- X is started with no rcfile on the command line). */
- X
- X#define ETCRCS "/etc/procmailrcs/" /* optional trusted path prefix for
- X rcfiles which will be executed with
- X the uid of the owner of the rcfile (this only happens if procmail is
- X called with the -m option, without variable assignments on the command
- X line). */
- X
- X/*#define console "/dev/console" /* uncomment if you want procmail to
- X use the console (or any other
- X terminal or file) to print any error messages that could not be dumped
- X in the "logfile"; only recommended for debugging purposes, if you have
- X trouble creating a "logfile" or suspect that the trouble starts before
- X procmail can interpret any rcfile or arguments. */
- X
- X/************************************************************************
- X * Only edit below this line if you *think* you know what you are doing *
- X ************************************************************************/
- X
- X#define ROOT_uid 0
- X
- X#define UPDATE_MASK S_IXOTH /* bit set on mailboxes when mail arrived */
- X#define OVERRIDE_MASK (S_IXUSR|S_ISUID|S_ISGID|S_ISVTX) /* if found set */
- X /* the permissions on the mailbox will be left untouched */
- X#define INIT_UMASK (S_IRWXG|S_IRWXO) /* == 077 */
- X#define NORMperm \
- X (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH|UPDATE_MASK)
- X /* == 0667, normal mode bits used to create files, before umask */
- X#define READperm (S_IRUSR|S_IRGRP|S_IROTH) /* == 0444 */
- X#define NORMdirperm (S_IRWXU|S_IRWXG|S_IRWXO) /* == 0777 */
- X#define LOCKperm READperm /* mode bits used while creating lockfiles */
- X#define MAX_locksize 16 /* lockfiles are expected not to be longer */
- X#ifndef SMALLHEAP
- X#define DEFlinebuf 2048 /* default max expanded line length */
- X#define BLKSIZ 16384 /* blocksize while reading/writing */
- X#define STDBUF 1024 /* blocksize for emulated stdio */
- X#else /* and some lower defaults for the unfortunate amongst us */
- X#define DEFlinebuf 512
- X#define BLKSIZ 1024
- X#define STDBUF 128
- X#endif /* SMALLHEAP */
- X#define FAKE_FIELD ">From "
- X#define HOSTNAMElen 9 /* determines hostname-ID-len on tempfiles */
- X#define BOGUSprefix "BOGUS." /* prepended to bogus mailboxes */
- X#define PROCMAILRC ".procmailrc"
- X#define DEFsuspend 16 /* multi-purpose 'idle loop' period */
- X#define DEFlocksleep 8
- X#define TOkey "^TO"
- X#define TOsubstitute "(^((Original-)?(Resent-)?(To|Cc|Bcc)|\
- X(X-Envelope|Apparently(-Resent)?)-To):(.*[^a-zA-Z])?)"
- X#define FROMDkey "^FROM_DAEMON" /* matches most daemons */
- X#define FROMDsubstitute "(^(Precedence:.*(junk|bulk|list)|\
- X(((Resent-)?(From|Sender)|X-Envelope-From):|>?From )(.*[^(.%@a-z0-9])?(\
- XPost(ma?(st(e?r)?|n)|office)|Mail(er)?|daemon|mmdf|root|uucp|LISTSERV|owner|\
- Xrequest|bounce|serv(ices?|er)|Admin(istrator)?)([^).!:a-z0-9].*)?$[^>]))"
- X#define FROMMkey "^FROM_MAILER" /* matches most mailer-daemons */
- X#define FROMMsubstitute "(^(((Resent-)?(From|Sender)|X-Envelope-From):|\
- X>?From )(.*[^(.%@a-z0-9])?(Post(ma(st(er)?|n)|office)|Mail(er)?|daemon|mmdf|\
- Xroot|uucp|serv(ices?|er)|Admin(istrator)?)([^).!:a-z0-9].*)?$[^>])"
- X#define DEFshellmetas "&|<>~;?*[" /* never put '$' in here */
- X#define DEFmaildir "$HOME"
- X#define DEFdefault "$ORGMAIL"
- X#define DEFmsgprefix "msg."
- X#define DEFlockext ".lock"
- X#define DEFshellflags "-c"
- X#define DEFlocktimeout 1024 /* defaults to about 17 minutes */
- X#define DEFtimeout (DEFlocktimeout-64) /* 64 seconds to clean up */
- X#define DEFnoresretry 4 /* default nr of retries if no resources left */
- X#define nfsTRY (7+1) /* nr of times+1 to ignore spurious NFS errors */
- X#define DEFlogabstract -1 /* abstract by default, but don't mail it back */
- X#define COMSAThost "localhost" /* where the biff/comsat daemon lives */
- X#define COMSATservice "biff" /* the service name of the comsat daemon */
- X#define COMSATprotocol "udp" /* if you change this, comsat() needs patching */
- X#define COMSATxtrsep ":" /* mailbox-spec extension separator */
- X#define SERV_ADDRsep '@' /* when overriding in COMSAT=serv@addr */
- X#define DEFcomsat "no" /* when an rcfile has been specified */
- X
- X#define BinSh "/bin/sh"
- X#define RootDir "/"
- X#define DevNull "/dev/null"
- X#define NICE_RANGE 39 /* maximal nice difference */
- X#define chCURDIR '.' /* the current directory */
- X#define chPARDIR ".." /* the parent directory */
- X#define DIRSEP "/" /* directory separator symbols, the */
- X /* last one should be the most common one */
- X
- X#define EOFName " \t\n#`'\");"
- X
- X#define HELPOPT1 'h' /* options to get command line help */
- X#define HELPOPT2 '?'
- X
- X#define VERSIONOPT 'v' /* option to display version */
- X#define PRESERVOPT 'p' /* preserve environment */
- X#define TEMPFAILOPT 't' /* return EX_TEMPFAIL on error */
- X#define MAILFILTOPT 'm' /* act as a general purpose mail filter */
- X#define FROMWHOPT 'f' /* set name on From_ line */
- X#define REFRESH_TIME '-' /* when given as argument to -f */
- X#define ALTFROMWHOPT 'r' /* alternate and obsolete form of -f */
- X#define OVERRIDEOPT 'o' /* do not generate >From_ lines */
- X#define ARGUMENTOPT 'a' /* set $1 */
- X#define DELIVEROPT 'd' /* deliver mail to named recipient */
- X#define PM_USAGE \
- X "Usage: procmail [-vpto] [-f fromwhom] [parameter=value | rcfile] ...\
- X\n Or: procmail [-to] [-f fromwhom] [-a argument] -d recipient ...\
- X\n Or: procmail [-pt] -m [parameter=value] ... rcfile mail_from rcpt_to ...\
- X\n"
- X#define PM_HELP \
- X "\t-v\t\tdisplay the version number and exit\
- X\n\t-p\t\tpreserve (most of) the environment upon startup\
- X\n\t-t\t\tfail softly if mail is undeliverable\
- X\n\t-f fromwhom\t(re)generate the leading 'From ' line\
- X\n\t-o override the leading 'From ' line if necessary\
- X\n\t-a argument\twill set $1\
- X\n\t-d recipient\texplicit delivery mode\
- X\n\t-m\t\tact as a general purpose mail filter\n"
- X#define PM_QREFERENCE \
- X "Recipe flag quick reference:\
- X\n\tH egrep header (default)\tB egrep body\
- X\n\tD distinguish case\
- X\n\tA also execute this recipe if the common condition matched\
- X\n\ta same as 'A', but only if the previous recipe was successful\
- X\n\tE else execute this recipe, if the preceding condition didn't match\
- X\n\te on error execute this recipe, if the previous recipe failed\
- X\n\th deliver header (default)\tb deliver body (default)\
- X\n\tf filter\t\t\ti ignore write errors\
- X\n\tc continue with the next recipe in any case\
- X\n\tw wait for a filter or program\
- X\n\tW same as 'w', but suppress 'Program failure' messages\n"
- X
- X#define MINlinebuf 128 /* minimal LINEBUF length (don't change this) */
- X#define FROM_EXPR "\nFrom "
- X#define FROM "From "
- X#define SHFROM "From"
- X#define NSUBJECT "^Subject:.*$"
- X#define MAXSUBJECTSHOW 78
- X#define FOLDER " Folder: "
- X#define LENtSTOP 9 /* tab stop at which message length will be logged */
- X
- X#define TABCHAR "\t"
- X#define TABWIDTH 8
- X
- X#define RECFLAGS "HBDAahbfcwWiEe"
- X#define HEAD_GREP 0
- X#define BODY_GREP 1
- X#define DISTINGUISH_CASE 2
- X#define ALSO_NEXT_RECIPE 3
- X#define ALSO_N_IF_SUCC 4
- X#define PASS_HEAD 5
- X#define PASS_BODY 6
- X#define FILTER 7
- X#define CONTINUE 8
- X#define WAIT_EXIT 9
- X#define WAIT_EXIT_QUIET 10
- X#define IGNORE_WRITERR 11
- X#define ELSE_DO 12
- X#define ERROR_DO 13
- X
- X#define UNIQ_PREFIX '_' /* prepended to temporary unique filenames */
- X#define ESCAP ">"
- X
- X /* some formail-specific configuration options: */
- X
- X#define UNKNOWN "foo@bar" /* formail default originator name */
- X#define OLD_PREFIX "Old-" /* formail field-Old-prefix */
- X#define BABYL_SEP1 '\037' /* BABYL format separator one */
- X#define BABYL_SEP2 '\f' /* BABYL format separator two */
- X#define DEFfileno "FILENO=000" /* split counter for formail */
- X#define LEN_FILENO_VAR 7 /* =strlen("FILENO=") */
- X#define CHILD_FACTOR 3/4 /* do not parenthesise; average running children */
- X
- X#define FM_SKIP '+' /* skip the first nnn messages */
- X#define FM_TOTAL '-' /* only spit out a total of nnn messages */
- X#define FM_BOGUS 'b' /* leave bogus Froms intact */
- X#define FM_QPREFIX 'p' /* define quotation prefix */
- X#define FM_CONCATENATE 'c' /* concatenate continued header-fields */
- X#define FM_FORCE 'f' /* force formail to accept an arbitrary format */
- X#define FM_REPLY 'r' /* generate an auto-reply header */
- X#define FM_KEEPB 'k' /* keep the header, when replying */
- X#define FM_TRUST 't' /* trust the sender to supply a valid header */
- X#define FM_LOGSUMMARY 'l' /* generate a procmail-compatible log summary */
- X#define FM_SPLIT 's' /* split it up */
- X#define FM_NOWAIT 'n' /* don't wait for the programs */
- X#define FM_EVERY 'e' /* don't require empty lines leading headers */
- X#define FM_MINFIELDS 'm' /* the number of fields that have to be found */
- X#define DEFminfields 2 /* before a header is recognised as such */
- X#define FM_DIGEST 'd' /* split up digests */
- X#define FM_BABYL 'B' /* split up BABYL format rmail files */
- X#define FM_QUIET 'q' /* be quiet */
- X#define FM_DUPLICATE 'D' /* return success on duplicate mails */
- X#define FM_EXTRACT 'x' /* extract field contents */
- X#define FM_EXTRC_KEEP 'X' /* extract field */
- X#define FM_ADD_IFNOT 'a' /* add a field if not already there */
- X#define FM_ADD_ALWAYS 'A' /* add this field in any case */
- X#define FM_REN_INSERT 'i' /* rename and insert a field */
- X#define FM_DEL_INSERT 'I' /* delete and insert a field */
- X#define FM_FIRST_UNIQ 'u' /* preserve the first occurrence */
- X#define FM_LAST_UNIQ 'U' /* preserve the last occurrence */
- X#define FM_ReNAME 'R' /* rename a field */
- X#define FM_USAGE "\
- XUsage: formail [-bcfrktq] [-D nnn idcache] [-p prefix] [-l folder]\n\
- X\t[-xXaAiIuU field] [-R ofield nfield]\n\
- X Or: formail [+nnn] [-nnn] [-bcfrktnedqB] [-D nnn idcache] [-p prefix]\n\
- X\t[-m nnn] [-l folder] [-xXaAiIuU field] [-R ofield nfield]\n\
- X\t-s [prg [arg ...]]\n"
- X#define FM_HELP \
- X " -b\t\tdon't escape bogus mailbox headers\
- X\n -c\t\tconcatenate continued header-fields\
- X\n -f\t\tforce formail to pass along any non-mailbox format\
- X\n -r\t\tgenerate an auto-reply header, preserve fields with -i\
- X\n -k\t\ton auto-reply keep the body, prevent escaping with -b\
- X\n -t\t\ttrust the sender for his return address\
- X\n -l folder\tgenerate a procmail-compatible log summary\
- X\n -D nnn idcache\tdetect duplicates with an idcache of length nnn\
- X\n -s prg arg\tsplit the mail, startup prg for every message\
- X\n +nnn\t\tskip the first nnn\t-nnn\toutput at most nnn messages\
- X\n -n\t\tdon't serialise splits\t-e\tempty lines are optional\
- X\n -d\t\taccept digest format\t-B\texpect BABYL rmail format\
- X\n -q\t\tbe quiet\t\t-p prefix\tquotation prefix\
- X\n -m nnn \tmin fields threshold (default 2) for start of message\
- X\n -x field\textract contents\t-X field\textract fully\
- X\n -a field\tadd if not present\t-A field\tadd in any case\
- X\n -i field\trename and insert\t-I field\tdelete and insert\
- X\n -u field\tfirst unique\t\t-U field\tlast unique\
- X\n -R oldfield newfield\trename\n"
- END_OF_FILE
- if test 14070 -ne `wc -c <'procmail-3.03/config.h'`; then
- echo shar: \"'procmail-3.03/config.h'\" unpacked with wrong size!
- fi
- # end of 'procmail-3.03/config.h'
- fi
- if test -f 'procmail-3.03/src/locking.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'procmail-3.03/src/locking.c'\"
- else
- echo shar: Extracting \"'procmail-3.03/src/locking.c'\" \(7423 characters\)
- sed "s/^X//" >'procmail-3.03/src/locking.c' <<'END_OF_FILE'
- X/************************************************************************
- X * Whatever is needed for (un)locking files in various ways *
- X * *
- X * Copyright (c) 1990-1994, S.R. van den Berg, The Netherlands *
- X * #include "../README" *
- X ************************************************************************/
- X#ifdef RCS
- Xstatic /*const*/char rcsid[]=
- X "$Id: locking.c,v 1.40 1994/06/28 16:56:23 berg Exp $";
- X#endif
- X#include "procmail.h"
- X#include "robust.h"
- X#include "shell.h"
- X#include "misc.h"
- X#include "pipes.h"
- X#include "exopen.h"
- X#include "locking.h"
- X
- Xvoid lockit(name,lockp)char*name;char**const lockp;
- X{ int permanent=nfsTRY,triedforce=0,locktype=doLOCK;struct stat stbuf;time_t t;
- X zombiecollect();
- X if(*lockp)
- X { if(!strcmp(name,*lockp)) /* compare the previous lockfile to this one */
- X return; /* they're equal, save yourself some effort */
- X unlock(lockp); /* unlock any previous lockfile FIRST */
- X } /* to prevent deadlocks (I hate deadlocks) */
- X if(!*name)
- X return;
- X if(!strcmp(name,defdeflock)) /* is it the system mailbox lockfile? */
- X { locktype=doCHECK|doLOCK;
- X#ifndef fdlock
- X if(!accspooldir)
- X { yell("Bypassed locking",name);
- X return;
- X }
- X else
- X#endif
- X setegid(sgid); /* try and get some extra permissions */
- X }
- X name=tstrdup(name); /* allocate now, so we won't hang on memory *and* lock */
- X for(lcking|=lck_LOCKFILE;;)
- X { yell("Locking",name); /* in order to cater for clock skew: get */
- X if(!xcreat(name,LOCKperm,&t,locktype)) /* time t from the filesystem */
- X { *lockp=name; /* lock acquired, hurray! */
- X break;
- X }
- X switch(errno)
- X { case EEXIST: /* check if it's time for a lock override */
- X if(!lstat(name,&stbuf)&&stbuf.st_size<=MAX_locksize&&locktimeout
- X &&!lstat(name,&stbuf)&&locktimeout<t-stbuf.st_mtime)
- X /*
- X * stat() till unlink() should be atomic, but can't guarantee that
- X */
- X { if(triedforce) /* already tried, not trying */
- X goto faillock; /* again */
- X if(S_ISDIR(stbuf.st_mode)||unlink(name))
- X triedforce=1,nlog("Forced unlock denied on"),logqnl(name);
- X else
- X { nlog("Forcing lock on");logqnl(name);suspend();
- X goto ce;
- X }
- X }
- X else
- X triedforce=0; /* legitimate iteration, clear flag */
- X break;
- X case ENOSPC: /* no space left, treat it as a transient */
- X#ifdef EDQUOT /* NFS failure */
- X case EDQUOT: /* maybe it was a short term shortage? */
- X#endif
- X case ENOENT:case ENOTDIR:case EIO:case EACCES:
- X if(--permanent)
- X goto ds;
- X goto faillock;
- X#ifdef ENAMETOOLONG
- X case ENAMETOOLONG: /* maybe filename too long, shorten and retry */
- X { int i;
- X if(0<(i=strlen(name)-1)&&!strchr(dirsep,name[i-1]))
- X { nlog("Truncating");logqnl(name);elog(" and retrying lock\n");
- X name[i]='\0';permanent=nfsTRY;
- X goto ce;
- X }
- X }
- X#endif
- X default:
- Xfaillock: nlog("Lock failure on");logqnl(name);
- X goto term;
- X }
- X permanent=nfsTRY;
- Xds: ssleep((unsigned)locksleep);
- Xce: if(nextexit)
- Xterm: { free(name); /* drop the preallocated buffer */
- X break;
- X }
- X }
- X if(rcstate==rc_NORMAL) /* we already set our ids */
- X setegid(gid); /* we put back our regular permissions */
- X lcking&=~lck_LOCKFILE;
- X if(nextexit)
- X elog(whilstwfor),elog("lockfile"),logqnl(name),Terminate();
- X}
- X
- Xvoid lcllock P((void)) /* lock a local lockfile */
- X{ char*lckfile; /* locking /dev/null or | would be silly */
- X if(tolock||strcmp(buf2,devnull)&&strcmp(buf2,"|"))
- X { lckfile=tolock?tolock:strcat(buf2,lockext);
- X if(globlock&&!strcmp(lckfile,globlock)) /* same as global lockfile? */
- X nlog("Deadlock attempted on"),logqnl(lckfile);
- X else
- X lockit(lckfile,&loclock);
- X }
- X}
- X
- Xvoid unlock(lockp)char**const lockp;
- X{ lcking|=lck_LOCKFILE;
- X if(*lockp)
- X { if(!strcmp(*lockp,defdeflock)) /* is it the system mailbox lockfile? */
- X setegid(sgid); /* try and get some extra permissions */
- X yell("Unlocking",*lockp);
- X if(unlink(*lockp))
- X nlog("Couldn't unlock"),logqnl(*lockp);
- X if(rcstate==rc_NORMAL) /* we already set our ids */
- X setegid(gid); /* we put back our regular permissions */
- X if(!nextexit) /* if not inside a signal handler */
- X free(*lockp);
- X *lockp=0;
- X }
- X offguard();
- X}
- X /* an NFS secure exclusive file open */
- Xint xcreat(name,mode,tim,chownit)const char*const name;const mode_t mode;
- X time_t*const tim;const int chownit;
- X{ char*p;int j= -2;size_t i;
- X i=lastdirsep(name)-name;strncpy(p=malloc(i+UNIQnamelen),name,i);
- X if(unique(p,p+i,mode,verbose,chownit)) /* try & rename the unique filename */
- X { if(tim)
- X { struct stat stbuf; /* return the filesystem time to the caller */
- X stat(p,&stbuf);*tim=stbuf.st_mtime;
- X }
- X j=myrename(p,name);
- X }
- X free(p);
- X return j;
- X}
- X /* if you've ever wondered what conditional compilation was good for */
- X#ifndef fdlock /* watch closely :-) */
- X#ifdef USEflock
- X#ifndef SYS_FILE_H_MISSING
- X#include <sys/file.h>
- X#endif
- X#define REITflock 1
- X#else
- X#define REITflock 0
- X#endif /* USEflock */
- Xstatic oldfdlock= -1; /* the fd we locked last */
- X#ifndef NOfcntl_lock
- Xstatic struct flock flck; /* why can't it be a local variable? */
- X#define REITfcntl 1
- X#else
- X#define REITfcntl 0
- X#endif /* NOfcntl_lock */
- X#ifdef USElockf
- Xstatic off_t oldlockoffset;
- X#define REITlockf 1
- X#else
- X#define REITlockf 0
- X#endif /* USElockf */
- X
- Xint fdlock(fd)
- X{ int ret;
- X if(verbose)
- X nlog("Acquiring kernel-lock\n");
- X#if REITfcntl+REITflock+REITlockf>1
- X for(;!toutflag;verbose&&(nlog("Reiterating kernel-lock\n"),0),
- X ssleep((unsigned)locksleep))
- X#endif
- X { zombiecollect();
- X#ifndef NOfcntl_lock
- X flck.l_type=F_WRLCK;flck.l_whence=SEEK_SET;flck.l_len=0;
- X flck.l_start=tell(fd);
- X#endif
- X#ifdef USElockf
- X oldlockoffset=tell(fd);
- X#endif
- X lcking|=lck_KERNEL;
- X#ifndef NOfcntl_lock
- X ret=fcntl(fd,F_SETLKW,&flck);
- X#ifdef USElockf
- X if((ret|=lockf(fd,F_TLOCK,(off_t)0))&&(errno==EAGAIN||errno==EACCES||
- X errno==EWOULDBLOCK))
- Xufcntl:
- X { flck.l_type=F_UNLCK;fcntl(fd,F_SETLK,&flck);
- X continue;
- X }
- X#ifdef USEflock
- X if((ret|=flock(fd,LOCK_EX|LOCK_NB))&&(errno==EAGAIN||errno==EACCES||
- X errno==EWOULDBLOCK))
- X { lockf(fd,F_ULOCK,(off_t)0);
- X goto ufcntl;
- X }
- X#endif /* USEflock */
- X#else /* USElockf */
- X#ifdef USEflock
- X if((ret|=flock(fd,LOCK_EX|LOCK_NB))&&(errno==EAGAIN||errno==EACCES||
- X errno==EWOULDBLOCK))
- X { flck.l_type=F_UNLCK;fcntl(fd,F_SETLK,&flck);
- X continue;
- X }
- X#endif /* USEflock */
- X#endif /* USElockf */
- X#else /* NOfcntl_lock */
- X#ifdef USElockf
- X ret=lockf(fd,F_LOCK,(off_t)0);
- X#ifdef USEflock
- X if((ret|=flock(fd,LOCK_EX|LOCK_NB))&&(errno==EAGAIN||errno==EACCES||
- X errno==EWOULDBLOCK))
- X { lockf(fd,F_ULOCK,(off_t)0);
- X continue;
- X }
- X#endif /* USEflock */
- X#else /* USElockf */
- X#ifdef USEflock
- X ret=flock(fd,LOCK_EX);
- X#endif /* USEflock */
- X#endif /* USElockf */
- X#endif /* NOfcntl_lock */
- X oldfdlock=fd;lcking&=~lck_KERNEL;
- X return ret;
- X }
- X}
- X
- Xint fdunlock P((void))
- X{ int i;
- X if(oldfdlock<0)
- X return -1;
- X i=0;
- X#ifdef USEflock
- X i|=flock(oldfdlock,LOCK_UN);
- X#endif
- X#ifdef USElockf
- X lseek(oldfdlock,oldlockoffset,SEEK_SET);i|=lockf(oldfdlock,F_ULOCK,(off_t)0);
- X#endif
- X#ifndef NOfcntl_lock
- X flck.l_type=F_UNLCK;i|=fcntl(oldfdlock,F_SETLK,&flck);
- X#endif
- X oldfdlock= -1;
- X return i;
- X}
- X#endif /* fdlock */
- END_OF_FILE
- if test 7423 -ne `wc -c <'procmail-3.03/src/locking.c'`; then
- echo shar: \"'procmail-3.03/src/locking.c'\" unpacked with wrong size!
- fi
- # end of 'procmail-3.03/src/locking.c'
- fi
- if test -f 'procmail-3.03/src/mailfold.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'procmail-3.03/src/mailfold.c'\"
- else
- echo shar: Extracting \"'procmail-3.03/src/mailfold.c'\" \(14078 characters\)
- sed "s/^X//" >'procmail-3.03/src/mailfold.c' <<'END_OF_FILE'
- X/************************************************************************
- X * Routines that deal with the mailfolder(format) *
- X * *
- X * Copyright (c) 1990-1994, S.R. van den Berg, The Netherlands *
- X * #include "../README" *
- X ************************************************************************/
- X#ifdef RCS
- Xstatic /*const*/char rcsid[]=
- X "$Id: mailfold.c,v 1.49 1994/06/28 16:56:26 berg Exp $";
- X#endif
- X#include "procmail.h"
- X#include "acommon.h"
- X#include "sublib.h"
- X#include "robust.h"
- X#include "shell.h"
- X#include "misc.h"
- X#include "pipes.h"
- X#include "common.h"
- X#include "exopen.h"
- X#include "goodies.h"
- X#include "locking.h"
- X#include "mailfold.h"
- X#ifndef NO_COMSAT
- X#include "network.h"
- X#endif
- X
- Xint logopened,tofile;
- Xoff_t lasttell;
- Xstatic long lastdump;
- Xstatic volatile mailread; /* if the mail is completely read in already */
- Xstatic struct dyna_long escFrom_,confield; /* escapes, concatenations */
- X /* inserts escape characters on outgoing mail */
- Xstatic long getchunk(s,fromw,len)const int s;const char*fromw;const long len;
- X{ long dist,dif;int i;static const char esc[]=ESCAP;
- X dist=fromw-themail; /* where are we now in transmitting? */
- X for(dif=len,i=0;i<escFrom_.filled;) /* let's see if we can find this */
- X if(!(dif=escFrom_.offs[i++]-dist)) /* this exact spot? */
- X { rwrite(s,esc,STRLEN(esc));lastdump++; /* escape it */
- X if(i>=escFrom_.filled) /* last block? */
- X return len; /* yes, give all what's left */
- X dif=escFrom_.offs[i]-dist; /* the whole next block */
- X break;
- X }
- X else if(dif>0) /* passed this spot already? */
- X break;
- X return dif<len?dif:len;
- X}
- X
- Xlong dump(s,source,len)const int s;const char*source;long len;
- X{ int i;long part;
- X lasttell=i= -1;
- X if(s>=0)
- X { if(tofile&&(lseek(s,(off_t)0,SEEK_END),fdlock(s)))
- X nlog("Kernel-lock failed\n");
- X lastdump=len;part=tofile==to_FOLDER?getchunk(s,source,len):len;
- X lasttell=lseek(s,(off_t)0,SEEK_END);smboxseparator(s); /* optional */
- X#ifndef NO_NFS_ATIME_HACK /* separator */
- X if(part&&tofile) /* if it is a file, trick NFS into an */
- X len--,part--,rwrite(s,source++,1),ssleep(1); /* a_time<m_time */
- X#endif
- X goto jin;
- X do
- X { part=getchunk(s,source,len);
- Xjin: while(part&&(i=rwrite(s,source,BLKSIZ<part?BLKSIZ:(int)part)))
- X { if(i<0)
- X goto writefin;
- X part-=i;len-=i;source+=i;
- X }
- X }
- X while(len);
- X if(!len&&(lastdump<2||!(source[-1]=='\n'&&source[-2]=='\n')))
- X lastdump++,rwrite(s,newline,1); /* message always ends with a */
- X emboxseparator(s); /* newline and an optional custom separator */
- Xwritefin:
- X if(tofile&&fdunlock())
- X nlog("Kernel-unlock failed\n");
- X i=rclose(s);
- X } /* return an error even if nothing was to be sent */
- X tofile=0;
- X return i&&!len?-1:len;
- X}
- X
- Xstatic int dirfile(chp,linkonly)char*const chp;const int linkonly;
- X{ const static char lkingto[]="Linking to";
- X if(chp)
- X { long i=0; /* first let us try to prime i with the */
- X#ifndef NOopendir /* highest MH folder number we can find */
- X long j;DIR*dirp;struct dirent*dp;char*chp2;
- X if(dirp=opendir(buf))
- X { while(dp=readdir(dirp)) /* there still are directory entries */
- X if((j=strtol(dp->d_name,&chp2,10))>i&&!*chp2)
- X i=j; /* yep, we found a higher number */
- X closedir(dirp); /* aren't we neat today */
- X }
- X else
- X readerr(buf);
- X#endif /* NOopendir */
- X ;{ int ok;
- X do ultstr(0,++i,chp); /* find first empty MH folder */
- X while((ok=linkonly?link(buf2,buf):hlink(buf2,buf))&&errno==EEXIST);
- X if(linkonly)
- X { yell(lkingto,buf);
- X if(ok)
- X goto nolnk;
- X goto ret;
- X }
- X }
- X unlink(buf2);
- X goto opn;
- X }
- X ;{ struct stat stbuf;
- X stat(buf2,&stbuf);
- X ultoan((unsigned long)stbuf.st_ino, /* filename with i-node number */
- X strchr(strcat(buf,msgprefix),'\0'));
- X }
- X if(linkonly)
- X { yell(lkingto,buf);
- X if(link(buf2,buf)) /* hardlink the new file, it's a directory folder */
- Xnolnk: nlog("Couldn't make link to"),logqnl(buf);
- X goto ret;
- X }
- X if(!rename(buf2,buf)) /* rename it, we need the same i-node */
- Xopn: return opena(buf);
- Xret:
- X return -1;
- X}
- X
- Xstatic int ismhdir(chp)char*const chp;
- X{ if(chp-1>=buf&&chp[-1]==*MCDIRSEP_&&*chp==chCURDIR)
- X { chp[-1]='\0';
- X return 1;
- X }
- X return 0;
- X}
- X /* open file or new file in directory */
- Xint deliver(boxname,linkfolder)char*boxname,*linkfolder;
- X{ struct stat stbuf;char*chp;int mhdir;mode_t numask;
- X asgnlastf=1;
- X if(*boxname=='|'&&(!linkfolder||linkfolder==Tmnate))
- X { setlastfolder(boxname);
- X return rdup(savstdout);
- X }
- X numask=UPDATE_MASK&~cumask;tofile=to_FILE;
- X if(boxname!=buf)
- X strcpy(buf,boxname); /* boxname can be found back in buf */
- X if(*(chp=buf)) /* not null length target? */
- X chp=strchr(buf,'\0')-1; /* point to just before the end */
- X mhdir=ismhdir(chp); /* is it an MH folder? */
- X if(!stat(boxname,&stbuf)) /* it exists */
- X { if(numask&&!(stbuf.st_mode&UPDATE_MASK))
- X chmod(boxname,stbuf.st_mode|UPDATE_MASK);
- X if(!S_ISDIR(stbuf.st_mode)) /* it exists and is not a directory */
- X goto makefile; /* no, create a regular file */
- X }
- X else if(!mhdir||mkdir(buf,NORMdirperm)) /* shouldn't it be a directory? */
- Xmakefile:
- X { if(linkfolder) /* any leftovers? Now is the time to display them */
- X concatenate(linkfolder),skipped(linkfolder);
- X tofile=strcmp(devnull,buf)?to_FOLDER:0;
- X return opena(boxname);
- X }
- X if(linkfolder) /* any additional directories specified? */
- X { size_t blen;
- X if(blen=Tmnate-linkfolder) /* copy the names into safety */
- X Tmnate=(linkfolder=tmemmove(malloc(blen),linkfolder,blen))+blen;
- X else
- X linkfolder=0;
- X }
- X if(mhdir) /* buf should contain directory name */
- X *chp='\0',chp[-1]= *MCDIRSEP_,strcpy(buf2,buf); /* it ended in /. */
- X else /* fixup directory name, append a / */
- X strcat(chp,MCDIRSEP_),strcpy(buf2,buf),chp=0;
- X ;{ int fd= -1; /* generate the name for the first directory */
- X if(unique(buf2,strchr(buf2,'\0'),NORMperm,verbose,0)&&
- X (fd=dirfile(chp,0))>=0&&linkfolder) /* save the file descriptor */
- X for(strcpy(buf2,buf),boxname=linkfolder;boxname!=Tmnate;)
- X { strcpy(buf,boxname); /* go through the list of other dirs */
- X if(*(chp=buf))
- X chp=strchr(buf,'\0')-1;
- X mhdir=ismhdir(chp); /* is it an MH folder? */
- X if(stat(boxname,&stbuf)) /* it doesn't exist */
- X mkdir(buf,NORMdirperm); /* create it */
- X else if(numask&&!(stbuf.st_mode&UPDATE_MASK))
- X chmod(buf,stbuf.st_mode|UPDATE_MASK);
- X if(mhdir)
- X *chp='\0',chp[-1]= *MCDIRSEP_;
- X else /* fixup directory name, append a / */
- X strcat(chp,MCDIRSEP_),chp=0;
- X dirfile(chp,1); /* link it with the original in buf2 */
- X while(*boxname++); /* skip to the next directory name */
- X }
- X if(linkfolder) /* free our cache */
- X free(linkfolder);
- X return fd; /* return the file descriptor we saved */
- X }
- X}
- X
- Xvoid logabstract(lstfolder)const char*const lstfolder;
- X{ if(lgabstract>0||logopened&&lgabstract) /* don't mail it back unrequested */
- X { char*chp,*chp2;int i;static const char sfolder[]=FOLDER;
- X if(mailread) /* is the mail completely read in? */
- X { *thebody='\0'; /* terminate the header, just in case */
- X if(eqFrom_(chp=themail)) /* any "From " header */
- X { if(chp=strchr(themail,'\n'))
- X *chp++='\0';
- X else
- X chp=thebody; /* preserve mailbox format */
- X elog(themail);elog(newline); /* (any length) */
- X }
- X if(!(lcking&lck_ALLOCLIB)&& /* don't reenter malloc/free */
- X (chp=egrepin(NSUBJECT,chp,(long)(thebody-chp),0)))
- X { for(chp2= --chp;*--chp2!='\n'&&*chp2;);
- X if(chp-++chp2>MAXSUBJECTSHOW) /* keep it within bounds */
- X chp2[MAXSUBJECTSHOW]='\0';
- X *chp='\0';detab(chp2);elog(" ");elog(chp2);elog(newline);
- X }
- X }
- X elog(sfolder);
- X i=strlen(strncpy(buf,lstfolder,MAXfoldlen))+STRLEN(sfolder);
- X buf[MAXfoldlen]='\0';detab(buf);elog(buf);i-=i%TABWIDTH; /* last dump */
- X do elog(TABCHAR);
- X while((i+=TABWIDTH)<LENoffset);
- X ultstr(7,lastdump,buf);elog(buf);elog(newline);
- X }
- X#ifndef NO_COMSAT
- X ;{ int s;struct sockaddr_in addr;char*chp,*chad; /* @ seperator? */
- X if(chad=strchr(chp=(char*)scomsat,SERV_ADDRsep))
- X *chad++='\0'; /* split it up in service and hostname */
- X else if(!renvint(-1L,chp)) /* or is it a false boolean? */
- X return; /* ok, no comsat then */
- X else
- X chp=""; /* set to yes, so take the default */
- X if(!chad||!*chad) /* no host */
- X#ifndef IP_localhost
- X chad=COMSAThost; /* use default */
- X#else /* IP_localhost */
- X { static const unsigned char ip_localhost[]=IP_localhost;
- X addr.sin_family=AF_INET;
- X tmemmove(&addr.sin_addr,ip_localhost,sizeof ip_localhost);
- X }
- X else
- X#endif /* IP_localhost */
- X { const struct hostent*host; /* what host? paranoid checks */
- X if(!(host=gethostbyname(chad))||!host->h_0addr_list)
- X { endhostent(); /* host can't be found, too bad */
- X return;
- X }
- X addr.sin_family=host->h_addrtype; /* address number found */
- X tmemmove(&addr.sin_addr,host->h_0addr_list,host->h_length);
- X endhostent();
- X }
- X if(!*chp) /* no service */
- X chp=BIFF_serviceport; /* use default */
- X s=strtol(chp,&chad,10);
- X if(chp==chad) /* the service is not numeric */
- X { const struct servent*serv;
- X if(!(serv=getservbyname(chp,COMSATprotocol))) /* so get its no. */
- X { endservent();
- X return;
- X }
- X addr.sin_port=serv->s_port;endservent();
- X }
- X else
- X addr.sin_port=htons((short)s); /* network order */
- X cat(tgetenv(lgname),"@"); /* should always fit in buf */
- X if(lasttell>=0) /* was it a file? */
- X ultstr(0,(unsigned long)lasttell,buf2),catlim(buf2); /* yep */
- X catlim(COMSATxtrsep); /* custom seperator */
- X if(lasttell>=0&&!strchr(dirsep,*lstfolder)) /* relative filename? */
- X catlim(tgetenv(maildir)),catlim(MCDIRSEP_); /* prepend current dir */
- X catlim(lstfolder);s=socket(AF_INET,SOCK_DGRAM,UDP_protocolno);
- X sendto(s,buf,strlen(buf),0,(const void*)&addr,sizeof(addr));rclose(s);
- X yell("Notified comsat:",buf);
- X }
- X#endif /* NO_COMSAT */
- X}
- X
- Xstatic int concnd; /* last concatenation value */
- X
- Xvoid concon(ch)const int ch; /* flip between concatenated and split fields */
- X{ size_t i;
- X if(concnd!=ch) /* is this run redundant? */
- X { concnd=ch; /* no, but note this one for next time */
- X for(i=confield.filled;i;) /* step through the saved offsets */
- X themail[confield.offs[--i]]=ch; /* and flip every one */
- X }
- X}
- X
- Xstatic void ffrom(chp)const char*chp;
- X{ while(chp=strstr(chp,FROM_EXPR))
- X app_val(&escFrom_,(off_t)(++chp-themail)); /* bogus From_ found! */
- X}
- X
- Xvoid readmail(rhead,tobesent)const long tobesent;
- X{ char*chp,*pastend,*realstart;static size_t contlengthoffset;
- X ;{ long dfilled;
- X if(rhead) /* only read in a new header */
- X { dfilled=mailread=0;chp=readdyn(malloc(1),&dfilled);filled-=tobesent;
- X if(tobesent<dfilled) /* adjust buffer size (grow only) */
- X { realstart=themail;
- X thebody=(themail=realloc(themail,dfilled+filled))+
- X (thebody-realstart);
- X }
- X tmemmove(themail+dfilled,thebody,filled);tmemmove(themail,chp,dfilled);
- X free(chp);themail=realloc(themail,1+(filled+=dfilled));
- X }
- X else
- X { if(!mailread||!filled)
- X rhead=1; /* yup, we read in a new header as well as new mail */
- X mailread=0;dfilled=thebody-themail;themail=readdyn(themail,&filled);
- X }
- X *(pastend=filled+(thebody=themail))='\0'; /* terminate mail */
- X while(thebody<pastend&&*thebody++=='\n'); /* skip leading garbage */
- X realstart=thebody;
- X if(rhead) /* did we read in a new header anyway? */
- X { confield.filled=0;concnd='\n';
- X while(thebody=strchr(thebody,'\n'))
- X switch(*++thebody) /* mark continuated fields */
- X { case '\t':case ' ':app_val(&confield,(off_t)(thebody-1-themail));
- X default:
- X continue; /* empty line marks end of header */
- X case '\n':thebody++;
- X goto eofheader;
- X }
- X thebody=pastend; /* provide a default, in case there is no body */
- Xeofheader:
- X contlengthoffset=0;
- X if(chp=egrepin("^Content-Length:",themail,(long)(thebody-themail),0))
- X contlengthoffset=chp-themail;
- X }
- X else /* no new header read, keep it simple */
- X thebody=themail+dfilled; /* that means we know where the body starts */
- X } /* to make sure that the first From_ line is uninjured */
- X escFrom_.filled=0;
- X ;{ int i; /* eradicate From_ in the header */
- X i= *thebody;*thebody='\0';ffrom(realstart);*thebody=i;
- X }
- X if((chp=thebody)>themail)
- X chp--;
- X if(contlengthoffset)
- X { unsigned places;long cntlen,actcntlen; /* minus one, for safety */
- X chp=themail+contlengthoffset;cntlen=filled-(thebody-themail)-1;
- X for(actcntlen=places=0;;
- X *chp++=cntlen>0?(actcntlen=actcntlen*10+9,'9'):' ',places++)
- X { switch(*chp)
- X { default: /* fill'r up, please */
- X continue;
- X case '\n':case '\0':; /* ok, end of the line */
- X }
- X break;
- X }
- X if(cntlen>0) /* any Content-Length at all? */
- X { charNUM(num,cntlen);
- X ultstr(places,cntlen,num); /* our preferred size */
- X if(!num[places]) /* does it fit in the existing space? */
- X tmemmove(chp-places,num,places),actcntlen=cntlen; /* yup */
- X chp=thebody+actcntlen; /* skip the actual no we specified */
- X }
- X }
- X ffrom(chp);mailread=1; /* eradicate From_ in the rest of the body */
- X}
- X
- Xchar*findtstamp(start,end)const char*start,*end;
- X{ start=skpspace(start);start+=strcspn(start," \t\n");
- X if(skpspace(start)>=(end-=25))
- X return (char*)start;
- X while(!(end[13]==':'&&end[15]==':')&&--end>start);
- X ;{ int spc=0;
- X while(end-->start)
- X { switch(*end)
- X { case ' ':case '\t':spc=1;
- X continue;
- X }
- X if(!spc)
- X continue;
- X break;
- X }
- X return (char*)end+1;
- X }
- X}
- END_OF_FILE
- if test 14078 -ne `wc -c <'procmail-3.03/src/mailfold.c'`; then
- echo shar: \"'procmail-3.03/src/mailfold.c'\" unpacked with wrong size!
- fi
- # end of 'procmail-3.03/src/mailfold.c'
- fi
- if test -f 'procmail-3.03/src/misc.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'procmail-3.03/src/misc.c'\"
- else
- echo shar: Extracting \"'procmail-3.03/src/misc.c'\" \(14083 characters\)
- sed "s/^X//" >'procmail-3.03/src/misc.c' <<'END_OF_FILE'
- X/************************************************************************
- X * Miscellaneous routines used by procmail *
- X * *
- X * Copyright (c) 1990-1994, S.R. van den Berg, The Netherlands *
- X * #include "../README" *
- X ************************************************************************/
- X#ifdef RCS
- Xstatic /*const*/char rcsid[]=
- X "$Id: misc.c,v 1.55 1994/06/28 16:56:31 berg Exp $";
- X#endif
- X#include "procmail.h"
- X#include "acommon.h"
- X#include "sublib.h"
- X#include "robust.h"
- X#include "misc.h"
- X#include "pipes.h"
- X#include "common.h"
- X#include "cstdio.h"
- X#include "exopen.h"
- X#include "regexp.h"
- X#include "mcommon.h"
- X#include "goodies.h"
- X#include "locking.h"
- X#include "mailfold.h"
- X
- Xstruct varval strenvvar[]={{"LOCKSLEEP",DEFlocksleep},
- X {"LOCKTIMEOUT",DEFlocktimeout},{"SUSPEND",DEFsuspend},
- X {"NORESRETRY",DEFnoresretry},{"TIMEOUT",DEFtimeout},{"VERBOSE",DEFverbose},
- X {"LOGABSTRACT",DEFlogabstract}};
- Xstruct varstr strenstr[]={{"SHELLMETAS",DEFshellmetas},{"LOCKEXT",DEFlockext},
- X {"MSGPREFIX",DEFmsgprefix},{"COMSAT",""},{"TRAP",""},
- X {"SHELLFLAGS",DEFshellflags},{"DEFAULT",DEFdefault},{"SENDMAIL",DEFsendmail}};
- X
- X#define MAXvarvals maxindex(strenvvar)
- X#define MAXvarstrs maxindex(strenstr)
- X
- Xconst char lastfolder[]="LASTFOLDER";
- Xint didchd;
- Xchar*globlock;
- Xstatic time_t oldtime;
- Xstatic int fakedelivery;
- X /* line buffered to keep concurrent entries untangled */
- Xvoid elog(newt)const char*const newt;
- X{ int lnew;size_t i;static lold;static char*old;char*p;
- X#ifndef O_CREAT
- X lseek(STDERR,(off_t)0,SEEK_END); /* locking should be done actually */
- X#endif
- X if(!(lnew=strlen(newt))||nextexit) /* force flush? */
- X goto flush;
- X i=lold+lnew;
- X if(p=lold?realloc(old,i):malloc(i)) /* unshelled malloc */
- X { memmove((old=p)+lold,newt,(size_t)lnew); /* append */
- X if(p[(lold=i)-1]=='\n') /* EOL? */
- X rwrite(STDERR,p,(int)i),lold=0,free(p); /* flush the line(s) */
- X }
- X else /* no memory, force flush */
- Xflush:
- X { if(lold)
- X { rwrite(STDERR,old,lold);lold=0;
- X if(!nextexit)
- X free(old); /* don't use free in signal handlers */
- X }
- X if(lnew)
- X rwrite(STDERR,newt,lnew);
- X }
- X}
- X
- X#include "shell.h"
- X
- Xvoid ignoreterm P((void))
- X{ signal(SIGTERM,SIG_IGN);signal(SIGHUP,SIG_IGN);signal(SIGINT,SIG_IGN);
- X signal(SIGQUIT,SIG_IGN);
- X}
- X
- Xvoid shutdesc P((void))
- X{ rclose(savstdout);closelog();closerc();
- X}
- X
- Xvoid setids P((void))
- X{ if(rcstate!=rc_NORMAL)
- X { if(setrgid(gid)) /* due to these !@#$%^&*() POSIX semantics, setgid() */
- X setgid(gid); /* sets the saved gid as well; we can't use that! */
- X setruid(uid);setuid(uid);setegid(gid);rcstate=rc_NORMAL;
- X#if !DEFverbose
- X verbose=0;
- X#endif
- X }
- X}
- X
- Xvoid writeerr(line)const char*const line;
- X{ nlog(errwwriting);logqnl(line);
- X}
- X
- Xint forkerr(pid,a)const pid_t pid;const char*const a;
- X{ if(pid==-1)
- X { nlog("Failed forking");logqnl(a);
- X return 1;
- X }
- X return 0;
- X}
- X
- Xvoid progerr(line,xitcode)const char*const line;int xitcode;
- X{ charNUM(num,thepid);
- X nlog("Program failure (");
- X if(xitcode<0)
- X xitcode= -xitcode,elog("-");
- X ultstr(0,(unsigned long)xitcode,num);elog(num);
- X elog(") of");logqnl(line);
- X}
- X
- Xvoid chderr(dir)const char*const dir;
- X{ nlog("Couldn't chdir to");logqnl(dir);
- X}
- X
- Xvoid readerr(file)const char*const file;
- X{ nlog("Couldn't read");logqnl(file);
- X}
- X
- Xvoid verboff P((void))
- X{ verbose=0;
- X#ifdef SIGUSR1
- X qsignal(SIGUSR1,(void(*)())verboff);
- X#endif
- X}
- X
- Xvoid verbon P((void))
- X{ verbose=1;
- X#ifdef SIGUSR2
- X qsignal(SIGUSR2,(void(*)())verbon);
- X#endif
- X}
- X
- Xvoid yell(a,b)const char*const a,*const b; /* log if VERBOSE=on */
- X{ if(verbose)
- X nlog(a),logqnl(b);
- X}
- X
- Xvoid newid P((void))
- X{ thepid=getpid();oldtime=0;
- X}
- X
- Xvoid zombiecollect P((void))
- X{ while(waitpid((pid_t)-1,(int*)0,WNOHANG)>0); /* collect any zombies */
- X}
- X
- Xvoid nlog(a)const char*const a;
- X{ time_t newtime;
- X static const char colnsp[]=": ";
- X elog(procmailn);elog(colnsp);
- X if(verbose&&oldtime!=(newtime=time((time_t*)0)))
- X { charNUM(num,thepid);
- X elog("[");oldtime=newtime;ultstr(0,(unsigned long)thepid,num);elog(num);
- X elog("] ");elog(ctime(&oldtime));elog(procmailn);elog(colnsp);
- X }
- X elog(a);
- X}
- X
- Xvoid logqnl(a)const char*const a;
- X{ elog(oquote);elog(a);elog(cquote);
- X}
- X
- Xvoid skipped(x)const char*const x;
- X{ if(*x)
- X nlog("Skipped"),logqnl(x);
- X}
- X
- Xint nextrcfile P((void)) /* next rcfile specified on the command line */
- X{ const char*p;int rval=2;
- X while(p= *gargv)
- X { gargv++;
- X if(!strchr(p,'='))
- X { rcfile=p;
- X return rval;
- X }
- X rval=1; /* not the first argument encountered */
- X }
- X return 0;
- X}
- X
- Xvoid onguard P((void))
- X{ lcking|=lck_LOCKFILE;
- X}
- X
- Xvoid offguard P((void))
- X{ lcking&=~lck_LOCKFILE;
- X if(nextexit==1) /* make sure we are not inside Terminate() already */
- X elog(newline),Terminate();
- X}
- X
- Xvoid sterminate P((void))
- X{ static const char*const msg[]={"memory","fork", /* crosscheck with */
- X "a file descriptor","a kernel-lock"}; /* lck_ defs in procmail.h */
- X ignoreterm();
- X if(pidchild>0) /* don't kill what is not ours, we might be root */
- X kill(pidchild,SIGTERM);
- X if(!nextexit)
- X { nextexit=1;nlog("Terminating prematurely");
- X if(!(lcking&lck_LOCKFILE))
- X { register unsigned i,j;
- X if(i=(lcking&~(lck_ALLOCLIB|lck_LOCKFILE))>>1)
- X { elog(whilstwfor);
- X for(j=0;!((i>>=1)&1);j++);
- X elog(msg[j]);
- X }
- X elog(newline);Terminate();
- X }
- X }
- X}
- X
- Xvoid Terminate P((void))
- X{ ignoreterm();
- X if(retvl2!=EX_OK)
- X fakedelivery=0,retval=retvl2;
- X if(getpid()==thepid)
- X { if(retval!=EX_OK)
- X { tofile=0;lasttell= -1; /* mark it for logabstract */
- X logabstract(fakedelivery?"**Lost**":
- X retval==EX_TEMPFAIL?"**Requeued**":"**Bounced**");
- X }
- X else
- X logabstract(tgetenv(lastfolder));
- X shutdesc();
- X if(!(lcking&lck_ALLOCLIB)) /* don't reenter malloc/free */
- X exectrap(traps);
- X nextexit=2;unlock(&loclock);unlock(&globlock);fdunlock();
- X } /* flush the logfile & exit procmail */
- X elog("");exit(fakedelivery==2?EX_OK:retval);
- X}
- X
- Xvoid suspend P((void))
- X{ ssleep((unsigned)suspendv);
- X}
- X
- Xvoid app_val(sp,val)struct dyna_long*const sp;const off_t val;
- X{ if(sp->filled==sp->tspace) /* growth limit reached? */
- X { if(!sp->offs)
- X sp->offs=malloc(1);
- X sp->offs=realloc(sp->offs,(sp->tspace+=4)*sizeof sp->offs); /* expand */
- X }
- X sp->offs[sp->filled++]=val; /* append to it */
- X}
- X
- Xint alphanum(c)const unsigned c;
- X{ return numeric(c)||c-'a'<='z'-'a'||c-'A'<='Z'-'A'||c=='_';
- X}
- X
- Xvoid firstchd P((void))
- X{ if(!didchd) /* have we been here already? */
- X { const char*p;
- X didchd=1; /* no, well, then try an initial chdir */
- X if(chdir(p=tgetenv(maildir)))
- X { chderr(p);
- X if(chdir(p=tgetenv(home)))
- X chderr(p);
- X }
- X }
- X}
- X
- Xvoid srequeue P((void))
- X{ retval=EX_TEMPFAIL;sterminate();
- X}
- X
- Xvoid slose P((void))
- X{ fakedelivery=2;sterminate();
- X}
- X
- Xvoid sbounce P((void))
- X{ retval=EX_CANTCREAT;sterminate();
- X}
- X
- Xvoid catlim(src)register const char*src;
- X{ register char*dest=buf;register size_t lim=linebuf;
- X while(lim&&*dest)
- X dest++,lim--;
- X if(lim)
- X { while(--lim&&(*dest++= *src++));
- X *dest='\0';
- X }
- X}
- X
- Xvoid setdef(name,contents)const char*const name,*const contents;
- X{ strcat(strcat(strcpy((char*)(sgetcp=buf2),name),"="),contents);
- X readparse(buf,sgetc,2);sputenv(buf);
- X}
- X
- Xvoid metaparse(p)const char*p; /* result in buf */
- X{ if(sh=!!strpbrk(p,shellmetas))
- X strcpy(buf,p); /* copy literally, shell will parse */
- X else
- X#ifndef GOT_bin_test
- X { sgetcp=p=tstrdup(p);
- X readparse(buf,sgetc,0); /* parse it yourself */
- X if(!strcmp(test,buf))
- X strcpy(buf,p),sh=1; /* oops, `test' found */
- X free((char*)p);
- X }
- X#else
- X sgetcp=p,readparse(buf,sgetc,0);
- X#endif
- X}
- X
- Xvoid concatenate(p)register char*p;
- X{ while(p!=Tmnate) /* concatenate all other arguments */
- X { while(*p++);
- X p[-1]=' ';
- X }
- X *p=p[-1]='\0';
- X}
- X
- Xchar*lastdirsep(filename)const char*filename; /* finds the next character */
- X{ const char*p; /* following the last DIRSEP */
- X while(p=strpbrk(filename,dirsep))
- X filename=p+1;
- X return (char*)filename;
- X}
- X
- Xchar*cat(a,b)const char*const a,*const b;
- X{ return strcat(strcpy(buf,a),b);
- X}
- X
- Xchar*tstrdup(a)const char*const a;
- X{ int i;
- X i=strlen(a)+1;
- X return tmemmove(malloc(i),a,i);
- X}
- X
- Xconst char*tgetenv(a)const char*const a;
- X{ const char*b;
- X return (b=getenv(a))?b:"";
- X}
- X
- Xchar*cstr(a,b)char*const a;const char*const b; /* dynamic buffer management */
- X{ if(a)
- X free(a);
- X return tstrdup(b);
- X}
- X
- Xvoid setlastfolder(folder)const char*const folder;
- X{ if(asgnlastf)
- X { char*chp;
- X asgnlastf=0;
- X strcpy(chp=malloc(STRLEN(lastfolder)+1+strlen(folder)+1),lastfolder);
- X chp[STRLEN(lastfolder)]='=';strcpy(chp+STRLEN(lastfolder)+1,folder);
- X sputenv(chp);free(chp);
- X }
- X}
- X
- Xchar*gobenv(chp)char*chp;
- X{ int found,i;
- X found=0;
- X if(alphanum(i=getb())&&!numeric(i))
- X for(found=1;*chp++=i,alphanum(i=getb()););
- X *chp='\0';ungetb(i);
- X switch(i)
- X { case ' ':case '\t':case '\n':case '=':
- X if(found)
- X return chp;
- X }
- X return 0;
- X}
- X
- Xint asenvcpy(src)char*src;
- X{ strcpy(buf,src);
- X if(src=strchr(buf,'=')) /* is it an assignment? */
- X { const char*chp;
- X strcpy((char*)(sgetcp=buf2),++src);readparse(src,sgetc,2);
- X chp=sputenv(buf);src[-1]='\0';asenv(chp);
- X return 1;
- X }
- X return 0;
- X}
- X
- Xvoid asenv(chp)const char*const chp;
- X{ static const char slinebuf[]="LINEBUF",logfile[]="LOGFILE",Log[]="LOG",
- X sdelivered[]="DELIVERED",includerc[]="INCLUDERC",eumask[]="UMASK",
- X dropprivs[]="DROPPRIVS",shift[]="SHIFT";
- X if(!strcmp(buf,slinebuf))
- X { if((linebuf=renvint(0L,chp)+XTRAlinebuf)<MINlinebuf+XTRAlinebuf)
- X linebuf=MINlinebuf+XTRAlinebuf; /* check minimum size */
- X free(buf);free(buf2);buf=malloc(linebuf);buf2=malloc(linebuf);
- X }
- X else if(!strcmp(buf,maildir))
- X if(chdir(chp))
- X chderr(chp);
- X else
- X didchd=1;
- X else if(!strcmp(buf,logfile))
- X opnlog(chp);
- X else if(!strcmp(buf,Log))
- X elog(chp);
- X else if(!strcmp(buf,exitcode))
- X setxit=1;
- X else if(!strcmp(buf,shift))
- X { int i;
- X if((i=renvint(0L,chp))>0)
- X { if(i>crestarg)
- X i=crestarg;
- X crestarg-=i;restargv+=i; /* shift away arguments */
- X }
- X }
- X else if(!strcmp(buf,dropprivs)) /* drop privileges */
- X { if(renvint(0L,chp))
- X setids();
- X }
- X else if(!strcmp(buf,sdelivered)) /* fake delivery */
- X { if(renvint(0L,chp)) /* is it really? */
- X { onguard();
- X if((thepid=sfork())>0) /* signals may cause trouble */
- X nextexit=2,lcking&=~lck_LOCKFILE,exit(retvl2);
- X if(!forkerr(thepid,procmailn))
- X fakedelivery=1;
- X newid();offguard();
- X }
- X }
- X else if(!strcmp(buf,lockfile))
- X lockit((char*)chp,&globlock);
- X else if(!strcmp(buf,eumask))
- X doumask((mode_t)strtol(chp,(char**)0,8));
- X else if(!strcmp(buf,includerc))
- X pushrc(chp);
- X else if(!strcmp(buf,host))
- X { const char*name;
- X if(strcmp(chp,name=hostname()))
- X { yell("HOST mismatched",name);
- X if(rc<0||!nextrcfile()) /* if no rcfile opened yet */
- X retval=EX_OK,Terminate(); /* exit gracefully as well */
- X closerc();
- X }
- X }
- X else
- X { int i=MAXvarvals;
- X do /* several numeric assignments */
- X if(!strcmp(buf,strenvvar[i].name))
- X strenvvar[i].val=renvint(strenvvar[i].val,chp);
- X while(i--);
- X i=MAXvarstrs;
- X do /* several text assignments */
- X if(!strcmp(buf,strenstr[i].sname))
- X strenstr[i].sval=chp;
- X while(i--);
- X }
- X}
- X
- Xlong renvint(i,env)const long i;const char*const env;
- X{ const char*p;long t;
- X t=strtol(env,(char**)&p,10); /* parse like a decimal nr */
- X if(p==env)
- X { for(;;p++) /* skip leading whitespace */
- X { switch(*p)
- X { case '\t':case ' ':
- X continue;
- X }
- X break;
- X }
- X t=i;
- X if(!strnIcmp(p,"on",(size_t)2)||!strnIcmp(p,"y",(size_t)1)||
- X !strnIcmp(p,"t",(size_t)1)||!strnIcmp(p,"e",(size_t)1))
- X t=1;
- X else if(!strnIcmp(p,"off",(size_t)3)||!strnIcmp(p,"n",(size_t)1)||
- X !strnIcmp(p,"f",(size_t)1)||!strnIcmp(p,"d",(size_t)1))
- X t=0;
- X }
- X return t;
- X}
- X
- Xvoid squeeze(target)char*target;
- X{ int state;char*src;
- X for(state=0,src=target;;target++,src++)
- X { switch(*target= *src)
- X { case '\n':
- X if(state==1)
- X target-=2; /* throw out \ \n pairs */
- X state=2;
- X continue;
- X case '\\':state=1;
- X continue;
- X case ' ':case '\t':
- X if(state==2) /* skip leading */
- X { target--; /* whitespace */
- X continue;
- X }
- X default:state=0;
- X continue;
- X case '\0':;
- X }
- X break;
- X }
- X}
- X
- Xchar*egrepin(expr,source,len,casesens)char*expr;const char*source;
- X const long len;int casesens;
- X{ if(*expr) /* only do the search if the expression is nonempty */
- X { source=(const char*)bregexec((struct eps*)(expr=(char*)
- X bregcomp(expr,!casesens)),(const uchar*)source,(const uchar*)source,
- X len>0?(size_t)len:(size_t)0,!casesens);
- X free(expr);
- X }
- X return (char*)source;
- X}
- X
- Xconst struct passwd*savepass(spass,uid)struct passwd*const spass;
- X const uid_t uid;
- X{ struct passwd*tpass;
- X if(spass->pw_name&&spass->pw_uid==uid)
- X goto ret;
- X if(tpass=getpwuid(uid)) /* save by copying */
- X { spass->pw_uid=tpass->pw_uid;spass->pw_gid=tpass->pw_gid;
- X spass->pw_name=cstr(spass->pw_name,tpass->pw_name);
- X spass->pw_dir=cstr(spass->pw_dir,tpass->pw_dir);
- X spass->pw_shell=cstr(spass->pw_shell,tpass->pw_shell);
- Xret: return spass;
- X }
- X return (const struct passwd*)0;
- X}
- X
- Xint enoughprivs(passinvk,euid,egid,uid,gid)const struct passwd*const passinvk;
- X const uid_t euid,uid;const gid_t egid,gid;
- X{ return euid==ROOT_uid||passinvk&&passinvk->pw_uid==uid||euid==uid&&egid==gid;
- X}
- X
- Xvoid initdefenv P((void))
- X{ int i=MAXvarstrs;
- X do /* initialise all non-empty string variables into the environment */
- X if(*strenstr[i].sval)
- X setdef(strenstr[i].sname,strenstr[i].sval);
- X while(i--);
- X}
- X
- Xconst char*newdynstring(adrp,chp)struct dynstring**const adrp;
- X const char*const chp;
- X{ struct dynstring*curr;size_t len;
- X curr=malloc(ioffsetof(struct dynstring,ename[0])+(len=strlen(chp)+1));
- X tmemmove(curr->ename,chp,len);curr->enext= *adrp;*adrp=curr;
- X return curr->ename;
- X}
- END_OF_FILE
- if test 14083 -ne `wc -c <'procmail-3.03/src/misc.c'`; then
- echo shar: \"'procmail-3.03/src/misc.c'\" unpacked with wrong size!
- fi
- # end of 'procmail-3.03/src/misc.c'
- fi
- echo shar: End of archive 5 \(of 10\).
- cp /dev/null ark5isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 10 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 10 archives.
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still must unpack the following archives:
- echo " " ${MISSING}
- fi
- exit 0
- exit 0 # Just in case...
-