|
|
1.1 root 1: /*
2: * $Header: /newbits/bin/mail.c,v 1.6 89/02/22 05:34:00 bin Exp $
3: * $Log: /newbits/bin/mail.c,v $
4: * Revision 1.6 89/02/22 05:34:00 bin
5: * Changes by rec to integrate with lauren's uumail.
6: *
7: * Revision 1.5 88/09/01 14:49:01 bin
8: * Source administration: Re-install declaration of getenv.
9: * It was inserted after epstein made his copy.
10: *
11: * Revision 1.4 88/09/01 14:44:49 bin
12: * Mark Epsteins changes for ASKCC and for message scrolling, and interrupt
13: * handling during processing.
14: *
15: * Revision 1.3 88/09/01 14:27:41 bin
16: * declare getenv to get rid of integer pointer pun error message.
17: *
18: * Revision 1.2 88/09/01 11:02:23 bin
19: * Remove extra declaration of header which had rcs stuff in it.
20: *
21: * Revision 1.1 88/09/01 10:55:34 bin
22: * Initial revision
23: *
24: */
25: static char *rcsrev = "$Revision 1.1 $";
26: static char *rcshdr =
27: "$Header: /newbits/bin/mail.c,v 1.6 89/02/22 05:34:00 bin Exp $";
28:
29: /*
30: * The mail command.
31: * Coherent electronic postal system.
32: * (NOTE: this command is written in such a way that
33: * it assumed that it is setuid on execution to `root'.
34: * All file accession is checked on this basis).
35: * Modifications by rec january 1986 to include xmail.
36: * by epstein november 1987 to include CC:
37: * by epstein november 1987 to allow ^C exit to leave you in
38: * mail command processor
39: * by epstein november 1987 to substitute /usr/games/fortune
40: * for printing encrypted messages
41: * by rec february 1989 to tail to lauren weinstein's
42: * mail for alias expansion and uucp queuing.
43: */
44:
45: char helpmessage[] = "\
46: \
47: mail -- computer mail\n\
48: xmail -- secret computer mail\n\
49: Usage: mail [ options ] [ user ... ]\n\
50: or: xmail [ options ] user [ ... ]\n\
51: Options:\n\
52: -f file Print mail from 'file' instead of the default\n\
53: -p Print mail non-interactively\n\
54: -q Exit on interrupt, leaving mail unchanged\n\
55: -r Print mail in reverse order, latest first\n\
56: If 'user' is present, send each a mail message read from standard input.\n\
57: If 'xmail' is the command, use xencode to encrypt the mail messages.\n\
58: Mail message ends with EOF of a line containing only '.'. Otherwise, read\n\
59: and print the invoking user's mailbox.\n\
60: \
61: ";
62:
63: char isummary[] = "\
64: \
65: Command summary:\n\
66: d Delete current message and print the next message\n\
67: m [user ...] Mail current message to each named 'user'\n\
68: p Print current message again\n\
69: q Quit and update the mailbox\n\
70: r Reverse direction of scan\n\
71: s [file ...] Save message in each named 'file'\n\
72: t [user ...] Mail standard input to each named 'user'\n\
73: w [file ...] Save message in each named 'file' without its header\n\
74: x Exit without updating mailbox\n\
75: newline Print the next message\n\
76: . Print current message again\n\
77: + Print the next message\n\
78: - Print the previous message\n\
79: EOF Put undeleted mail back into mailbox and quit\n\
80: ? Print this command summary\n\
81: !command Pass 'command' to the shell to execute\n\
82: If no 'file' is specified, 'mbox' in user's home directory is default.\n\
83: If no 'user' is specified, the invoking user is default.\n\
84: If the 'm', 'p', 't' commands are followed by an 'x',\n\
85: then the public key cryptosystem is applied to the message.\n\
86: \
87: ";
88:
89: #include <stdio.h>
90: #include <pwd.h>
91: #include <utmp.h>
92: #include <types.h>
93: #include <access.h>
94: #include <signal.h>
95: #include <sys/mdata.h>
96: #include <sys/stat.h>
97: #include <time.h>
98:
99: #define SPOOLDIR "/usr/spool/mail/"
100: #define PUBKEYDIR "/usr/spool/pubkey/"
101: #define NARGS 64 /* Maximum # args to interactive command */
102: #define NLINE 512 /* Longest line in a message */
103: #define NCLINE 256 /* Length of an interactive command */
104:
105: extern char *getenv();
106:
107:
108:
109: int rflag; /* Reverse order of print */
110: int qflag; /* Exit after interrrupts */
111: int pflag; /* Print mail */
112: int eflag; /* Edit this mail */
113: int callmexmail; /* Xmail modifier present */
114:
115: struct msg {
116: struct msg *m_next; /* Link to next message */
117: struct msg *m_prev; /* Link to previous message */
118: int m_flag; /* Flags - non-zero if deleted */
119: int m_hsize; /* Size of header of message */
120: fsize_t m_seek; /* Start position of message */
121: fsize_t m_end; /* End of message */
122: };
123: struct msg *m_first = NULL; /* First message */
124: struct msg *m_last = NULL; /* Last message */
125:
126: struct tm *tp;
127:
128: char iusage[] = "Bad command--type '?' for command summary\n";
129: char nombox[] = "No mailbox '%s'.\n";
130: char nomail[] = "No mail.\n";
131: char noperm[] = "Mailbox '%s' access denied.\n";
132: char nosend[] = "Can't send mail to '%s'\n";
133: char moerr[] = "Cannot open mailbox '%s'\n";
134: char wrerr[] = "Write error on '%s'\n";
135: char toerr[] = "Cannot create temporary file\n";
136: char nosave[] = "Cannot save letter in '%s'\n";
137: char nopubk[] = "Can't send xmail to '%s'\n";
138:
139: FILE *mfp; /* Mailbox stream */
140: int myuid; /* User-id of mail user */
141: int mygid; /* Group-id of mail user */
142: char myname[25]; /* User name */
143: char mymbox[256]; /* $HOME/mbox */
144: char spoolname[50] = SPOOLDIR;
145: char *mailbox = spoolname;
146: char boxname[64]; /* Destination mailbox */
147: char keyname[64]; /* Destination public key file name */
148: char cmdname[1024]; /* Command for x{en,de}code filter */
149: /* and for tail recursion to uumail */
150: /* and for editor recursion */
151: char header[256]; /* Message header */
152:
153: char *args[NARGS]; /* Interactive command arglist */
154: char msgline[NLINE];
155: char cline[NCLINE] = "+\n";
156:
157: char *temp; /* Currently open temp file */
158: char templ[] = "/tmp/mailXXXXXX"; /* Temp file name template */
159: char *editname; /* name of editor */
160: char *askcc; /* Ask for CC: list? (YES/NO) */
161:
162: fsize_t ftell();
163: char *getlogin();
164: char *mktemp();
165: char *index();
166: char *parent();
167: int catchintr();
168: char *malloc();
169:
170: main(argc, argv)
171: char *argv[];
172: {
173: register char *ap;
174:
175: callmexmail = (strcmp(argv[0], "xmail") == 0);
176: if (signal(SIGINT, SIG_IGN) != SIG_IGN)
177: signal(SIGINT, catchintr);
178: if (argc>1 && *argv[1]=='-') {
179: while (argc>1 && *argv[1]=='-') {
180: for (ap=&argv[1][1]; *ap != '\0'; ap++)
181: switch (*ap) {
182: case 'f':
183: if (argc < 3)
184: usage();
185: mailbox = argv[2];
186: argv++;
187: argc--;
188: break;
189:
190: case 'm':
191: break;
192:
193: case 'p':
194: pflag++;
195: break;
196:
197: case 'q':
198: qflag++;
199: break;
200:
201: case 'r':
202: rflag++;
203: break;
204:
205: default:
206: usage();
207: }
208: argv++;
209: argc--;
210: }
211: }
212: setname();
213: if (argc > 1) {
214: qflag = 1;
215: send(stdin, &argv[1], (fsize_t)0, (fsize_t)MAXLONG);
216: } else {
217: if ( ! pflag)
218: callmexmail = 0;
219: commands();
220: }
221: rmexit(0);
222: }
223:
224: /*
225: * Setup all the identities for the current user.
226: */
227: setname()
228: {
229: register struct passwd *pwp;
230: register char *np;
231:
232: if ((np = getlogin()) == NULL) {
233: myuid = getuid();
234: if ((pwp = getpwuid(myuid)) == NULL)
235: merr("Who are you?\n");
236: np = pwp->pw_name;
237: } else {
238: if ((pwp = getpwnam(np)) != NULL)
239: myuid = pwp->pw_uid;
240: }
241: mygid = pwp->pw_gid;
242: strcat(spoolname, np);
243: strcpy(myname, np);
244: strcpy(mymbox, pwp->pw_dir);
245: strcat(mymbox, "/mbox");
246: mktemp(templ);
247:
248: if ((editname=getenv("EDITOR"))==NULL)
249: editname = "/bin/ed";
250:
251: if ((askcc=getenv("ASKCC")) != NULL)
252: if ( strcmp(askcc, "YES") || !isatty(fileno(stdin)) )
253: askcc = NULL;
254: }
255:
256: /*
257: * Send the message found on
258: * the file pointer to the list
259: * of people (argv style) with
260: * a NULL pointer at the end.
261: * The message is copied to a temp-file
262: * from position `start' to `end' (or EOF).
263: */
264: send(fp, users, start, end)
265: FILE *fp;
266: register char **users;
267: fsize_t start, end;
268: {
269: FILE *tfp, *xfp;
270: char **getcc();
271:
272: temp = templ;
273: if ((tfp = fopen(temp, "w")) != NULL) {
274: fclose(tfp);
275: if ((tfp = fopen(temp, "r+w")) == NULL)
276: merr(toerr);
277: } else
278: merr(toerr);
279: chown(temp, myuid, mygid);
280: unlink(temp);
281: temp = NULL;
282: fseek(fp, start, 0);
283: end -= start;
284:
285: eflag = 0;
286: for (;;) {
287: if (fgets(msgline, sizeof msgline, fp) == NULL)
288: break;
289: if (fp == stdin)
290: if ((strcmp(".\n", msgline)==0))
291: break;
292: else if ((strcmp("?\n", msgline)==0)) {
293: eflag = 1;
294: break;
295: }
296: if (strncmp("From ", msgline, 5) == 0)
297: putc('>', tfp);
298: fputs(msgline, tfp);
299:
300: end -= strlen(msgline); /* compiler bug */
301: if (end <= 0) {
302: break;
303: }
304: }
305: /*
306: * If interrupted, bug out.
307: */
308: if (intcheck()) {
309: fclose(tfp);
310: return;
311: }
312: /*
313: * Now, see if user wants to edit the message
314: */
315: if (eflag) {
316: xfp = tfp;
317: temp = templ;
318: if ((tfp = fopen(temp, "wr")) == NULL)
319: merr(toerr);
320: chown(temp, myuid, mygid);
321: mcopy(xfp, tfp, (fsize_t)0, (fsize_t)MAXLONG, 0);
322: fclose(xfp);
323: sprintf(cmdname, "%s %s", editname, templ);
324: system(cmdname);
325: unlink(temp);
326: temp = NULL;
327: }
328: /*
329: * Otherwise if empty message, bug out.
330: */
331: else if (ftell(tfp) == 0) {
332: fclose(tfp);
333: return;
334: }
335: /*
336: * Now see if a copy list is requested.
337: */
338: if (askcc)
339: users = getcc(users);
340: /*
341: * Now send the message.
342: */
343: if (callmexmail)
344: xsend(users, tfp);
345: else
346: usend(users, tfp);
347: }
348:
349: char *subject()
350: {
351: /* lauren's mail refuses to read a subject from standard input */
352: /* without discarding the rest of the message */
353: /* and refuses to accept an empty subject on the command line */
354: /* so we supply a subject */
355: static char *subject[] = {
356: #if 0
357: "national security", "world peace", "elvis sighted",
358: "ayatollah ups reward", "new version", "old version",
359: "budget deficit", "technical support", "worker satisfaction",
360: "profit sharing", "fringe benefit", "coherent software",
361: "computer virus", "no subject", "forbidden",
362: "to memory failure", "ive", "object", "not specified",
363: "new policy", "old policy", "pass words",
364: #else
365: " "
366: #endif
367: };
368: srand((int)time(NULL));
369: return subject[rand() % (sizeof(subject)/sizeof(subject[0]))];
370: }
371:
372: usend(users, tfp) char **users; FILE *tfp;
373: {
374: FILE *xfp;
375: strcpy(cmdname, "/usr/bin/uumail");
376: while (*users) {
377: strcat(cmdname, " ");
378: strcat(cmdname, *users++);
379: }
380: strcat(cmdname, " -n -s'");
381: strcat(cmdname, subject());
382: strcat(cmdname, "'");
383: rewind(tfp);
384: if ((xfp = popen(cmdname, "w")) == NULL) {
385: mmsg("Can't pipe to uumail\n");
386: return;
387: }
388: if (mcopy(tfp, xfp, (fsize_t)0, (fsize_t)MAXLONG), 0)
389: merr(wrerr, cmdname);
390: pclose(xfp);
391: }
392: xsend(users, tfp) char **users; FILE *tfp;
393: {
394: register char **ulist;
395: register char *cp;
396: register struct passwd *pwp;
397: time_t curtime;
398: FILE *xfp;
399:
400: time(&curtime);
401: tp = localtime(&curtime);
402: cp = asctime(tp);
403: cp[strlen(cp)-1] = 0;
404: sprintf(header, "From %s %s %s\n", myname, cp,
405: tzname[tp->tm_isdst ? 1 : 0]);
406: if (users[0]!=NULL && users[1]!=NULL) {
407: strcat(header, "(cc:");
408: for (ulist = users; *ulist != NULL; ulist++) {
409: strcat(header, " ");
410: strcat(header, *ulist);
411: }
412: strcat(header, ")\n");
413: }
414: for (ulist = users; *ulist!=NULL; ulist++) {
415: rewind(tfp);
416: sprintf(boxname, "%s%s", SPOOLDIR, *ulist);
417: sprintf(cmdname, "xencode %s >> %s", *ulist, boxname);
418: if (index(*ulist, '!') != NULL
419: || (pwp = getpwnam(*ulist)) == NULL) {
420: mmsg(nosend, *ulist);
421: continue;
422: }
423: if (xaccess(*ulist) == 0) {
424: mmsg(nopubk, *ulist);
425: continue;
426: }
427: mlock(pwp->pw_uid);
428: if ((xfp = fopen(boxname, "a")) == NULL) {
429: mmsg(nosend, *ulist);
430: munlock();
431: continue;
432: }
433: chown(boxname, pwp->pw_uid, pwp->pw_gid);
434: fprintf(xfp, "From xmail %s %s\n", cp,
435: tzname[tp->tm_isdst ? 1 : 0]);
436: fclose(xfp);
437: if ((xfp = popen(cmdname, "w")) == NULL) {
438: mmsg("Can't pipe to xencode\n");
439: continue;
440: }
441: if (fwrite(header, strlen(header), 1, xfp) != 1
442: || mcopy(tfp, xfp, (fsize_t)0, (fsize_t)MAXLONG), 0) {
443: merr(wrerr, cmdname);
444: }
445: pclose(xfp);
446: munlock();
447: }
448: fclose(tfp);
449: }
450:
451: /*
452: * Check access on a file.
453: */
454: maccess(name)
455: char *name;
456: {
457: struct stat sb;
458:
459: if (stat(name, &sb) < 0) {
460: if (access(parent(name), ACREAT) < 0)
461: return (-1);
462: } else if (access(name, AWRITE) < 0)
463: return (-1);
464: return (0);
465: }
466:
467: /*
468: * Check enrollment for xmail.
469: */
470: xaccess(name) char *name;
471: {
472: struct stat sb;
473: sprintf(keyname, "%s%s", PUBKEYDIR, name);
474: return stat(keyname, &sb) >= 0;
475: }
476: /*
477: * Find the parent directory for access permissions.
478: */
479: char *
480: parent(name)
481: char *name;
482: {
483: register char *cp, *xp;
484: static char p[256];
485: char *rindex();
486:
487: xp = rindex(name, '/');
488: if (xp == NULL)
489: return (".");
490: if (xp == name)
491: return ("/");
492: if (xp - name >= 256)
493: return ("");
494: cp = p;
495: while (name < xp)
496: *cp++ = *name++;
497: *cp = 0;
498: return (p);
499: }
500:
501: /*
502: * Copy from the file stream `ifp' (starting at
503: * position `start' and ending at `end' or EOF)
504: * to the file stream `ofp' which is assumed
505: * to be already correctly positioned.
506: * Returns non-zero on errors.
507: * intstop == 1 means stop on interrupt
508: * intstop == 0 means ignore interrupt
509: */
510: mcopy(ifp, ofp, start, end, intstop)
511: register FILE *ifp, *ofp;
512: fsize_t start, end;
513: {
514: register int c;
515:
516: fseek(ifp, start, 0);
517: end -= start;
518: if (intstop)
519: while (!intcheck() && end-- > 0 && (c = getc(ifp))!=EOF)
520: putc(c, ofp);
521: else
522: while (end-- > 0 && (c = getc(ifp))!=EOF)
523: putc(c, ofp);
524: fflush(ofp);
525: if (ferror(ofp))
526: return (1);
527: return (0);
528: }
529:
530: /*
531: * Process mail's interactive commands
532: * for reading/deleting/saving mail.
533: */
534: commands()
535: {
536: register struct msg *mp;
537: struct msg *dest;
538: register char **fnp;
539: register FILE *fp;
540: fsize_t seek;
541:
542: readmail();
543: mprint(mp = rflag ? m_last : m_first);
544: for (;;) {
545: readmail();
546: intcheck();
547: if ( ! pflag) {
548: callmexmail = 0;
549: mmsg("? ");
550: if (fgets(cline, sizeof cline, stdin) == NULL) {
551: if (intcheck())
552: continue;
553: break;
554: }
555: }
556: switch (cline[0]) {
557: case 'd':
558: if (cline[1] != '\n')
559: goto usage;
560: mp->m_flag += 1;
561: goto advance;
562:
563: case 'm':
564: case 't':
565: if (csplit(cline, args) == 1) {
566: args[1] = myname;
567: args[2] = NULL;
568: }
569: callmexmail = (cline[1] == 'x');
570: if (cline[0] == 'm')
571: send(mfp, args+1, mp->m_seek, mp->m_end);
572: else
573: send(stdin, args+1, 0L, (fsize_t)MAXLONG);
574: break;
575:
576: case '.':
577: case 'p':
578: if (cline[1] == 'x') {
579: callmexmail = 1;
580: if (cline[2] != '\n')
581: goto usage;
582: } else if (cline[1] != '\n')
583: goto usage;
584: if (mprint(mp))
585: break;
586: goto advance;
587:
588: case 'q':
589: if (cline[1] != '\n')
590: goto usage;
591: mquit();
592: /* NOTREACHED */
593:
594: case 'r':
595: if (cline[1] != '\n')
596: goto usage;
597: rflag = ! rflag;
598: break;
599: case 's':
600: case 'w':
601: if (csplit(cline, args) == 1) {
602: args[1] = mymbox;
603: args[2] = NULL;
604: }
605: seek = mp->m_seek;
606: if (cline[0] == 'w')
607: seek += mp->m_hsize;
608: for (fnp = &args[1]; *fnp != NULL; fnp++) {
609: fp = NULL;
610: if (maccess(*fnp) < 0
611: || (fp = fopen(*fnp, "a")) == NULL
612: || mcopy(mfp, fp, seek, mp->m_end, 0))
613: mmsg(nosave, *fnp);
614: if (fp != NULL) {
615: fclose(fp);
616: chown(*fnp, myuid, mygid);
617: }
618: }
619: break;
620:
621: case 'x':
622: if (cline[1] != '\n')
623: goto usage;
624: rmexit(0);
625: /* NOTREACHED */
626:
627: case '!':
628: if (system(cline+1) == 127)
629: mmsg("Try again\n");
630: else
631: mmsg("!\n");
632: break;
633:
634: case '?':
635: mmsg(isummary);
636: break;
637:
638: case '-':
639: if (cline[1] != '\n')
640: goto usage;
641: dest = rflag ? m_last : m_first;
642: goto nextmsg;
643:
644: case '+':
645: if (cline[1] != '\n')
646: goto usage;
647: case '\n':
648: advance:
649: dest = rflag ? m_first : m_last;
650: nextmsg:
651: do {
652: if (mp == dest) {
653: if (pflag)
654: return;
655: mmsg("No more messages.\n");
656: break;
657: }
658: mp = (dest==m_last) ? mp->m_next : mp->m_prev;
659: } while (mprint(mp) == 0);
660: break;
661:
662: default:
663: usage:
664: mmsg(iusage);
665: break;
666: }
667: }
668: putc('\n', stderr);
669: mquit();
670: }
671:
672: /*
673: * Read through the mail-box file
674: * constructing list of letters.
675: * On subsequent calls, append any additional mail
676: * and notify the user.
677: */
678: readmail()
679: {
680: register struct msg *mp, *lmp;
681: struct stat sb;
682: static long m_last_end;
683: long last;
684:
685: if (m_first == NULL) {
686: if (stat(mailbox, &sb) < 0)
687: merr(nombox, mailbox);
688: if (sb.st_size == 0)
689: merr(nomail);
690: if (access(mailbox, AREAD) < 0)
691: merr(noperm, mailbox);
692: if ((mfp = fopen(mailbox, "r")) == NULL)
693: merr(moerr, mailbox);
694: mp = lmp = NULL;
695: last = m_last_end = 0;
696: } else {
697: fstat(fileno(mfp), &sb);
698: if (sb.st_size == m_last_end)
699: return;
700: mmsg("More mail received.\n");
701: mp = lmp = m_last;
702: last = mp->m_end;
703: fseek(mfp, m_last_end, 0);
704: }
705: mlock(myuid);
706: while (fgets(msgline, sizeof msgline, mfp) != NULL) {
707: if (strncmp("From ", msgline, 5) == 0) {
708: mp = (struct msg *)malloc(sizeof(*mp));
709: mp->m_prev = NULL;
710: mp->m_next = NULL;
711: mp->m_flag = 0;
712: mp->m_hsize = strlen(msgline);
713: mp->m_seek = ftell(mfp)-mp->m_hsize;
714: if (lmp == NULL) {
715: m_first = mp;
716: } else {
717: lmp->m_next = mp;
718: lmp->m_end = last;
719: }
720: mp->m_prev = lmp;
721: m_last = lmp = mp;
722: }
723: if (strcmp("\n", msgline) != 0
724: && strcmp("\1\1\n", msgline) != 0)
725: last = ftell(mfp);
726: }
727: if (mp == NULL)
728: merr("Not mailbox format '%s'\n", mailbox);
729: mp->m_end = last;
730: m_last_end = ftell(mfp);
731: munlock();
732: }
733:
734: /*
735: * Split a command line up into
736: * argv (passed) and argc (returned).
737: */
738: int
739: csplit(command, args)
740: char *command;
741: char **args;
742: {
743: register char *cp;
744: register char **ap;
745: register int c;
746:
747: cp = command;
748: ap = args;
749: for (;;) {
750: while ((c = *cp)==' ' || c=='\t')
751: *cp++ = '\0';
752: if (*cp == '\n')
753: *cp = '\0';
754: if (*cp == '\0')
755: break;
756: *ap++ = cp;
757: while ((c = *cp)!=' ' && c!='\t' && c!='\n' && c!='\0')
758: cp++;
759: }
760: *ap = NULL;
761: return (ap - args);
762: }
763:
764: /*
765: * Lock the appropriately-numbered mailbox
766: * (numbered by user-number) from multiple
767: * accesses. There is a (small) race here
768: * which will be overlooked for now.
769: */
770: char *lockname;
771:
772: mlock(uid)
773: int uid;
774: {
775: register int fd;
776: static char lock[32];
777:
778: lockname = lock;
779: sprintf(lock, "/tmp/maillock%d", uid);
780: while (access(lockname, 0) == 0)
781: sleep(1);
782: if ((fd = creat(lockname, 0)) >= 0)
783: close(fd);
784: }
785:
786: /*
787: * Unlock the currently-set lock (by `mlock')
788: * also called from rmexit.
789: */
790: munlock()
791: {
792: if (lockname != NULL)
793: unlink(lockname);
794: lockname = NULL;
795: }
796:
797: /*
798: * Exit, after rewriting the
799: * mailbox
800: */
801: mquit()
802: {
803: register struct msg *mp;
804: register FILE *nfp;
805: struct stat sb;
806:
807: readmail();
808: mlock(myuid);
809: if (mailbox != spoolname && maccess(mailbox) < 0)
810: merr(noperm, mailbox);
811: fstat(fileno(mfp), &sb);
812: signal(SIGINT, SIG_IGN);
813: unlink(mailbox);
814: if ((nfp = fopen(mailbox, "w")) == NULL)
815: merr("Cannot re-write '%s'\n", mailbox);
816: chown(mailbox, sb.st_uid, sb.st_gid);
817: chmod(mailbox, sb.st_mode&0777);
818: for (mp = m_first; mp != NULL; mp = mp->m_next)
819: if (mp->m_flag == 0
820: && mcopy(mfp, nfp, mp->m_seek, mp->m_end, 0))
821: merr(wrerr, mailbox);
822: fclose(nfp);
823: fclose(mfp);
824: munlock();
825: rmexit(0);
826: }
827:
828: /*
829: * Print the current message, given by
830: * the message pointer (`mp').
831: */
832: mprint(mp)
833: register struct msg *mp;
834: {
835: FILE *xfp;
836: if (mp->m_flag)
837: return 0;
838: if (callmexmail) {
839: sprintf(cmdname, "xdecode");
840: if ((xfp = popen(cmdname, "w")) == NULL) {
841: return 0;
842: }
843: mcopy(mfp, xfp, mp->m_seek+mp->m_hsize, mp->m_end, 1);
844: pclose(xfp);
845: } else {
846: fseek(mfp, mp->m_seek, 0);
847: if (fgets(msgline, sizeof msgline, mfp) != NULL &&
848: strncmp(msgline, "From xmail", 10) == 0) {
849: printf("From xmail\n");
850: system("/usr/games/fortune");
851: return(1);
852: }
853: mcopy(mfp, stdout, mp->m_seek, mp->m_end, 1);
854: }
855: return (1);
856: }
857:
858: /*
859: * Get additional users to receive message (CC:)
860: */
861:
862: char **
863: getcc(users)
864: register char **users;
865: {
866: register char **ulist = args;
867: static char names[NCLINE];
868:
869: mmsg("CC: ");
870: if ( fgets(names, sizeof names, stdin) == NULL )
871: return(users);
872:
873: while (*users != NULL)
874: *ulist++ = *users++;
875:
876: csplit(names, ulist);
877: return(args);
878: }
879:
880:
881: /*
882: * Errors, usage, and exit removing
883: * any tempfiles left around.
884: */
885: mmsg(x, s)
886: char *x, *s;
887: {
888: fprintf(stderr, x, s);
889: }
890:
891: merr(x, s)
892: char *x, *s;
893: {
894: mmsg(x, s);
895: rmexit(1);
896: }
897:
898: usage()
899: {
900: mmsg(helpmessage);
901: rmexit(1);
902: }
903:
904: rmexit(s)
905: int s;
906: {
907: if (temp != NULL)
908: unlink(temp);
909: munlock();
910: exit(s);
911: }
912:
913: /*
914: * Catch interrupts, taking the
915: * appropriate action based on
916: * the `-q' option.
917: */
918: int intflag; /* On when interrupt sent */
919:
920: catchintr()
921: {
922: signal(SIGINT, SIG_IGN);
923: if (qflag)
924: rmexit(1);
925: intflag = 1;
926: signal(SIGINT, catchintr);
927: }
928:
929: intcheck()
930: {
931: if (intflag) {
932: intflag = 0;
933: putc('\n', stderr);
934: return (1);
935: }
936: return (0);
937: }
938:
939: /*
940: * Call the system to execute a command line
941: * which is passed as an argument.
942: * Change the user id and group id.
943: */
944: system(line)
945: char *line;
946: {
947: int status, pid;
948: register wpid;
949: register int (*intfun)(), (*quitfun)();
950:
951: if ((pid = fork()) < 0)
952: return (-1);
953: if (pid == 0) { /* Child */
954: setuid(myuid);
955: setgid(mygid);
956: execl("/bin/sh", "sh", "-c", line, NULL);
957: exit(0177);
958: }
959: intfun = signal(SIGINT, SIG_IGN);
960: quitfun = signal(SIGQUIT, SIG_IGN);
961: while ((wpid = wait(&status))!=pid && wpid>=0)
962: ;
963: if (wpid < 0)
964: status = wpid;
965: signal(SIGINT, intfun);
966: signal(SIGQUIT, quitfun);
967: return (status);
968: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.