|
|
1.1 root 1: #include <stdio.h>
2: #include <sys/types.h>
3: #include <sys/mdata.h>
4: #include <time.h>
5: #include <pwd.h>
6: #include <utmp.h>
7: #include <sys/stat.h>
8: #include "mail.h"
9:
10: #define SITENAMELEN 32 /* max length of sitename */
11: #define NODENAME "/etc/uucpname"
12: #define DOMAINNAME "/etc/domain"
13: #define ALIAS "/usr/lib/mail/aliases"
14: char domain [64];
15:
16: extern char *strtok();
17: FILE *aliasfp;
18: char aliasbuf [BUFSIZ];
19: char *findalias();
20: static **gusers;
21: char mysite[SITENAMELEN]; /* this host's uucpname */
22:
23: extern char *temp;
24: extern int myuid; /* User-id of mail user */
25: extern int mygid; /* Group-id of mail user */
26: extern char cmdname[]; /* Command for x{en,de}code filter */
27: /* and for tail recursion to uumail */
28: /* and for editor recursion */
29: extern char *editname; /* name of editor */
30: extern char *askcc; /* Ask for CC: list? (YES/NO) */
31: extern int callmexmail; /* Xmail modifier present */
32: extern char wrerr[];
33: extern char myname[]; /* User name */
34: extern char myfullname[]; /* full user name */
35: extern int mflag; /* `You have mail.' message to recipient */
36: extern int verbflag; /* verbose flag */
37: extern char templ[]; /* Temp file name template */
38: extern char mydead[]; /* $HOME/dead.letter */
39: extern char mysig[];
40: extern char nosave[];
41: extern int callmermail;
42:
43: static int eflag; /* Edit this mail */
44: static int senderr;
45: struct tm *tp;
46: char toerr[] = "Cannot create temporary file\n";
47: char header[BUFSIZ]; /* Message header */
48: char boxname[256]; /* Destination mailbox */
49: char aftralias [BUFSIZ]; /* name after alias processing */
50: char remotefrom [32]; /* "remote from uucp" */
51:
52: char nosend[] = "Can't send mail to '%s'\n";
53: char nopubk[] = "Can't send xmail to '%s'\n";
54: static int fromtty;
55:
56: /*
57: * Send the message found on
58: * the file pointer to the list
59: * of people (argv style) with
60: * a NULL pointer at the end.
61: * The message is copied to a temp-file
62: * from position `start' to `end' (or EOF).
63: */
64: send2(fp, users, start, end, asksubj)
65: FILE *fp;
66: register char **users;
67: fsize_t start, end;
68: int asksubj;
69: {
70: char **getcc();
71: FILE *xfp, *tfp, *sigfp;
72: time_t curtime;
73:
74: uucpname();
75: domainname();
76: senderr = 0;
77: temp = templ;
78: /*fprintf(stderr, "send2(fp, users, %ld, %ld, %d)\n", start, end, asksubj);*/
79: fromtty = isatty(fileno(fp));
80: if ((tfp = fopen(temp, "w")) != NULL) {
81: fclose(tfp);
82: if ((tfp = fopen(temp, "r+w")) == NULL)
83: merr(toerr);
84: } else
85: merr(toerr);
86: chown(temp, myuid, mygid);
87: unlink(temp);
88: temp = NULL;
89: fseek(fp, start, 0);
90: end -= start;
91:
92: eflag = 0;
93: if (fromtty && asksubj && !callmermail) {
94: fprintf(stdout, "Subject: ");
95: fflush(stdout);
96: if (fgets(msgline, NLINE, fp) != NULL) {
97: if (strlen(msgline) > 1)
98: fprintf(tfp, "Subject: %s", msgline);
99: }
100: }
101: for (;;) {
102: if (fgets(msgline, NLINE, fp) == NULL)
103: break;
104: if (fp == stdin)
105: if ((strcmp(".\n", msgline)==0))
106: break;
107: else if ((strcmp("?\n", msgline)==0)) {
108: eflag = 1;
109: break;
110: }
111: /* fprintf(stderr, ":%s:", msgline); */
112: fputs(msgline, tfp);
113: end -= strlen(msgline); /* compiler bug */
114: if (end <= 0) {
115: break;
116: }
117: }
118: if (!callmermail && (sigfp = fopen(mysig, "r")) != NULL) {
119: fputs("\n", tfp);
120: while (fgets(msgline, NLINE, sigfp) != NULL) {
121: fputs(msgline, tfp);
122: }
123: fclose(sigfp);
124: }
125: /*
126: * If interrupted, bug out.
127: */
128: if (intcheck()) {
129: fclose(tfp);
130: return;
131: }
132: /*
133: * Now, see if user wants to edit the message
134: */
135: if (eflag) {
136: xfp = tfp;
137: temp = templ;
138: if ((tfp = fopen(temp, "wr")) == NULL)
139: merr(toerr);
140: chown(temp, myuid, mygid);
141: mcopy(xfp, tfp, (fsize_t)0, (fsize_t)MAXLONG, 0);
142: fclose(xfp);
143: sprintf(cmdname, "%s %s", editname, templ);
144: system(cmdname);
145: unlink(temp);
146: temp = NULL;
147: }
148: /*
149: * Otherwise if empty message, bug out.
150: */
151: else if (ftell(tfp) == 0) {
152: fclose(tfp);
153: return;
154: }
155: /*
156: * Now see if a copy list is requested.
157: */
158: if (askcc)
159: users = getcc(users);
160: gusers = users;
161: /*
162: * Now send the message.
163: */
164: time(&curtime);
165: tp = localtime(&curtime);
166: if (callmexmail)
167: xsend(users, tfp);
168: else
169: usend(users, tfp);
170: }
171:
172: usend(users, tfp)
173: char **users;
174: FILE *tfp;
175: {
176: FILE *xfp;
177: char *cp, *ap;
178: char **ulist;
179: register struct passwd *pwp;
180:
181: for (ulist = users; *ulist != NULL; ulist++) {
182: rewind(tfp);
183: strcpy(aftralias, *ulist);
184: if (index(*ulist, '!') == 0) {
185: ap = findalias(*ulist);
186: if (ap != NULL) {
187: strcpy(aftralias, ap);
188: if (verbflag && strcmp(aftralias, ap))
189: fprintf(stderr,
190: "name %s aliased to %s\n",
191: *ulist, aftralias);
192: }
193: }
194: if ((cp = index(aftralias, '!')) != NULL) {
195: *cp++ = '\0';
196: if (rsend(aftralias, cp, tfp) != 0)
197: senderr = 1;
198: continue;
199: }
200: sprintf(boxname, "%s%s", SPOOLDIR, aftralias);
201: if ((pwp = getpwnam(aftralias)) == NULL) {
202: mmsg(nosend, aftralias);
203: senderr = 1;
204: continue;
205: }
206: mlock(pwp->pw_uid);
207: if ((xfp = fopen(boxname, "a")) == NULL) {
208: mmsg(nosend, aftralias);
209: senderr = 1;
210: munlock();
211: continue;
212: }
213: chown(boxname, pwp->pw_uid, pwp->pw_gid);
214: if (build_header(aftralias, NULL, tfp, xfp) != 1
215: || mcopy(tfp, xfp, ftell(tfp), (fsize_t)MAXLONG, 0)) {
216: merr(wrerr, boxname);
217: senderr = 1;
218: } else
219: fprintf(xfp, "\1\1\n");
220: fflush(xfp);
221: munlock();
222: advise(aftralias);
223: }
224: if (senderr && fromtty && ! callmexmail) {
225: if (maccess(mydead) < 0
226: || (xfp = fopen(mydead, "a")) == NULL
227: || mcopy(tfp, xfp, (fsize_t)0, (fsize_t)MAXLONG, 0))
228: mmsg(nosave, mydead);
229: else
230: mmsg("Letter saved in %s\n", mydead);
231: if (xfp != NULL) {
232: chown(mydead, myuid, mygid);
233: fclose(xfp);
234: }
235: }
236: fclose(tfp);
237: }
238:
239: rsend(system, user, tfp)
240: char *user;
241: char *system;
242: FILE *tfp;
243: {
244: FILE *xfp;
245: int i;
246:
247: sprintf(cmdname, "uux -r - %s!rmail '(%s)'", system, user);
248: if (verbflag)
249: fprintf(stderr, "Queueing remote mail to %s!%s\n",
250: system, user);
251: if ((xfp = popen(cmdname, "w")) == NULL) {
252: mmsg("Can't pipe to %s\n", cmdname);
253: return 1;
254: }
255: if (build_header(user, mysite, tfp, xfp) != 1
256: || mcopy(tfp, xfp, ftell(tfp), (fsize_t)MAXLONG, 0)) {
257: merr(wrerr, cmdname);
258: return 1;
259: }
260: if (i = (pclose(xfp) != 0)) {
261: mmsg("uux has failed, status %d\n", i);
262: return 1;
263: }
264: return 0;
265: }
266:
267: xsend(users, tfp) char **users; FILE *tfp;
268: {
269: register char **ulist;
270: register char *cp;
271: register struct passwd *pwp;
272: FILE *xfp;
273:
274: for (ulist = users; *ulist!=NULL; ulist++) {
275: rewind(tfp);
276: sprintf(boxname, "%s%s", SPOOLDIR, *ulist);
277: sprintf(cmdname, "xencode %s >> %s", *ulist, boxname);
278: if (index(*ulist, '!') != NULL
279: || (pwp = getpwnam(*ulist)) == NULL) {
280: mmsg(nosend, *ulist);
281: continue;
282: }
283: if (xaccess(*ulist) == 0) {
284: mmsg(nopubk, *ulist);
285: continue;
286: }
287: mlock(pwp->pw_uid);
288: if ((xfp = fopen(boxname, "a")) == NULL) {
289: mmsg(nosend, *ulist);
290: munlock();
291: continue;
292: }
293: chown(boxname, pwp->pw_uid, pwp->pw_gid);
294: fprintf(xfp, "From xmail %s %s\n", cp,
295: tzname[tp->tm_isdst ? 1 : 0]);
296: fclose(xfp);
297: if ((xfp = popen(cmdname, "w")) == NULL) {
298: mmsg("Can't pipe to xencode\n");
299: continue;
300: }
301: if (fwrite(header, strlen(header), 1, xfp) != 1
302: || mcopy(tfp, xfp, (fsize_t)0, (fsize_t)MAXLONG, 0)) {
303: merr(wrerr, cmdname);
304: }
305: pclose(xfp);
306: munlock();
307: }
308: fclose(tfp);
309: }
310:
311: /*
312: * If the `-m' option is specified, advise
313: * the recipient of the presence of mail.
314: */
315: advise(recipient)
316: char *recipient;
317: {
318: register FILE *fp;
319: register FILE *tfp;
320: struct utmp ut;
321: char tty[30];
322: struct stat sb;
323:
324: if (!mflag)
325: return;
326: if ((fp = fopen("/etc/utmp", "r")) == NULL)
327: return;
328: while (fread(&ut, sizeof ut, 1, fp) == 1)
329: if (strncmp(ut.ut_name, recipient, DIRSIZ) == 0) {
330: sprintf(tty, "/dev/%s", ut.ut_line);
331: if (stat(tty, &sb)<0 || (sb.st_mode&S_IEXEC)==0)
332: continue;
333: if ((tfp = fopen(tty, "w")) != NULL) {
334: fprintf(tfp, "\7%s: you have mail.\n", myname);
335: fclose(tfp);
336: }
337: }
338: fclose(fp);
339: }
340:
341: uucpname()
342: {
343: FILE *uufile;
344:
345: if (NULL == (uufile = fopen(NODENAME, "r"))) {
346: strcpy(mysite, "<unknown>");
347: return;
348: }
349: fgets(mysite, sizeof mysite, uufile);
350: mysite[strlen(mysite) - 1] = '\0'; /* remove '\n' */
351: fclose(uufile);
352: return;
353: }
354:
355: domainname()
356: {
357: FILE *domfile;
358: if((domfile = fopen(DOMAINNAME, "r")) == NULL) {
359: strcpy(domain, ".UNKNOWN");
360: return;
361: }
362: fgets(domain, sizeof domain, domfile);
363: domain [strlen(domain) - 1] = '\0';
364: fclose (domfile);
365: return;
366: }
367:
368: char *
369: findalias(who)
370: {
371: char *name, *newname;
372: static whobuf [64];
373: int recurcount;
374: int hit;
375:
376: if (aliasfp == NULL) {
377: if ((aliasfp = fopen(ALIAS, "r")) == NULL) {
378: mmsg("Cannot open alias file\n");
379: return who;
380: }
381: }
382: recurcount = 0;
383: strcpy(whobuf, who);
384: for (; ; ) {
385: fseek(aliasfp, 0L, 0);
386: hit = 0;
387: while (fgets(aliasbuf, BUFSIZ, aliasfp) != NULL) {
388: name = strtok(aliasbuf," #:\t");
389: newname = strtok(NULL, "#(), \t\n");
390: if (strcmp(name, whobuf) == 0) {
391: strcpy(whobuf, newname);
392: if (recurcount++ > 4) {
393: sprintf(whobuf,
394: "Too many alias recursions for %s\n",
395: who);
396: mmsg(whobuf);
397: return who;
398: }
399: hit = 1;
400: break;
401: }
402: }
403: if (hit == 0)
404: return whobuf;
405: }
406: return whobuf;
407: }
408:
409: char *
410: arpadate(tp)
411: struct tm *tp;
412: {
413: static char arpabuf [64];
414: static char months[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
415: sprintf(arpabuf, "%d %c%c%c %d %02d:%02d:%02d",
416: tp->tm_mday,
417: months[tp->tm_mon * 3],
418: months[tp->tm_mon * 3 + 1],
419: months[tp->tm_mon * 3 + 2],
420: tp->tm_year,
421: tp->tm_hour, tp->tm_min, tp->tm_sec);
422: return arpabuf;
423: }
424:
425: char *
426: msgid(tp)
427: struct tm *tp;
428: {
429: static char msgidbuf [32];
430: sprintf(msgidbuf, "%02d%02d%02d%02d%02d",
431: tp->tm_year, tp->tm_mon + 1, tp->tm_mday, tp->tm_hour, tp->tm_min);
432: return msgidbuf;
433: }
434:
435: build_header(user, site, tfp, xfp)
436: char *user;
437: char *site;
438: FILE *tfp;
439: FILE *xfp;
440: {
441: char *cp;
442: char **ulist;
443: long pos;
444: int processid;
445:
446: cp = asctime(tp);
447: cp[strlen(cp)-1] = 0;
448: /* if (!callmermail) { */
449: sprintf(header, "From %s %s %s", myname, cp,
450: tzname[tp->tm_isdst ? 1 : 0]);
451: if (site != NULL) {
452: strcat(header, " remote from ");
453: strcat(header, site);
454: }
455: strcat(header, "\n");
456: /* } */
457: if (fwrite(header, strlen(header), 1, xfp) != 1)
458: return 0;
459: pos = ftell(tfp);
460: /* scan to end of From_ lines */
461: while (fgets(header, NLINE, tfp) != NULL) {
462: if ((strncmp (header, "From ", 5) != 0) &&
463: (strncmp (header, ">From ", 6) != 0)) {
464: break;
465: }
466: if (fwrite(header, strlen(header), 1, xfp) != 1)
467: return 0;
468: pos = ftell(tfp);
469: }
470: fseek(tfp, pos, 0);
471: processid = getpid();
472: if (callmermail) {
473: sprintf(header,
474: "Received: by %s (mail v %s)\n\tid AA%d; %s\n",
475: mysite, revnop(), processid, arpadate(tp));
476: if (fwrite(header, strlen(header), 1, xfp) != 1)
477: return 0;
478: } else {
479: sprintf(header, "Message-Id: <%s.AA%d.V%s.%s@%s>\n",
480: msgid(tp), processid, revnop(), mysite, domain);
481: if (fwrite(header, strlen(header), 1, xfp) != 1)
482: return 0;
483: sprintf(header, "Date: %s\nFrom: %s!%s (%s)\n",
484: arpadate(tp), mysite, myname, myfullname);
485: if (fwrite(header, strlen(header), 1, xfp) != 1)
486: return 0;
487: sprintf(header, "To: %s\n", user);
488: if (fwrite(header, strlen(header), 1, xfp) != 1)
489: return 0;
490: if (gusers[0] != NULL && gusers[1] != NULL) {
491: strcpy(header, "cc:");
492: for (ulist = gusers; *ulist != NULL; ulist++) {
493: strcat(header, " ");
494: strcat(header, *ulist);
495: }
496: strcat(header, "\n");
497: if (fwrite(header, strlen(header), 1, xfp) != 1)
498: return 0;
499: }
500: }
501: return 1;
502: }
503:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.