File:  [MW Coherent from dump] / coherent / b / bin / mail / mail.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Wed May 29 04:56:36 2019 UTC (7 years, 2 months ago) by root
Branches: MarkWilliams, MAIN
CVS tags: relic, HEAD
coherent

static	char	*rcsrev = "$Revision: 1.1.1.1 $";
static	char	*rcshdr =
"$Header: /var/lib/cvsd/repos/coherent/coherent/b/bin/mail/mail.c,v 1.1.1.1 2019/05/29 04:56:36 root Exp $";
/*
 * $Header: /var/lib/cvsd/repos/coherent/coherent/b/bin/mail/mail.c,v 1.1.1.1 2019/05/29 04:56:36 root Exp $
 * $Log: mail.c,v $
 * Revision 1.1.1.1  2019/05/29 04:56:36  root
 * coherent
 *
 * Revision 1.5  93/06/21  17:47:04  bin
 * bob h removed xmail referencs from help message.
 * 
 * Revision 1.4  92/05/28  10:28:53  bin
 * bob h added a test for new msgsep scheme so that mail will exit
 * if it does not detect the new sep scheme.
 * 
 * Revision 1.2  92/04/20  10:07:46  bin
 * The 'final' fix using CORRECT sources to properly write a msgsep at the
 * top of a save file if new file is opened or if saving the first message
 * of a mailbox to a file
 * 
 * Revision 1.1  92/04/20  09:03:08  bin
 * Initial revision
 * 
 * Revision 3.4	91/02/18  17:14:10	piggy
 * Fixed "q" command so that it works with a non-setuid mail.
 * 
 * Revision 3.3	91/02/18  09:30:09	piggy
 * Fixed two mishandlings of args[].
 * 
 * Revision 3.2	91/02/08  15:16:07	piggy
 * Updated error messages to include malloc failures.
 * 
 * Revision 3.1	91/02/08  14:34:28	piggy
 * Made csplit non-destructive.
 * 
 * Revision 3.0	91/02/07  15:19:14	piggy
 * *** empty log message ***
 * 
 * Revision 2.13	90/03/30  16:16:19 	wgl
 * Correct seek pointer work within readmail.
 * 
 * Revision 2.12	90/03/12  14:19:08 	wgl
 * New version of send doing aliases in a different place.
 * 
 * Revision 2.11	90/03/08  16:41:15 	wgl
 * Add code to get signature file.
 * 
 * Revision 2.10	90/03/02  10:41:59 	wgl
 * Add the -a flag so that uucp does not look like it is coming from
 * somewhere else.
 * 
 * Revision 2.9	90/03/01  11:17:19 	wgl
 * Final conversion to rely soley on ^A^A as separators.
 * Effectively delete concept of m_hsize.
 * 
 * Revision 2.8	90/03/01  10:14:31 	wgl
 * Go buy separators, not "From_" lines.
 * 
 * Revision 2.7	90/02/28  17:11:41 	wgl
 * Add version print, add some changes to the message-id field.
 * 
 * Revision 2.6	90/02/28  16:42:09 	wgl
 * Version number fakeout.
 * 
 * Revision 2.5	90/02/28  16:19:44 	wgl
 * Try again to get versioin number right.
 * 
 * Revision 2.4	90/02/28  16:18:56 	wgl
 * Get version number right.
 * 
 * Revision 2.3	90/02/28  16:04:59 	wgl
 * Many changes; ripped out send.
 * Changes are to make it work with uucp and internet mail.
 * 
 * Revision 1.6	89/02/22  05:34:00 	bin
 * Changes by rec to integrate with lauren's uumail.
 * 
 * Revision 1.5	88/09/01  14:49:01	bin
 * Source administration: Re-install declaration of getenv. 
 * It was inserted after epstein made his copy.
 * 
 * Revision 1.4	88/09/01  14:44:49	bin
 * Mark Epsteins changes for ASKCC and for message scrolling, and interrupt
 * handling during processing.
 * 
 * Revision 1.3	88/09/01  14:27:41	bin
 * declare getenv to get rid of integer pointer pun error message.
 * 
 * Revision 1.2	88/09/01  11:02:23	bin
 * Remove extra declaration of header which had rcs stuff in it.
 * 
 * Revision 1.1	88/09/01  10:55:34	bin
 * Initial revision
 * 
 */
