1 # include "sendmail.h" 2 3 static char SccsId[] = "@(#)srvrsmtp.c 3.2 10/20/81"; 4 5 /* 6 ** SMTP -- run the SMTP protocol. 7 ** 8 ** Parameters: 9 ** none. 10 ** 11 ** Returns: 12 ** never. 13 ** 14 ** Side Effects: 15 ** Reads commands from the input channel and processes 16 ** them. 17 */ 18 19 struct cmd 20 { 21 char *cmdname; /* command name */ 22 int cmdcode; /* internal code, see below */ 23 }; 24 25 /* values for cmdcode */ 26 # define CMDERROR 0 /* bad command */ 27 # define CMDMAIL 1 /* mail -- designate sender */ 28 # define CMDMRCP 2 /* mrcp -- designate recipient */ 29 # define CMDDATA 3 /* data -- send message text */ 30 # define CMDDOIT 4 /* doit -- actually do delivery */ 31 # define CMDRSET 5 /* rset -- reset state */ 32 # define CMDVRFY 6 /* vrfy -- verify address */ 33 # define CMDHELP 7 /* help -- give usage info */ 34 # define CMDNOOP 8 /* noop -- do nothing */ 35 # define CMDQUIT 9 /* quit -- close connection and die */ 36 37 static struct cmd CmdTab[] = 38 { 39 "mail", CMDMAIL, 40 "mrcp", CMDMRCP, 41 "data", CMDDATA, 42 "doit", CMDDOIT, 43 "rset", CMDRSET, 44 "vrfy", CMDVRFY, 45 "help", CMDHELP, 46 "noop", CMDNOOP, 47 "quit", CMDQUIT, 48 NULL, CMDERROR, 49 }; 50 51 smtp() 52 { 53 char inp[MAXLINE]; 54 register char *p; 55 struct cmd *c; 56 char *cmd; 57 extern char *skipword(); 58 extern bool sameword(); 59 bool hasmail; /* mail command received */ 60 bool hasmrcp; /* has a recipient */ 61 bool hasdata; /* has mail data */ 62 63 /*%%%*/ HostName = "XYZZY"; 64 hasmail = hasmrcp = hasdata = FALSE; 65 message("220", "%s Sendmail at your service", HostName); 66 for (;;) 67 { 68 To = NULL; 69 Errors = 0; 70 if (fgets(inp, sizeof inp, InChannel) == NULL) 71 { 72 /* end of file, just die */ 73 message("421", "Lost input channel"); 74 finis(); 75 } 76 77 /* clean up end of line */ 78 p = index(inp, '\n'); 79 if (p != NULL) 80 *p = '\0'; 81 p = index(inp, '\r'); 82 if (p != NULL) 83 *p = '\0'; 84 85 /* break off command */ 86 for (p = inp; isspace(*p); p++) 87 continue; 88 cmd = p; 89 while (*++p != '\0' && !isspace(*p)) 90 continue; 91 if (*p != '\0') 92 *p++ = '\0'; 93 94 /* decode command */ 95 for (c = CmdTab; c->cmdname != NULL; c++) 96 { 97 if (sameword(c->cmdname, cmd)) 98 break; 99 } 100 101 /* process command */ 102 switch (c->cmdcode) 103 { 104 case CMDMAIL: /* mail -- designate sender */ 105 p = skipword(p, "from"); 106 if (p == NULL) 107 break; 108 if (index(p, ',') != NULL) 109 { 110 message("501", "Source routing not implemented"); 111 Errors++; 112 break; 113 } 114 setsender(p); 115 if (Errors == 0) 116 { 117 message("250", "Sender ok"); 118 hasmail = TRUE; 119 } 120 break; 121 122 case CMDMRCP: /* mrcp -- designate recipient */ 123 p = skipword(p, "to"); 124 if (p == NULL) 125 break; 126 if (index(p, ',') != NULL) 127 { 128 message("501", "Source routing not implemented"); 129 Errors++; 130 break; 131 } 132 sendto(p, 1, NULL); 133 if (Errors == 0) 134 { 135 message("250", "Recipient ok"); 136 hasmrcp = TRUE; 137 } 138 break; 139 140 case CMDDATA: /* data -- text of mail */ 141 message("354", "Enter mail, end with dot"); 142 collect(); 143 if (Errors == 0) 144 { 145 message("250", "Message stored"); 146 hasdata = TRUE; 147 } 148 break; 149 150 case CMDDOIT: /* doit -- actually send everything */ 151 if (!hasmail) 152 message("503", "Need MAIL command"); 153 else if (!hasmrcp) 154 message("503", "Need MRCP (recipient)"); 155 else if (!hasdata) 156 message("503", "No message, use DATA"); 157 else 158 { 159 sendall(FALSE); 160 if (Errors == 0) 161 message("250", "Sent"); 162 } 163 break; 164 165 case CMDRSET: /* rset -- reset state */ 166 message("250", "Reset state"); 167 finis(); 168 169 case CMDVRFY: /* vrfy -- verify address */ 170 sendto(p, 1, NULL); 171 if (Errors == 0) 172 message("250", "user ok"); 173 break; 174 175 case CMDHELP: /* help -- give user info */ 176 message("502", "HELP not implemented"); 177 break; 178 179 case CMDNOOP: /* noop -- do nothing */ 180 message("200", "OK"); 181 break; 182 183 case CMDQUIT: /* quit -- leave mail */ 184 message("221", "%s closing connection", HostName); 185 finis(); 186 187 case CMDERROR: /* unknown command */ 188 message("500", "Command unrecognized"); 189 break; 190 191 default: 192 syserr("smtp: unknown code %d", c->cmdcode); 193 break; 194 } 195 } 196 } 197 /* 198 ** SKIPWORD -- skip a fixed word. 199 ** 200 ** Parameters: 201 ** p -- place to start looking. 202 ** w -- word to skip. 203 ** 204 ** Returns: 205 ** p following w. 206 ** NULL on error. 207 ** 208 ** Side Effects: 209 ** clobbers the p data area. 210 */ 211 212 static char * 213 skipword(p, w) 214 register char *p; 215 char *w; 216 { 217 register char *q; 218 extern bool sameword(); 219 220 /* find beginning of word */ 221 while (isspace(*p)) 222 p++; 223 q = p; 224 225 /* find end of word */ 226 while (*p != '\0' && *p != ':' && !isspace(*p)) 227 p++; 228 while (isspace(*p)) 229 *p++ = '\0'; 230 if (*p != ':') 231 { 232 syntax: 233 message("501", "Syntax error"); 234 Errors++; 235 return (NULL); 236 } 237 *p++ = '\0'; 238 while (isspace(*p)) 239 p++; 240 241 /* see if the input word matches desired word */ 242 if (!sameword(q, w)) 243 goto syntax; 244 245 return (p); 246 } 247