|
|
1.1 root 1: static char *rcsrev = "$Revision: 1.3 $";
2: static char *rcshdr =
3: "$Header: /src386/bin/lmail/RCS/lmail.c,v 1.3 92/11/03 09:06:26 bin Exp Locker: bin $";
4: /*
5: * $Header: /src386/bin/lmail/RCS/lmail.c,v 1.3 92/11/03 09:06:26 bin Exp Locker: bin $
6: * $Log: lmail.c,v $
7: * Revision 1.3 92/11/03 09:06:26 bin
8: * Bob H: restructures routines to lock and write mailboxes and wait for mailbox to become available.
9: *
10: * Revision 1.1 92/03/13 12:19:15 bin
11: * Initial revision
12: *
13: * Revision 1.2 92/01/07 08:46:20 bin
14: * Piggy changes for so that if an all caps sitename fails, it will try
15: * lower case.
16: *
17: * Revision 2.13 90/03/30 16:16:19 wgl
18: * Correct seek pointer work within readmail.
19: *
20: * Revision 2.12 90/03/12 14:19:08 wgl
21: * New version of send doing aliases in a different place.
22: *
23: * Revision 2.11 90/03/08 16:41:15 wgl
24: * Add code to get signature file.
25: *
26: * Revision 2.10 90/03/02 10:41:59 wgl
27: * Add the -a flag so that uucp does not look like it is coming from
28: * somewhere else.
29: *
30: * Revision 2.9 90/03/01 11:17:19 wgl
31: * Final conversion to rely soley on ^A^A as separators.
32: * Effectively delete concept of m_hsize.
33: *
34: * Revision 2.8 90/03/01 10:14:31 wgl
35: * Go buy separators, not "From_" lines.
36: *
37: * Revision 2.7 90/02/28 17:11:41 wgl
38: * Add version print, add some changes to the message-id field.
39: *
40: * Revision 2.6 90/02/28 16:42:09 wgl
41: * Version number fakeout.
42: *
43: * Revision 2.5 90/02/28 16:19:44 wgl
44: * Try again to get versioin number right.
45: *
46: * Revision 2.4 90/02/28 16:18:56 wgl
47: * Get version number right.
48: *
49: * Revision 2.3 90/02/28 16:04:59 wgl
50: * Many changes; ripped out send.
51: * Changes are to make it work with uucp and internet mail.
52: *
53: * Revision 1.6 89/02/22 05:34:00 bin
54: * Changes by rec to integrate with lauren's uumail.
55: *
56: * Revision 1.5 88/09/01 14:49:01 bin
57: * Source administration: Re-install declaration of getenv.
58: * It was inserted after epstein made his copy.
59: *
60: * Revision 1.4 88/09/01 14:44:49 bin
61: * Mark Epsteins changes for ASKCC and for message scrolling, and interrupt
62: * handling during processing.
63: *
64: * Revision 1.3 88/09/01 14:27:41 bin
65: * declare getenv to get rid of integer pointer pun error message.
66: *
67: * Revision 1.2 88/09/01 11:02:23 bin
68: * Remove extra declaration of header which had rcs stuff in it.
69: *
70: * Revision 1.1 88/09/01 10:55:34 bin
71: * Initial revision
72: *
73: */
74: /*
75: * The mail command.
76: * Coherent electronic postal system.
77: * (NOTE: this command is written in such a way that
78: * it assumed that it is setuid on execution to `root'.
79: * All file accession is checked on this basis).
80: * Modifications by rec january 1986 to include xmail.
81: * by epstein november 1987 to include CC:
82: * by epstein november 1987 to allow ^C exit to leave you in
83: * mail command processor
84: * by epstein november 1987 to substitute /usr/games/fortune
85: * for printing encrypted messages
86: * by rec february 1989 to tail to lauren weinstein's
87: * mail for alias expansion and uucp queuing.
88: * by wgl January 1990 to handle uucp mail more directly.
89: */
90:
91: char isummary[] = "\
92: \
93: Command summary:\n\
94: d Delete current message and print the next message\n\
95: m [user ...] Mail current message to each named 'user'\n\
96: p Print current message again\n\
97: q Quit and update the mailbox\n\
98: r Reverse direction of scan\n\
99: s [file ...] Save message in each named 'file'\n\
100: t [user ...] Mail standard input to each named 'user'\n\
101: w [file ...] Save message in each named 'file' without its header\n\
102: x Exit without updating mailbox\n\
103: newline Print the next message\n\
104: . Print current message again\n\
105: + Print the next message\n\
106: - Print the previous message\n\
107: EOF Put undeleted mail back into mailbox and quit\n\
108: ? Print this command summary\n\
109: !command Pass 'command' to the shell to execute\n\
110: If no 'file' is specified, 'mbox' in user's home directory is default.\n\
111: If no 'user' is specified, the invoking user is default.\n\
112: If the 'm', 'p', 't' commands are followed by an 'x',\n\
113: then the public key cryptosystem is applied to the message.\n\
114: \
115: ";
116:
117: #include "mail.h"
118:
119: #define NARGS 64 /* Maximum # args to interactive command */
120:
121: extern char *getenv();
122: extern int optind;
123: extern char *optarg;
124: extern char getopt();
125: char *revnop();
126:
127: char BOBerrmsg[50];
128:
129: int mflag; /* `You have mail.' message to recipient */
130: int rflag; /* Reverse order of print */
131: int qflag; /* Exit after interrrupts */
132: int pflag; /* Print mail */
133: int verbflag; /* verbose */
134: int callmexmail; /* Xmail modifier present */
135: int callmermail; /* rmail modifier present */
136: struct msg {
137: struct msg *m_next; /* Link to next message */
138: struct msg *m_prev; /* Link to previous message */
139: int m_flag; /* Flags - non-zero if deleted */
140: int m_hsize; /* Size of header of message */
141: fsize_t m_seek; /* Start position of message */
142: fsize_t m_end; /* End of message */
143: };
144: struct msg *m_first = NULL; /* First message */
145: struct msg *m_last = NULL; /* Last message */
146:
147: struct tm *tp;
148:
149: char iusage[] = "Bad command--type '?' for command summary\n";
150: char nombox[] = "No mailbox '%s'.\n";
151: char nomail[] = "No mail.\n";
152: char noperm[] = "Mailbox '%s' access denied.\n";
153: char moerr[] = "Cannot open mailbox '%s'\n";
154: char wrerr[] = "Write error on '%s'\n";
155: char nosave[] = "Cannot save letter in '%s'\n";
156:
157: FILE *mfp; /* Mailbox stream */
158: int myuid; /* User-id of mail user */
159: int mygid; /* Group-id of mail user */
160: char myname[25]; /* User name */
161: char myfullname[50];
162: char mymbox[256]; /* $HOME/mbox */
163: char spoolname[50] = SPOOLDIR;
164: char *mailbox = spoolname;
165: char cmdname[1024]; /* Command for x{en,de}code filter */
166: /* and for tail recursion to uumail */
167: /* and for editor recursion */
168:
169: char *args[NARGS]; /* Interactive command arglist */
170: char msgline[NLINE];
171: char cline[NCLINE] = "+\n";
172: char *temp; /* Currently open temp file */
173: char templ[] = "/tmp/mailXXXXXX"; /* Temp file name template */
174: char *editname; /* name of editor */
175: char *scatname; /* name of scat filter */
176: char *askcc; /* Ask for CC: list? (YES/NO) */
177:
178: fsize_t ftell();
179: char *getlogin();
180: char *mktemp();
181: int catchintr();
182: int catchpipe();
183: void catchchild();
184: int close_fds();
185: char asuser [32];
186:
187: main(argc, argv)
188: char *argv[];
189: {
190: register char *ap;
191: char c, *foo;
192:
193: close_fds();
194: logopen();
195:
196: ap = argv[0];
197: if ( (foo=rindex(ap, '/')) != NULL )
198: ap = foo+1;
199: callmermail = (strcmp(ap, "rmail") == 0);
200: callmexmail = (strcmp(ap, "xmail") == 0);
201:
202: if (callmermail)
203: logdump("argv0 = rmail\n");
204:
205: asuser [0] = '\0';
206: signal(SIGCLD, catchchild);
207: signal(SIGINT, catchintr);
208: signal(SIGPIPE, catchpipe);
209: while ((c = getopt(argc, argv, "a:f:mpqrv")) != EOF) {
210: switch(c) {
211: case 'f':
212: if (!callmermail)
213: mailbox = optarg;
214: break;
215: case 'a':
216: strcpy(asuser, optarg);
217: break;
218: case 'm':
219: mflag++;
220: break;
221: case 'p':
222: pflag++;
223: break;
224: case 'q':
225: qflag++;
226: break;
227: case 'r':
228: rflag++;
229: break;
230: case 'v':
231: fprintf(stderr, "mail, ver. %s\n", revnop());
232: verbflag++;
233: break;
234: default:
235: usage();
236: }
237: }
238: if (callmermail)
239: verbflag = mflag = pflag = rflag = 0;
240: setname();
241: if (optind < argc) {
242: qflag = 1;
243: if ( send2(stdin, &argv[optind], (fsize_t)0,
244: (fsize_t)MAXLONG, 1) != 0 )
245: rmexit(1);
246: } else {
247: if ( ! pflag)
248: callmexmail = 0;
249: }
250: rmexit(0);
251: }
252:
253: /*
254: * Setup all the identities for the current user.
255: */
256: setname()
257: {
258: register struct passwd *pwp;
259: register char *np;
260: extern struct passwd * getpwnam();
261:
262: if (strlen(asuser) > 0) {
263: if((pwp = getpwnam(asuser)) == NULL)
264: merr("No such user %s.\n", asuser);
265: myuid = pwp -> pw_uid;
266: } else
267: myuid = getuid();
268: if ((pwp = getpwuid(myuid)) == NULL)
269: merr("Who are you?\n");
270: np = pwp->pw_name;
271: mygid = pwp->pw_gid;
272: strcat(spoolname, np);
273: strcpy(myname, np);
274: strcpy(myfullname, pwp->pw_gecos);
275: strcpy(mymbox, pwp->pw_dir);
276: strcat(mymbox, "/mbox");
277: mktemp(templ);
278:
279: if ((editname=getenv("EDITOR"))==NULL)
280: editname = "/bin/ed";
281:
282: if ( ((scatname=getenv("PAGER")) != NULL) &&
283: (strlen(scatname) == 0) )
284: scatname = NULL;
285:
286: if ((askcc=getenv("ASKCC")) != NULL)
287: if ( strcmp(askcc, "YES") )
288: askcc = NULL;
289: }
290:
291: /*
292: * Lock the appropriately-numbered mailbox
293: * (numbered by user-number) from multiple
294: * accesses. There is a (small) race here
295: * which will be overlooked for now.
296: */
297: char *lockname;
298:
299: mlock(uid)
300: int uid;
301: {
302: register int fd;
303: static char lock[32];
304:
305: lockname = lock;
306: sprintf(lock, "/tmp/maillock%d", uid);
307:
308: while ( (access(lockname, AEXISTS)) == 0 ){
309: sprintf(BOBerrmsg, "{%d} sleeping(1)\n",getpid());
310: logdump(BOBerrmsg);
311: sleep(1);
312: }
313:
314: if ((fd = creat(lockname, 0)) >= 0){
315: close(fd);
316: return(0);
317: }else{
318: return(1);
319: }
320: }
321:
322: /*
323: * Unlock the currently-set lock (by `mlock')
324: * also called from rmexit.
325: */
326: munlock()
327: {
328: if (lockname != NULL)
329: unlink(lockname);
330: lockname = NULL;
331: }
332:
333: /*
334: * Errors, usage, and exit removing
335: * any tempfiles left around.
336: */
337: mmsg(x)
338: {
339: fprintf(stderr, "%r", &x);
340: }
341:
342: merr(x, s)
343: char *x, *s;
344: {
345: mmsg(x, s);
346: logdump("merr: ");
347: logdump(x, s);
348: rmexit(1);
349: }
350:
351: rmexit(s)
352: int s;
353: {
354: if (temp != NULL)
355: unlink(temp);
356:
357: /* only unlock the mailbox if we are exiting normally. Remember,
358: * the box may have been locked by another process.
359: */
360:
361: if(s == 0)
362: munlock();
363:
364: sprintf(BOBerrmsg,"{%d} About to exit, status = 0x%04x\n", getpid(),s);
365: logdump(BOBerrmsg);
366: logclose();
367:
368: exit(s);
369: }
370:
371: /*
372: * Catch interrupts, taking the
373: * appropriate action based on
374: * the `-q' option.
375: */
376: int intrflag; /* On when interrupt sent */
377: int pipeflag; /* On when broken pipe caught */
378:
379: catchintr()
380: {
381: logdump("Caught SIGINT\n");
382: if (qflag)
383: rmexit(1);
384: intrflag = 1;
385: signal(SIGINT, catchintr);
386: }
387:
388: void catchchild()
389: {
390: logdump("Caught SIGCLD\n");
391: signal(SIGCLD, catchchild);
392: }
393:
394: catchpipe()
395: {
396: logdump("Caught SIGPIPE\n");
397: pipeflag = 1;
398: signal(SIGPIPE, catchpipe);
399: }
400:
401: intcheck()
402: {
403: if (intrflag || pipeflag) {
404: if (intrflag){
405: putc('\n', stdout);
406: sprintf(BOBerrmsg,"{%d} lmail caught interrupt signal\n",
407: getpid());
408: }else{
409: sprintf(BOBerrmsg,"{%d} lmail caught broken pipe signal",
410: getpid());
411: }
412:
413: logdump(BOBerrmsg);
414:
415: intrflag = pipeflag = 0;
416: return (1);
417: }
418: return (0);
419: }
420:
421: char *
422: revnop()
423: {
424: register char *cp;
425: register char c;
426: static char revnobuf[32];
427:
428: if ((cp = index(rcsrev, ' ')) != NULL) {
429: while (((c = *++cp) == ' ') && (c != '\0'))
430: ;
431: strcpy(revnobuf, cp);
432: if ((cp = index(revnobuf, ' ')) != NULL)
433: *cp = '\0';
434: return (revnobuf);
435: } else
436: return("OOPS");
437: }
438:
439:
440: /* close any unwanted file descriptors that we may have inheritted */
441:
442: close_fds()
443: {
444:
445: int i;
446:
447: for(i = fileno(stderr) +1 ; i < _NFILE ; i++){
448: close(i);
449: }
450: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.