1: #include <arpa/netopen.h>
2: #include "srvrftp.h"
3: #include <statbuf.h>
4: #include <arpa/hostnames.h>
5: #include <io_buf.h>
6: #include <arpa/mail.h>
7: #include <ident.h>
8: #include <signal.h>
9: #include <log.h>
10: extern int fout;
11:
12: #if !defined(lint) && defined(DOSCCS)
13: static char SccsId[] = "@(#)mail-dm.c 4.1.1 1996/11/29";
14: #endif
15:
16: /*
17: Name:
18: mail
19:
20: Function:
21: handle the MAIL <user> command over the command connection
22:
23: Algorithm:
24: see if we have a known user
25:
26: if mailbox file can't be gotten
27: return
28: tell him it is ok to go ahead with mail
29:
30: while he doesn't type a period
31: read and write data
32: say completed
33:
34: Parameters:
35: username in arg
36:
37: Returns:
38: nothing
39:
40: Globals:
41: arg
42: username=
43:
44: Calls:
45: strmove
46: getuser
47: loguser
48: openmail
49: closemail
50: getline
51: chown (sys)
52: time (sys)
53: printf (sys)
54: getch (util)
55: putch (util)
56:
57: Called by:
58: main thru command array
59:
60: History:
61: initial coding Mark Kampe UCLA-ATS
62: modified 4/13/76 by S. F. Holmgren for Illinois version
63: modified 6/30/76 by S. F. Holmgren to call getmbox
64: modified 10/18/76 by J. S. Kravitz to improve net mail header
65: chown removed by R. Balocca @ CAC, Sunday 1977 February 20
66: getline removed and limit on line length removed by using
67: getch and putch added by R. Balocca @ CAC, 1977 March 8 Tuesday
68: Fixed oversight in above (forgot to translate <crlf> to <lf>)
69: 1977 March 10 Thursday by Rick Balocca @ CAC
70: Added openmail & closemail, added logging, and fixed several
71: bugs on or about 12/21/79 by Eric Allman, UCB/INGRES.
72: Changed to always accept mail -- bad mail will be sent back --
73: 1/9/80 by Eric Allman, UCB/INGRES.
74: Don't print out 350 enter mail or 256 mail accepted messages --
75: sendmail will do that. 8/19/81 Eric Allman UCB/INGRES.
76: */
77: #define gt (c = getch())
78: mail()
79: {
80: register char *p; /* general use */
81: register int c;
82: int i;
83:
84: /* extern struct io_buf obuf; */
85:
86: /* get to open mailbox file descriptor */
87: fflush(&fout);
88: if( (fout = openmail(arg, 0)) < 0 )
89: return;
90:
91: for(;;) /* while no error or <crlf>.<crlf> */
92: {
93: /* we are at beginning of line */
94:
95: if(gt=='.') /*"."*/
96: {
97: if(gt=='\r') /*".\r"*/
98: {
99: if(gt=='\n') /*".\r\n"*/
100: {
101: /* end of message */
102: break;
103: }
104: else
105: { /*".\r"c*/
106: putch('.');
107: putch('\r');
108: }
109: }
110: else /*"."c"*/
111: putch('.');
112: }
113: /*"-"*/
114: /* c */
115: for(;;)
116: {
117: for(; c != '\r'; gt)
118: {
119: if( c < 0 )
120: {
121: fflush(&fout);
122: write(fout, "\n***** Sender aborted connection *****\n", 39);
123: goto out;
124: }
125: else
126: putch(c);
127: }
128:
129: /*"\r"*/
130: if( gt == '\n' )
131: { /*"\r\n"*/
132: crlf:
133: putch('\n');
134: break;
135: }
136: else
137: { /*"\r"c*/
138: crc:
139: putch('\r');
140: if(c=='\0')
141: gt; /* "\r\0" */
142: /* is arpa escape for "\r" */
143: }
144: }
145: }
146:
147: out:
148: fflush(&fout);
149: closemail(fout);
150: }
151:
152: /*
153: Name:
154: datamail
155:
156: Function:
157: handle the MLFL command
158:
159: Algorithm:
160: fork
161: make sure we have a valid user
162: say bad user and exit
163: send sock command
164: open data connection
165: get open mailbox file descriptor
166: call rcvdata to receive mail
167:
168: Parameters:
169: username in arg
170:
171: Returns:
172: nothing
173:
174: Globals:
175: arg
176:
177: Calls:
178: fork (sys)
179: strmove
180: netreply
181: sendsock
182: dataconnection
183: getmbox
184: rcvdata
185: printf (sys)
186: time (sys)
187:
188: Called by:
189: main thru command array
190:
191: History:
192: initial coding 4/13/76 by S. F. Holmgren
193: modified 10/18/76 by J. S. Kravitz to put net mail header
194: chown removed by R. Balocca @ CAC, Sunday 1977 February 20
195: */
196: datamail()
197: {
198: register netdata;
199: /* register mboxfid; */
200: register int i;
201:
202: i = fork();
203: if (i < 0)
204: {
205: netreply("455 Mail server temporarily unavailable\r\n");
206: return;
207: }
208: else if (i == 0)
209: {
210: fflush(&fout);
211: if ((fout = openmail(arg, 1)) < 0)
212: exit(3);
213:
214: /* send sock command */
215: sendsock( U4 );
216:
217: /* open data connection */
218: netdata = dataconnection( U4 );
219:
220: /* say its ok to proceed */
221: numreply( NUM250 );
222:
223: /* get data from net connection and copy to mail file */
224: /* rcvdata( netdata,mboxfid ); */
225: if (rcvdata(netdata, fout) < 0)
226: exit(1);
227:
228: /* close the mail, see if ok; if so say ok */
229: fflush(&fout);
230: closemail(fout);
231:
232: exit( 0 );
233: }
234: }
235: /*
236: ** OPENMAIL -- Open a channel to the mail server
237: **
238: ** Gets the mail server started up ready to handle our
239: ** mail.
240: **
241: ** Algorithm:
242: ** See if the user is specified.
243: ** If not, send to user "root".
244: ** See if the user exists.
245: ** If not, signal error 450 and return.
246: ** Fork.
247: ** Create a pipe
248: ** Signal "unavailable" and exit on failure.
249: ** Fork.
250: ** Signal "unavailable" and exit on failure
251: ** In child:
252: ** Call mailer: delivermail is preferred.
253: ** In parent:
254: ** Avoid pipe signals in case delivermail dies.
255: ** Save the childs pid.
256: ** Return file descriptor.
257: **
258: ** Notes:
259: ** The check to see if the user actually exists should
260: ** go away so that we can do real mail forwarding.
261: **
262: ** Parameters:
263: ** who -- the user to send the mail to.
264: ** mode -- 0 -- called from mail
265: ** 1 -- called from mlfl
266: **
267: ** Returns:
268: ** File descriptor to send mail to.
269: ** -1 on failure.
270: **
271: ** Side Effects:
272: ** Forks /usr/sbin/delivermail or /bin/mail or /usr/bin/mail.
273: ** Becomes "network" in the child.
274: **
275: ** Requires:
276: ** strmove
277: ** getuser
278: ** netreply
279: ** pipe (sys)
280: ** fork (sys)
281: ** close (sys)
282: ** dup (sys)
283: ** execl (sys)
284: ** signal (sys)
285: ** exit (sys)
286: **
287: ** Called By:
288: ** mail
289: ** datamail
290: **
291: ** History:
292: ** 1/9/80 -- Added 050 & 455 reply messages if execl's
293: ** fail. Eric Allman UCB/INGRES.
294: ** 11/26/79 -- Modified to map upper case to lower
295: ** case. Eric Allman UCB/INGRES.
296: ** 11/10/79 -- Written by Eric Allman UCB/INGRES
297: ** 3/6/80 -- Dropped case mapping; /usr/sbin/delivermail does
298: ** that now. EPA UCB/INGRES.
299: ** 8/19/81 -- Added "mode" parameter; call sendmail
300: ** instead of /usr/sbin/delivermail. EPA
301: */
302:
303: int Mail_pid;
304: char *Mail_user;
305:
306: openmail(who, mode)
307: char *who;
308: int mode;
309: {
310: register char *w;
311: register int i;
312: int pvect[2];
313: register char *p;
314:
315: w = who;
316: if (w == 0)
317: w = "root";
318: Mail_user = w;
319:
320: /* see if the user exists */
321: strmove(w, username);
322:
323: /* try to get a pipe to the mailer */
324: if (pipe(pvect) < 0)
325: {
326: unavailable:
327: netreply("455 Mail server temporarily unavailable\r\n");
328: return (-1);
329: }
330:
331: /* fork */
332: i = fork();
333: if (i < 0)
334: {
335: /* failure */
336: close(pvect[0]);
337: close(pvect[1]);
338: goto unavailable;
339: }
340: else if (i == 0)
341: {
342: /* child */
343: close(pvect[1]);
344: close(0);
345: dup(pvect[0]);
346: close(pvect[0]);
347: setuid(NETUID);
348:
349: /* try to call something to deliver the mail */
350: execl("/usr/sbin/sendmail", "sendmail", "-v", mode == 1 ? "-af" : "-am", w, 0);
351:
352: /* doesn't seem to be anything around */
353: netreply("455 Mail server unavailable\r\n");
354: exit(3);
355: }
356:
357: /* else parent */
358: signal(SIGPIPE, SIG_IGN);
359: Mail_pid = i;
360: close(pvect[0]);
361: return (pvect[1]);
362: }
363: /*
364: ** CLOSEMAIL -- Close the mail file and get actual status
365: **
366: ** The mail file is closed.
367: **
368: ** Algorithm:
369: ** Wait for the mailer to die.
370: ** If it wasn't there, be non-comittal.
371: ** If it died a violent death, give error.
372: **
373: ** Parameters:
374: ** fd -- the file descriptor of the mail file.
375: **
376: ** Returns:
377: ** none.
378: **
379: ** Side Effects:
380: ** mailer is soaked up.
381: **
382: ** Requires:
383: ** close (sys)
384: ** wait (sys)
385: **
386: ** Called By:
387: ** mail
388: ** datamail
389: **
390: ** History:
391: ** 1/9/80 -- Changed to not check for errors in mailing,
392: ** since these will be mailed back.
393: ** 11/10/79 -- Written by Eric Allman UCB/INGRES.
394: */
395:
396: closemail(fd)
397: int fd;
398: {
399: auto int st;
400: register int i;
401:
402: /* close the pipe -- mail should go away */
403: close(fd);
404:
405: /* wait for its body */
406: while ((i = wait(&st)) != Mail_pid)
407: {
408: if (i < 0)
409: {
410: /* how did this happen? */
411: logmsg(LOG_ERR, "mail from host %d to %s: no child",
412: openparams.o_frnhost & 0377, Mail_user);
413: goto unavailable;
414: }
415: }
416:
417: /* 'st' is now the status of the mailer */
418: if ((st & 0377) != 0)
419: {
420: logmsg(LOG_ERR, "mail from host %d to %s: status %o",
421: openparams.o_frnhost & 0377, Mail_user, st);
422: unavailable:
423: netreply("455 Mail not delivered -- local system error\r\n");
424: return (-1);
425: }
426:
427: return (0);
428: }
Defined functions
mail
defined in line
78;
never used
Defined variables
Defined macros
gt
defined in line
77; used 6 times