|
|
1.1 root 1: /*
2: * subroutines that weren't worth their own files
3: */
4: #include <stdio.h>
5: #include <signal.h>
6: #include <sys/param.h>
7: #include "mail.h"
8: #include "string.h"
9:
10: /* configuration */
11: #define FRWRD "Forward to "
12: #define PIPE "Pipe to "
13: #define WHOAMI "/etc/whoami" /* file containing system name */
14: #define MAILROOT "/usr/spool/mail/" /* root of mail system */
15: #define UPASROOT "/usr/lib/upas/" /* root of upas system */
16:
17: /* imported */
18: int rmail; /* true if started as rmail (init if undefined) */
19: int onatty; /* true if on a tty (init if undefined) */
20: extern unsigned int alarm();
21:
22: /* return a pointer to last element of a pathname */
23: extern char *
24: basename(file)
25: char *file;
26: {
27: char *base;
28: char *strrchr();
29:
30: if ((base = strrchr(file, '/')) != 0)
31: base++; /* past '/' */
32: else
33: base = file;
34: return (base);
35: }
36:
37: /* get the next whitespace delimited token from a string */
38: extern char *
39: getarg(s, p) /* copy p... into s, update p */
40: register char *s, *p;
41: {
42: while (*p == ' ' || *p == '\t')
43: p++;
44: if (*p == '\n' || *p == '\0')
45: return(NULL);
46: while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0')
47: *s++ = *p++;
48: *s = '\0';
49: return(p);
50: }
51:
52: /* a path to a mail file */
53: extern char *
54: mailpath(relp)
55: char *relp; /* relative path name */
56: {
57: static char pathname[128];
58:
59: if (*relp == '/')
60: *pathname = '\0';
61: else
62: (void)strcpy(pathname, MAILROOT);
63: (void)strcat(pathname, relp);
64: return pathname;
65: }
66:
67: /* a path to a special upas file */
68: extern char *
69: upaspath(relp)
70: char *relp; /* relative path name */
71: {
72: static char pathname[128];
73:
74: if (*relp == '/')
75: *pathname = '\0';
76: else
77: (void)strcpy(pathname, UPASROOT);
78: (void)strcat(pathname, relp);
79: return pathname;
80: }
81:
82: /* get the system's name */
83: extern char *
84: getsysname()
85: {
86: int f;
87: char *strchr();
88: static char wsysname[33];
89:
90: f = open(WHOAMI, 0);
91: if (f>=0) {
92: wsysname[0] = '\0';
93: read(f, wsysname, 32);
94: if (strchr(wsysname, '\n')) {
95: *strchr(wsysname, '\n') = '\0';
96: }
97: close(f);
98: }
99: return wsysname;
100: }
101:
102: /*
103: * Return:
104: * 0 if no special action is requested
105: * 1 if fowarding (new address in param)
106: * 2 if mail is to be piped to a comand (command in param)
107: */
108: extern int
109: delivery_status(s, param)
110: char *s, *param;
111: {
112: FILE *fp;
113: char fbuf[CMDSIZE], *p, *sp;
114: int rv = MF_NORMAL;
115: extern char *stringin();
116:
117:
118: fp = fopen(s, "r");
119: if(fp == NULL)
120: return MF_NORMAL;
121: fbuf[0] = '\0';
122: fgets(fbuf, sizeof(fbuf), fp);
123: if (p = stringin(FRWRD, fbuf))
124: rv = MF_FORWARD;
125: else if (p = stringin(PIPE, fbuf))
126: rv = MF_PIPE;
127: if (rv != 0) {
128: while (*p == ' ')
129: p++;
130: sp = param;
131: while (*p && *p!='\n')
132: *sp++ = *p++;
133: *sp = '\0';
134: if (fgets(fbuf, sizeof(fbuf), fp) != NULL)
135: rv |= MFEXTRA;
136: }
137: fclose(fp);
138: return (*param != 0) ? rv : MF_NORMAL;
139: }
140:
141: /*
142: * Find one string within another.
143: * Return: NULL if line doesn't contain str
144: * a pointer to the first byte following str in line otherwise
145: */
146: extern char *
147: stringin(str, line)
148: char *str, *line;
149: {
150: register char *sp, *lp;
151:
152: while (*line) {
153: sp = str;
154: lp = line++;
155: for (;;) {
156: if (*sp != *lp) {
157: if (*sp=='\0')
158: return(lp);
159: break;
160: }
161: sp++;
162: lp++;
163: }
164: }
165: return(NULL);
166: }
167:
168: /* print error and core dump */
169: extern int
170: panic(s)
171: char *s;
172: {
173: fprintf(stderr, "mail: %s\n", s);
174: signal(SIGQUIT, SIG_DFL);
175: kill(getpid(), SIGQUIT);
176: exit(-1);
177: }
178:
179: /* global to from parsing */
180: static char rmtlist[ADDRSIZE];
181:
182: /* output a unix header with remote from blurb */
183: extern void
184: putrfunix(sender, date, sys, fp)
185: char *date, *sys, *sender;
186: FILE *fp;
187: {
188: fprintf(fp, "From %s %s%s%s\n", sender, date, REMFROM, sys);
189: }
190:
191: /* output a unix header */
192: extern void
193: putunix(sender, date, fp)
194: char *sender, *date;
195: FILE *fp;
196: {
197: fprintf(fp, "From %s %s\n", sender, date);
198: }
199:
200: /* start the unix parse */
201: extern void
202: initgetunix()
203: {
204: rmtlist[0] = '\0';
205: }
206:
207: /* get/parse unix from line */
208: extern int
209: getunix(line, sender, date)
210: char *line; /* line to parse */
211: char *sender; /* filled by parseline */
212: char *date; /* filled by parseline */
213: {
214: char *rp, *dp, *sp;
215:
216: /* look for a from */
217: if ((sp = stringin(FROM, line))!=NULL
218: || (sp = stringin(ALTFROM, line))!=NULL) {
219:
220: /* do we have a remote from? */
221: if ((rp = stringin(REMFROM, line))!=NULL) {
222:
223: /* add to remote list */
224: line[strlen(line)-1] = '\0';
225: *(rp - (sizeof(REMFROM)-1)) = '\0';
226: if ((dp = strchr(sp, ' ')) != NULL) {
227: strcpy(date, dp+1);
228: *dp = '\0';
229: }
230: (void)strcpy(sender, sp);
231: (void)strcat(rmtlist, rp);
232: (void)strcat(rmtlist, "!");
233: return -1;
234: }
235: }
236:
237: /* Not a from line */
238: /* Use what we've found so far */
239: (void)strcat(rmtlist, sender);
240: (void)strcpy(sender, rmtlist);
241: return 0;
242: }
243:
244: /*
245: * a paranoid's version of popen
246: */
247: #define RDR 0
248: #define WTR 1
249:
250: static int ppid;
251: static int perrfd;
252: static char *envp[] = {
253: "IFS= \n",
254: "PATH=/bin:/usr/bin:/usr/lib/upas",
255: 0
256: };
257:
258: static char perrbuf[CMDSIZE]; /* where to put standard error */
259: static int forked; /* true if we've already forked */
260:
261: /* here if popen times out */
262: static
263: ptimeout()
264: {
265: fprintf(stderr, "time out - possbile mail problem\n");
266: exit(1);
267: }
268:
269: extern FILE *
270: popen(cmd, uid, gid)
271: char *cmd;
272: int uid, gid;
273: {
274: register i;
275: int p[2], perr[2];
276:
277: /* do mail in background to keep user from getting bored */
278: if (onatty && !rmail && !forked) {
279: switch(fork()) {
280: case 0:
281: signal(SIGHUP, SIG_IGN);
282: signal(SIGINT, SIG_IGN);
283: signal(SIGQUIT, SIG_IGN);
284: signal(SIGTERM, SIG_IGN);
285: forked = 1;
286: break;
287: case -1:
288: break;
289: default:
290: exit(0);
291: }
292: }
293:
294: if(pipe(p) < 0)
295: return NULL;
296: if(pipe(perr) < 0) {
297: close(p[RDR]);
298: close(p[WTR]);
299: return NULL;
300: }
301: if((ppid = fork()) == 0) {
302: (void)setgid(gid);
303: (void)setuid(uid);
304: (void)dup2(p[RDR], 0);
305: (void)dup2(perr[WTR], 2);
306: (void)close(1);
307: for (i=3; i<NOFILE; i++)
308: close(i);
309: execle("/bin/sh", "sh", "-c", cmd, 0, envp);
310: _exit(1);
311: }
312: if(ppid == -1)
313: return NULL;
314:
315: signal(SIGALRM, ptimeout);
316: signal(SIGPIPE, SIG_IGN);
317: alarm(1200); /* in case of deadly embrace twixt stdin and stderr */
318:
319: close(perr[WTR]);
320: perrfd = perr[RDR];
321: close(p[RDR]);
322: return(fdopen(p[WTR], "w"));
323: }
324:
325: extern int
326: pclose(ptr, perrbuf, perrlen)
327: FILE *ptr;
328: char *perrbuf;
329: unsigned int perrlen;
330: {
331: register r, (*hstat)(), (*istat)(), (*qstat)();
332: int status, len, i;
333:
334: fclose(ptr);
335: istat = signal(SIGINT, SIG_IGN);
336: qstat = signal(SIGQUIT, SIG_IGN);
337: hstat = signal(SIGHUP, SIG_IGN);
338: if (perrlen > 0) {
339: for (i = 0; i < perrlen; i += len) {
340: len = read(perrfd, perrbuf+i, perrlen-i);
341: if (len <= 0)
342: break;
343: }
344: perrbuf[i] = '\0';
345: }
346: close(perrfd);
347: alarm(0); /* see alarm in popen */
348: signal(SIGALRM, SIG_IGN);
349: while((r = wait(&status)) != ppid && r != -1)
350: ;
351: if(r == -1)
352: status = 0;
353: signal(SIGINT, istat);
354: signal(SIGQUIT, qstat);
355: signal(SIGHUP, hstat);
356: return(status);
357: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.