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