/*
 * The mail command.
 * Coherent electronic postal system, user agent.
 * With v3.0 this program no longer runs setuid.
 * Modifications by rec january 1986 to include xmail.
 * 		 by epstein november 1987 to include CC:
 *		 by epstein november 1987 to allow ^C exit to leave you in
 *					  mail command processor
 *		 by epstein november 1987 to substitute /usr/games/fortune
 *					  for printing encrypted messages
 *		by rec february 1989 to tail to lauren weinstein's
 *			mail for alias expansion and uucp queuing.
 *		by wgl January 1990 to handle uucp mail more directly.
 */

char	isummary[] = "\
\
Command summary:\n\
	d		Delete current message and print the next message\n\
	m [user ...]	Mail current message to each named 'user'\n\
	p		Print current message again\n\
	q		Quit and update the mailbox\n\
	r		Reverse direction of scan\n\
	s [file ...]	Save message in each named 'file'\n\
	t [user ...]	Mail standard input to each named 'user'\n\
	w [file ...]	Save message in each named 'file' without its header\n\
	x		Exit without updating mailbox\n\
	newline		Print the next message\n\
	.		Print current message again\n\
	+		Print the next message\n\
	-		Print the previous message\n\
	EOF		Put undeleted mail back into mailbox and quit\n\
	?		Print this command summary\n\
	!command	Pass 'command' to the shell to execute\n\
If no 'file' is specified, 'mbox' in user's home directory is default.\n\
If no 'user' is specified, the invoking user is default.\n\
\
";

#include "mail.h"

#define	NARGS	64		/* Maximum # args to interactive command */

#define TRACE	printf
#define TRUE	1
#define FALSE	0

extern	char	*getenv();
extern	int	optind;
extern	char	*optarg;
extern	char	getopt();
extern	char	*malloc();
int	csplit();
char	*eat_ws();
char	*find_ws();
char	*revnop();

int	mflag;			/* `You have mail.' message to recipient */
int	rflag;			/* Reverse order of print */
int	qflag;			/* Exit after interrrupts */
int	pflag;			/* Print mail */
int	verbflag;		/* verbose */
int	callmexmail;		/* Xmail modifier present */
int	callmermail;		/* rmail modifier present */
struct	msg {
	struct msg *m_next;		/* Link to next message */
	struct msg *m_prev;		/* Link to previous message */
	int	m_flag;			/* Flags - non-zero if deleted */
	int	m_hsize;		/* Size of header of message */
	fsize_t	m_seek;			/* Start position of message */
	fsize_t	m_end;			/* End of message */
};
struct msg	*m_first = NULL;	/* First message */
struct msg	*m_last = NULL;		/* Last message */

struct	tm	*tp;

char	iusage[] = "Bad command--type '?' for command summary\n";
char	nombox[] = "No mailbox '%s'.\n";
char	nomail[] = "No mail.\n";
char	noperm[] = "Mailbox '%s' access denied.\n";
char	moerr[] = "Cannot open mailbox '%s'\n";
char	wrerr[] = "Write error on '%s'\n";
char	nosave[] = "Cannot save letter in '%s'\n";
char	allocerr[] = "%s: Can't malloc.\n";

FILE	*mfp;				/* Mailbox stream */
int	myuid;				/* User-id of mail user */
int	mygid;				/* Group-id of mail user */
char	myname[25];			/* User name */
char	myfullname[50];
char	mymbox[256];			/* $HOME/mbox		*/
char	mydead[256];			/* $HOME/dead.letter	*/
char	mysig[256];			/* $HOME/.sig.mail	*/
char	myalias[256];			/* $HOME/.aliases	*/
char	spoolname[50] = SPOOLDIR;
char	*mailbox = spoolname;
char	cmdname[1024];		/* Command for x{en,de}code filter */
				/* and for tail recursion to uumail */
				/* and for editor recursion */

char	*args[NARGS];			/* Interactive command arglist */
char	msgline[NLINE];
char	cline[NCLINE] = "+\n";
char	*temp;				/* Currently open temp file	*/
char	templ[] = "/tmp/mailXXXXXX";	/* Temp file name template	*/
char	*editname;			/* name of editor		*/
char	*scatname;			/* name of scat filter		*/
char	*askcc;				/* Ask for CC: list? (YES/NO)	*/

