|
|
1.1 root 1: #
2:
3: /*
4: * mail command usage
5: * mail [-yn]
6: * prints your mail
7: * mail people
8: * sends standard input to people
9: *
10: * mail -r machine user people
11: * sends mail from the network
12: *
13: * if NOTROOT is defined, don't run as root.
14: */
15:
16: #define SIGINT 2
17: #define DIRECT 040000
18: #define RMAILCMD "/usr/net/bin/sendmail"
19: #define GETUID() (getuid() & 0377)
20: #define SPOOLDIR "/usr/spool/mail/"
21: #define NOTROOT $
22:
23: struct inode {
24: char minor;
25: char major;
26: int inumber;
27: int flags;
28: char nlinks;
29: char uid;
30: char gid;
31: char size0;
32: int size1;
33: int addr[8];
34: int actime[2];
35: int modtime[2];
36: } inode;
37:
38: char lettmp[] "/tmp/maXXXXX";
39: char preptmp[] "/tmp/mbXXXXX";
40: int pwfil;
41: int chew;
42: int errs;
43: char *strcat(), *strcpy();
44:
45: main(argc, argv)
46: char **argv;
47: {
48: register int me;
49: extern int fout;
50: int uf, delexit();
51: char namebuf[20];
52:
53: mktemp(lettmp);
54: mktemp(preptmp);
55: unlink(lettmp);
56: unlink(preptmp);
57: me = GETUID();
58: if (getname(me, namebuf) < 0) {
59: printf("Who are you?\n");
60: delexit(1);
61: }
62: if (argc < 2)
63: goto hitit;
64: for (argc--, argv++; argc > 0 && argv[0][0] == '-'; argc--, argv++)
65: switch(argv[0][1]) {
66: register char *cp, *np;
67:
68: case 'y':
69: case 'n':
70: argc++, argv--;
71: hitit:
72: printmail(argc, argv, namebuf);
73: delexit(0);
74:
75: case 'r':
76: if (argc < 2)
77: continue;
78: case 'f':
79: if (argc < 1)
80: continue;
81: if (!equal("network", namebuf) && me != 0) {
82: printf("Nice try!\n");
83: delexit(1);
84: }
85: chew++;
86: np = namebuf;
87: for (cp = argv[1]; *cp; cp++)
88: *np++ = *cp;
89: if (argv[0][1] == 'r')
90: {
91: argc--, argv++;
92: *np++ = ':';
93: for (cp = argv[1]; *cp; cp++)
94: *np++ = *cp;
95: }
96: *np++ = 0;
97: argc--, argv++;
98: continue;
99: }
100: if ((signal(SIGINT, 01) & 01) == 0)
101: signal(SIGINT, delexit);
102: unlink(lettmp);
103: # ifdef NOTROOT
104: fout = creat(lettmp, 0666);
105: # else
106: fout = creat(lettmp, 0600);
107: # endif
108: if (fout < 0) {
109: fout = 1;
110: perror(lettmp);
111: delexit(1);
112: }
113: argc++, argv--;
114: bulkmail(argc, argv, namebuf);
115: delexit(0);
116: }
117:
118: printmail(argc, argv, name)
119: char **argv;
120: char *name;
121: {
122: extern int fin, fout;
123: register n, c, f;
124: char *mname;
125:
126: mname = cat(SPOOLDIR, name);
127: if (stat(mname, &inode)>=0 && inode.nlinks==1 &&
128: fopen(mname, &fin)>=0 && (c = getchar())) {
129: putchar(c);
130: getput();
131: close(fin);
132: c = 'x';
133: if (argc<2) {
134: if (ttyn(0)!='x') {
135: printf("Save?");
136: fin = 0;
137: c = getchar();
138: }
139: } else
140: c = argv[1][1];
141: if (!any(c, "yn"))
142: delexit(0);
143: if (c == 'y') {
144: if (accesss("mbox")) {
145: printf("Saved mail in 'mbox'\n");
146: prepend(mname, "mbox", GETUID());
147: unlink(mname);
148: } else
149: printf("In wrong directory\n");
150: } else
151: unlink(mname);
152: } else
153: printf("No mail.\n");
154: }
155:
156: bulkmail(argc, argv, from)
157: char **argv, *from;
158: {
159: extern int fin, fout;
160: register int c;
161: register char *cp;
162: char linebuf[128];
163: int tbuf[2], ttyn1;
164:
165: fin = 0;
166: (&fin)[1] = 0;
167: time(tbuf);
168: ttyn1 = ttyn(1);
169: if (ttyn1 < 033) {
170: ttyn1 =+ 'a' - 1;
171: ttyn1 =<< 8;
172: ttyn1 =| '^';
173: }
174: printf("From %s tty%c %s", from, ttyn1, ctime(tbuf));
175:
176: /*
177: * If delivering mail from the network via mail -r,
178: * Strip the leading line and throw it away, as long
179: * as it begins with "From ..."
180: */
181:
182: if (chew) {
183: cp = linebuf;
184: do {
185: c = getchar();
186: if (cp - linebuf < 120)
187: *cp++ = c;
188: } while (c != '\n' && c != 0);
189: *cp = '\0';
190: if (linebuf[0] != 'F' || linebuf[1] != 'r' ||
191: linebuf[2] != 'o' || linebuf[3] != 'm')
192: printf("%s", linebuf);
193: }
194: getput();
195: putchar('\n');
196: flush();
197: close(fout);
198: while (--argc > 0)
199: sendto(*++argv);
200: delexit(errs);
201: }
202:
203: sendto(person)
204: char *person;
205: {
206: static int saved;
207: extern int fout, fin;
208: register char *filep;
209: register int him;
210: int i;
211:
212: if ((person[0] == 'i' || person[0] == 'I') && person[1] == ':')
213: person += 2;
214: for (i = 0; person[i] != '\0'; i++)
215: {
216: if (person[i] == ':')
217: {
218: person[i] = '\0';
219: if (equal(person, "ing70") || equal(person, "ingres"))
220: person += i + 1;
221: else
222: person[i] = ':';
223: break;
224: }
225: }
226: if (person[i] == ':' || equal(person, "msgs"))
227: {
228: int i = fork();
229: int s;
230:
231: if (i < 0) {
232: perror("fork");
233: goto assback;
234: }
235: if (i == 0) {
236: close(0);
237: open(lettmp, 0);
238: if (any(':', person)) {
239: execl(RMAILCMD, "sendmail", person, 0);
240: execl("/usr/bin/sendmail", "sendmail", person, 0);
241: execl("/bin/sendmail", "sendmail", person, 0);
242: perror("sendmail");
243: } else {
244: execl("/usr/new/msgs", "msgs", "-s", 0);
245: execl("/usr/ucb/msgs", "msgs", "-s", 0);
246: execl("/usr/bin/msgs", "msgs", "-s", 0);
247: }
248: exit(12);
249: }
250: for (;;) {
251: register int j = wait(&s);
252: if (j == -1)
253: goto assback;
254: if (j == i)
255: break;
256: }
257: if ((s & 0377) != 0 || (s >> 8) == 12)
258: goto assback;
259: return;
260: }
261:
262: if ((him = getuserid(person)) == -1) {
263: assback:
264: fout = 1;
265: flush();
266: printf("Can't send to %s.\n", person);
267: errs++;
268: if (ttyn(0)!='x' && saved==0) {
269: saved++;
270: if (accesss("dead.letter")) {
271: printf("Letter saved in 'dead.letter'\n");
272: prepend(lettmp, "dead.letter", GETUID());
273: } else
274: printf("In wrong directory\n");
275: }
276: return;
277: }
278: filep = cat(SPOOLDIR, person);
279: lock(filep);
280: prepend(lettmp, filep, him);
281: unlock();
282: }
283:
284: prepend(from, to, own)
285: char *from, *to;
286: {
287: extern int fin, fout;
288: register int sig;
289: int statb[18];
290:
291: if (stat(to, statb) >= 0 && (statb[2] & 060000) != 0) {
292: write(2, "Exotic destination\n", 19);
293: delexit(1);
294: }
295: unlink(preptmp);
296: if (fcreat(preptmp, &fout) < 0) {
297: fout = 1;
298: perror("mail");
299: delexit(1);
300: }
301: chmod(preptmp, 0600);
302: if (fopen(from, &fin) < 0) {
303: close(fout);
304: fout = 1;
305: perror("mail");
306: unlink(preptmp);
307: return(0);
308: }
309: getput();
310: close(fin);
311: fopen(to, &fin);
312: getput();
313: close(fin);
314: flush();
315: close(fout);
316: sig = signal(SIGINT, 01);
317: unlink(to);
318: if (fcreat(to, &fout) < 0) {
319: unlink(preptmp);
320: fout = 1;
321: signal(SIGINT, sig);
322: return(0);
323: }
324: # ifdef NOTROOT
325: chmod(to, 0666);
326: # else
327: chmod(to, 0600);
328: chown(to, own);
329: # endif
330: if(stat(to, &inode) < 0 || inode.nlinks != 1) {
331: close(fout);
332: fout = 1;
333: unlink(preptmp);
334: signal(SIGINT, sig);
335: return(0);
336: }
337: if (fopen(preptmp, &fin) < 0) {
338: fout = 1;
339: perror("mail");
340: signal(SIGINT, sig);
341: errs++;
342: return(0);
343: }
344: getput();
345: flush();
346: close(fout);
347: close(fin);
348: fout = 1;
349: signal(SIGINT, sig);
350: return(1);
351: }
352:
353: delexit(ex)
354: {
355: unlock();
356: unlink(lettmp);
357: unlink(preptmp);
358: exit(ex);
359: }
360:
361: equal(as1, as2)
362: {
363: register char *s1, *s2;
364:
365: s1 = as1;
366: s2 = as2;
367: while (*s1++ == *s2)
368: if (*s2++ == 0)
369: return(1);
370: return(0);
371: }
372:
373: cat(ap1, ap2)
374: char *ap1, *ap2;
375: {
376: register char *p1, *p2;
377: static char fn[32];
378:
379: p1 = ap1;
380: p2 = fn;
381: while (*p2++ = *p1++);
382: p2--;
383: p1 = ap2;
384: while (*p2++ = *p1++);
385: return(fn);
386: }
387:
388: getput()
389: {
390: extern int errno;
391: register c;
392:
393: while(c = getchar()) {
394: errno = 0;
395: putchar(c);
396: if(errno) {
397: perror("mail");
398: delexit(1);
399: }
400: }
401: }
402:
403: accesss(s1)
404: {
405: if (access(".", 2) != -1 && (stat(s1, &inode)<0 || access(s1, 2)==0))
406: return(1);
407: return(0);
408: }
409:
410: any(c, str)
411: char *str;
412: {
413: register char *f;
414:
415: f = str;
416: while (*f)
417: if (c == *f++)
418: return(1);
419: return(0);
420: }
421:
422: char *maillock = ".lock"; /* Lock suffix for mailname */
423: char *lockname = "/usr/spool/mail/tmXXXXXX";
424: char locktmp[30]; /* Usable lock temporary */
425: char curlock[50]; /* Last used name of lock */
426: int locked; /* To note that we locked it */
427:
428: /*
429: * Lock the specified mail file by setting the file mailfile.lock.
430: * We must, of course, be careful to unlink the lock file by a call
431: * to unlock before we stop. The algorithm used here is to see if
432: * the lock exists, and if it does, to check its modify time. If it
433: * is older than 30 seconds, we assume error and set our own file.
434: * Otherwise, we wait for 5 seconds and try again.
435: */
436:
437: lock(file)
438: char *file;
439: {
440: register int f;
441: long age;
442: struct inode sbuf;
443: long curtime;
444:
445: if (file == (char *) 0) {
446: printf("Locked = %d\n", locked);
447: return(0);
448: }
449: if (locked)
450: return(0);
451: strcpy(curlock, file);
452: strcat(curlock, maillock);
453: strcpy(locktmp, lockname);
454: mktemp(locktmp);
455: unlink(locktmp);
456: for (;;) {
457: f = lock1(locktmp, curlock);
458: if (f == 0) {
459: locked = 1;
460: return(0);
461: }
462: if (stat(curlock, &sbuf) < 0)
463: return(0);
464: time(&curtime);
465: age = * ((long *) sbuf.modtime);
466: if (curtime < age + 30) {
467: sleep(5);
468: continue;
469: }
470: unlink(curlock);
471: }
472: }
473:
474: /*
475: * Remove the mail lock, and note that we no longer
476: * have it locked.
477: */
478:
479: unlock()
480: {
481:
482: if (locked)
483: unlink(curlock);
484: locked = 0;
485: }
486:
487: /*
488: * Attempt to set the lock by creating the temporary file,
489: * then doing a link/unlink. If it fails, return -1 else 0
490: */
491:
492: lock1(tempfile, name)
493: char tempfile[], name[];
494: {
495: register int fd;
496:
497: fd = creat(tempfile, 0);
498: if (fd < 0)
499: return(-1);
500: close(fd);
501: if (link(tempfile, name) < 0) {
502: unlink(tempfile);
503: return(-1);
504: }
505: unlink(tempfile);
506: return(0);
507: }
508:
509: /*
510: * Concatenate s2 on the end of s1. S1's space must be large enough.
511: * Return s1.
512: */
513:
514: char *
515: strcat(s1, s2)
516: register char *s1, *s2;
517: {
518: register os1;
519:
520: os1 = s1;
521: while (*s1++)
522: ;
523: *--s1;
524: while (*s1++ = *s2++)
525: ;
526: return(os1);
527: }
528:
529: /*
530: * Copy string s2 to s1. s1 must be large enough.
531: * return s1
532: */
533:
534: char *
535: strcpy(s1, s2)
536: register char *s1, *s2;
537: {
538: register os1;
539:
540: os1 = s1;
541: while (*s1++ = *s2++)
542: ;
543: return(os1);
544: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.