home *** CD-ROM | disk | FTP | other *** search
- /******************************************************************************
- * *
- * LISTSERV V2 - Standalone incoming mail interface (unix) *
- * *
- * Copyright L-Soft international 1994 - All rights reserved *
- * *
- * Syntax: add entries to /etc/aliases using either of the following forms *
- * *
- * listserv: "|/.../lsv_amin spool_dir listserv" *
- * listserv: "|/.../lsv_amin -t listserv" *
- * *
- * Where "..." represents the path to the executable (which should run with *
- * setuid listserv rather than root, for increased security), "spool_dir" is *
- * the absolute path to the LISTSERV spool directory, and the third parameter *
- * is a copy of the userid the entry is for (the name before the colon). If *
- * no spool directory is specified, the default (defined in the Makefile and *
- * also in lsv_amin.h) will be used. *
- * *
- * You must define entries for the reserved addresses LISTSERV and *
- * owner-LISTSERV. In addition, for each list you must define entries for *
- * listname, owner-listname, listname-request and listname-server. Example: *
- * *
- * listserv: "|/usr/listserv/lsv_amin -t listserv" *
- * owner-listserv: "|/usr/listserv/lsv_amin -t owner-listserv" *
- * *
- * test-l: "|/usr/listserv/lsv_amin -t test-l" *
- * test-l-request: "|/usr/listserv/lsv_amin -t test-l-request" *
- * test-l-server: "|/usr/listserv/lsv_amin -t test-l-server" *
- * owner-test-l: "|/usr/listserv/lsv_amin -t owner-test-l" *
- * *
- *****************************************************************************/
-
- #include <sys/types.h>
- #include <stdio.h>
- #include <string.h>
- #include <errno.h>
- #include <time.h>
- #include <sys/stat.h>
- #include <syslog.h>
- #include <signal.h>
-
- typedef unsigned char LSV_char;
- #include "lsv_amin.h"
-
- #define Err_Invalid 200
- #define Err_BadSyntax 201
- #define Err_SysCallFailed 202
- #define Err_NoFilename 203
-
- #define P_SCAN 0
- #define P_DONE 1
- #define P_NEW 2
- #define P_ERR 3
- #define P_CONT 4
-
- #define TIME_LEN 8
- #define TIME_CONV "%.8x"
- #define PROC_LEN 5
- #define PROC_CONV "%.6x"
- #define MAXTRIES 10
- #define JOB_EXT ".job"
- #define JOB_PRE "in"
- #define LISTSERV "LISTSERV"
- #define PROGNAME "lsv_amin"
- #define PROGVER "1.0b"
- #define REPORT_IND "X-REPORT-TYPE:"
-
- #define SM1_Delim "----- Transcript of session follows -----"
- #define SM2_Delim "--- The transcript of the session follows ---"
- #define SM3_Delim "----- The following addresses had delivery problems -----"
- #define SM_Cont "..."
- #define SM_UOpen "(expanded from:"
- #define SM_UClose ")"
-
- #define XRHeader \
- "X-Report-Type: Nondelivery; boundary=\"> Error description:\""
-
- static LSV_char L_TA2E[] = {
- /* 0 */ 0x00,0x01,0x02,0x03,0x37,0x2D,0x2E,0x2F,
- 0x16,0x05,0x25,0x0B,0x0C,0x0D,0x0E,0x0F,
- /* 1 */ 0x10,0x11,0x12,0x13,0x3C,0x3D,0x32,0x26,
- 0x18,0x19,0x3F,0x27,0x1C,0x1D,0x1E,0x1F,
- /* 2 */ 0x40,0x5A,0x7F,0x7B,0x5B,0x6C,0x50,0x7D,
- 0x4D,0x5D,0x5C,0x4E,0x6B,0x60,0x4B,0x61,
- /* 3 */ 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,
- 0xF8,0xF9,0x7A,0x5E,0x4C,0x7E,0x6E,0x6F,
- /* 4 */ 0x7C,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,
- 0xC8,0xC9,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,
- /* 5 */ 0xD7,0xD8,0xD9,0xE2,0xE3,0xE4,0xE5,0xE6,
- 0xE7,0xE8,0xE9,0xAD,0xE0,0xBD,0x5F,0x6D,
- /* 6 */ 0x79,0x81,0x82,0x83,0x84,0x85,0x86,0x87,
- 0x88,0x89,0x91,0x92,0x93,0x94,0x95,0x96,
- /* 7 */ 0x97,0x98,0x99,0xA2,0xA3,0xA4,0xA5,0xA6,
- 0xA7,0xA8,0xA9,0xC0,0x4F,0xD0,0xA1,0x07,
- /* 8 */ 0x20,0x21,0x22,0x23,0x24,0x2A,0x06,0x17,
- 0x28,0x29,0x15,0x2B,0x2C,0x09,0x0A,0x1B,
- /* 9 */ 0x30,0x31,0x1A,0x33,0x34,0x35,0x36,0x08,
- 0x38,0x39,0x3A,0x3B,0x04,0x14,0x3E,0xE1,
- /* A */ 0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,
- 0x49,0x51,0x52,0x53,0x54,0x55,0x56,0x57,
- /* B */ 0x58,0x59,0x62,0x63,0x64,0x65,0x66,0x67,
- 0x68,0x69,0x70,0x71,0x72,0x73,0x74,0x75,
- /* C */ 0x76,0x77,0x78,0x80,0x8A,0x8B,0x8C,0x8D,
- 0x8E,0x8F,0x90,0x9A,0x9B,0x9C,0x9D,0x9E,
- /* D */ 0x9F,0xA0,0xAA,0xAB,0xAC,0xBB,0xAE,0xAF,
- 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,
- /* E */ 0xB8,0xB9,0xBA,0x4A,0xBC,0xFC,0xBE,0xBF,
- 0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xDA,0xDB,
- /* F */ 0xDC,0xDD,0xDE,0xDF,0xEA,0xEB,0xEC,0xED,
- 0xEE,0xEF,0xFA,0xFB,0x6A,0xFD,0xFE,0xFF
- };
-
- char *LSV_ErrFields[] =
- { "--> Error description:",
- "Error-For: ",
- "Error-Code:",
- "Error-Text:",
- "Error-End: "
- };
-
- struct err_entry {
- int msg_num;
- char *msg_text;
- };
-
- struct err_entry err_repos[] =
- { { Err_Invalid,
- "Program error.*"
- },
-
- { Err_BadSyntax,
- #ifdef MAIL_PP
- "Syntax is, lsv_amin spool-directory to-user from-user"
- #else
- "Syntax is, lsv_amin spool-directory to-user"
- #endif
- },
-
- { Err_SysCallFailed,
- "An unknown system call failed.*"
- },
-
- { Err_NoFilename,
- "The incoming mail directory is full."
- }
- };
-
- char *user = "", *routine_in_err = "";
- LSV_char buf[ 65537];
-
- /* - STREXTR -
- * String parser.
- */
- int strextr( buff, pre, pos, skip, rsize, result, sc_end)
- char *buff, *pre, *pos, *skip, *result, **sc_end;
- int rsize;
-
- { int rc = 0, off;
- char *ch, *start, *wk;
-
- for( ch = buff; !rc && *ch; )
- { for( off = 0; *(pre + off) && *(pre + off) == *(ch + off); off++) ;
- rc = !*(pre + off);
- if( !rc) ch++;
- else ch += off;
- }
- rc = *ch;
-
- if( rc && *skip)
- { for( rc = 0; !rc && *ch; )
- { for( rc = 1, wk = skip; rc && *wk; wk++)
- rc = *wk != *ch;
- if( !rc) ch++;
- }
- rc = *ch;
- }
- start = ch;
-
- if( rc)
- { if( *pos)
- { for( rc = 0; !rc && *ch; )
- { for( off = 0; *(pos + off) && *(pos + off) == *(ch + off); off++) ;
- rc = !*( pos + off);
- if( !rc) ch++;
- }
- if( (rc = ch - start) > rsize - 1) rc = rsize - 1;
- if( rc > 0) strncpy( result, start, rc);
- if( rc >= 0) result[ rc] = '\0';
- *sc_end = ch + off;
- if( *(pos + off)) rc = -rc;
- }
- else
- { rc = strlen( start);
- *sc_end = start + rc;
- if( rc > rsize - 1) rc = rsize - 1;
- if( rc > 0) strncpy( result, start, rc);
- if( rc >= 0) result[ rc] = '\0';
- rc = -rc;
- }
- }
-
- return rc;
- }
-
- /* - ERR_LOOKUP -
- * Translate mail delivery errors to LISTSERV error codes.
- */
- int err_lookup( reason)
- char *reason;
- {
- int rc = -1, wh = 0;
- struct SM_Err_type *next, *last;
-
- last = (struct SM_Err_type *)((int) err_list + sizeof err_list);
-
- for( next = err_list; next < last && rc == -1; next++)
- if( !strncmp( reason, next->err_msg, strlen( next->err_msg)))
- rc = next->err_type;
-
- if( rc == -1) rc = err_list[ 0].err_type;
-
- return rc;
- }
-
- /* - PUTSTR_EBC -
- * Convert '\0' terminated string of ASCII characters to EBCDIC and
- * write them to a file.
- */
- void putstr_EBC( st, file)
- LSV_char *st;
- FILE *file;
- {
- LSV_char *ch;
- int l;
-
- #ifdef DBG_ASCII
- fprintf( file, "%s\n", st);
- fprintf( stdout, "%s\n", st);
- #else
- l = strlen(st);
- putc(l >> 8, file);
- putc(l & 255, file);
-
- for( ch = st; *ch; ch++)
- if( fputc( L_TA2E[ *ch], file) == EOF) syscall_failed( "fputc");
- #endif
-
- return;
- }
-
- /* - HAS_LSVERR -
- * Scan message text for existing LISTSERV style error indicators.
- */
- int has_LSVErr( st)
- LSV_char *st;
- {
- static LSV_char **mlevel = 0, **last = 0;
-
- if( !last)
- {
- mlevel = (LSV_char **) LSV_ErrFields;
- last = (LSV_char **) ((int) LSV_ErrFields + (sizeof LSV_ErrFields));
- last--;
- }
-
- if( *st && *st != '\n' && *st != ' ' && *st != '\t' && mlevel < last)
- {
- if( !strncmp( st, *mlevel, strlen( *mlevel))) mlevel++;
- else mlevel = (LSV_char **) LSV_ErrFields;
- }
-
- return mlevel >= last;
- }
-
- /* - PUTBLOCK_EBC -
- * Scan a block of text for '\n' terminated lines, and write each out
- * as a separate EBCDIC record.
- */
- LSV_char *putblock_EBC( pool, out)
- LSV_char *pool;
- FILE *out;
- {
- LSV_char *start, *EOR;
-
- for( start = pool, EOR = start; *EOR; )
- {
- for( ; *EOR && *EOR != '\n'; EOR++) ;
- if( *EOR == '\n')
- {
- *EOR = '\0';
- putstr_EBC( start, out);
- *(EOR++) = '\n';
- start = EOR;
- }
- }
-
- return start;
- }
-
- /* - PARSE_SM_RESP -
- * Check a line of text for Sendmail style delivery errors, then extract
- * the reason for the error, and the failing address.
- */
- void parse_SM_resp( pos, addr, asize, reason, rsize)
- LSV_char *pos, *addr, *reason;
- int asize, rsize;
- {
- LSV_char *next, trash, *s_addr = &trash, *s_reason = &trash, test[ 200];
- int l_addr = sizeof trash, l_reason = sizeof trash;
- static int has_LSVErr = 0;
-
- if( !*addr)
- {
- s_addr = addr;
- l_addr = asize;
- }
- if( !*reason)
- {
- s_reason = reason;
- l_reason = rsize;
- }
-
- if( strextr( pos, SM_UOpen, SM_UClose, " ", sizeof test, test, &next) > 0)
- if( !strextr( test, "<", ">", " ", l_addr, s_addr, &next))
- strncpy( s_addr, test, l_addr);
-
- strextr( pos, "", " ", " ", sizeof test, test, &next);
- if( *test == '5' && strlen( test) == 3)
- {
- if( strextr( next, "<", ">", " ", l_addr, s_addr, &next))
- strextr( next, "...", "\n", " \n\t", l_reason, s_reason, &next);
- else
- {
- strextr( next, "", "...", " \t", l_addr, s_addr, &next);
- strextr( next, "", "\n", " \n\t", l_reason, s_reason, &next);
- }
- }
- if( !strcmp( test, "<<<"))
- {
- strextr( pos+4, "", " ", " ", sizeof test, test, &next);
- if( *test == '5' && strlen( test) == 3)
- {
- if( strextr( next, "<", ">", " ", l_addr, s_addr, &next))
- strextr( next, "...", "\n", " \n\t", l_reason, s_reason, &next);
- else
- {
- strextr( next, "", "...", " \t", l_addr, s_addr, &next);
- strextr( next, "", "\n", " \n\t", l_reason, s_reason, &next);
- }
- }
- else if( !strcmp( test, "RCPT"))
- strextr( pos, "<<<", "\n", " ", l_reason, s_reason, &next);
- }
- else (void) strextr( pos, "uux:", "\n", " \t", l_reason, s_reason, &next);
-
- if( *s_addr) for( next = s_addr + strlen( s_addr) - 1;
- next >= s_addr && (*next == ' ' || *next == '\n');
- *(next--) = '\0') ;
-
- return;
- }
-
- /* - SCAN_MSG -
- * Scan mail intended for an owner-* type address for Sendmail errors and
- * convert them to LISTSERV edible mail delivery indicators.
- */
- void scan_msg( out)
- FILE *out;
- {
- int in_hdr = 1, copy_asis = 0, psize, pfree, rl = 0, stat = P_SCAN, line;
- LSV_char *pool, *ch, *pos, *start;
- char *XReport, address[ 200], reason[ 200], *test, *AppendMSG;
-
- AppendMSG = (char *) malloc( sizeof ErrInsert);
- strcpy( AppendMSG, ErrInsert);
- XReport = (char *) malloc( sizeof REPORT_IND);
- strcpy( XReport, REPORT_IND);
- test = (char *) malloc( sizeof SM_Cont);
- strcpy( test, SM_Cont);
-
- psize = MAX_BODY_BUFFER * 1024;
- pool = (LSV_char *) malloc( psize);
- if( !pool) syscall_failed( "malloc");
- pfree = psize;
- *address = '\0';
- *reason = '\0';
-
- for(; in_hdr && !copy_asis && stat != P_DONE; )
- {
- if( !fgets( pool, psize, stdin))
- stat = P_DONE;
- else
- {
- for( pos= pool; *pos && (*pos == ' ' || *pos == '\n'); pos++) ;
- if( !*pos) in_hdr = 0;
- else
- {
- for( ch = (LSV_char *) XReport, pos = pool, copy_asis = 1;
- copy_asis && *ch && *pos; )
- if( *(ch++) != toupper( *(pos++))) copy_asis = 0;
- (void) putblock_EBC( pool, out);
- }
- }
- }
-
- if( stat == P_DONE) rl = -1;
- else if( copy_asis) putstr_EBC( "\n", out);
- else
- {
- pos = pool;
- for( line= 0; line <= MAX_BODY_LINES && stat != P_DONE && stat != P_ERR;
- line++)
- {
- if( !fgets( pos, pfree, stdin))
- {
- rl = -1;
- if( stat == P_CONT) (void) parse_SM_resp( start, address,
- sizeof address, reason, sizeof reason);
- stat = P_DONE;
- }
- else rl = strlen( pos);
-
- if( has_LSVErr( pos))
- {
- putstr_EBC( XRHeader, out);
- *reason = '\0';
- *address = '\0';
- stat = P_DONE;
- }
- else if( stat == P_SCAN)
- {
- for(; *pos != '\0' && *pos != '\n' && (*pos == ' ' || *pos == '\t');
- pos++) ;
- if( !strncmp( pos, SM1_Delim, (sizeof SM1_Delim) - 1) ||
- !strncmp( pos, SM2_Delim, (sizeof SM2_Delim) - 1) ||
- !strncmp( pos, SM3_Delim, (sizeof SM3_Delim) - 1)) stat = P_NEW;
- }
- else if( stat == P_NEW)
- {
- stat = P_CONT;
- start = pos;
- }
- else if( stat == P_CONT)
- {
- *test = '\0';
- (void) strextr( pos, "", " ", " \t", sizeof test, test, &ch);
- if( strcmp( SM_Cont, test))
- {
- *test = *pos;
- *pos = '\0';
- (void) parse_SM_resp( start, address, sizeof address, reason,
- sizeof reason);
- *pos = *test;
- if( *reason && *address) stat = P_DONE;
- else start = pos;
- }
- }
-
- if( rl >= 0)
- {
- pos += strlen( pos);
- pfree -= rl;
- if( pfree <= 1 && *(pos - 1) != '\n')
- {
- syslog( LOG_ERR, "**Warning** Buffer exhausted, consider \
- increasing MAX_BODY_BUFFER");
- fprintf( stderr, "**Warning** Buffer exhausted, consider \
- increasing MAX_BODY_BUFFER.\n");
- *reason = '\0';
- *address = '\0';
- stat = P_ERR;
- pos = putblock_EBC( pool, out);
- if( pos)
- {
- /* Try to salvage the partial line in the buffer without splitting it. */
- strncpy( buf, pos, sizeof buf);
- pos = buf + strlen( buf);
- fgets( pos, (sizeof buf) - strlen( buf), stdin);
- putstr_EBC( buf, out);
- *pool = '\0';
- }
- }
- }
-
- if( *reason && *address)
- {
- putstr_EBC( XRHeader, out);
- (void) putblock_EBC( AppendMSG, out);
- sprintf( buf, "%s\n%s %s\n%s %d\n%s %s\n\n%s %s\n", LSV_ErrFields[ 0],
- LSV_ErrFields[ 1], address, LSV_ErrFields[ 2], err_lookup( reason),
- LSV_ErrFields[ 3], reason, LSV_ErrFields[ 4], "One error reported.");
- (void) putblock_EBC( buf, out);
- }
- }
-
- if( stat != P_ERR) putstr_EBC( "\n", out);
- if( *pool) (void) putblock_EBC( pool, out);
- }
-
- if( rl >= 0) for(; fgets( pool, psize, stdin); )
- putblock_EBC( pool, out);
-
- return;
- }
-
- /* - FILE_EXISTS -
- * Return 1/0 indicating whether or not the indicated file exists.
- */
- int file_exists( path)
- char *path;
- {
- struct stat stat_buff;
-
- return( !lstat( path, &stat_buff));
- }
-
- /* - SYSCALL_FAILED -
- * Save the name of the system call that bombed and log the error.
- */
- syscall_failed( which)
- char *which;
- {
- routine_in_err = which;
- err_exit( Err_SysCallFailed);
-
- exit( Err_SysCallFailed); /* Shouldn't get here! */
- }
-
- /* - ERR_EXIT -
- * Construct an appropriate error message and log it to stderr and syslog.
- */
- err_exit( rc)
- int rc;
- {
- int last_entry, wh = 0;
- char *msg = "";
-
- if( *user != '\0')
- {
- syslog( LOG_ERR, "Unable to deliver mail to: %s", user);
- fprintf( stderr, "lsv_amin: Unable to deliver mail to: %s\n", user);
- }
-
- if( rc == Err_SysCallFailed)
- {
- msg = (char *)malloc( 80);
- if( *routine_in_err == '\0') msg = "An unknown system call failed.*";
- else sprintf( msg, "A call to %s() failed.*", routine_in_err);
- }
- else
- {
- last_entry = (int)err_repos + sizeof( err_repos);
-
- for( ; (int)&err_repos[ wh] < last_entry && *msg == '\0'; wh++)
- if( rc == err_repos[ wh].msg_num) msg = err_repos[ wh].msg_text;
-
- if( *msg == '\0') msg = err_repos[ 0].msg_text;
- }
-
- if( msg[ strlen( msg) - 1] == '*')
- {
- msg[ strlen( msg) - 1] = '\0';
- syslog( LOG_ERR, "**Error(%d)** %s", errno, msg);
- fprintf( stderr, "lsv_amin: **Error(%d)** %s\n", errno, msg);
- }
- else
- {
- syslog( LOG_ERR, "**Error** %s", msg);
- fprintf( stderr, "lsv_amin: **Error** %s\n", msg);
- }
-
- closelog();
- exit( rc);
- }
-
- /* - LSV_AMIN -
- */
- main( narg, args)
- int narg;
- char **args;
- {
- long staging, proc;
- int ii, ntry, plen, ch, xam, xown;
- char *conv, *fsuffix, *final, *workfile, *fprefix, *w, *r, Fromline[1024],
- *fromid = "", uid[256], *spool_dir = "", **which, *def_spool, *callname;
- time_t now;
- FILE *out = 0, *pidfile;
-
- fsuffix = (char *) malloc( sizeof JOB_EXT);
- strcpy( fsuffix, JOB_EXT);
- fprefix = (char *) malloc( sizeof JOB_PRE);
- strcpy( fprefix, JOB_PRE);
- def_spool = (char *) malloc( sizeof SPOOL_DIR);
- strcpy( def_spool, SPOOL_DIR);
-
- openlog( "LSV:lsv_amin", LOG_PID, LOG_FACILITY);
-
- callname = args[ 0];
- for( w = callname; *w; w++) if( *w == '/') callname = w + 1;
- if( strcmp( callname, PROGNAME)) user = callname;
-
- if( narg > 1)
- {
- if( !strcmp( args[ 1], "-v"))
- {
- fprintf( stdout, "%s release %s\n", PROGNAME, PROGVER);
- exit( 0);
- }
-
- if( *args[ 1] == '-') which = 0;
- else which = &spool_dir;
- }
-
- for( ii= 1; ii < narg; ii++)
- {
- w = args[ ii];
- if( which)
- {
- *which = w;
- which = 0;
- }
- #ifdef MAIL_PP
- else if( !strcmp( w, "-f")) which = &fromid;
- #endif
- else if( !strcmp( w, "-s")) which = &spool_dir;
- else if( !strcmp( w, "-t")) which = &user;
- else
- {
- if( *spool_dir == '\0') spool_dir = w;
- else if( *user == '\0') user = w;
- #ifdef MAIL_PP
- else if( *fromid == '\0') fromid = w;
- #endif
- else (void) err_exit( Err_BadSyntax);
- which = 0;
- }
- }
-
- if( !*spool_dir) spool_dir = def_spool;
- #ifdef MAIL_PP
- if( !*fromid || !*user) (void) err_exit( Err_BadSyntax);
- #else
- if( !*user) (void) err_exit( Err_BadSyntax);
- #endif
-
- #ifdef DBG_ASCII
- fprintf( stdout, "To<%s> Sp<%s>\n", user, spool_dir);
- #endif
-
- for (r = user, w = uid; *r; *w++ = toupper(*r), r++);
- *w = '\0';
-
- workfile = (char *)malloc( strlen( spool_dir) + TIME_LEN + PROC_LEN +
- strlen( fprefix) + 3);
- final = (char *)malloc( strlen( spool_dir) + TIME_LEN + PROC_LEN +
- strlen( fsuffix) + 3);
- conv = (char *)malloc( (sizeof staging) * 2 + 1);
-
- strcpy( final, spool_dir);
- if( final[ (ii = strlen( final)) - 1] != '/')
- {
- final[ ii] = '/';
- final[ ii + 1] = '\0';
- }
- plen = strlen( final);
-
- for( ntry = 1; ntry <= MAXTRIES && !out; ntry++)
- {
- final[ plen] = '\0';
- strcat( final, fprefix);
-
- time( &now);
- sprintf( conv, TIME_CONV, (staging = now));
- strcat( final, (conv + strlen( conv)) - TIME_LEN);
-
- sprintf( conv, PROC_CONV, getpid());
- strcat( final, (conv + strlen( conv)) - (PROC_LEN + 1));
- final[ strlen( final) - (PROC_LEN + 1)] = '-';
-
- strcpy( workfile, final);
- strcat( final, fsuffix);
-
- if( !file_exists( workfile) && !file_exists( final))
- {
- if( !(out = fopen( workfile, "w"))) syscall_failed( "fopen");
- }
- else sleep( 1);
- }
-
- if( out)
- {
- if( fwrite("*LSV-V*", 7, 1, out) <= 0) syscall_failed( "fwrite");
- for( w = user; *w; *w++ = tolower( *w)) ;
-
- /* See if it is an administrative (owner-xxx/xxx-request) message */
- xown = !strncmp(user, "owner-", 6);
- xam = xown || !strncmp(w - 8, "-request", 8) ||
- !strncmp(w - 7, "-server", 7);
- /* Format and write the header */
- sprintf(buf, "1 M %s %s *MAILER* INCOMING MAIL",
- uid,
- (xam || !strcmp(uid, LISTSERV)) ? "STANDARD" :
- "$NOJOB$");
-
- ii = strlen(buf);
- #ifndef DBG_ASCII
- putc(ii >> 8, out);
- putc(ii & 255, out);
- fwrite(buf, ii, 1, out);
- putc(0, out);
- putc(0, out);
- #else
- fwrite(buf, ii, 1, out);
- fputc( '\n', out);
- fputc( '\n', stdout);
- #endif
-
- /* For administrative messages, generate X-ADMMAIL JCL */
- #ifndef MAIL_PP
- fgets(Fromline, sizeof(Fromline), stdin);
- #endif
- if (xam) {
- putstr_EBC("// JOB Echo=No", out);
- #ifndef MAIL_PP
- for (fromid = Fromline; *fromid && *fromid++ != ' ';);
- #endif
- for (w = fromid; *w && *w != ' ' && *w != '\n'; w++);
- *w = '\0';
- if( *fromid == '<' && fromid[ strlen( fromid) - 1] == '>')
- {
- fromid[ strlen( fromid) - 1] = '\0';
- fromid++;
- }
- sprintf(buf, "X-ADMMAIL %s %s", user, fromid);
- putstr_EBC(buf, out);
- putstr_EBC("//DATA DD *,EOF", out);
- }
-
- /* If this is going to an owner-* type address, try to convert the
- * mail delivery error to something LISTSERV can act on.
- */
- if( xown) scan_msg( out);
- else for (; fgets(buf, sizeof(buf), stdin);) {
- buf[strlen(buf) - 1] = '\0';
- putstr_EBC(buf, out);
- }
-
- if( fclose( out)) syscall_failed( "fclose");
- if( link( workfile, final)) syscall_failed( "link");
- if( unlink( workfile)) syscall_failed( "unlink");
-
- syslog( LOG_INFO, "Mail for %s (from %d/%d) delivered to LISTSERV.",
- user, getuid(), geteuid());
-
- sprintf(buf, "%s/listserv.PID", spool_dir);
- if (pidfile = fopen(buf, "r")) {
- fscanf(pidfile, "%lu\n", &proc);
- kill(proc, SIGUSR1);
- fclose(pidfile);
- }
- }
- else err_exit( Err_NoFilename);
-
- exit( 0);
- }
-