|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "%W% %E%";
3: #endif
4: /*
5: * v6mail
6: */
7: #include <sysexits.h>
8:
9: #include <sys/param.h>
10: #include <sys/stat.h>
11: #include <sys/dir.h>
12: #include <sys/times.h>
13: #include <ctype.h>
14: #include <errno.h>
15: #include <pwd.h>
16: #include <signal.h>
17:
18: char *ctime(), *index(), *rindex(), *ctime(), *strcpy(), *getlogin();
19: char *mktemp(), *sprintf();
20: struct passwd *getpwnam(), *getpwuid();
21: time_t time();
22: struct utmp *getutmp();
23: char *getdate();
24: int errno;
25:
26: #include <stdio.h>
27:
28: #define MAILMODE 0644
29: #define MSGSCMD "/usr/ucb/msgs"
30: #define MAILDIR "/usr/spool/mail"
31:
32: char lettmp[] = "/tmp/MaXXXXX"; /* keep letter before sending it */
33: char preptmp[] = "/tmp/mbXXXXX"; /* if prepending msg, use this file */
34: int chew; /* if true, strip extra from lines */
35: int dflag; /* if true, don't call sendmail */
36: char shopcnt[30] = "0"; /* hop count parameter for rmt mail */
37: int errs; /* no of errs in sending */
38: char deleteonly; /* if true, just delete mailbox */
39: char remname[50]; /* if non-empty, from line extra */
40:
41: main(argc, argv)
42: int argc;
43: char **argv;
44: {
45: register int myuid;
46: int delexit();
47: char namebuf[128], *sn = NULL, logindir[60];
48: struct passwd *pwd;
49:
50: (void) mktemp(lettmp);
51: (void) mktemp(preptmp);
52: (void) unlink(lettmp);
53: (void) unlink(preptmp);
54: myuid = getuid();
55: logindir[0] = 0;
56: sn = getlogin();
57: if (sn == NULL || *sn == 0 || *sn == ' ') {
58: pwd = getpwuid(myuid); /* will read passwd file */
59: if (pwd != NULL){
60: sn = pwd->pw_name;
61: (void) strcpy(logindir, pwd->pw_dir);
62: }
63: if (sn == NULL) {
64: fprintf(stderr, "Who are you?\n");
65: delexit(EX_OSFILE);
66: }
67: }
68: (void) strcpy(namebuf, sn);
69: if (argc < 2)
70: goto hitit;
71: for (argc--, argv++; argc > 0 && argv[0][0] == '-'; argc--, argv++)
72: switch (argv[0][1]) {
73:
74: case 'y':
75: case 'n':
76: argc++, argv--;
77: hitit:
78: printmail(argc, argv, namebuf, logindir);
79: delexit(EX_OK);
80:
81: case 'r': /* one-arg -r-- -r addr */
82: if (argc < 2)
83: continue;
84: /* ignore -r if not network or root */
85: if (strcmp("network", namebuf) == 0 || myuid == 0 ||
86: /*###86 [lint] index arg. 1 used inconsistently v6mail.c(86) :: v6mail.c(244)%%%*/
87: /*###86 [lint] index arg. 2 used inconsistently v6mail.c(86) :: v6mail.c(244)%%%*/
88: strcmp("uucp", namebuf) == 0 || index('!', argv[1])) {
89: (void) strcpy(namebuf, argv[1]);
90: chew++; /* eat From lines */
91: }
92: else
93: (void) strcpy(remname, argv[1]);
94: argc--, argv++;
95: continue;
96:
97: case 'h': /* hop count - used by network */
98: if (argc < 2)
99: continue;
100: (void) strcpy(shopcnt, argv[1]);
101: argc--, argv++;
102: continue;
103:
104: case 'd': /* really deliver this message */
105: dflag++;
106: continue;
107:
108: case 'D': /* only delete the invokers mailbox */
109: deleteonly++;
110: goto hitit; /* delete mail box, thats all */
111: }
112: /* if we are already ignoring signals, catch sigint */
113: if (signal(SIGINT, SIG_IGN) != SIG_IGN)
114: (void) signal(SIGINT, delexit);
115: argc++, argv--;
116: bulkmail(argc, argv, namebuf);
117: delexit(EX_OK);
118: }
119:
120: printmail(argc, argv, name, logindir)
121: int argc;
122: char **argv;
123: char *name, *logindir;
124: {
125: register int c;
126: FILE *fdin;
127: char sfnmail[60], mbox[120];
128: struct stat stb;
129:
130: (void) sprintf(sfnmail, "%s/%s", MAILDIR, name);
131: if (deleteonly) {
132: remove(sfnmail);
133: return;
134: }
135: fdin = fopen(sfnmail, "r");
136: if (fdin < 0 || fstat(fileno(fdin), &stb) < 0 || stb.st_size == 0) {
137: printf("No mail.\n");
138: return;
139: }
140: if (stb.st_nlink > 1) {
141: printf("%s: Too many links.\n", sfnmail);
142: return;
143: }
144: (void) getput(fdin, stdout);
145: (void) fclose(fdin);
146: (void) fflush(stdout);
147: c = 'y';
148: if (argc < 2) {
149: if (isatty(0)) {
150: printf("Save (y or n) ?"); (void) fflush(stdout);
151: c = getchar();
152: }
153: } else
154: c = argv[1][1];
155: switch (c) {
156:
157: default:
158: delexit(EX_OK);
159: /*NOTREACHED*/
160:
161: case 'x':
162: return;
163:
164: case 'y':
165: (void) sprintf(mbox, "%s/mbox", logindir);
166: if (writeable(mbox)) {
167: perror(mbox);
168: return;
169: }
170: printf("Saving mail in %s.\n", mbox);
171: if (append(sfnmail, mbox, getuid(), getgid()) == 0)
172: return;
173: /* fall into... */
174:
175: case 'n':
176: remove(sfnmail);
177: return;
178: }
179: }
180:
181: bulkmail(argc, argv, from)
182: char **argv, *from;
183: {
184: char linebuf[BUFSIZ];
185: FILE *fdout;
186:
187: if (dflag == 0) {
188: argv[0] = "sendmail";
189: argv[argc] = 0;
190: execv("/usr/lib/sendmail", argv);
191: perror("/usr/lib/sendmail");
192: _exit(1);
193: }
194: fdout = fopen(lettmp, "w");
195: if (fdout == NULL) {
196: perror(lettmp);
197: delexit(EX_OSFILE);
198: }
199:
200: /*
201: * If delivering mail from the network via mail -r,
202: * Strip the leading line and throw it away, as long
203: * as it begins with "From ..." (and preserve the date if poss.)
204: */
205: if (chew) {
206: if (fgets(linebuf, BUFSIZ, stdin) == 0)
207: goto skip;
208: if (!strncmp(linebuf, "From ", 5) != 0)
209: printfromline(fdout, getdate(linebuf), from);
210: else {
211: printfromline(fdout, (char *)0, from);
212: fprintf(fdout, "%s", linebuf);
213: }
214: } else
215: printfromline(fdout, (char *)0, from);
216: skip:
217: if (remname[0])
218: fprintf(fdout, "(from %s)\n", remname);
219: if (getput(stdin, fdout) == 0)
220: delexit(EX_OSERR);
221: putc('\n', fdout);
222: (void) fclose(fdout);
223: while (--argc > 0)
224: sendto(*++argv);
225: delexit(errs);
226: }
227:
228: printfromline(fdout, date, from)
229: FILE *fdout;
230: char *date, *from;
231: {
232: time_t t;
233:
234: if (date == NULL) {
235: t = time((time_t *)0);
236: date = ctime(&t);
237: }
238: fprintf(fdout, "From %s %s", from, date);
239: }
240:
241: /* look over linebuf and return ptr to date, NULL if error */
242: char *
243: getdate(linebuf)
244: char *linebuf;
245: {
246: register char *s = linebuf;
247:
248: /*###244 [lint] index arg. 2 used inconsistently v6mail.c(86) :: v6mail.c(244)%%%*/
249: /*###244 [lint] index arg. 1 used inconsistently v6mail.c(86) :: v6mail.c(244)%%%*/
250: while (s = index(' ', s))
251: if (!strncmp(s, " Sun ", 5) ||
252: !strncmp(s, " Mon ", 5) ||
253: !strncmp(s, " Tue ", 5) ||
254: !strncmp(s, " Wed ", 5) ||
255: !strncmp(s, " Thu ", 5) ||
256: !strncmp(s, " Fri ", 5) ||
257: !strncmp(s, " Sat ", 5))
258: return (s + 1);
259: return (0);
260: }
261:
262: int saved = 0;
263:
264: sendto(person)
265: char *person;
266: {
267: char mailboxname[BUFSIZ];
268: struct passwd *pwd;
269:
270: if (index('/', person)) {
271: if (!writeable(person)) {
272: perror(person);
273: return;
274: }
275: lock(person);
276: (void) append(lettmp, person, -1, -1);
277: unlock();
278: return;
279: }
280: pwd = getpwnam(person);
281: if (pwd) {
282: (void) sprintf(mailboxname, "%s/%s", MAILDIR, person);
283: lock(mailboxname);
284: (void) append(lettmp, mailboxname, pwd->pw_uid, pwd->pw_gid);
285: unlock();
286: return;
287: }
288: fprintf(stderr, "Can't send to %s.\n", person);
289: errs++;
290: if (!isatty(0) || saved)
291: return;
292: saved++;
293: if (!writeable("dead.letter")) {
294: perror("dead.letter");
295: return;
296: }
297: printf("Letter saved in 'dead.letter'\n");
298: (void) append(lettmp, "dead.letter", getuid(), getgid());
299: }
300:
301: #include <sys/socket.h>
302: #include <net/in.h>
303:
304: struct sockaddr_in biffaddr = { AF_INET, IPPORT_BIFFUDP };
305:
306: append(from, to, uid, gid)
307: char *from, *to;
308: int uid, gid;
309: {
310: register FILE *fdin, *fdout;
311: int ret;
312: struct stat stb;
313: char *cp, buf[100]; int f;
314:
315: if (stat(to, &stb) >= 0 && (stb.st_mode&S_IFMT) != S_IFREG) {
316: fprintf(stderr, "Not a plain file: %s\n", to);
317: goto fail;
318: }
319: fdout = fopen(to, "a");
320: if (fdout == NULL) {
321: perror(to);
322: goto fail;
323: }
324: if (uid != -1) {
325: (void) chown(to, uid, gid);
326: (void) chmod(to, MAILMODE);
327: }
328: if ((fdin = fopen(from, "r")) == NULL) {
329: perror(from);
330: return (0);
331: }
332: cp = rindex(to, '/');
333: if (cp) {
334: char *host = "localhost";
335: biffaddr.sin_addr.s_addr = rhost(&host);
336: #if vax || pdp11
337: biffaddr.sin_port =
338: (biffaddr.sin_port<<8) | ((biffaddr.sin_port>>8) & 0xff);
339: #endif
340: f = socket(SOCK_DGRAM, 0, 0, 0);
341: (void) sprintf(buf, "%s@%d\n", cp+1, ftell(fdout));
342: }
343: ret = getput(fdin, fdout);
344: (void) fclose(fdin);
345: (void) fclose(fdout);
346: if (cp && f >= 0) {
347: send(f, &biffaddr, buf, strlen(buf)+1);
348: (void) close(f);
349: }
350: return (ret);
351: fail:
352: errs++;
353: return (0);
354: }
355:
356: delexit(status)
357: int status;
358: {
359:
360: (void) unlink(lettmp);
361: (void) unlink(preptmp);
362: exit(status);
363: }
364:
365: getput(fdin, fdout)
366: register FILE *fdin, *fdout;
367: {
368: register int c;
369:
370: while ((c = getc(fdin)) != EOF) {
371: errno = 0;
372: putc(c, fdout);
373: if (errno) {
374: perror("mail");
375: return (0);
376: }
377: }
378: return (1);
379: }
380:
381: writeable(name)
382: char *name;
383: {
384: struct stat stb;
385: char *cp;
386: int ok;
387:
388: if (stat(name, &stb) < 0) {
389: cp = rindex(name, '/');
390: if (cp)
391: *cp = 0;
392: ok = access(cp ? "." : name, 2) == 0;
393: if (cp)
394: *cp = '/';
395: return (ok);
396: }
397: return (access(name, 2) == 0);
398: }
399:
400: char locktmp[30]; /* Usable lock temporary */
401: char curlock[50]; /* Last used name of lock */
402: int locked; /* To note that we locked it */
403:
404: /*
405: * Lock the specified mail file by setting the file mailfile.lock.
406: * We must, of course, be careful to unlink the lock file by a call
407: * to unlock before we stop. The algorithm used here is to see if
408: * the lock exists, and if it does, to check its modify time. If it
409: * is older than 30 seconds, we assume error and set our own file.
410: * Otherwise, we wait for 5 seconds and try again.
411: */
412: lock(file)
413: char *file;
414: {
415: register int f;
416: struct stat statbuf;
417: time_t curtime;
418:
419: if (locked)
420: return;
421: (void) sprintf(curlock, "%s%s", file, ".lock");
422: (void) sprintf(locktmp, "%s/tmXXXXXX", MAILDIR);
423: (void) mktemp(locktmp);
424: (void) unlink(locktmp);
425: for (;;) {
426: f = lock1(locktmp, curlock);
427: if (f == 0) {
428: locked = 1;
429: return;
430: }
431: if (stat(curlock, &statbuf) < 0)
432: return;
433: (void) time(&curtime);
434: if (curtime < statbuf.st_mtime + 30) {
435: sleep(5);
436: continue;
437: }
438: (void) unlink(curlock);
439: }
440: }
441:
442: unlock()
443: {
444:
445: if (locked)
446: (void) unlink(curlock);
447: locked = 0;
448: }
449:
450: /*
451: * Attempt to set the lock by creating the temporary file,
452: * then doing a link/unlink. If it fails, return -1 else 0
453: */
454: lock1(tempfile, name)
455: char tempfile[], name[];
456: {
457: int fno;
458:
459: fno = creat(tempfile, 0400);
460: if (fno < 0)
461: return (-1);
462: (void) close(fno);
463: if (link(tempfile, name) < 0) {
464: (void) unlink(tempfile);
465: return (-1);
466: }
467: (void) unlink(tempfile);
468: return (0);
469: }
470:
471: remove(sfn)
472: char *sfn;
473: {
474: int i;
475:
476: if (unlink(sfn) < 0) {
477: i = creat(sfn, MAILMODE);
478: if (i >= 0)
479: (void) close(i);
480: }
481: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.