xref: /original-bsd/bin/rmail/rmail.c (revision 2301fdfb)
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.11 (Berkeley) 11/15/88";
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++] = "-ee";
150 	if (fsys[0] != '\0') {
151 		static char junk2[512];
152 
153 		if (index(fsys, '.') == NULL) {
154 			(void) strcat(fsys, ".");
155 			(void) strcat(fsys, Domain);
156 		}
157 		(void) sprintf(junk2, "-oMs%s", fsys);
158 		args[i++] = junk2;
159 	}
160 	(void) sprintf(junk, "-oMr%s", Domain);
161 	args[i++] = junk;
162 	if (from[0] != '\0') {
163 		static char junk2[512];
164 
165 		(void) sprintf(junk2, "-f%s", from);
166 		args[i++] = junk2;
167 	}
168 	for (; *++argv != NULL; i++) {
169 		/*
170 		 * don't copy arguments beginning with - as they will
171 		 * be passed to sendmail and could be interpreted as flags
172 		 */
173 		if (**argv != '-')
174 			args[i] = *argv;
175 	}
176 	args[i] = NULL;
177 #ifdef DEBUG
178 	if (Debug) {
179 		printf("Command:");
180 		for (i = 0; args[i]; i++)
181 			printf(" %s", args[i]);
182 		printf("\n");
183 	}
184 #endif
185 	if ((sbuf.st_mode & S_IFMT) != S_IFREG) {
186 		/*
187 		 * If we were not called with standard input on a regular
188 		 * file, then we have to fork another process to send the
189 		 * first line down the pipe.
190 		 */
191 		int pipefd[2];
192 # ifdef DEBUG
193 		if (Debug)
194 			printf("Not a regular file!\n");
195 # endif DEBUG
196 		if (pipe(pipefd) < 0)
197 			exit(EX_OSERR);
198 		if (fork() == 0) {
199 			/*
200 			 * Child: send the message down the pipe.
201 			 */
202 			FILE *out;
203 
204 			out = fdopen(pipefd[1], "w");
205 			close(pipefd[0]);
206 			fputs(lbuf, out);
207 			while (fgets(lbuf, sizeof lbuf, stdin))
208 				fputs(lbuf, out);
209 			(void) fclose(out);
210 			exit(EX_OK);
211 		}
212 		/*
213 		 * Parent: call sendmail with pipe as standard input
214 		 */
215 		close(pipefd[1]);
216 		dup2(pipefd[0], 0);
217 	}
218 	execv(MAILER, args);
219 	fprintf(stderr, "Exec of %s failed!\n", MAILER);
220 	exit(EX_OSERR);
221 }
222