xref: /original-bsd/bin/rmail/rmail.c (revision bb2d502b)
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.12 (Berkeley) 01/19/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 <stdio.h>
37 #include <sysexits.h>
38 #include <sys/types.h>
39 #include <sys/file.h>
40 #include <sys/stat.h>
41 
42 typedef char bool;
43 #define TRUE	1
44 #define FALSE	0
45 
46 extern char *index();
47 extern char *rindex();
48 
49 char *Domain = "UUCP";		/* Default "Domain" */
50 
51 #define MAILER	"/usr/lib/sendmail"
52 
53 main(argc, argv)
54 	int argc;
55 	char **argv;
56 {
57 	char lbuf[1024];	/* one line of the message */
58 	char from[512];		/* accumulated path of sender */
59 	char ufrom[512];	/* user on remote system */
60 	char sys[512];		/* a system in path */
61 	char fsys[512];		/* first system in path */
62 	char junk[1024];	/* scratchpad */
63 	char *args[100];	/* arguments to mailer command */
64 	register char *cp;
65 	register char *uf = NULL;	/* ptr into ufrom */
66 	int i;
67 	long position;
68 	struct stat sbuf;
69 #ifdef DEBUG
70 	bool Debug;
71 
72 	if (argc > 1 && strcmp(argv[1], "-T") == 0) {
73 		Debug = TRUE;
74 		argc--;
75 		argv++;
76 	}
77 #endif
78 
79 	if (argc < 2) {
80 		fprintf(stderr, "Usage: rmail user ...\n");
81 		exit(EX_USAGE);
82 	}
83 	if (argc > 2 && strncmp(argv[1], "-D", 2) == 0) {
84 		Domain = &argv[1][2];
85 		argc -= 2;
86 		argv += 2;
87 	}
88 	from[0] = '\0';
89 	fsys[0] = '\0';
90 	(void) strcpy(ufrom, "/dev/null");
91 
92 	for (position = 0;; position = ftell(stdin)) {
93 		(void) fgets(lbuf, sizeof lbuf, stdin);
94 		if (strncmp(lbuf, "From ", 5) != 0 &&
95 		    strncmp(lbuf, ">From ", 6) != 0)
96 			break;
97 		(void) sscanf(lbuf, "%s %s", junk, ufrom);
98 		cp = lbuf;
99 		uf = ufrom;
100 		for (;;) {
101 			cp = index(cp + 1, 'r');
102 			if (cp == NULL) {
103 				register char *p = rindex(uf, '!');
104 
105 				if (p != NULL) {
106 					*p = '\0';
107 					(void) strcpy(sys, uf);
108 					uf = p + 1;
109 					break;
110 				}
111 				(void) strcpy(sys, "");
112 				break;	/* no "remote from" found */
113 			}
114 #ifdef DEBUG
115 			if (Debug)
116 				printf("cp='%s'\n", cp);
117 #endif
118 			if (strncmp(cp, "remote from ", 12) == 0)
119 				break;
120 		}
121 		if (cp != NULL)
122 			(void) sscanf(cp, "remote from %s", sys);
123 		if (fsys[0] == '\0')
124 			(void) strcpy(fsys, sys);
125 		if (sys[0]) {
126 			(void) strcat(from, sys);
127 			(void) strcat(from, "!");
128 		}
129 #ifdef DEBUG
130 		if (Debug)
131 			printf("ufrom='%s', sys='%s', from now '%s'\n", uf, sys, from);
132 #endif
133 	}
134 	if (uf == NULL) {	/* No From line was provided */
135 		fprintf(stderr, "No From line in rmail\n");
136 		exit(EX_DATAERR);
137 	}
138 	(void) strcat(from, uf);
139 	(void) fstat(0, &sbuf);
140 	(void) lseek(0, position, L_SET);
141 
142 	/*
143 	 * Now we rebuild the argument list and chain to sendmail. Note that
144 	 * the above lseek might fail on irregular files, but we check for
145 	 * that case below.
146 	 */
147 	i = 0;
148 	args[i++] = MAILER;
149 	args[i++] = "-oee";		/* no errors, just status */
150 	args[i++] = "-odq";		/* queue it, don't try to deliver */
151 	args[i++] = "-oi";		/* ignore '.' on a line by itself */
152 	if (fsys[0] != '\0') {		/* set sender's host name */
153 		static char junk2[512];
154 
155 		if (index(fsys, '.') == NULL) {
156 			(void) strcat(fsys, ".");
157 			(void) strcat(fsys, Domain);
158 		}
159 		(void) sprintf(junk2, "-oMs%s", fsys);
160 		args[i++] = junk2;
161 	}
162 					/* set protocol used */
163 	(void) sprintf(junk, "-oMr%s", Domain);
164 	args[i++] = junk;
165 	if (from[0] != '\0') {		/* set name of ``from'' person */
166 		static char junk2[512];
167 
168 		(void) sprintf(junk2, "-f%s", from);
169 		args[i++] = junk2;
170 	}
171 	for (; *++argv != NULL; i++) {
172 		/*
173 		 * don't copy arguments beginning with - as they will
174 		 * be passed to sendmail and could be interpreted as flags
175 		 * should be fixed in sendmail by using getopt(3), and
176 		 * just passing "--" before regular args.
177 		 */
178 		if (**argv != '-')
179 			args[i] = *argv;
180 	}
181 	args[i] = NULL;
182 #ifdef DEBUG
183 	if (Debug) {
184 		printf("Command:");
185 		for (i = 0; args[i]; i++)
186 			printf(" %s", args[i]);
187 		printf("\n");
188 	}
189 #endif
190 	if ((sbuf.st_mode & S_IFMT) != S_IFREG) {
191 		/*
192 		 * If we were not called with standard input on a regular
193 		 * file, then we have to fork another process to send the
194 		 * first line down the pipe.
195 		 */
196 		int pipefd[2];
197 #ifdef DEBUG
198 		if (Debug)
199 			printf("Not a regular file!\n");
200 #endif
201 		if (pipe(pipefd) < 0)
202 			exit(EX_OSERR);
203 		if (fork() == 0) {
204 			/*
205 			 * Child: send the message down the pipe.
206 			 */
207 			FILE *out;
208 
209 			out = fdopen(pipefd[1], "w");
210 			close(pipefd[0]);
211 			fputs(lbuf, out);
212 			while (fgets(lbuf, sizeof lbuf, stdin))
213 				fputs(lbuf, out);
214 			(void) fclose(out);
215 			exit(EX_OK);
216 		}
217 		/*
218 		 * Parent: call sendmail with pipe as standard input
219 		 */
220 		close(pipefd[1]);
221 		dup2(pipefd[0], 0);
222 	}
223 	execv(MAILER, args);
224 	fprintf(stderr, "Exec of %s failed!\n", MAILER);
225 	exit(EX_OSERR);
226 }
227