/* fsize_t	ftell(); */
char	*getlogin();
char	*mktemp();
int	catchintr();
int	catchpipe();
char	asuser [32];

typedef short int bool;
bool watch_first_msg;
bool delete_first_msg;

main(argc, argv)
char *argv[];
{
	register char *ap;
	char	c, *foo;
	int i;

	umask(077);
	logopen();

	/* Explicitly NULL out args.  */
	for (i = 0; i < NARGS; ++i) {
		args[i] = NULL;
	}

	ap = argv[0];
	if ( (foo=rindex(ap, '/')) != NULL )
		ap = foo+1;

	callmermail = (strcmp(ap, "rmail") == 0);
	callmexmail = (strcmp(ap, "xmail") == 0);

	if (callmermail)
		logdump("argv0 = rmail\n");

	asuser [0] = '\0';
	signal(SIGINT, catchintr);
	signal(SIGPIPE, catchpipe);
	while ((c = getopt(argc, argv, "a:f:mpqrv")) != EOF) {
		switch(c) {
		case 'f':
			if (!callmermail)
				mailbox = optarg;
			break;
		case 'a':
			strcpy(asuser, optarg);
			break;
		case 'm':
			mflag++;
			break;
		case 'p':
			pflag++;
			break;
		case 'q':
			qflag++;
			break;
		case 'r':
			rflag++;
			break;
		case 'v':
			fprintf(stderr, "mail, ver. %s\n", revnop());
			verbflag++;
			break;
		default:
			usage();
		}
	}
	if (callmermail) 
		verbflag = mflag = pflag = rflag = 0;
	setname();
	if (optind < argc) {
		qflag = 1;
		if ( send2(stdin, &argv[optind], (fsize_t)0,
						 (fsize_t)MAXLONG, 1) != 0 )
			rmexit(1);
	} else {
		if ( ! pflag)
			callmexmail = 0;
		commands();
	}
	rmexit(0);
}

/*
 * Setup all the identities for the current user.
 */
setname()
{
	register struct passwd *pwp;
	register char *np;
	extern struct passwd * getpwnam();

	if (strlen(asuser) > 0) {
		if((pwp = getpwnam(asuser)) == NULL)
			merr("No such user %s.\n", asuser);
		myuid = pwp -> pw_uid;
	} else 		
		myuid = getuid();
	if ((pwp = getpwuid(myuid)) == NULL)
		merr("Who are you?\n");
	np = pwp->pw_name;
	mygid = pwp->pw_gid;
	strcat(spoolname, np);
	strcpy(myname, np);
	strcpy(myfullname, pwp->pw_gecos);
	strcpy(mymbox, pwp->pw_dir);
	strcat(mymbox, "/mbox");
	strcpy(mydead, pwp->pw_dir);
	strcat(mydead, "/dead.letter");
	strcpy(mysig, pwp->pw_dir);
	strcat(mysig, "/.sig.mail");
	strcpy(myalias, pwp->pw_dir);
	strcat(myalias, "/.aliases");
	mktemp(templ);

	if ((editname=getenv("EDITOR"))==NULL)
		editname = "/bin/ed";

	if ( ((scatname=getenv("PAGER")) != NULL) &&
	     (strlen(scatname) == 0) )
		scatname = NULL;

	if ((askcc=getenv("ASKCC")) != NULL)
		if ( strcmp(askcc, "YES") )
			askcc = NULL;
}

/*
 * Process mail's interactive commands
 * for reading/deleting/saving mail.
 */
