xref: /csrg-svn/bin/rmail/rmail.c (revision 37973)
1 /*
2  * Copyright (c) 1981, 1988 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that the above copyright notice and this paragraph are
7  * duplicated in all such forms and that any documentation,
8  * advertising materials, and other materials related to such
9  * distribution and use acknowledge that the software was developed
10  * by the University of California, Berkeley.  The name of the
11  * University may not be used to endorse or promote products derived
12  * from this software without specific prior written permission.
13  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  */
17 
18 #ifndef lint
19 char copyright[] =
20 "@(#) Copyright (c) 1981, 1988 The Regents of the University of California.\n\
21  All rights reserved.\n";
22 #endif /* not lint */
23 
24 #ifndef lint
25 static char sccsid[] = "@(#)rmail.c	4.13 (Berkeley) 05/11/89";
26 #endif /* not lint */
27 
28 /*
29  * RMAIL -- UUCP mail server.
30  *
31  *	This program reads the >From ... remote from ... lines that
32  *	UUCP is so fond of and turns them into something reasonable.
33  *	It calls sendmail giving it a -f option built from these lines.
34  */
35 
36 #include <sysexits.h>
37 #include <sys/types.h>
38 #include <sys/file.h>
39 #include <sys/stat.h>
40 #include <stdio.h>
41 #include <paths.h>
42 
43 typedef char bool;
44 #define TRUE	1
45 #define FALSE	0
46 
47 extern char *index();
48 extern char *rindex();
49 
50 char *Domain = "UUCP";		/* Default "Domain" */
51 
52 main(argc, argv)
53 	int argc;
54 	char **argv;
55 {
56 	char lbuf[1024];	/* one line of the message */
57 	char from[512];		/* accumulated path of sender */
58 	char ufrom[512];	/* user on remote system */
59 	char sys[512];		/* a system in path */
60 	char fsys[512];		/* first system in path */
61 	char junk[1024];	/* scratchpad */
62 	char *args[100];	/* arguments to mailer command */
63 	register char *cp;
64 	register char *uf = NULL;	/* ptr into ufrom */
65 	int i;
66 	long position;
67 	struct stat sbuf;
68 #ifdef DEBUG
69 	bool Debug;
70 
71 	if (argc > 1 && strcmp(argv[1], "-T") == 0) {
72 		Debug = TRUE;
73 		argc--;
74 		argv++;
75 	}
76 #endif
77 
78 	if (argc < 2) {
79 		fprintf(stderr, "Usage: rmail user ...\n");
80 		exit(EX_USAGE);
81 	}
82 	if (argc > 2 && strncmp(argv[1], "-D", 2) == 0) {
83 		Domain = &argv[1][2];
84 		argc -= 2;
85 		argv += 2;
86 	}
87 	from[0] = '\0';
88 	fsys[0] = '\0';
89 	(void) strcpy(ufrom, _PATH_DEVNULL);
90 
91 	for (position = 0;; position = ftell(stdin)) {
92 		(void) fgets(lbuf, sizeof lbuf, stdin);
93 		if (strncmp(lbuf, "From ", 5) != 0 &&
94 		    strncmp(lbuf, ">From ", 6) != 0)
95 			break;
96 		(void) sscanf(lbuf, "%s %s", junk, ufrom);
97 		cp = lbuf;
98 		uf = ufrom;
99 		for (;;) {
100 			cp = index(cp + 1, 'r');
101 			if (cp == NULL) {
102 				register char *p = rindex(uf, '!');
103 
104 				if (p != NULL) {
105 					*p = '\0';
106 					(void) strcpy(sys, uf);
107 					uf = p + 1;
108 					break;
109 				}
110 				(void) strcpy(sys, "");
111 				break;	/* no "remote from" found */
112 			}
113 #ifdef DEBUG
114 			if (Debug)
115 				printf("cp='%s'\n", cp);
116 #endif
117 			if (strncmp(cp, "remote from ", 12) == 0)
118 				break;
119 		}
120 		if (cp != NULL)
121 			(void) sscanf(cp, "remote from %s", sys);
122 		if (fsys[0] == '\0')
123 			(void) strcpy(fsys, sys);
124 		if (sys[0]) {
125 			(void) strcat(from, sys);
126 			(void) strcat(from, "!");
127 		}
128 #ifdef DEBUG
129 		if (Debug)
130 			printf("ufrom='%s', sys='%s', from now '%s'\n", uf, sys, from);
131 #endif
132 	}
133 	if (uf == NULL) {	/* No From line was provided */
134 		fprintf(stderr, "No From line in rmail\n");
135 		exit(EX_DATAERR);
136 	}
137 	(void) strcat(from, uf);
138 	(void) fstat(0, &sbuf);
139 	(void) lseek(0, position, L_SET);
140 
141 	/*
142 	 * Now we rebuild the argument list and chain to sendmail. Note that
143 	 * the above lseek might fail on irregular files, but we check for
144 	 * that case below.
145 	 */
146 	i = 0;
147 	args[i++] = _PATH_SENDMAIL;
148 	args[i++] = "-oee";		/* no errors, just status */
149 	args[i++] = "-odq";		/* queue it, don't try to deliver */
150 	args[i++] = "-oi";		/* ignore '.' on a line by itself */
151 	if (fsys[0] != '\0') {		/* set sender's host name */
152 		static char junk2[512];
153 
154 		if (index(fsys, '.') == NULL) {
155 			(void) strcat(fsys, ".");
156 			(void) strcat(fsys, Domain);
157 		}
158 		(void) sprintf(junk2, "-oMs%s", fsys);
159 		args[i++] = junk2;
160 	}
161 					/* set protocol used */
162 	(void) sprintf(junk, "-oMr%s", Domain);
163 	args[i++] = junk;
164 	if (from[0] != '\0') {		/* set name of ``from'' person */
165 		static char junk2[512];
166 
167 		(void) sprintf(junk2, "-f%s", from);
168 		args[i++] = junk2;
169 	}
170 	for (; *++argv != NULL; i++) {
171 		/*
172 		 * don't copy arguments beginning with - as they will
173 		 * be passed to sendmail and could be interpreted as flags
174 		 * should be fixed in sendmail by using getopt(3), and
175 		 * just passing "--" before regular args.
176 		 */
177 		if (**argv != '-')
178 			args[i] = *argv;
179 	}
180 	args[i] = NULL;
181 #ifdef DEBUG
182 	if (Debug) {
183 		printf("Command:");
184 		for (i = 0; args[i]; i++)
185 			printf(" %s", args[i]);
186 		printf("\n");
187 	}
188 #endif
189 	if ((sbuf.st_mode & S_IFMT) != S_IFREG) {
190 		/*
191 		 * If we were not called with standard input on a regular
192 		 * file, then we have to fork another process to send the
193 		 * first line down the pipe.
194 		 */
195 		int pipefd[2];
196 #ifdef DEBUG
197 		if (Debug)
198 			printf("Not a regular file!\n");
199 #endif
200 		if (pipe(pipefd) < 0)
201 			exit(EX_OSERR);
202 		if (fork() == 0) {
203 			/*
204 			 * Child: send the message down the pipe.
205 			 */
206 			FILE *out;
207 
208 			out = fdopen(pipefd[1], "w");
209 			close(pipefd[0]);
210 			fputs(lbuf, out);
211 			while (fgets(lbuf, sizeof lbuf, stdin))
212 				fputs(lbuf, out);
213 			(void) fclose(out);
214 			exit(EX_OK);
215 		}
216 		/*
217 		 * Parent: call sendmail with pipe as standard input
218 		 */
219 		close(pipefd[1]);
220 		dup2(pipefd[0], 0);
221 	}
222 	execv(_PATH_SENDMAIL, args);
223 	fprintf(stderr, "Exec of %s failed!\n", _PATH_SENDMAIL);
224 	exit(EX_OSERR);
225 }
226