1 #include <ctype.h>
2 #include <stdio.h>
3 #include <pwd.h>
4 #include <utmp.h>
5 #include <signal.h>
6 #include <sys/types.h>
7 #include <sys/stat.h>
8 #include <setjmp.h>
9 #include <whoami.h>
10 #include <sysexits.h>
11 
12 static char SccsId[] = "@(#)mail.local.c	4.1	10/01/80";
13 
14 #define DELIVERMAIL	"/etc/delivermail"
15 
16 
17 /*copylet flags */
18 	/*remote mail, add rmtmsg */
19 #define REMOTE	1
20 	/* zap header and trailing empty line */
21 #define ZAP	3
22 #define ORDINARY 2
23 #define	FORWARD	4
24 #define	LSIZE	256
25 #define	MAXLET	300	/* maximum number of letters */
26 #define	MAILMODE (~0644)		/* mode of created mail */
27 # ifndef DELIVERMAIL
28 #define	RMAIL	"/usr/net/bin/sendberkmail"
29 #define LOCNAM1	"csvax"
30 #define LOCNAM2	"ucbvax"
31 #define LOCNAM3	"vax"
32 #define LOCNAM4	"v"
33 # endif
34 
35 char	line[LSIZE];
36 char	resp[LSIZE];
37 struct let {
38 	long	adr;
39 	char	change;
40 } let[MAXLET];
41 int	nlet	= 0;
42 char	lfil[50];
43 long	iop, time();
44 char	*getenv();
45 char	*index();
46 char	lettmp[] = "/tmp/maXXXXX";
47 char	maildir[] = "/usr/spool/mail/";
48 char	mailfile[] = "/usr/spool/mail/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
49 char	dead[] = "dead.letter";
50 char	*thissys = sysname;
51 char	*netname = "vax";
52 char	forwmsg[] = " forwarded\n";
53 FILE	*tmpf;
54 FILE	*malf;
55 char	*my_name;
56 char	*getlogin();
57 struct	passwd	*getpwuid();
58 int	error;
59 int	changed;
60 int	forward;
61 char	from[] = "From ";
62 long	ftell();
63 int	delete();
64 char	*ctime();
65 int	flgf;
66 int	flgp;
67 int	delflg = 1;
68 int	hseqno;
69 jmp_buf	sjbuf;
70 int	rmail;
71 
72 main(argc, argv)
73 char **argv;
74 {
75 	register i;
76 	char sobuf[BUFSIZ];
77 
78 	setbuf(stdout, sobuf);
79 	mktemp(lettmp);
80 	unlink(lettmp);
81 	my_name = getlogin();
82 	if (my_name == NULL || strlen(my_name) == 0) {
83 		struct passwd *pwent;
84 		pwent = getpwuid(getuid());
85 		if (pwent==NULL)
86 			my_name = "???";
87 		else
88 			my_name = pwent->pw_name;
89 	}
90 	if(setjmp(sjbuf)) done();
91 	for (i=0; i<20; i++)
92 		setsig(i, delete);
93 	tmpf = fopen(lettmp, "w");
94 	if (tmpf == NULL) {
95 		fprintf(stderr, "mail: cannot open %s for writing\n", lettmp);
96 		done();
97 	}
98 	if (argv[0][0] == 'r')
99 		rmail++;
100 	if (argv[0][0] != 'r' &&	/* no favors for rmail*/
101 	   (argc == 1 || argv[1][0] == '-' && !any(argv[1][1], "rhd")))
102 		printmail(argc, argv);
103 	else
104 		sendmail(argc, argv);
105 	done();
106 }
107 
108 setsig(i, f)
109 int i;
110 int (*f)();
111 {
112 	if(signal(i, SIG_IGN)!=SIG_IGN)
113 		signal(i, f);
114 }
115 
116 any(c, str)
117 	register int c;
118 	register char *str;
119 {
120 
121 	while (*str)
122 		if (c == *str++)
123 			return(1);
124 	return(0);
125 }
126 
127 printmail(argc, argv)
128 char **argv;
129 {
130 	int flg, i, j, print;
131 	char *p, *getarg();
132 	struct stat statb;
133 
134 	setuid(getuid());
135 	cat(mailfile, maildir, my_name);
136 	if (stat(mailfile, &statb) >= 0
137 	    && (statb.st_mode & S_IFMT) == S_IFDIR) {
138 		strcat(mailfile, "/");
139 		strcat(mailfile, my_name);
140 	}
141 	for (; argc>1; argv++, argc--) {
142 		if (argv[1][0]=='-') {
143 			if (argv[1][1]=='q')
144 				delflg = 0;
145 			else if (argv[1][1]=='p') {
146 				flgp++;
147 				delflg = 0;
148 			} else if (argv[1][1]=='f') {
149 				if (argc>=3) {
150 					strcpy(mailfile, argv[2]);
151 					argv++;
152 					argc--;
153 				}
154 			} else if (argv[1][1]=='r') {
155 				forward = 1;
156 			} else if (argv[1][1]=='h') {
157 				forward = 1;
158 			} else {
159 				fprintf(stderr, "mail: unknown option %c\n", argv[1][1]);
160 				done();
161 			}
162 		} else
163 			break;
164 	}
165 	malf = fopen(mailfile, "r");
166 	if (malf == NULL) {
167 		fprintf(stdout, "No mail.\n");
168 		return;
169 	}
170 	lock(mailfile);
171 	copymt(malf, tmpf);
172 	fclose(malf);
173 	fclose(tmpf);
174 	unlock();
175 	tmpf = fopen(lettmp, "r");
176 
177 	changed = 0;
178 	print = 1;
179 	for (i = 0; i < nlet; ) {
180 		j = forward ? i : nlet - i - 1;
181 		if(setjmp(sjbuf)) {
182 			print=0;
183 		} else {
184 			if (print)
185 				copylet(j, stdout, ORDINARY);
186 			print = 1;
187 		}
188 		if (flgp) {
189 			i++;
190 			continue;
191 		}
192 		setjmp(sjbuf);
193 		fprintf(stdout, "? ");
194 		fflush(stdout);
195 		if (fgets(resp, LSIZE, stdin) == NULL)
196 			break;
197 		switch (resp[0]) {
198 
199 		default:
200 			fprintf(stderr, "usage\n");
201 		case '?':
202 			print = 0;
203 			fprintf(stderr, "q\tquit\n");
204 			fprintf(stderr, "x\texit without changing mail\n");
205 			fprintf(stderr, "p\tprint\n");
206 			fprintf(stderr, "s[file]\tsave (default mbox)\n");
207 			fprintf(stderr, "w[file]\tsame without header\n");
208 			fprintf(stderr, "-\tprint previous\n");
209 			fprintf(stderr, "d\tdelete\n");
210 			fprintf(stderr, "+\tnext (no delete)\n");
211 			fprintf(stderr, "m user\tmail to user\n");
212 			fprintf(stderr, "! cmd\texecute cmd\n");
213 			break;
214 
215 		case '+':
216 		case 'n':
217 		case '\n':
218 			i++;
219 			break;
220 		case 'x':
221 			changed = 0;
222 		case 'q':
223 			goto donep;
224 		case 'p':
225 			break;
226 		case '^':
227 		case '-':
228 			if (--i < 0)
229 				i = 0;
230 			break;
231 		case 'y':
232 		case 'w':
233 		case 's':
234 			flg = 0;
235 			if (resp[1] != '\n' && resp[1] != ' ') {
236 				printf("illegal\n");
237 				flg++;
238 				print = 0;
239 				continue;
240 			}
241 			if (resp[1] == '\n' || resp[1] == '\0') {
242 				p = getenv("HOME");
243 				if(p != 0)
244 					cat(resp+1, p, "/mbox");
245 				else
246 					cat(resp+1, "", "mbox");
247 			}
248 			for (p = resp+1; (p = getarg(lfil, p)) != NULL; ) {
249 				malf = fopen(lfil, "a");
250 				if (malf == NULL) {
251 					fprintf(stdout, "mail: cannot append to %s\n", lfil);
252 					flg++;
253 					continue;
254 				}
255 				copylet(j, malf, resp[0]=='w'? ZAP: ORDINARY);
256 				fclose(malf);
257 			}
258 			if (flg)
259 				print = 0;
260 			else {
261 				let[j].change = 'd';
262 				changed++;
263 				i++;
264 			}
265 			break;
266 		case 'm':
267 			flg = 0;
268 			if (resp[1] == '\n' || resp[1] == '\0') {
269 				i++;
270 				continue;
271 			}
272 			if (resp[1] != ' ') {
273 				printf("invalid command\n");
274 				flg++;
275 				print = 0;
276 				continue;
277 			}
278 			for (p = resp+1; (p = getarg(lfil, p)) != NULL; )
279 				if (!sendrmt(j, lfil, "/bin/mail"))	/* couldn't send it */
280 					flg++;
281 			if (flg)
282 				print = 0;
283 			else {
284 				let[j].change = 'd';
285 				changed++;
286 				i++;
287 			}
288 			break;
289 		case '!':
290 			system(resp+1);
291 			printf("!\n");
292 			print = 0;
293 			break;
294 		case 'd':
295 			let[j].change = 'd';
296 			changed++;
297 			i++;
298 			if (resp[1] == 'q')
299 				goto donep;
300 			break;
301 		}
302 	}
303    donep:
304 	if (changed)
305 		copyback();
306 }
307 
308 copyback()	/* copy temp or whatever back to /usr/spool/mail */
309 {
310 	register i, n, c;
311 	int new = 0;
312 	struct stat stbuf;
313 
314 	signal(SIGINT, SIG_IGN);
315 	signal(SIGHUP, SIG_IGN);
316 	signal(SIGQUIT, SIG_IGN);
317 	lock(mailfile);
318 	stat(mailfile, &stbuf);
319 	if (stbuf.st_size != let[nlet].adr) {	/* new mail has arrived */
320 		malf = fopen(mailfile, "r");
321 		if (malf == NULL) {
322 			fprintf(stdout, "mail: can't re-read %s\n", mailfile);
323 			done();
324 		}
325 		fseek(malf, let[nlet].adr, 0);
326 		fclose(tmpf);
327 		tmpf = fopen(lettmp, "a");
328 		fseek(tmpf, let[nlet].adr, 0);
329 		while ((c = fgetc(malf)) != EOF)
330 			fputc(c, tmpf);
331 		fclose(malf);
332 		fclose(tmpf);
333 		tmpf = fopen(lettmp, "r");
334 		let[++nlet].adr = stbuf.st_size;
335 		new = 1;
336 	}
337 	malf = fopen(mailfile, "w");
338 	if (malf == NULL) {
339 		fprintf(stderr, "mail: can't rewrite %s\n", lfil);
340 		done();
341 	}
342 	n = 0;
343 	for (i = 0; i < nlet; i++)
344 		if (let[i].change != 'd') {
345 			copylet(i, malf, ORDINARY);
346 			n++;
347 		}
348 	fclose(malf);
349 	if (new)
350 		fprintf(stdout, "new mail arrived\n");
351 	unlock();
352 }
353 
354 copymt(f1, f2)	/* copy mail (f1) to temp (f2) */
355 FILE *f1, *f2;
356 {
357 	long nextadr;
358 
359 	nlet = nextadr = 0;
360 	let[0].adr = 0;
361 	while (fgets(line, LSIZE, f1) != NULL) {
362 		if (isfrom(line))
363 			let[nlet++].adr = nextadr;
364 		nextadr += strlen(line);
365 		fputs(line, f2);
366 	}
367 	let[nlet].adr = nextadr;	/* last plus 1 */
368 }
369 
370 copylet(n, f, type) FILE *f;
371 {	int ch, k;
372 	fseek(tmpf, let[n].adr, 0);
373 	k = let[n+1].adr - let[n].adr;
374 	while(k-- > 1 && (ch=fgetc(tmpf))!='\n')
375 		if(type!=ZAP) fputc(ch,f);
376 	if(type==REMOTE)
377 		fprintf(f, " remote from %s\n", thissys);
378 	else if (type==FORWARD)
379 		fprintf(f, forwmsg);
380 	else if(type==ORDINARY)
381 		fputc(ch,f);
382 	while(k-->1)
383 		fputc(ch=fgetc(tmpf), f);
384 	if(type!=ZAP || ch!= '\n')
385 		fputc(fgetc(tmpf), f);
386 }
387 
388 isfrom(lp)
389 register char *lp;
390 {
391 	register char *p;
392 
393 	for (p = from; *p; )
394 		if (*lp++ != *p++)
395 			return(0);
396 	return(1);
397 }
398 
399 sendmail(argc, argv)
400 char **argv;
401 {
402 	char truename[100];
403 	int first;
404 	register char *cp;
405 	int gaver = 0;
406 # ifdef DELIVERMAIL
407 	char *newargv[1000];
408 	register char **ap;
409 	register char **vp;
410 	int dflag;
411 
412 	dflag = 0;
413 	if (argc < 1)
414 		fprintf(stderr, "puke\n");
415 	for (vp = argv, ap = newargv + 1; (*ap = *vp++) != 0; ap++)
416 	{
417 		if (ap[0][0] == '-' && ap[0][1] == 'd')
418 			dflag++;
419 	}
420 	if (!dflag)
421 	{
422 		/* give it to delivermail, rah rah! */
423 		unlink(lettmp);
424 		ap = newargv+1;
425 		if (rmail)
426 			*ap-- = "-s";
427 		*ap = "-delivermail";
428 		execv(DELIVERMAIL, ap);
429 		perror(DELIVERMAIL);
430 		exit(EX_UNAVAILABLE);
431 	}
432 # endif DELIVERMAIL
433 
434 	truename[0] = 0;
435 	line[0] = '\0';
436 
437 	/*
438 	 * When we fall out of this, argv[1] should be first name,
439 	 * argc should be number of names + 1.
440 	 */
441 
442 	while (argc > 1 && *argv[1] == '-') {
443 		cp = *++argv;
444 		argc--;
445 		switch (cp[1]) {
446 		case 'r':
447 			if (argc <= 0) {
448 				usage();
449 				done();
450 			}
451 			gaver++;
452 			strcpy(truename, argv[1]);
453 			fgets(line, LSIZE, stdin);
454 			if (strcmpn("From", line, 4) == 0)
455 				line[0] = '\0';
456 			argv++;
457 			argc--;
458 			break;
459 
460 		case 'h':
461 			if (argc <= 0) {
462 				usage();
463 				done();
464 			}
465 			hseqno = atoi(argv[1]);
466 			argv++;
467 			argc--;
468 			break;
469 
470 # ifdef DELIVERMAIL
471 		case 'd':
472 			break;
473 # endif DELIVERMAIL
474 
475 		default:
476 			usage();
477 			done();
478 		}
479 	}
480 	if (argc <= 1) {
481 		usage();
482 		done();
483 	}
484 	if (gaver == 0)
485 		strcpy(truename, my_name);
486 	/*
487 	if (argc > 4 && strcmp(argv[1], "-r") == 0) {
488 		strcpy(truename, argv[2]);
489 		argc -= 2;
490 		argv += 2;
491 		fgets(line, LSIZE, stdin);
492 		if (strcmpn("From", line, 4) == 0)
493 			line[0] = '\0';
494 	} else
495 		strcpy(truename, my_name);
496 	*/
497 	time(&iop);
498 	fprintf(tmpf, "%s%s %s", from, truename, ctime(&iop));
499 	iop = ftell(tmpf);
500 	flgf = 1;
501 	for (first = 1;; first = 0) {
502 		if (first && line[0] == '\0' && fgets(line, LSIZE, stdin) == NULL)
503 			break;
504 		if (!first && fgets(line, LSIZE, stdin) == NULL)
505 			break;
506 		if (line[0] == '.' && line[1] == '\n' && isatty(fileno(stdin)))
507 			break;
508 		if (isfrom(line))
509 			fputs(">", tmpf);
510 		fputs(line, tmpf);
511 		flgf = 0;
512 	}
513 	fputs("\n", tmpf);
514 	nlet = 1;
515 	let[0].adr = 0;
516 	let[1].adr = ftell(tmpf);
517 	fclose(tmpf);
518 	if (flgf)
519 		return;
520 	tmpf = fopen(lettmp, "r");
521 	if (tmpf == NULL) {
522 		fprintf(stderr, "mail: cannot reopen %s for reading\n", lettmp);
523 		return;
524 	}
525 	while (--argc > 0)
526 		if (!send(0, *++argv, truename))
527 			error++;
528 	if (error) {
529 		setuid(getuid());
530 		malf = fopen(dead, "w");
531 		if (malf == NULL) {
532 			fprintf(stdout, "mail: cannot open %s\n", dead);
533 			fclose(tmpf);
534 			return;
535 		}
536 		copylet(0, malf, ZAP);
537 		fclose(malf);
538 		fprintf(stdout, "Mail saved in %s\n", dead);
539 	}
540 	fclose(tmpf);
541 }
542 
543 sendrmt(n, name, rcmd)
544 char *name;
545 char *rcmd;
546 {
547 	FILE *rmf, *popen();
548 	register char *p;
549 	char rsys[64], cmd[64];
550 	register local, pid;
551 	int sts;
552 
553 	local = 0;
554 	if (index(name, '^')) {
555 		while (p = index(name, '^'))
556 			*p = '!';
557 		if (strncmp(name, "researc", 7)) {
558 			strcpy(rsys, "research");
559 			if (*name != '!')
560 				--name;
561 			goto skip;
562 		}
563 	}
564 	if (*name=='!')
565 		name++;
566 	for(p=rsys; *name!='!'; *p++ = *name++)
567 		if (*name=='\0') {
568 			local++;
569 			break;
570 		}
571 	*p = '\0';
572 	if ((!local && *name=='\0') || (local && *rsys=='\0')) {
573 		fprintf(stdout, "null name\n");
574 		return(0);
575 	}
576 skip:
577 	if ((pid = fork()) == -1) {
578 		fprintf(stderr, "mail: can't create proc for remote\n");
579 		return(0);
580 	}
581 	if (pid) {
582 		while (wait(&sts) != pid) {
583 			if (wait(&sts)==-1)
584 				return(0);
585 		}
586 		return(!sts);
587 	}
588 	setuid(getuid());
589 	if (local)
590 		sprintf(cmd, "%s %s", rcmd, rsys);
591 	else {
592 		if (index(name+1, '!'))
593 			sprintf(cmd, "uux - %s!rmail \\(%s\\)", rsys, name+1);
594 		else
595 			sprintf(cmd, "uux - %s!rmail %s", rsys, name+1);
596 	}
597 	if ((rmf=popen(cmd, "w")) == NULL)
598 		exit(1);
599 	copylet(n, rmf, local ? !strcmp(rcmd, "/bin/mail") ? FORWARD : ORDINARY : REMOTE);
600 	pclose(rmf);
601 	exit(0);
602 }
603 
604 # ifndef DELIVERMAIL
605 /*
606  * Send mail on the Berkeley network.
607  * Sorry Bill, sendrmt() is so awful we just gave up.
608  */
609 
610 sendberkmail(n, name, fromaddr)
611 	char name[];
612 	char fromaddr[];
613 {
614 	char cmd[200];
615 	register FILE *cmdf;
616 
617 	sprintf(cmd, "%s -h %d -f %s -t %s", RMAIL, hseqno, fromaddr, name);
618 	if ((cmdf = popen(cmd, "w")) == NULL) {
619 		perror(RMAIL);
620 		return(0);
621 	}
622 	copylet(n, cmdf, ORDINARY);
623 	pclose(cmdf);
624 	return(9);
625 }
626 # endif
627 
628 usage()
629 {
630 
631 	fprintf(stderr, "Usage: mail [ -f ] people . . .\n");
632 }
633 
634 send(n, name, fromaddr)
635 int n;
636 char *name;
637 char *fromaddr;
638 {
639 	char file[100];
640 	register char *p;
641 	register mask;
642 	struct passwd *pw, *getpwnam();
643 	struct stat statb;
644 
645 # ifndef DELIVERMAIL
646 	stripfx(LOCNAM1, &name);
647 	stripfx(LOCNAM2, &name);
648 	stripfx(LOCNAM3, &name);
649 	stripfx(LOCNAM4, &name);
650 	if(*name == ':')name++;		/* skip colon in to-name */
651 	for(p=name; *p!=':' && *p!='!' && *p!='^' &&*p!='\0'; p++);
652 	/* if(*p == ':') return(sendrmt(n, name, RMAIL)); */
653 	if (*p == ':')
654 		return(sendberkmail(n, name, fromaddr));
655 	else if (*p=='\0' && strcmp(name, "msgs") == 0)
656 		return(sendrmt(n, "-s", "/usr/ucb/msgs"));
657 # endif
658 	for(p=name; *p!='!'&&*p!='^' &&*p!='\0'; p++)
659 		;
660 	if (*p == '!'|| *p=='^')
661 		return(sendrmt(n, name, 0));
662 	if ((pw = getpwnam(name)) == NULL) {
663 		fprintf(stdout, "mail: can't send to %s\n", name);
664 		return(0);
665 	}
666 	cat(file, maildir, name);
667 	if (stat(file, &statb) >= 0 && (statb.st_mode & S_IFMT) == S_IFDIR) {
668 		strcat(file, "/");
669 		strcat(file, name);
670 	}
671 	mask = umask(MAILMODE);
672 	malf = fopen(file, "a");
673 	umask(mask);
674 	if (malf == NULL) {
675 		fprintf(stdout, "mail: cannot append to %s\n", file);
676 		return(0);
677 	}
678 	lock(file);
679 	chown(file, pw->pw_uid, pw->pw_gid);
680 	copylet(n, malf, ORDINARY);
681 	fclose(malf);
682 	unlock();
683 	return(1);
684 }
685 
686 delete(i)
687 {
688 	setsig(i, delete);
689 	fprintf(stderr, "\n");
690 	if(delflg)
691 		longjmp(sjbuf, 1);
692 	done();
693 }
694 
695 /*
696  * Lock the specified mail file by setting the file mailfile.lock.
697  * We must, of course, be careful to unlink the lock file by a call
698  * to unlock before we stop.  The algorithm used here is to see if
699  * the lock exists, and if it does, to check its modify time.  If it
700  * is older than 30 seconds, we assume error and set our own file.
701  * Otherwise, we wait for 5 seconds and try again.
702  */
703 
704 char	*maillock	= ".lock";		/* Lock suffix for mailname */
705 char	*lockname	= "/usr/spool/mail/tmXXXXXX";
706 char	locktmp[30];				/* Usable lock temporary */
707 char	curlock[50];				/* Last used name of lock */
708 int	locked;					/* To note that we locked it */
709 
710 lock(file)
711 char *file;
712 {
713 	register int f;
714 	struct stat sbuf;
715 	long curtime;
716 	int statfailed;
717 
718 	if (locked || flgf)
719 		return(0);
720 	strcpy(curlock, file);
721 	strcat(curlock, maillock);
722 	strcpy(locktmp, lockname);
723 	mktemp(locktmp);
724 	unlink(locktmp);
725 	statfailed = 0;
726 	for (;;) {
727 		f = lock1(locktmp, curlock);
728 		if (f == 0) {
729 			locked = 1;
730 			return(0);
731 		}
732 		if (stat(curlock, &sbuf) < 0) {
733 			if (statfailed++ > 5)
734 				return(-1);
735 			sleep(5);
736 			continue;
737 		}
738 		statfailed = 0;
739 		time(&curtime);
740 		if (curtime < sbuf.st_ctime + 30) {
741 			sleep(5);
742 			continue;
743 		}
744 		unlink(curlock);
745 	}
746 }
747 
748 /*
749  * Remove the mail lock, and note that we no longer
750  * have it locked.
751  */
752 
753 unlock()
754 {
755 
756 	unlink(curlock);
757 	locked = 0;
758 }
759 
760 /*
761  * Attempt to set the lock by creating the temporary file,
762  * then doing a link/unlink.  If it fails, return -1 else 0
763  */
764 
765 lock1(tempfile, name)
766 	char tempfile[], name[];
767 {
768 	register int fd;
769 
770 	fd = creat(tempfile, 0);
771 	if (fd < 0)
772 		return(-1);
773 	close(fd);
774 	if (link(tempfile, name) < 0) {
775 		unlink(tempfile);
776 		return(-1);
777 	}
778 	unlink(tempfile);
779 	return(0);
780 }
781 
782 done()
783 {
784 	if(locked)
785 		unlock();
786 	unlink(lettmp);
787 	unlink(locktmp);
788 	exit(error);
789 }
790 
791 cat(to, from1, from2)
792 char *to, *from1, *from2;
793 {
794 	int i, j;
795 
796 	j = 0;
797 	for (i=0; from1[i]; i++)
798 		to[j++] = from1[i];
799 	for (i=0; from2[i]; i++)
800 		to[j++] = from2[i];
801 	to[j] = 0;
802 }
803 
804 char *getarg(s, p)	/* copy p... into s, update p */
805 register char *s, *p;
806 {
807 	while (*p == ' ' || *p == '\t')
808 		p++;
809 	if (*p == '\n' || *p == '\0')
810 		return(NULL);
811 	while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0')
812 		*s++ = *p++;
813 	*s = '\0';
814 	return(p);
815 }
816 # ifndef DELIVERMAIL
817 /*
818 	stripfx(prefix string, pointer to string)
819 
820 	takes a ptr to string and compares it to prefix string.
821 	may be called multiple times
822 */
823 stripfx(pfx, name)
824 	char *pfx;
825 	char **name;
826 {
827 	register char *cp = *name;
828 
829 	while (*pfx && (*cp == *pfx || *cp == toupper(*pfx)))
830 		cp++, pfx++;
831 	if (*cp != ':' || *pfx != 0)
832 		return;
833 	*name = cp;
834 }
835 # endif
836