commands()
{
	register struct msg *mp;
	struct msg *dest;
	struct stat filestats;
	register char **fnp;
	register FILE *fp;
	fsize_t seek;
	int need_to_add_sep;
	char am_i_sep[7];
	bool first_msg_read;
	int testfile; /* used to test if file exists */

	readmail();
	mprint(mp = rflag ? m_last : m_first);
	for (;;) {
		readmail();
		intcheck();

	/* if pflag is set, then we will loop through and print all messages
	 * without stopping between messages for command prompts
	 */
		if(!pflag){
			callmexmail = 0;
			mmsg("? ");
			if (fgets(cline, sizeof cline, stdin) == NULL){
				if(intcheck())
					continue;
				break;
			}
		}

		switch (cline[0]) {
		case 'd':
			if (cline[1] != '\n')
				goto usage;
			mp->m_flag += 1;
			if(mp->m_seek == 5)
				delete_first_msg = TRUE;
			goto advance;

		case 'm':
		case 't':
			if (csplit(cline, args) == 1) {
				/* We don't want to put anything into
				   args that we didn't get from malloc. */

				if (args[1] != NULL) {
					free(args[1]);
				}
				args[1] = malloc(strlen(myname) + 1);
				strcpy(args[1], myname);
				args[2] = NULL;
			}
			callmexmail = (cline[1] == 'x');
			if (cline[0] == 'm') {
	/* when forwarding mail, seek  to msg start + 5 to rid the msgsep */
			send2(mfp, args+1, (mp->m_seek + 5), mp->m_end - ((sizeof(MSGSEP) - 1) *2), 0);
				fseek(mfp, mp->m_seek, 0);
			} else
				send2(stdin, args+1, 0L, (fsize_t)MAXLONG, 1);
			break;

		case '.':
		case 'p':
			if (cline[1] == 'x') {
				callmexmail = 1;
				if (cline[2] != '\n')
					goto usage;
			} else if (cline[1] != '\n')
				goto usage;
			if (mprint(mp))
				break;
			goto advance;

		case 'q':
			if (cline[1] != '\n')
				goto usage;
			mquit();
			/* NOTREACHED */

		case 'r':
			if (cline[1] != '\n')
				goto usage;
			rflag = ! rflag;
			break;
		case 's':
		case 'w':
			if (csplit(cline, args) == 1) {
				/* We don't want to put anything into
				   args that we didn't get from malloc. */

				if (args[1] != NULL) {
					free(args[1]);
				}
				args[1] = malloc(strlen(mymbox) + 1);
				strcpy(args[1], mymbox);
				args[2] = NULL;
			}
			seek = mp->m_seek;
			if (cline[0] == 'w')
				seek += mp->m_hsize;
			for (fnp = &args[1]; *fnp != NULL; fnp++) {
				fp = NULL;

				testfile = stat(*fnp, &filestats);

		/* attempt to open the file and write */

				if ( (maccess(*fnp) < 0) 
				  || ( (fp = fopen(*fnp,"a")) == NULL)
				  || (mcopy(mfp,fp,seek,mp->m_end,0)))
					mmsg(nosave, *fnp);

		/* close the output file. Because some screwy 'not logic'
		 * was used to determine how msg seps were treated in elm
		 * (and I actually understood it after a while), it was
		 * semi implemented here for SCO mail format compatibility.
		 * Unfortunately, for reasons not clear to me yet, sometimes
		 * a message is copied to the out file with no msgsep appended
		 * to the end of it. So, after appending our message to the
		 * outfile, we will reopen the outfile, seek to the last
		 * byte - 5, and see if the last 5 bytes are a msgsep. If
		 * not, close the file and reopen for append and then write
		 * the msgsep.
		 */
				if (fp != NULL) {
					fflush(fp);
					fclose(fp);
					stat(*fnp,&filestats);
					fp = fopen(*fnp,"r");
/*		TRACE("Seeking to position %d\n",(filestats.st_size - 5)); */
				fseek(fp,(filestats.st_size - 5),0);
					fgets(am_i_sep,sizeof(MSGSEP),fp);
					fclose(fp);
					need_to_add_sep = strcmp(am_i_sep,MSGSEP
);
					if(need_to_add_sep){
						fp = fopen(*fnp,"a");
						fprintf(fp,MSGSEP);
						fflush(fp);
						fclose(fp);
					}
			
					
					chown(*fnp, myuid, mygid);
				}
			}
			break;

		case 'x':
			if (cline[1] != '\n')
				goto usage;
			rmexit(0);
			/* NOTREACHED */

		case '!':
			if (system(cline+1) == 127)
				mmsg("Try again\n");
			else
				mmsg("!\n");
			break;

		case '?':
			mmsg(isummary);
			break;

		case '-':
			if (cline[1] != '\n')
				goto usage;
			dest = rflag ? m_last : m_first;
			goto nextmsg;

		case '+':
			if (cline[1] != '\n')
				goto usage;
		case '\n':
		advance:
			dest = rflag ? m_first : m_last;
		nextmsg:
			do {
				if (mp == dest) {
					if (pflag)
						return;
					mmsg("No more messages.\n");
					break;
				}
				mp = (dest==m_last) ? mp->m_next : mp->m_prev;
			} while (mprint(mp) == 0);
			break;

		default:
		usage:
			mmsg(iusage);
			break;
		}
	}
	putc('\n', stderr);
	mquit();
}

