|
|
1.1 root 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:
11: /*copylet flags */
12: /*remote mail, add rmtmsg */
13: #define REMOTE 1
14: /* zap header and trailing empty line */
15: #define ZAP 3
16: #define ORDINARY 2
17: #define FORWARD 4
18: #define LSIZE 256
19: #define MAXLET 300 /* maximum number of letters */
20: #define MAILMODE (~0644) /* mode of created mail */
21: #define RMAIL "/usr/net/bin/sendmail"
22:
23: char line[LSIZE];
24: char resp[LSIZE];
25: struct let {
26: long adr;
27: char change;
28: } let[MAXLET];
29: int nlet = 0;
30: char lfil[50];
31: long iop, time();
32: char *getenv();
33: char *index();
34: char lettmp[] = "/tmp/maXXXXX";
35: char maildir[] = "/usr/spool/mail/";
36: char mailfile[] = "/usr/spool/mail/xxxxxxxxxxxxxxxxxxxxxxx";
37: char dead[] = "dead.letter";
38: char *thissys = sysname;
39: char *netname = "vax";
40: char forwmsg[] = " forwarded\n";
41: char *curlock;
42: int lockerror;
43: FILE *tmpf;
44: FILE *malf;
45: char *my_name;
46: char *getlogin();
47: struct passwd *getpwuid();
48: int error;
49: int locked;
50: int changed;
51: int forward;
52: char from[] = "From ";
53: long ftell();
54: int delete();
55: char *ctime();
56: int flgf;
57: int flgp;
58: int delflg = 1;
59: jmp_buf sjbuf;
60:
61: main(argc, argv)
62: char **argv;
63: {
64: register i;
65: char sobuf[BUFSIZ];
66:
67: setbuf(stdout, sobuf);
68: mktemp(lettmp);
69: unlink(lettmp);
70: my_name = getlogin();
71: if (my_name == NULL || strlen(my_name) == 0) {
72: struct passwd *pwent;
73: pwent = getpwuid(getuid());
74: if (pwent==NULL)
75: my_name = "???";
76: else
77: my_name = pwent->pw_name;
78: }
79: if(setjmp(sjbuf)) done();
80: for (i=0; i<20; i++)
81: setsig(i, delete);
82: tmpf = fopen(lettmp, "w");
83: if (tmpf == NULL) {
84: fprintf(stderr, "mail: cannot open %s for writing\n", lettmp);
85: done();
86: }
87: if (argv[0][0] != 'r' && /* no favors for rmail*/
88: (argc == 1 || argv[1][0] == '-' && argv[1][1] != 'r'))
89: printmail(argc, argv);
90: else
91: sendmail(argc, argv);
92: done();
93: }
94:
95: setsig(i, f)
96: int i;
97: int (*f)();
98: {
99: if(signal(i, SIG_IGN)!=SIG_IGN)
100: signal(i, f);
101: }
102:
103: printmail(argc, argv)
104: char **argv;
105: {
106: int flg, i, j, print;
107: char *p, *getarg();
108:
109: setuid(getuid());
110: cat(mailfile, maildir, my_name);
111: for (; argc>1; argv++, argc--) {
112: if (argv[1][0]=='-') {
113: if (argv[1][1]=='q')
114: delflg = 0;
115: else if (argv[1][1]=='p') {
116: flgp++;
117: delflg = 0;
118: } else if (argv[1][1]=='f') {
119: if (argc>=3) {
120: strcpy(mailfile, argv[2]);
121: argv++;
122: argc--;
123: }
124: } else if (argv[1][1]=='r') {
125: forward = 1;
126: } else {
127: fprintf(stderr, "mail: unknown option %c\n", argv[1][1]);
128: done();
129: }
130: } else
131: break;
132: }
133: malf = fopen(mailfile, "r");
134: if (malf == NULL) {
135: fprintf(stdout, "No mail.\n");
136: return;
137: }
138: lock(mailfile);
139: copymt(malf, tmpf);
140: fclose(malf);
141: fclose(tmpf);
142: unlock();
143: tmpf = fopen(lettmp, "r");
144:
145: changed = 0;
146: print = 1;
147: for (i = 0; i < nlet; ) {
148: j = forward ? i : nlet - i - 1;
149: if(setjmp(sjbuf)) {
150: print=0;
151: } else {
152: if (print)
153: copylet(j, stdout, ORDINARY);
154: print = 1;
155: }
156: if (flgp) {
157: i++;
158: continue;
159: }
160: setjmp(sjbuf);
161: fprintf(stdout, "? ");
162: fflush(stdout);
163: if (fgets(resp, LSIZE, stdin) == NULL)
164: break;
165: switch (resp[0]) {
166:
167: default:
168: fprintf(stderr, "usage\n");
169: case '?':
170: print = 0;
171: fprintf(stderr, "q\tquit\n");
172: fprintf(stderr, "x\texit without changing mail\n");
173: fprintf(stderr, "p\tprint\n");
174: fprintf(stderr, "s[file]\tsave (default mbox)\n");
175: fprintf(stderr, "w[file]\tsame without header\n");
176: fprintf(stderr, "-\tprint previous\n");
177: fprintf(stderr, "d\tdelete\n");
178: fprintf(stderr, "+\tnext (no delete)\n");
179: fprintf(stderr, "m user\tmail to user\n");
180: fprintf(stderr, "! cmd\texecute cmd\n");
181: break;
182:
183: case '+':
184: case 'n':
185: case '\n':
186: i++;
187: break;
188: case 'x':
189: changed = 0;
190: case 'q':
191: goto donep;
192: case 'p':
193: break;
194: case '^':
195: case '-':
196: if (--i < 0)
197: i = 0;
198: break;
199: case 'y':
200: case 'w':
201: case 's':
202: flg = 0;
203: if (resp[1] != '\n' && resp[1] != ' ') {
204: printf("illegal\n");
205: flg++;
206: print = 0;
207: continue;
208: }
209: if (resp[1] == '\n' || resp[1] == '\0') {
210: p = getenv("HOME");
211: if(p != 0)
212: cat(resp+1, p, "/mbox");
213: else
214: cat(resp+1, "", "mbox");
215: }
216: for (p = resp+1; (p = getarg(lfil, p)) != NULL; ) {
217: malf = fopen(lfil, "a");
218: if (malf == NULL) {
219: fprintf(stdout, "mail: cannot append to %s\n", lfil);
220: flg++;
221: continue;
222: }
223: copylet(j, malf, resp[0]=='w'? ZAP: ORDINARY);
224: fclose(malf);
225: }
226: if (flg)
227: print = 0;
228: else {
229: let[j].change = 'd';
230: changed++;
231: i++;
232: }
233: break;
234: case 'm':
235: flg = 0;
236: if (resp[1] == '\n' || resp[1] == '\0') {
237: i++;
238: continue;
239: }
240: if (resp[1] != ' ') {
241: printf("invalid command\n");
242: flg++;
243: print = 0;
244: continue;
245: }
246: for (p = resp+1; (p = getarg(lfil, p)) != NULL; )
247: if (!sendrmt(j, lfil, "/bin/mail")) /* couldn't send it */
248: flg++;
249: if (flg)
250: print = 0;
251: else {
252: let[j].change = 'd';
253: changed++;
254: i++;
255: }
256: break;
257: case '!':
258: system(resp+1);
259: printf("!\n");
260: print = 0;
261: break;
262: case 'd':
263: let[j].change = 'd';
264: changed++;
265: i++;
266: if (resp[1] == 'q')
267: goto donep;
268: break;
269: }
270: }
271: donep:
272: if (changed)
273: copyback();
274: }
275:
276: copyback() /* copy temp or whatever back to /usr/spool/mail */
277: {
278: register i, n, c;
279: int new = 0;
280: struct stat stbuf;
281:
282: signal(SIGINT, SIG_IGN);
283: signal(SIGHUP, SIG_IGN);
284: signal(SIGQUIT, SIG_IGN);
285: lock(mailfile);
286: stat(mailfile, &stbuf);
287: if (stbuf.st_size != let[nlet].adr) { /* new mail has arrived */
288: malf = fopen(mailfile, "r");
289: if (malf == NULL) {
290: fprintf(stdout, "mail: can't re-read %s\n", mailfile);
291: done();
292: }
293: fseek(malf, let[nlet].adr, 0);
294: fclose(tmpf);
295: tmpf = fopen(lettmp, "a");
296: fseek(tmpf, let[nlet].adr, 0);
297: while ((c = fgetc(malf)) != EOF)
298: fputc(c, tmpf);
299: fclose(malf);
300: fclose(tmpf);
301: tmpf = fopen(lettmp, "r");
302: let[++nlet].adr = stbuf.st_size;
303: new = 1;
304: }
305: malf = fopen(mailfile, "w");
306: if (malf == NULL) {
307: fprintf(stderr, "mail: can't rewrite %s\n", lfil);
308: done();
309: }
310: n = 0;
311: for (i = 0; i < nlet; i++)
312: if (let[i].change != 'd') {
313: copylet(i, malf, ORDINARY);
314: n++;
315: }
316: fclose(malf);
317: if (new)
318: fprintf(stdout, "new mail arrived\n");
319: unlock();
320: }
321:
322: copymt(f1, f2) /* copy mail (f1) to temp (f2) */
323: FILE *f1, *f2;
324: {
325: long nextadr;
326:
327: nlet = nextadr = 0;
328: let[0].adr = 0;
329: while (fgets(line, LSIZE, f1) != NULL) {
330: if (isfrom(line))
331: let[nlet++].adr = nextadr;
332: nextadr += strlen(line);
333: fputs(line, f2);
334: }
335: let[nlet].adr = nextadr; /* last plus 1 */
336: }
337:
338: copylet(n, f, type) FILE *f;
339: { int ch, k;
340: fseek(tmpf, let[n].adr, 0);
341: k = let[n+1].adr - let[n].adr;
342: while(k-- > 1 && (ch=fgetc(tmpf))!='\n')
343: if(type!=ZAP) fputc(ch,f);
344: if(type==REMOTE)
345: fprintf(f, " remote from %s\n", thissys);
346: else if (type==FORWARD)
347: fprintf(f, forwmsg);
348: else if(type==ORDINARY)
349: fputc(ch,f);
350: while(k-->1)
351: fputc(ch=fgetc(tmpf), f);
352: if(type!=ZAP || ch!= '\n')
353: fputc(fgetc(tmpf), f);
354: }
355:
356: isfrom(lp)
357: register char *lp;
358: {
359: register char *p;
360:
361: for (p = from; *p; )
362: if (*lp++ != *p++)
363: return(0);
364: return(1);
365: }
366:
367: sendmail(argc, argv)
368: char **argv;
369: {
370: char truename[100];
371: int first;
372:
373: truename[0] = 0;
374: line[0] = '\0';
375: if (argc > 4 && strcmp(argv[1], "-r") == 0) {
376: strcpy(truename, argv[2]);
377: strcat(truename, ":");
378: strcat(truename, argv[3]);
379: argc -= 3;
380: argv += 3;
381: fgets(line, LSIZE, stdin);
382: if (strcmpn("From", line, 4) == 0)
383: line[0] = '\0';
384: } else
385: strcpy(truename, my_name);
386: time(&iop);
387: fprintf(tmpf, "%s%s %s", from, truename, ctime(&iop));
388: iop = ftell(tmpf);
389: flgf = 1;
390: for (first = 1;; first = 0) {
391: if (first && line[0] == '\0' && fgets(line, LSIZE, stdin) == NULL)
392: break;
393: if (!first && fgets(line, LSIZE, stdin) == NULL)
394: break;
395: if (line[0] == '.' && line[1] == '\n' && isatty(fileno(stdin)))
396: break;
397: if (isfrom(line))
398: fputs(">", tmpf);
399: fputs(line, tmpf);
400: flgf = 0;
401: }
402: fputs("\n", tmpf);
403: nlet = 1;
404: let[0].adr = 0;
405: let[1].adr = ftell(tmpf);
406: fclose(tmpf);
407: if (flgf)
408: return;
409: tmpf = fopen(lettmp, "r");
410: if (tmpf == NULL) {
411: fprintf(stderr, "mail: cannot reopen %s for reading\n", lettmp);
412: return;
413: }
414: while (--argc > 0)
415: if (!send(0, *++argv)) /* couldn't send to him */
416: error++;
417: if (error) {
418: setuid(getuid());
419: malf = fopen(dead, "w");
420: if (malf == NULL) {
421: fprintf(stdout, "mail: cannot open %s\n", dead);
422: fclose(tmpf);
423: return;
424: }
425: copylet(0, malf, ZAP);
426: fclose(malf);
427: fprintf(stdout, "Mail saved in %s\n", dead);
428: }
429: fclose(tmpf);
430: }
431:
432: sendrmt(n, name, rcmd)
433: char *name;
434: char *rcmd;
435: {
436: FILE *rmf, *popen();
437: register char *p;
438: char rsys[64], cmd[64];
439: register local, pid;
440: int sts;
441:
442: local = 0;
443: if (index(name, '^')) {
444: while (p = index(name, '^'))
445: *p = '!';
446: if (strncmp(name, "researc", 7)) {
447: strcpy(rsys, "research");
448: if (*name != '!')
449: --name;
450: goto skip;
451: }
452: }
453: if (*name=='!')
454: name++;
455: for(p=rsys; *name!='!'; *p++ = *name++)
456: if (*name=='\0') {
457: local++;
458: break;
459: }
460: *p = '\0';
461: if ((!local && *name=='\0') || (local && *rsys=='\0')) {
462: fprintf(stdout, "null name\n");
463: return(0);
464: }
465: skip:
466: if ((pid = fork()) == -1) {
467: fprintf(stderr, "mail: can't create proc for remote\n");
468: return(0);
469: }
470: if (pid) {
471: while (wait(&sts) != pid) {
472: if (wait(&sts)==-1)
473: return(0);
474: }
475: return(!sts);
476: }
477: setuid(getuid());
478: if (local)
479: sprintf(cmd, "%s %s", rcmd, rsys);
480: else {
481: if (index(name+1, '!'))
482: sprintf(cmd, "uux - %s!rmail \\(%s\\)", rsys, name+1);
483: else
484: sprintf(cmd, "uux - %s!rmail %s", rsys, name+1);
485: }
486: if ((rmf=popen(cmd, "w")) == NULL)
487: exit(1);
488: copylet(n, rmf, local ? !strcmp(rcmd, "/bin/mail") ? FORWARD : ORDINARY : REMOTE);
489: pclose(rmf);
490: exit(0);
491: }
492:
493: send(n, name) /* send letter n to name */
494: int n;
495: char *name;
496: {
497: char file[50];
498: register char *p;
499: register mask;
500: struct passwd *pw, *getpwnam();
501:
502: stripfx(netname, &name);
503: for(p=name; *p!=':' &&*p!='\0'; p++);
504: if(*p == ':') return(sendrmt(n, name, RMAIL));
505: else if (strcmp(name, "msgs") == 0) return(sendrmt(n, "-s", "/usr/ucb/msgs"));
506: for(p=name; *p!='!'&&*p!='^' &&*p!='\0'; p++)
507: ;
508: if (*p == '!'|| *p=='^')
509: return(sendrmt(n, name, 0));
510: if ((pw = getpwnam(name)) == NULL) {
511: fprintf(stdout, "mail: can't send to %s\n", name);
512: return(0);
513: }
514: cat(file, maildir, name);
515: mask = umask(MAILMODE);
516: malf = fopen(file, "a");
517: umask(mask);
518: if (malf == NULL) {
519: fprintf(stdout, "mail: cannot append to %s\n", file);
520: return(0);
521: }
522: lock(file);
523: chown(file, pw->pw_uid, pw->pw_gid);
524: copylet(n, malf, ORDINARY);
525: fclose(malf);
526: unlock();
527: return(1);
528: }
529:
530: delete(i)
531: {
532: setsig(i, delete);
533: fprintf(stderr, "\n");
534: if(delflg)
535: longjmp(sjbuf, 1);
536: done();
537: }
538:
539: done()
540: {
541: if(!lockerror)
542: unlock();
543: unlink(lettmp);
544: exit(error+lockerror);
545: }
546:
547: lock(file)
548: char *file;
549: {
550: struct stat stbuf;
551:
552: if (locked || flgf)
553: return;
554: if (stat(file, &stbuf)<0)
555: return;
556: if (stbuf.st_mode&01) { /* user x bit is the lock */
557: if (stbuf.st_ctime+60 >= time((long *)0)) {
558: fprintf(stderr, "%s busy; try again in a minute\n", file);
559: lockerror++;
560: done();
561: }
562: }
563: locked = stbuf.st_mode & ~01;
564: curlock = file;
565: chmod(file, stbuf.st_mode|01);
566: }
567:
568: unlock()
569: {
570: if (locked)
571: chmod(curlock, locked);
572: locked = 0;
573: }
574:
575: cat(to, from1, from2)
576: char *to, *from1, *from2;
577: {
578: int i, j;
579:
580: j = 0;
581: for (i=0; from1[i]; i++)
582: to[j++] = from1[i];
583: for (i=0; from2[i]; i++)
584: to[j++] = from2[i];
585: to[j] = 0;
586: }
587:
588: char *getarg(s, p) /* copy p... into s, update p */
589: register char *s, *p;
590: {
591: while (*p == ' ' || *p == '\t')
592: p++;
593: if (*p == '\n' || *p == '\0')
594: return(NULL);
595: while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0')
596: *s++ = *p++;
597: *s = '\0';
598: return(p);
599: }
600: stripfx(pfx, name)
601: char *pfx;
602: char **name;
603: {
604: register char *cp = *name;
605:
606: while (*pfx && (*cp == *pfx || *cp == toupper(*pfx)))
607: cp++, pfx++;
608: if (*cp++ != ':')
609: return;
610: *name = cp;
611: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.