|
|
1.1 root 1: static char *rcsrev = "$Revision: 1.5 $";
2: static char *rcshdr =
3: "$Header: /src386/bin/mail/RCS/mail.c,v 1.5 93/06/21 17:47:04 bin Exp Locker: bin $";
4: /*
5: * $Header: /src386/bin/mail/RCS/mail.c,v 1.5 93/06/21 17:47:04 bin Exp Locker: bin $
6: * $Log: mail.c,v $
7: * Revision 1.5 93/06/21 17:47:04 bin
8: * bob h removed xmail referencs from help message.
9: *
10: * Revision 1.4 92/05/28 10:28:53 bin
11: * bob h added a test for new msgsep scheme so that mail will exit
12: * if it does not detect the new sep scheme.
13: *
14: * Revision 1.2 92/04/20 10:07:46 bin
15: * The 'final' fix using CORRECT sources to properly write a msgsep at the
16: * top of a save file if new file is opened or if saving the first message
17: * of a mailbox to a file
18: *
19: * Revision 1.1 92/04/20 09:03:08 bin
20: * Initial revision
21: *
22: * Revision 3.4 91/02/18 17:14:10 piggy
23: * Fixed "q" command so that it works with a non-setuid mail.
24: *
25: * Revision 3.3 91/02/18 09:30:09 piggy
26: * Fixed two mishandlings of args[].
27: *
28: * Revision 3.2 91/02/08 15:16:07 piggy
29: * Updated error messages to include malloc failures.
30: *
31: * Revision 3.1 91/02/08 14:34:28 piggy
32: * Made csplit non-destructive.
33: *
34: * Revision 3.0 91/02/07 15:19:14 piggy
35: * *** empty log message ***
36: *
37: * Revision 2.13 90/03/30 16:16:19 wgl
38: * Correct seek pointer work within readmail.
39: *
40: * Revision 2.12 90/03/12 14:19:08 wgl
41: * New version of send doing aliases in a different place.
42: *
43: * Revision 2.11 90/03/08 16:41:15 wgl
44: * Add code to get signature file.
45: *
46: * Revision 2.10 90/03/02 10:41:59 wgl
47: * Add the -a flag so that uucp does not look like it is coming from
48: * somewhere else.
49: *
50: * Revision 2.9 90/03/01 11:17:19 wgl
51: * Final conversion to rely soley on ^A^A as separators.
52: * Effectively delete concept of m_hsize.
53: *
54: * Revision 2.8 90/03/01 10:14:31 wgl
55: * Go buy separators, not "From_" lines.
56: *
57: * Revision 2.7 90/02/28 17:11:41 wgl
58: * Add version print, add some changes to the message-id field.
59: *
60: * Revision 2.6 90/02/28 16:42:09 wgl
61: * Version number fakeout.
62: *
63: * Revision 2.5 90/02/28 16:19:44 wgl
64: * Try again to get versioin number right.
65: *
66: * Revision 2.4 90/02/28 16:18:56 wgl
67: * Get version number right.
68: *
69: * Revision 2.3 90/02/28 16:04:59 wgl
70: * Many changes; ripped out send.
71: * Changes are to make it work with uucp and internet mail.
72: *
73: * Revision 1.6 89/02/22 05:34:00 bin
74: * Changes by rec to integrate with lauren's uumail.
75: *
76: * Revision 1.5 88/09/01 14:49:01 bin
77: * Source administration: Re-install declaration of getenv.
78: * It was inserted after epstein made his copy.
79: *
80: * Revision 1.4 88/09/01 14:44:49 bin
81: * Mark Epsteins changes for ASKCC and for message scrolling, and interrupt
82: * handling during processing.
83: *
84: * Revision 1.3 88/09/01 14:27:41 bin
85: * declare getenv to get rid of integer pointer pun error message.
86: *
87: * Revision 1.2 88/09/01 11:02:23 bin
88: * Remove extra declaration of header which had rcs stuff in it.
89: *
90: * Revision 1.1 88/09/01 10:55:34 bin
91: * Initial revision
92: *
93: */
94: /*
95: * The mail command.
96: * Coherent electronic postal system, user agent.
97: * With v3.0 this program no longer runs setuid.
98: * Modifications by rec january 1986 to include xmail.
99: * by epstein november 1987 to include CC:
100: * by epstein november 1987 to allow ^C exit to leave you in
101: * mail command processor
102: * by epstein november 1987 to substitute /usr/games/fortune
103: * for printing encrypted messages
104: * by rec february 1989 to tail to lauren weinstein's
105: * mail for alias expansion and uucp queuing.
106: * by wgl January 1990 to handle uucp mail more directly.
107: */
108:
109: char isummary[] = "\
110: \
111: Command summary:\n\
112: d Delete current message and print the next message\n\
113: m [user ...] Mail current message to each named 'user'\n\
114: p Print current message again\n\
115: q Quit and update the mailbox\n\
116: r Reverse direction of scan\n\
117: s [file ...] Save message in each named 'file'\n\
118: t [user ...] Mail standard input to each named 'user'\n\
119: w [file ...] Save message in each named 'file' without its header\n\
120: x Exit without updating mailbox\n\
121: newline Print the next message\n\
122: . Print current message again\n\
123: + Print the next message\n\
124: - Print the previous message\n\
125: EOF Put undeleted mail back into mailbox and quit\n\
126: ? Print this command summary\n\
127: !command Pass 'command' to the shell to execute\n\
128: If no 'file' is specified, 'mbox' in user's home directory is default.\n\
129: If no 'user' is specified, the invoking user is default.\n\
130: \
131: ";
132:
133: #include "mail.h"
134:
135: #define NARGS 64 /* Maximum # args to interactive command */
136:
137: #define TRACE printf
138: #define TRUE 1
139: #define FALSE 0
140:
141: extern char *getenv();
142: extern int optind;
143: extern char *optarg;
144: extern char getopt();
145: extern char *malloc();
146: int csplit();
147: char *eat_ws();
148: char *find_ws();
149: char *revnop();
150:
151: int mflag; /* `You have mail.' message to recipient */
152: int rflag; /* Reverse order of print */
153: int qflag; /* Exit after interrrupts */
154: int pflag; /* Print mail */
155: int verbflag; /* verbose */
156: int callmexmail; /* Xmail modifier present */
157: int callmermail; /* rmail modifier present */
158: struct msg {
159: struct msg *m_next; /* Link to next message */
160: struct msg *m_prev; /* Link to previous message */
161: int m_flag; /* Flags - non-zero if deleted */
162: int m_hsize; /* Size of header of message */
163: fsize_t m_seek; /* Start position of message */
164: fsize_t m_end; /* End of message */
165: };
166: struct msg *m_first = NULL; /* First message */
167: struct msg *m_last = NULL; /* Last message */
168:
169: struct tm *tp;
170:
171: char iusage[] = "Bad command--type '?' for command summary\n";
172: char nombox[] = "No mailbox '%s'.\n";
173: char nomail[] = "No mail.\n";
174: char noperm[] = "Mailbox '%s' access denied.\n";
175: char moerr[] = "Cannot open mailbox '%s'\n";
176: char wrerr[] = "Write error on '%s'\n";
177: char nosave[] = "Cannot save letter in '%s'\n";
178: char allocerr[] = "%s: Can't malloc.\n";
179:
180: FILE *mfp; /* Mailbox stream */
181: int myuid; /* User-id of mail user */
182: int mygid; /* Group-id of mail user */
183: char myname[25]; /* User name */
184: char myfullname[50];
185: char mymbox[256]; /* $HOME/mbox */
186: char mydead[256]; /* $HOME/dead.letter */
187: char mysig[256]; /* $HOME/.sig.mail */
188: char myalias[256]; /* $HOME/.aliases */
189: char spoolname[50] = SPOOLDIR;
190: char *mailbox = spoolname;
191: char cmdname[1024]; /* Command for x{en,de}code filter */
192: /* and for tail recursion to uumail */
193: /* and for editor recursion */
194:
195: char *args[NARGS]; /* Interactive command arglist */
196: char msgline[NLINE];
197: char cline[NCLINE] = "+\n";
198: char *temp; /* Currently open temp file */
199: char templ[] = "/tmp/mailXXXXXX"; /* Temp file name template */
200: char *editname; /* name of editor */
201: char *scatname; /* name of scat filter */
202: char *askcc; /* Ask for CC: list? (YES/NO) */
203:
204: /* fsize_t ftell(); */
205: char *getlogin();
206: char *mktemp();
207: int catchintr();
208: int catchpipe();
209: char asuser [32];
210:
211: typedef short int bool;
212: bool watch_first_msg;
213: bool delete_first_msg;
214:
215: main(argc, argv)
216: char *argv[];
217: {
218: register char *ap;
219: char c, *foo;
220: int i;
221:
222: umask(077);
223: logopen();
224:
225: /* Explicitly NULL out args. */
226: for (i = 0; i < NARGS; ++i) {
227: args[i] = NULL;
228: }
229:
230: ap = argv[0];
231: if ( (foo=rindex(ap, '/')) != NULL )
232: ap = foo+1;
233:
234: callmermail = (strcmp(ap, "rmail") == 0);
235: callmexmail = (strcmp(ap, "xmail") == 0);
236:
237: if (callmermail)
238: logdump("argv0 = rmail\n");
239:
240: asuser [0] = '\0';
241: signal(SIGINT, catchintr);
242: signal(SIGPIPE, catchpipe);
243: while ((c = getopt(argc, argv, "a:f:mpqrv")) != EOF) {
244: switch(c) {
245: case 'f':
246: if (!callmermail)
247: mailbox = optarg;
248: break;
249: case 'a':
250: strcpy(asuser, optarg);
251: break;
252: case 'm':
253: mflag++;
254: break;
255: case 'p':
256: pflag++;
257: break;
258: case 'q':
259: qflag++;
260: break;
261: case 'r':
262: rflag++;
263: break;
264: case 'v':
265: fprintf(stderr, "mail, ver. %s\n", revnop());
266: verbflag++;
267: break;
268: default:
269: usage();
270: }
271: }
272: if (callmermail)
273: verbflag = mflag = pflag = rflag = 0;
274: setname();
275: if (optind < argc) {
276: qflag = 1;
277: if ( send2(stdin, &argv[optind], (fsize_t)0,
278: (fsize_t)MAXLONG, 1) != 0 )
279: rmexit(1);
280: } else {
281: if ( ! pflag)
282: callmexmail = 0;
283: commands();
284: }
285: rmexit(0);
286: }
287:
288: /*
289: * Setup all the identities for the current user.
290: */
291: setname()
292: {
293: register struct passwd *pwp;
294: register char *np;
295: extern struct passwd * getpwnam();
296:
297: if (strlen(asuser) > 0) {
298: if((pwp = getpwnam(asuser)) == NULL)
299: merr("No such user %s.\n", asuser);
300: myuid = pwp -> pw_uid;
301: } else
302: myuid = getuid();
303: if ((pwp = getpwuid(myuid)) == NULL)
304: merr("Who are you?\n");
305: np = pwp->pw_name;
306: mygid = pwp->pw_gid;
307: strcat(spoolname, np);
308: strcpy(myname, np);
309: strcpy(myfullname, pwp->pw_gecos);
310: strcpy(mymbox, pwp->pw_dir);
311: strcat(mymbox, "/mbox");
312: strcpy(mydead, pwp->pw_dir);
313: strcat(mydead, "/dead.letter");
314: strcpy(mysig, pwp->pw_dir);
315: strcat(mysig, "/.sig.mail");
316: strcpy(myalias, pwp->pw_dir);
317: strcat(myalias, "/.aliases");
318: mktemp(templ);
319:
320: if ((editname=getenv("EDITOR"))==NULL)
321: editname = "/bin/ed";
322:
323: if ( ((scatname=getenv("PAGER")) != NULL) &&
324: (strlen(scatname) == 0) )
325: scatname = NULL;
326:
327: if ((askcc=getenv("ASKCC")) != NULL)
328: if ( strcmp(askcc, "YES") )
329: askcc = NULL;
330: }
331:
332: /*
333: * Process mail's interactive commands
334: * for reading/deleting/saving mail.
335: */
336: commands()
337: {
338: register struct msg *mp;
339: struct msg *dest;
340: struct stat filestats;
341: register char **fnp;
342: register FILE *fp;
343: fsize_t seek;
344: int need_to_add_sep;
345: char am_i_sep[7];
346: bool first_msg_read;
347: int testfile; /* used to test if file exists */
348:
349: readmail();
350: mprint(mp = rflag ? m_last : m_first);
351: for (;;) {
352: readmail();
353: intcheck();
354:
355: /* if pflag is set, then we will loop through and print all messages
356: * without stopping between messages for command prompts
357: */
358: if(!pflag){
359: callmexmail = 0;
360: mmsg("? ");
361: if (fgets(cline, sizeof cline, stdin) == NULL){
362: if(intcheck())
363: continue;
364: break;
365: }
366: }
367:
368: switch (cline[0]) {
369: case 'd':
370: if (cline[1] != '\n')
371: goto usage;
372: mp->m_flag += 1;
373: if(mp->m_seek == 5)
374: delete_first_msg = TRUE;
375: goto advance;
376:
377: case 'm':
378: case 't':
379: if (csplit(cline, args) == 1) {
380: /* We don't want to put anything into
381: args that we didn't get from malloc. */
382:
383: if (args[1] != NULL) {
384: free(args[1]);
385: }
386: args[1] = malloc(strlen(myname) + 1);
387: strcpy(args[1], myname);
388: args[2] = NULL;
389: }
390: callmexmail = (cline[1] == 'x');
391: if (cline[0] == 'm') {
392: /* when forwarding mail, seek to msg start + 5 to rid the msgsep */
393: send2(mfp, args+1, (mp->m_seek + 5), mp->m_end - ((sizeof(MSGSEP) - 1) *2), 0);
394: fseek(mfp, mp->m_seek, 0);
395: } else
396: send2(stdin, args+1, 0L, (fsize_t)MAXLONG, 1);
397: break;
398:
399: case '.':
400: case 'p':
401: if (cline[1] == 'x') {
402: callmexmail = 1;
403: if (cline[2] != '\n')
404: goto usage;
405: } else if (cline[1] != '\n')
406: goto usage;
407: if (mprint(mp))
408: break;
409: goto advance;
410:
411: case 'q':
412: if (cline[1] != '\n')
413: goto usage;
414: mquit();
415: /* NOTREACHED */
416:
417: case 'r':
418: if (cline[1] != '\n')
419: goto usage;
420: rflag = ! rflag;
421: break;
422: case 's':
423: case 'w':
424: if (csplit(cline, args) == 1) {
425: /* We don't want to put anything into
426: args that we didn't get from malloc. */
427:
428: if (args[1] != NULL) {
429: free(args[1]);
430: }
431: args[1] = malloc(strlen(mymbox) + 1);
432: strcpy(args[1], mymbox);
433: args[2] = NULL;
434: }
435: seek = mp->m_seek;
436: if (cline[0] == 'w')
437: seek += mp->m_hsize;
438: for (fnp = &args[1]; *fnp != NULL; fnp++) {
439: fp = NULL;
440:
441: testfile = stat(*fnp, &filestats);
442:
443: /* attempt to open the file and write */
444:
445: if ( (maccess(*fnp) < 0)
446: || ( (fp = fopen(*fnp,"a")) == NULL)
447: || (mcopy(mfp,fp,seek,mp->m_end,0)))
448: mmsg(nosave, *fnp);
449:
450: /* close the output file. Because some screwy 'not logic'
451: * was used to determine how msg seps were treated in elm
452: * (and I actually understood it after a while), it was
453: * semi implemented here for SCO mail format compatibility.
454: * Unfortunately, for reasons not clear to me yet, sometimes
455: * a message is copied to the out file with no msgsep appended
456: * to the end of it. So, after appending our message to the
457: * outfile, we will reopen the outfile, seek to the last
458: * byte - 5, and see if the last 5 bytes are a msgsep. If
459: * not, close the file and reopen for append and then write
460: * the msgsep.
461: */
462: if (fp != NULL) {
463: fflush(fp);
464: fclose(fp);
465: stat(*fnp,&filestats);
466: fp = fopen(*fnp,"r");
467: /* TRACE("Seeking to position %d\n",(filestats.st_size - 5)); */
468: fseek(fp,(filestats.st_size - 5),0);
469: fgets(am_i_sep,sizeof(MSGSEP),fp);
470: fclose(fp);
471: need_to_add_sep = strcmp(am_i_sep,MSGSEP
472: );
473: if(need_to_add_sep){
474: fp = fopen(*fnp,"a");
475: fprintf(fp,MSGSEP);
476: fflush(fp);
477: fclose(fp);
478: }
479:
480:
481: chown(*fnp, myuid, mygid);
482: }
483: }
484: break;
485:
486: case 'x':
487: if (cline[1] != '\n')
488: goto usage;
489: rmexit(0);
490: /* NOTREACHED */
491:
492: case '!':
493: if (system(cline+1) == 127)
494: mmsg("Try again\n");
495: else
496: mmsg("!\n");
497: break;
498:
499: case '?':
500: mmsg(isummary);
501: break;
502:
503: case '-':
504: if (cline[1] != '\n')
505: goto usage;
506: dest = rflag ? m_last : m_first;
507: goto nextmsg;
508:
509: case '+':
510: if (cline[1] != '\n')
511: goto usage;
512: case '\n':
513: advance:
514: dest = rflag ? m_first : m_last;
515: nextmsg:
516: do {
517: if (mp == dest) {
518: if (pflag)
519: return;
520: mmsg("No more messages.\n");
521: break;
522: }
523: mp = (dest==m_last) ? mp->m_next : mp->m_prev;
524: } while (mprint(mp) == 0);
525: break;
526:
527: default:
528: usage:
529: mmsg(iusage);
530: break;
531: }
532: }
533: putc('\n', stderr);
534: mquit();
535: }
536:
537: /*
538: * Read through the mail-box file
539: * constructing list of letters.
540: * On subsequent calls, append any additional mail
541: * and notify the user.
542: */
543: readmail()
544: {
545: typedef short int bool;
546: register struct msg *mp;
547: struct stat sb;
548: static long m_last_end;
549: int datasw;
550: bool newmsg;
551: static bool checked_format;
552: static fsize_t original_box_size;
553: char convert_cmd[65];
554:
555: if (m_first == NULL) {
556: if (stat(mailbox, &sb) < 0)
557: merr(nombox, mailbox);
558: if (sb.st_size == 0)
559: merr(nomail);
560:
561: /* the following will open the mailbox and read the first
562: * line. If it is not a MSGSEP, then a message will be printed
563: * to run cvmail and exit.
564: */
565:
566: if(!checked_format){
567: if ((mfp = fopen(mailbox, "r")) == NULL)
568: merr(moerr, mailbox);
569: if(fgets(msgline, sizeof msgline, mfp) == NULL){
570: printf("Can not determine mailbox format\n");
571: exit(1);
572: }
573: fclose(mfp);
574: checked_format = TRUE;
575: if(strcmp(MSGSEP, msgline)){
576: printf("Your mailbox or mailfile needs to be converted to the proper format.\n");
577: strcpy(convert_cmd, "/bin/cvmail ");
578: strcat(convert_cmd, mailbox);
579: printf("\nTo manually convert your mailbox, run: %s\n\n", convert_cmd);
580: exit(1);
581: }
582: }
583:
584: original_box_size = sb.st_size;
585: if (access(mailbox, AREAD) < 0)
586: merr(noperm, mailbox);
587: if ((mfp = fopen(mailbox, "r")) == NULL)
588: merr(moerr, mailbox);
589: m_last_end = 0;
590: } else {
591: fstat(fileno(mfp), &sb);
592: if (sb.st_size == m_last_end)
593: return;
594: if (sb.st_size != original_box_size){
595: mmsg("More mail received.\n");
596: original_box_size = sb.st_size;
597: }
598: }
599:
600: /* we will enter a loop which reads the mailbox line by line.
601: * When it hits a MSGSEP indicating the end of a mail message,
602: * a struct msg will be set with the start and end positions
603: * of the message read. We will continue through this loop until
604: * struct msg's have been built for all messages.
605: */
606:
607: newmsg = TRUE;
608: for(mlock(myuid);;) {
609: fseek(mfp, m_last_end, 0);
610: datasw = 0;
611: while (fgets(msgline, sizeof msgline, mfp) != NULL) {
612: /* NB: this means the implicit message
613: seperator is actually "\n\1\1\n". */
614: if(!(datasw = strcmp(MSGSEP, msgline))){
615:
616: /* message seperator */
617: if (((newmsg = !newmsg) == TRUE) && (ftell(mfp) != 5)){
618: mp = (struct msg *)myalloc(sizeof(*mp));
619: mp->m_next = NULL;
620: mp->m_prev = m_last;
621: mp->m_flag = mp->m_hsize = 0;
622: /* start position of msg */ mp->m_seek = m_last_end;
623: /* end position of msg */ mp->m_end = m_last_end = ftell(mfp);
624: /* TRACE("Message ends at %ld\n",ftell(mfp)); */
625: if (m_first == NULL)
626: m_last = m_first = mp;
627: else
628: m_last = m_last->m_next = mp;
629: }
630: }
631: }
632:
633: if(!datasw) /* data ended with message seperator */
634: break;
635:
636: /* unterminated data, patch and retry */
637: fclose(mfp);
638: if ((mfp = fopen(mailbox, "a")) == NULL)
639: merr(moerr, mailbox);
640: fprintf(mfp, MSGSEP); /* terminate it */
641: fclose(mfp);
642: if ((mfp = fopen(mailbox, "r")) == NULL)
643: merr(moerr, mailbox);
644: mmsg("Incomplete message found.\n");
645: }
646: munlock();
647: }
648:
649: /*
650: * Lock the appropriately-numbered mailbox
651: * (numbered by user-number) from multiple
652: * accesses. There is a (small) race here
653: * which will be overlooked for now.
654: */
655: char *lockname;
656:
657: mlock(uid)
658: int uid;
659: {
660: register int fd;
661: static char lock[32];
662:
663: lockname = lock;
664: sprintf(lock, "/tmp/maillock%d", uid);
665: while (access(lockname, 0) == 0)
666: sleep(1);
667: if ((fd = creat(lockname, 0)) >= 0)
668: close(fd);
669: }
670:
671: /*
672: * Unlock the currently-set lock (by `mlock')
673: * also called from rmexit.
674: */
675: munlock()
676: {
677: if (lockname != NULL)
678: unlink(lockname);
679: lockname = NULL;
680: }
681:
682: /*
683: * Exit, after rewriting the
684: * mailbox
685: */
686: mquit()
687: {
688: register struct msg *mp;
689: register FILE *nfp, *tmpfp;
690: struct stat sb;
691:
692: /* Get new stuff. */
693: readmail();
694: /* There is a slight race here. We really should
695: lock BEFORE the readmail(), but readmail() does unlocks...
696: FIX ME. */
697: mlock(myuid);
698:
699: if (mailbox != spoolname && maccess(mailbox) < 0)
700: merr(noperm, mailbox);
701: fstat(fileno(mfp), &sb);
702: signal(SIGINT, SIG_IGN);
703: signal(SIGPIPE, SIG_IGN);
704:
705: /* Make a copy of the mail box; we're going to overwrite it. */
706: tmpfp = tmp_copy(mfp);
707: fclose(mfp);
708:
709: if ((nfp = fopen(mailbox, "w")) == NULL)
710: merr("Cannot re-write '%s'\n", mailbox);
711: chown(mailbox, sb.st_uid, sb.st_gid);
712: chmod(mailbox, sb.st_mode&0777);
713: for (mp = m_first; mp != NULL; mp = mp->m_next) {
714:
715: if (mp->m_flag == 0) {
716: if(delete_first_msg){
717: mp->m_seek = mp->m_seek+5;
718: delete_first_msg = FALSE;
719: }
720: if (mcopy(tmpfp, nfp, mp->m_seek, mp->m_end, 0)) {
721: merr(wrerr, mailbox);
722: }
723: } /* if (mp->m_flag == 0) */
724:
725: } /* for (walk through the linked list of messages) */
726:
727: fclose(nfp);
728: fclose(tmpfp);
729: munlock();
730: rmexit(0);
731: }
732:
733: /*
734: * Print the current message, given by
735: * the message pointer (`mp').
736: */
737: mprint(mp)
738: register struct msg *mp;
739: {
740: FILE *xfp;
741:
742: if (mp->m_flag)
743: return 0;
744: if (callmexmail) {
745: if (scatname != NULL)
746: sprintf(cmdname, "xdecode | %s", scatname);
747: else
748: sprintf(cmdname, "xdecode");
749: if ((xfp = popen(cmdname, "w")) == NULL)
750: return 0;
751: fprintf(xfp, MSGSEP);
752: mcopy(mfp, xfp, mp->m_seek+mp->m_hsize, mp->m_end, 1);
753: pclose(xfp);
754: } else {
755: fseek(mfp, mp->m_seek, 0);
756: if (fgets(msgline, sizeof msgline, mfp) != NULL &&
757: strncmp(msgline, "From xmail", 10) == 0) {
758: printf("From xmail\n");
759: system("/usr/games/fortune");
760: return(1);
761: }
762: if (scatname != NULL) {
763: sprintf(cmdname, "%s", scatname);
764: if ((xfp = popen(cmdname, "w")) == NULL)
765: return(0);
766: mcopy(mfp, xfp, mp->m_seek, mp->m_end - 5, 1);
767: if ( ((pclose(xfp)>>8)&0xFF) == SIGINT )
768: putc('\n', stdout);
769: } else {
770: mcopy(mfp, stdout, mp->m_seek, mp->m_end - 5, 1);
771: }
772: }
773: return (1);
774: }
775:
776: /*
777: * Get additional users to receive message (CC:)
778: */
779:
780: char **
781: getcc()
782: {
783: static char names[NCLINE];
784: static char *ccargs[NARGS];
785:
786: ccargs[0] = NULL;
787: mmsg("CC: ");
788: if ( fgets(names, sizeof names, stdin) == NULL )
789: return(ccargs);
790:
791: csplit(names, ccargs);
792: return(ccargs);
793: }
794:
795:
796: /*
797: * Errors, usage, and exit removing
798: * any tempfiles left around.
799: */
800: mmsg(x)
801: {
802: fprintf(stderr, "%r", &x);
803: }
804:
805: merr(x, s)
806: char *x, *s;
807: {
808: mmsg(x, s);
809: logdump("merr: ");
810: logdump(x, s);
811: rmexit(1);
812: }
813:
814: rmexit(s)
815: int s;
816: {
817: if (temp != NULL)
818: unlink(temp);
819: munlock();
820:
821: logdump("About to exit, status = 0x%04x\n", s);
822: logclose();
823:
824: exit(s);
825: }
826:
827: /*
828: * Catch interrupts, taking the
829: * appropriate action based on
830: * the `-q' option.
831: */
832: int intrflag; /* On when interrupt sent */
833: int pipeflag; /* On when broken pipe caught */
834:
835: catchintr()
836: {
837: logdump("Caught SIGINT\n");
838: if (qflag)
839: rmexit(1);
840: intrflag = 1;
841: signal(SIGINT, catchintr);
842: }
843:
844: catchpipe()
845: {
846: logdump("Caught SIGPIPE\n");
847: pipeflag = 1;
848: signal(SIGPIPE, catchpipe);
849: }
850:
851: intcheck()
852: {
853: if (intrflag || pipeflag) {
854: if (intrflag)
855: putc('\n', stdout);
856: intrflag = pipeflag = 0;
857: return (1);
858: }
859: return (0);
860: }
861:
862: /*
863: * Call the system to execute a command line
864: * which is passed as an argument.
865: * Change the user id and group id.
866: */
867: system(line)
868: char *line;
869: {
870: int status, pid;
871: register wpid;
872: register int (*intfun)(), (*quitfun)();
873:
874: if ((pid = fork()) < 0)
875: return (-1);
876: if (pid == 0) { /* Child */
877: setuid(myuid);
878: setgid(mygid);
879: execl("/bin/sh", "sh", "-c", line, NULL);
880: exit(0177);
881: }
882: intfun = signal(SIGINT, SIG_IGN);
883: quitfun = signal(SIGQUIT, SIG_IGN);
884: while ((wpid = wait(&status))!=pid && wpid>=0)
885: ;
886: if (wpid < 0)
887: status = wpid;
888: signal(SIGINT, intfun);
889: signal(SIGQUIT, quitfun);
890: return (status);
891: }
892:
893: char *
894: revnop()
895: {
896: register char *cp;
897: register char c;
898: static char revnobuf[32];
899:
900: if ((cp = index(rcsrev, ' ')) != NULL) {
901: while (((c = *++cp) == ' ') && (c != '\0'))
902: ;
903: strcpy(revnobuf, cp);
904: if ((cp = index(revnobuf, ' ')) != NULL)
905: *cp = '\0';
906: return (revnobuf);
907: } else
908: return("OOPS");
909: }
910:
911: /*
912: * Split a command line up into
913: * argv (passed) and argc (returned).
914: * We assume that elements of "args" are either NULL or they were
915: * returned from malloc, so that they can be freed.
916: */
917: int
918: csplit(command, args)
919: char *command;
920: char **args;
921: {
922: register char *cp;
923: int i, argsize;
924:
925: i = 0; /* Start filling in at the zero'th arg. */
926: cp = eat_ws(command);
927:
928: /* Walk "cp" through "command", copying segments as we go. */
929: while ( *cp != CNULL ) {
930: /* We've found an argument; find some space. */
931: if (args[i] != NULL ) {
932: free(args[i]);
933: }
934:
935: /* Figure out how big the argment is. */
936: argsize = (int) (find_ws(cp) - cp);
937:
938: /* Alloc enough space for it--include the trailing NULL. */
939: if ((args[i] = malloc(argsize + 1)) == NULL) {
940: mmsg(allocerr, "csplit");
941: return(0); /* Is this the approriate action?? */
942: }
943:
944: /* Copy the argument into the space. */
945: memcpy(args[i], cp, argsize);
946: args[i][argsize] = CNULL; /* This may be redundant. */
947:
948: /* Make sure that cp points to after the argument. */
949: cp += argsize;
950:
951: cp = eat_ws(cp);
952: ++i;
953: } /* while (walk "cp" through "command") */
954:
955: args[i] = NULL;
956: return (i);
957: }
958:
959: /*
960: * Find the next occurence of non-white space in character string s.
961: */
962: char *
963: eat_ws(s)
964: char *s;
965: {
966: while(isspace(*s)){
967: ++s;
968: }
969: return(s);
970: }
971:
972: /*
973: * Find next occurence of white space in character string s.
974: */
975: char *
976: find_ws(s)
977: register char *s;
978: {
979: while((*s != CNULL) && !isspace(*s) ){
980: ++s;
981: }
982: return(s);
983: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.