/*
 * Read through the mail-box file
 * constructing list of letters.
 * On subsequent calls, append any additional mail
 * and notify the user.
 */
readmail()
{
	typedef short int bool;
	register struct msg *mp;
	struct stat sb;
	static long m_last_end;
	int datasw;
	bool newmsg;
	static bool checked_format;
	static fsize_t original_box_size;
	char convert_cmd[65];

	if (m_first == NULL) {
		if (stat(mailbox, &sb) < 0)
			merr(nombox, mailbox);
		if (sb.st_size == 0)
			merr(nomail);

		/* the following will open the mailbox and read the first
		 * line. If it is not a MSGSEP, then a message will be printed
		 * to run cvmail and exit.
		 */

		if(!checked_format){
			if ((mfp = fopen(mailbox, "r")) == NULL)
				merr(moerr, mailbox);
			if(fgets(msgline, sizeof msgline, mfp) == NULL){
				printf("Can not determine mailbox format\n");
				exit(1);
			}
			fclose(mfp);
			checked_format = TRUE;
			if(strcmp(MSGSEP, msgline)){
				printf("Your mailbox or mailfile needs to be converted to the proper format.\n");
				strcpy(convert_cmd, "/bin/cvmail ");
				strcat(convert_cmd, mailbox);
				printf("\nTo manually convert your mailbox, run: %s\n\n", convert_cmd);
				exit(1);
			}
		}

		original_box_size = sb.st_size;
		if (access(mailbox, AREAD) < 0)
			merr(noperm, mailbox);
		if ((mfp = fopen(mailbox, "r")) == NULL)
			merr(moerr, mailbox);
		m_last_end = 0;
	} else {
		fstat(fileno(mfp), &sb);
		if (sb.st_size == m_last_end)
			return;
		if (sb.st_size != original_box_size){
			mmsg("More mail received.\n");
			original_box_size = sb.st_size;
		}
	}

	/* we will enter a loop which reads the mailbox line by line.
	 * When it hits a MSGSEP indicating the end of a mail message,
	 * a struct msg will be set with the start and end positions
	 * of the message read. We will continue through this loop until 
	 * struct msg's have been built for all messages.
	 */

	newmsg = TRUE;
	for(mlock(myuid);;) {
		fseek(mfp, m_last_end, 0);
		datasw = 0;
		while (fgets(msgline, sizeof msgline, mfp) != NULL) {
			/* NB: this means the implicit message
			   seperator is actually "\n\1\1\n".  */
			if(!(datasw = strcmp(MSGSEP, msgline))){

				/* message seperator */
				if (((newmsg = !newmsg) == TRUE) && (ftell(mfp) != 5)){
					mp = (struct msg *)myalloc(sizeof(*mp));
					mp->m_next = NULL;
					mp->m_prev = m_last;
					mp->m_flag = mp->m_hsize = 0;
	/* start position of msg */	mp->m_seek = m_last_end;
	/* end position of msg */	mp->m_end = m_last_end = ftell(mfp);
/*	TRACE("Message ends at %ld\n",ftell(mfp)); */
					if (m_first == NULL)
						m_last = m_first = mp;
					else
						m_last = m_last->m_next = mp;
				}
			}
		}

		if(!datasw) /* data ended with message seperator */
			break;

		/* unterminated data, patch and retry */
		fclose(mfp);
		if ((mfp = fopen(mailbox, "a")) == NULL)
			merr(moerr, mailbox);
		fprintf(mfp, MSGSEP); /* terminate it */
		fclose(mfp);
		if ((mfp = fopen(mailbox, "r")) == NULL)
			merr(moerr, mailbox);
		mmsg("Incomplete message found.\n");
	}
	munlock();
}

