1N/A * Copyright (c) 1998-2007, 2009 Sendmail, Inc. and its suppliers. 1N/A * All rights reserved. 1N/A * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. 1N/A * Copyright (c) 1988, 1993 1N/A * The Regents of the University of California. All rights reserved. 1N/A * By using this file, you agree to the terms and conditions set 1N/A * forth in the LICENSE file which can be found at the top level of 1N/A * the sendmail distribution. 1N/A** NEWSTR -- Create a copy of a C string 1N/A** s -- the string to copy. 1N/A** pointer to newly allocated string. 1N/A** ADDQUOTES -- Adds quotes & quote bits to a string. 1N/A** Runs through a string and adds backslashes and quote bits. 1N/A** s -- the string to modify. 1N/A** rpool -- resource pool from which to allocate result 1N/A** pointer to quoted string. 1N/A char *p = s, *q, *r;
1N/A /* Find length of quoted string */ 1N/A while ((c = *p++) !=
'\0')
1N/A if (c ==
'\\' || c ==
'"')
1N/A /* add leading quote */ 1N/A while ((c = *p++) !=
'\0')
1N/A if (c ==
'\\' || c ==
'"')
1N/A** STRIPBACKSLASH -- Strip all leading backslashes from a string, provided 1N/A** the following character is alpha-numerical. 1N/A** This is done in place. 1N/A** s -- the string to strip. 1N/A }
while (c !=
'\0');
1N/A** RFC822_STRING -- Checks string for proper RFC822 string quoting. 1N/A** Runs through a string and verifies RFC822 special characters 1N/A** are only found inside comments, quoted strings, or backslash 1N/A** escaped. Also verified balanced quotes and parenthesis. 1N/A** s -- the string to modify. 1N/A** true iff the string is RFC822 compliant, false otherwise. 1N/A /* escaped character */ 1N/A /* unbalanced ')' */ 1N/A /* unbalanced '"' or '(' */ 1N/A** SHORTEN_RFC822_STRING -- Truncate and rebalance an RFC822 string 1N/A** Arbitrarily shorten (in place) an RFC822 string and rebalance 1N/A** comments and quotes. 1N/A** string -- the string to shorten 1N/A** length -- the maximum size, 0 if no maximum 1N/A** true if string is changed, false otherwise 1N/A** Changes string in place, possibly resulting 1N/A** in a shorter string. 1N/A ** If have to rebalance an already short enough string, 1N/A ** need to do it within allocated space. 1N/A /* Inside a comment, quotes don't matter */ 1N/A /* Check for sufficient space for next character */ 1N/A /* Not enough, backtrack */ 1N/A** FIND_CHARACTER -- find an unquoted character in an RFC822 string 1N/A** Find an unquoted, non-commented character in an RFC822 1N/A** string and return a pointer to its location in the 1N/A** string -- the string to search 1N/A** character -- the character to find 1N/A** pointer to the character, or 1N/A** a pointer to the end of the line if character is not found 1N/A /* Inside a comment, nothing matters */ 1N/A /* Return pointer to the character */ 1N/A** CHECK_BODYTYPE -- check bodytype parameter 1N/A** bodytype -- bodytype parameter 1N/A** BODYTYPE_* according to parameter 1N/A /* check body type for legality */ 1N/A** TRUNCATE_AT_DELIM -- truncate string at a delimiter and append "..." 1N/A** str -- string to truncate 1N/A** len -- maximum length (including '\0') (0 for unlimited) 1N/A** delim -- delimiter character 1N/A /* Couldn't find a place to append "..." */ 1N/A** XALLOC -- Allocate memory, raise an exception on error 1N/A** sz -- size of area to allocate. 1N/A** pointer to data region. 1N/A** SmHeapOutOfMemory (F:sm.heap) -- cannot allocate memory 1N/A** Memory is allocated. 1N/A#
else /* SM_HEAP_CHECK */ 1N/A#
endif /* SM_HEAP_CHECK */ 1N/A /* some systems can't handle size zero mallocs */ 1N/A /* scaffolding for testing error handling code */ 1N/A** COPYPLIST -- copy list of pointers. 1N/A** This routine is the equivalent of strdup for lists of 1N/A** list -- list of pointers to copy. 1N/A** Must be NULL terminated. 1N/A** copycont -- if true, copy the contents of the vector 1N/A** (which must be a string) also. 1N/A** rpool -- resource pool from which to allocate storage, 1N/A** COPYQUEUE -- copy address queue. 1N/A** This routine is the equivalent of strdup for address queues; 1N/A** addresses marked as QS_IS_DEAD() aren't copied 1N/A** addr -- list of address structures to copy. 1N/A** rpool -- resource pool from which to allocate storage 1N/A** LOG_SENDMAIL_PID -- record sendmail pid and command line. 1N/A** e -- the current envelope. 1N/A** writes pidfile, logs command line. 1N/A** keeps file open and locked to prevent overwrite of active file 1N/A /* write the pid to the log file for posterity */ 1N/A "unable to write pid to %s: file in use by another process",
1N/A "unable to write pid to %s: %s",
1N/A /* write the process id on line 1 */ 1N/A /* line 2 contains all command line flags */ 1N/A ** Leave pid file open until process ends 1N/A ** so it's not overwritten by another 1N/A** CLOSE_SENDMAIL_PID -- close sendmail pid file 1N/A** SET_DELIVERY_MODE -- set and record the delivery mode 1N/A** mode -- delivery mode 1N/A** e -- the current envelope. 1N/A** sets {deliveryMode} macro 1N/A** SET_OP_MODE -- set and record the op mode 1N/A** e -- the current envelope. 1N/A** sets {opMode} macro 1N/A** PRINTAV -- print argument vector. 1N/A** fp -- output file pointer. 1N/A** av -- argument vector. 1N/A** XPUTS -- put string doing control escapes. 1N/A** fp -- output file pointer. 1N/A** s -- string to put. 1N/A "@(#)$Debug: ANSI - enable reverse video in debug output $");
1N/A ** TermEscape is set here, rather than in main(), 1N/A ** because ANSI mode can be turned on or off at any time 1N/A ** if we are in -bt rule testing mode. 1N/A while ((c = (*s++ & 0
377)) !=
'\0')
1N/A else if (*s !=
'\0')
1N/A /* unrecognized meta character */ 1N/A /* wasn't a meta-macro -- find another way to print it */ 1N/A** MAKELOWER -- Translate a line into lower case 1N/A** p -- the string to translate. If NULL, return is 1N/A** String pointed to by p is translated to lower case. 1N/A for (; (c = *p) !=
'\0'; p++)
1N/A** FIXCRLF -- fix <CR><LF> in line. 1N/A** Looks for the <CR><LF> combination and turns it into the 1N/A** UNIX canonical <NL> character. It only takes one line, 1N/A** i.e., it is assumed that the first <NL> found is the end 1N/A** line -- the line to fix. 1N/A** stripnl -- if true, strip the newline also. 1N/A** line is changed in place. 1N/A** PUTLINE -- put a line like fputs obeying SMTP conventions 1N/A** This routine always guarantees outputing a newline (or CRLF, 1N/A** as appropriate) at the end of the string. 1N/A** mci -- the mailer connection information. 1N/A** true iff line was written successfully 1N/A** output of l to mci->mci_out. 1N/A** PUTXLINE -- putline with flags bits. 1N/A** This routine always guarantees outputing a newline (or CRLF, 1N/A** as appropriate) at the end of the string. 1N/A** len -- the length of the line. 1N/A** mci -- the mailer connection information. 1N/A** pxflags -- flag bits: 1N/A** PXLF_MAPFROM -- map From_ to >From_. 1N/A** PXLF_STRIP8BIT -- strip 8th bit. 1N/A** PXLF_HEADER -- map bare newline in header to newline space. 1N/A** PXLF_NOADDEOL -- don't add an EOL if one wasn't present. 1N/A** PXLF_STRIPMQUOTE -- strip METAQUOTE bytes. 1N/A** true iff line was written successfully 1N/A** output of l to mci->mci_out. 1N/A unsigned char c = (
unsigned char) *l++; \
1N/A /* strip out 0200 bits -- these can look like TELNET protocol */ 1N/A /* find the end of the line */ 1N/A /* check for line overflow */ 1N/A else if (l[0] ==
'F' &&
slop == 0 &&
1N/A /* output last part */ 1N/A else if (l[0] ==
'F' &&
slop == 0 &&
1N/A if (*++l !=
' ' && *l !=
'\t' && *l !=
'\0' &&
1N/A** XUNLINK -- unlink a file, doing logging as appropriate. 1N/A** f -- name of file to unlink. 1N/A** return value of unlink() 1N/A** SFGETS -- "safe" fgets -- times out and ignores random interrupts. 1N/A** buf -- place to put the input line. 1N/A** siz -- size of buf. 1N/A** fp -- file to read from. 1N/A** timeout -- the timeout before error occurs. 1N/A** during -- what we are trying to read (for error messages). 1N/A** NULL on error (including timeout). This may also leave 1N/A** buf containing a null string. 1N/A /* convert the timeout to sm_io notation */ 1N/A /* The sm_io_fgets() call timedout */ 1N/A "timeout waiting for input from %.100s during %s",
1N/A "%05d <<< [TIMEOUT]\n",
1N/A /* clean up the books and exit */ 1N/A for (p =
buf; *p !=
'\0'; p++)
1N/A for (p =
buf; *p !=
'\0'; p++)
1N/A** FGETFOLDED -- like fgets, but knows about folded lines. 1N/A** buf -- place to put result. 1N/A** np -- pointer to bytes available; will be updated with 1N/A** the actual buffer size (not number of bytes filled) 1N/A** f -- file to read from. 1N/A** input line(s) on success, NULL on error or SM_IO_EOF. 1N/A** This will normally be buf -- unless the line is too 1N/A** long, when it will be sm_malloc_x()ed. 1N/A** buf gets lines from f, with continuation lines (lines 1N/A** with leading white space) appended. CRLF's are mapped 1N/A** into single newlines. Any trailing NL is stripped. 1N/A /* allocate new space */ 1N/A if (i !=
' ' && i !=
'\t')
1N/A** CURTIME -- return current time. 1N/A** ATOBOOL -- convert a string representation to boolean. 1N/A** s -- string to convert. Takes "tTyY", empty, and NULL as true, 1N/A** A boolean representation of the string. 1N/A** ATOOCT -- convert a string representation to octal. 1N/A** s -- string to convert. 1N/A** An integer representing the string interpreted as an 1N/A while (*s >=
'0' && *s <=
'7')
1N/A i = (i <<
3) | (*s++ -
'0');
1N/A** BITINTERSECT -- tell if two bitmaps intersect 1N/A** a, b -- the bitmaps in question 1N/A** true if they have a non-null intersection 1N/A if ((a[i] & b[i]) != 0)
1N/A** BITZEROP -- tell if a bitmap is all zero 1N/A** map -- the bit map to check 1N/A** true if map is all zero. 1N/A** false if there are any bits set in map. 1N/A** STRCONTAINEDIN -- tell if one string is contained in another 1N/A** icase -- ignore case? 1N/A** a -- possible substring. 1N/A** b -- possible superstring. 1N/A** true if a is contained in b (case insensitive). 1N/A** CHECKFD012 -- check low numbered file descriptors 1N/A** File descriptors 0, 1, and 2 should be open at all times. 1N/A** This routine verifies that, and fixes it if not true. 1N/A** where -- a tag printed if the assertion failed 1N/A for (i = 0; i <
3; i++)
1N/A** CHECKFDOPEN -- make sure file descriptor is open -- for extended debugging 1N/A** fd -- file descriptor to check. 1N/A** where -- tag to print on failure. 1N/A** CHECKFDS -- check for new or missing file descriptors 1N/A** where -- tag for printing. If null, take a base line. 1N/A** If where is set, shows changes since the last call. 1N/A /* file state has changed */ 1N/A** PRINTOPENFDS -- print the open file descriptors (for debugging) 1N/A** logit -- if set, send output to syslog; otherwise 1N/A** print for debugging. 1N/A#
endif /* NETINET || NETINET6 */ 1N/A** DUMPFD -- dump a file descriptor 1N/A** fd -- the file descriptor to dump. 1N/A** printclosed -- if set, print a notification even if 1N/A** it is closed; otherwise print nothing. 1N/A** logit -- if set, use sm_syslog instead of sm_dprintf() 1N/A#
endif /* S_IFSOCK */ 1N/A#
else /* STAT64 > 0 */ 1N/A#
endif /* STAT64 > 0 */ 1N/A#
else /* STAT64 > 0 */ 1N/A#
endif /* STAT64 > 0 */ 1N/A#
endif /* NETINET */ 1N/A#
endif /* NETINET6 */ 1N/A#
endif /* NETINET */ 1N/A#
endif /* NETINET6 */ 1N/A#
endif /* S_IFSOCK */ 1N/A#
endif /* defined(S_IFIFO) && (!defined(S_IFSOCK) || S_IFIFO != S_IFSOCK) */ 1N/A "dev=%d/%d, ino=%llu, nlink=%d, u/gid=%d/%d, ",
1N/A** SHORTEN_HOSTNAME -- strip local domain information off of hostname. 1N/A** host -- the host to shorten (stripped in place). 1N/A** place where string was truncated, NULL if not truncated. 1N/A /* strip off final dot */ 1N/A /* see if there is any domain at all -- if not, we are done */ 1N/A /* yes, we have a domain -- see if it looks like us */ 1N/A** PROG_OPEN -- open a program for reading 1N/A** argv -- the argument list. 1N/A** pfd -- pointer to a place to store the file descriptor. 1N/A** e -- the current envelope. 1N/A** pid of the process -- -1 if it failed. 1N/A /* Reset global flags */ 1N/A ** Initialize exception stack and default exception 1N/A ** handler for child process. 1N/A /* child -- close stdin */ 1N/A /* stdout goes back to parent */ 1N/A /* stderr goes to transcript if available */ 1N/A /* this process has no right to the queue file */ 1N/A /* chroot to the program mailer directory, if defined */ 1N/A /* run as default user */ 1N/A#
endif /* _FFR_MEMSTAT */ 1N/A /* run in some directory */ 1N/A /* backup directories */ 1N/A /* Check safety of program to be run */ 1N/A "Warning: prog_open: program %s unsafe: %s",
1N/A /* arrange for all the files to be closed */ 1N/A /* now exec the process */ 1N/A return -
1;
/* avoid compiler warning on IRIX */ 1N/A** GET_COLUMN -- look up a Column in a line buffer 1N/A** line -- the raw text line to search. 1N/A** col -- the column number to fetch. 1N/A** delim -- the delimiter between columns. If null, 1N/A** buf -- the output buffer. 1N/A** buflen -- the length of buf. 1N/A** buf if successful. 1N/A return NULL;
/* first column empty */ 1N/A** CLEANSTRCPY -- copy string keeping out bogus characters 1N/A** f -- "from" string. 1N/A** l -- length of space available in "to" string. 1N/A /* check for newlines and log if necessary */ 1N/A while (l > 0 && *f !=
'\0')
1N/A** DENLSTRING -- convert newlines in a string to spaces 1N/A** s -- the input string 1N/A** strict -- if set, don't permit continuation lines. 1N/A** logattacks -- if set, log attempted attacks. 1N/A** A pointer to a version of the string with newlines 1N/A** mapped to spaces. This should be copied. 1N/A /* allocate more space */ 1N/A "POSSIBLE ATTACK from %.100s: newline in string \"%s\"",
1N/A** STRREPLNONPRT -- replace "unprintable" characters in a string with subst 1N/A** s -- string to manipulate (in place) 1N/A** subst -- character to use as replacement 1N/A** true iff string did not contain "unprintable" characters 1N/A** PATH_IS_DIR -- check to see if file exists and is a directory. 1N/A** There are some additional checks for security violations in 1N/A** here. This routine is intended to be used for the host status 1N/A** pathname -- pathname to check for directory-ness. 1N/A** createflag -- if set, create directory if needed. 1N/A** true -- if the indicated pathname is a directory 1N/A** false -- otherwise 1N/A#
endif /* HASLSTAT */ 1N/A /* security: don't allow writable directories */ 1N/A** PROC_LIST_ADD -- add process id to list of our children 1N/A** pid -- pid to add to list. 1N/A** task -- task of pid. 1N/A** type -- type of process. 1N/A** count -- number of processes. 1N/A** other -- other information for this type. 1N/A** May increase CurChildren. May grow ProcList. 1N/A /* probe the existing vector to avoid growing infinitely */ 1N/A /* now scan again */ 1N/A /* grow process list */ 1N/A /* Block SIGCHLD so reapchild() doesn't mess with us */ 1N/A /* XXX just use memset() to initialize this part? */ 1N/A /* if process adding itself, it's not a child */ 1N/A** PROC_LIST_SET -- set pid task in process list 1N/A** task -- task of pid 1N/A** PROC_LIST_DROP -- drop pid from process list 1N/A** pid -- pid to drop 1N/A** st -- process status 1N/A** other -- storage for proc_other (return). 1N/A** May decrease CurChildren, CurRunners, or 1N/A** set RestartRequest or ShutdownRequest. 1N/A** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 1N/A** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 1N/A /* if so, see if we need to restart or shutdown */ 1N/A /* restart this persistent runner */ 1N/A** PROC_LIST_CLEAR -- clear the process list 1N/A** Sets CurChildren to zero. 1N/A /* start from 1 since 0 is the daemon itself */ 1N/A** PROC_LIST_PROBE -- probe processes in the list to see if they still exist 1N/A** May decrease CurChildren. 1N/A /* start from 1 since 0 is the daemon itself */ 1N/A "proc_list_probe: lost pid %d",
1N/A "proc_list_probe: found %d children, expected %d",
1N/A** PROC_LIST_DISPLAY -- display the process list 1N/A** out -- output file pointer 1N/A** prefix -- string to output in front of each line. 1N/A** PROC_LIST_SIGNAL -- send a signal to a type of process in the list 1N/A** type -- type of process to signal 1N/A** signal -- the type of signal to send 1N/A** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 1N/A** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 1N/A /* block these signals so that we may signal cleanly */ 1N/A /* Find all processes of type and send signal */ 1N/A /* restore the signals */ 1N/A** COUNT_OPEN_CONNECTIONS 1N/A** hostaddr - ClientAddress 1N/A** the number of open connections for this client 1N/A ** This code gets called before proc_list_add() gets called, 1N/A ** so we (the daemon child for this connection) have not yet 1N/A ** counted ourselves. Hence initialize the counter to 1 1N/A ** instead of 0 to compensate. 1N/A#
endif /* NETINET6 */