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