/*
 * Lock the appropriately-numbered mailbox
 * (numbered by user-number) from multiple
 * accesses. There is a (small) race here
 * which will be overlooked for now.
 */
char	*lockname;

mlock(uid)
int uid;
{
	register int fd;
	static char lock[32];

	lockname = lock;
	sprintf(lock, "/tmp/maillock%d", uid);
	while (access(lockname, 0) == 0)
		sleep(1);
	if ((fd = creat(lockname, 0)) >= 0)
		close(fd);
}

/*
 * Unlock the currently-set lock (by `mlock')
 * also called from rmexit.
 */
munlock()
{
	if (lockname != NULL)
		unlink(lockname);
	lockname = NULL;
}

/*
 * Exit, after rewriting the
 * mailbox
 */
mquit()
{
	register struct msg *mp;
	register FILE *nfp, *tmpfp;
	struct stat sb;

	/* Get new stuff. */
	readmail();
	/* There is a slight race here.  We really should
	   lock BEFORE the readmail(), but readmail() does unlocks...
	   FIX ME. */
	mlock(myuid);

	if (mailbox != spoolname && maccess(mailbox) < 0)
		merr(noperm, mailbox);
	fstat(fileno(mfp), &sb);
	signal(SIGINT, SIG_IGN);
	signal(SIGPIPE, SIG_IGN);

	/* Make a copy of the mail box; we're going to overwrite it.  */
	tmpfp = tmp_copy(mfp);
	fclose(mfp);

	if ((nfp = fopen(mailbox, "w")) == NULL)
		merr("Cannot re-write '%s'\n", mailbox);
	chown(mailbox, sb.st_uid, sb.st_gid);
	chmod(mailbox, sb.st_mode&0777);
	for (mp = m_first; mp != NULL; mp = mp->m_next) {

		if (mp->m_flag == 0) {
			if(delete_first_msg){
				mp->m_seek = mp->m_seek+5;
				delete_first_msg = FALSE;
			}
			if (mcopy(tmpfp, nfp, mp->m_seek, mp->m_end, 0)) {
				merr(wrerr, mailbox);
			}
		} /* if (mp->m_flag == 0) */

	} /* for (walk through the linked list of messages) */

	fclose(nfp);
	fclose(tmpfp);
	munlock();
	rmexit(0);
}

/*
 * Print the current message, given by
 * the message pointer (`mp').
 */
mprint(mp)
register struct msg *mp;
{
	FILE *xfp;

	if (mp->m_flag)
		return 0;
	if (callmexmail) {
		if (scatname != NULL) 
			sprintf(cmdname, "xdecode | %s", scatname);
		else
			sprintf(cmdname, "xdecode");
		if ((xfp = popen(cmdname, "w")) == NULL)
			return 0;
		fprintf(xfp, MSGSEP);
		mcopy(mfp, xfp, mp->m_seek+mp->m_hsize, mp->m_end, 1);
		pclose(xfp);
	} else {
		fseek(mfp, mp->m_seek, 0);
		if (fgets(msgline, sizeof msgline, mfp) != NULL &&
		    strncmp(msgline, "From xmail", 10) == 0) {
			printf("From xmail\n");
			system("/usr/games/fortune");
			return(1);
		}
		if (scatname != NULL) {
			sprintf(cmdname, "%s", scatname);
			if ((xfp = popen(cmdname, "w")) == NULL)
				return(0);
			mcopy(mfp, xfp, mp->m_seek, mp->m_end - 5, 1);
			if ( ((pclose(xfp)>>8)&0xFF) == SIGINT )
				putc('\n', stdout);
		} else {
			mcopy(mfp, stdout, mp->m_seek, mp->m_end - 5, 1);
		}
	}
	return (1);
}

/*
 *	Get additional users to receive message (CC:)
 */

char **
getcc()
{
	static	char names[NCLINE];
	static	char *ccargs[NARGS];

	ccargs[0] = NULL;
	mmsg("CC: ");
	if ( fgets(names, sizeof names, stdin) == NULL )
		return(ccargs);

	csplit(names, ccargs);
	return(ccargs);
}

	
/*
 * Errors, usage, and exit removing
 * any tempfiles left around.
 */
