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