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