mmsg(x)
{
	fprintf(stderr, "%r", &x);
}

merr(x, s)
char *x, *s;
{
	mmsg(x, s);
	logdump("merr: ");
	logdump(x, s);
	rmexit(1);
}

rmexit(s)
int s;
{
	if (temp != NULL)
		unlink(temp);
	munlock();

	logdump("About to exit, status = 0x%04x\n", s);
	logclose();

	exit(s);
}

/*
 * Catch interrupts, taking the
 * appropriate action based on
 * the `-q' option.
 */
int	intrflag;		/* On when interrupt sent	*/
int	pipeflag;		/* On when broken pipe caught	*/

catchintr()
{
	logdump("Caught SIGINT\n");
	if (qflag)
		rmexit(1);
	intrflag = 1;
	signal(SIGINT, catchintr);
}

catchpipe()
{
	logdump("Caught SIGPIPE\n");
	pipeflag = 1;
	signal(SIGPIPE, catchpipe);
}

intcheck()
{
	if (intrflag || pipeflag) {
		if (intrflag)
			putc('\n', stdout);
		intrflag = pipeflag = 0;
		return (1);
	}
	return (0);
}

/*
 * Call the system to execute a command line
 * which is passed as an argument.
 * Change the user id and group id.
 */
system(line)
char *line;
{
	int status, pid;
	register wpid;
	register int (*intfun)(), (*quitfun)();

	if ((pid = fork()) < 0)
		return (-1);
	if (pid == 0) {		/* Child */
		setuid(myuid);
		setgid(mygid);
		execl("/bin/sh", "sh", "-c", line, NULL);
		exit(0177);
	}
	intfun = signal(SIGINT, SIG_IGN);
	quitfun = signal(SIGQUIT, SIG_IGN);
	while ((wpid = wait(&status))!=pid && wpid>=0)
		;
	if (wpid < 0)
		status = wpid;
	signal(SIGINT, intfun);
	signal(SIGQUIT, quitfun);
	return (status);
}

char	*
revnop()
{
	register	char *cp;
	register	char c;
	static		char revnobuf[32];

	if ((cp = index(rcsrev, ' ')) != NULL) {
		while (((c = *++cp) == ' ') && (c != '\0'))
			;
		strcpy(revnobuf, cp);
		if ((cp = index(revnobuf, ' ')) != NULL)
			*cp = '\0';
		return (revnobuf);
	} else
		return("OOPS");
}

/*
 * Split a command line up into
 * argv (passed) and argc (returned).
 * We assume that elements of "args" are either NULL or they were
 * returned from malloc, so that they can be freed.
 */
int
csplit(command, args)
char *command;
char **args;
{
	register char *cp;
	int i, argsize;

	i = 0; /* Start filling in at the zero'th arg.  */
	cp = eat_ws(command);	

	/* Walk "cp" through "command", copying segments as we go.  */
	while ( *cp != CNULL ) {
		/* We've found an argument; find some space.  */
		if (args[i] != NULL ) {
			free(args[i]);
		}

		/* Figure out how big the argment is.  */
		argsize = (int) (find_ws(cp) - cp);

		/* Alloc enough space for it--include the trailing NULL.  */
		if ((args[i] = malloc(argsize + 1)) == NULL) {
			mmsg(allocerr, "csplit");
			return(0);  /* Is this the approriate action?? */
		}

		/* Copy the argument into the space.  */
		memcpy(args[i], cp, argsize);
		args[i][argsize] = CNULL; /* This may be redundant.  */

		/* Make sure that cp points to after the argument.  */
		cp += argsize;

		cp = eat_ws(cp);
		++i;
	} /* while (walk "cp" through "command") */

	args[i] = NULL;
	return (i);
}

/*
 * Find the next occurence of non-white space in character string s.
 */
char *
eat_ws(s)
	char *s;
{
	while(isspace(*s)){
		++s;
	}
	return(s);
}

/*
 * Find next occurence of white space in character string s.
 */
char *
find_ws(s)
	register char *s;
{
	while((*s != CNULL) && !isspace(*s) ){
		++s;
	}
	return(s);
}	

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.