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