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