1 # include <pwd.h> 2 # include "sendmail.h" 3 4 static char SccsId[] = "@(#)recipient.c 3.11 09/07/81"; 5 6 /* 7 ** SENDTO -- Designate a send list. 8 ** 9 ** The parameter is a comma-separated list of people to send to. 10 ** This routine arranges to send to all of them. 11 ** 12 ** Parameters: 13 ** list -- the send list. 14 ** copyf -- the copy flag; passed to parse. 15 ** 16 ** Returns: 17 ** none 18 ** 19 ** Side Effects: 20 ** none. 21 */ 22 23 # define MAXRCRSN 10 24 25 sendto(list, copyf) 26 char *list; 27 int copyf; 28 { 29 register char *p; 30 bool more; /* set if more addresses to send to */ 31 ADDRESS *al; /* list of addresses to send to */ 32 33 # ifdef DEBUG 34 if (Debug > 1) 35 printf("sendto: %s\n", list); 36 # endif DEBUG 37 38 more = TRUE; 39 al = NULL; 40 for (p = list; more; ) 41 { 42 register char *q; 43 register char c; 44 ADDRESS *a; 45 46 /* find the end of this address */ 47 while (*p == ' ' || *p == '\t') 48 p++; 49 q = p; 50 while ((c = *p++) != '\0' && c != ',' && c != '\n') 51 continue; 52 more = c != '\0'; 53 *--p = '\0'; 54 if (more) 55 p++; 56 if (*q == '\0') 57 continue; 58 59 /* parse the address */ 60 if ((a = parse(q, (ADDRESS *) NULL, copyf)) == NULL) 61 continue; 62 63 /* put it on the local send list */ 64 a->q_next = al; 65 al = a; 66 } 67 68 /* arrange to send to everyone on the local send list */ 69 while (al != NULL) 70 { 71 register ADDRESS *a = al; 72 73 al = a->q_next; 74 recipient(a); 75 } 76 77 To = NULL; 78 } 79 /* 80 ** RECIPIENT -- Designate a message recipient 81 ** 82 ** Saves the named person for future mailing. 83 ** 84 ** Parameters: 85 ** a -- the (preparsed) address header for the recipient. 86 ** 87 ** Returns: 88 ** none. 89 ** 90 ** Side Effects: 91 ** none. 92 */ 93 94 recipient(a) 95 register ADDRESS *a; 96 { 97 register ADDRESS *q; 98 ADDRESS **pq; 99 register struct mailer *m; 100 101 To = a->q_paddr; 102 m = Mailer[a->q_mailer]; 103 errno = 0; 104 # ifdef DEBUG 105 if (Debug) 106 printf("recipient(%s)\n", To); 107 # endif DEBUG 108 109 /* break aliasing loops */ 110 if (AliasLevel > MAXRCRSN) 111 { 112 usrerr("aliasing/forwarding loop broken"); 113 return; 114 } 115 116 /* 117 ** Do sickly crude mapping for program mailing, etc. 118 */ 119 120 if (a->q_mailer == MN_LOCAL) 121 { 122 if (a->q_user[0] == '|') 123 { 124 a->q_mailer = MN_PROG; 125 m = Mailer[MN_PROG]; 126 a->q_user++; 127 # ifdef PARANOID 128 if (AliasLevel <= 0) 129 { 130 usrerr("Cannot mail directly to programs"); 131 a->q_flags |= QDONTSEND; 132 } 133 # endif PARANOID 134 } 135 } 136 137 /* 138 ** Look up this person in the recipient list. If they 139 ** are there already, return, otherwise continue. 140 ** If the list is empty, just add it. 141 */ 142 143 for (pq = &m->m_sendq; (q = *pq) != NULL; pq = &q->q_next) 144 { 145 if (!ForceMail && sameaddr(q, a, FALSE)) 146 { 147 # ifdef DEBUG 148 if (Debug) 149 printf("(%s in sendq)\n", a->q_paddr); 150 # endif DEBUG 151 if (Verbose && !bitset(QDONTSEND, a->q_flags)) 152 message(Arpa_Info, "duplicate suppressed"); 153 return; 154 } 155 } 156 157 /* add address on list */ 158 *pq = a; 159 a->q_next = NULL; 160 if (DontSend) 161 a->q_flags |= QDONTSEND; 162 163 /* 164 ** Alias the name and handle :include: specs. 165 */ 166 167 if (a->q_mailer == MN_LOCAL) 168 { 169 if (strncmp(a->q_user, ":include:", 9) == 0) 170 { 171 a->q_flags |= QDONTSEND; 172 if (Verbose) 173 message(Arpa_Info, "including file %s", &a->q_user[9]); 174 include(&a->q_user[9], " sending"); 175 } 176 else 177 alias(a); 178 } 179 180 /* 181 ** If the user is local and still being sent, verify that 182 ** the address is good. If it is, try to forward. 183 ** If the address is already good, we have a forwarding 184 ** loop. This can be broken by just sending directly to 185 ** the user (which is probably correct anyway). 186 */ 187 188 if (!bitset(QDONTSEND, a->q_flags) && a->q_mailer == MN_LOCAL) 189 { 190 char buf[MAXNAME]; 191 register char *p; 192 193 strcpy(buf, a->q_user); 194 stripquotes(buf, TRUE); 195 196 /* see if this is to a file */ 197 if ((p = rindex(buf, '/')) != NULL) 198 { 199 /* check if writable or creatable */ 200 if ((access(buf, 0) >= 0) ? 201 (access(buf, 2) < 0) : 202 (*p = '\0', access(buf, 3) < 0)) 203 { 204 a->q_flags |= QBADADDR; 205 giveresponse(EX_CANTCREAT, TRUE, m); 206 } 207 } 208 else 209 { 210 register struct passwd *pw; 211 extern struct passwd *getpwnam(); 212 pw = getpwnam(buf); 213 if (pw == NULL) 214 { 215 a->q_flags |= QBADADDR; 216 giveresponse(EX_NOUSER, TRUE, m); 217 } 218 else 219 { 220 a->q_home = newstr(pw->pw_dir); 221 a->q_uid = pw->pw_uid; 222 if (strcmp(buf, a->q_user) == 0) 223 forward(a); 224 } 225 } 226 } 227 } 228 /* 229 ** INCLUDE -- handle :include: specification. 230 ** 231 ** Parameters: 232 ** fname -- filename to include. 233 ** msg -- message to print in verbose mode. 234 ** 235 ** Returns: 236 ** none. 237 ** 238 ** Side Effects: 239 ** reads the :include: file and sends to everyone 240 ** listed in that file. 241 */ 242 243 include(fname, msg) 244 char *fname; 245 char *msg; 246 { 247 char buf[MAXLINE]; 248 register FILE *fp; 249 char *oldto = To; 250 251 fp = fopen(fname, "r"); 252 if (fp == NULL) 253 { 254 usrerr("Cannot open %s", fname); 255 return; 256 } 257 258 /* read the file -- each line is a comma-separated list. */ 259 while (fgets(buf, sizeof buf, fp) != NULL) 260 { 261 register char *p = index(buf, '\n'); 262 263 if (p != NULL) 264 *p = '\0'; 265 if (buf[0] == '\0') 266 continue; 267 To = oldto; 268 if (Verbose) 269 message(Arpa_Info, "%s to %s", msg, buf); 270 AliasLevel++; 271 sendto(buf, 1); 272 AliasLevel--; 273 } 274 275 (void) fclose(fp); 276 } 277 /* 278 ** SENDTOARGV -- send to an argument vector. 279 ** 280 ** Parameters: 281 ** argv -- argument vector to send to. 282 ** 283 ** Returns: 284 ** none. 285 ** 286 ** Side Effects: 287 ** puts all addresses on the argument vector onto the 288 ** send queue. 289 */ 290 291 sendtoargv(argv) 292 register char **argv; 293 { 294 register char *p; 295 extern bool sameword(); 296 297 while ((p = *argv++) != NULL) 298 { 299 if (argv[0] != NULL && argv[1] != NULL && sameword(argv[0], "at")) 300 { 301 char nbuf[MAXNAME]; 302 303 if (strlen(p) + strlen(argv[1]) + 2 > sizeof nbuf) 304 usrerr("address overflow"); 305 else 306 { 307 (void) strcpy(nbuf, p); 308 (void) strcat(nbuf, "@"); 309 (void) strcat(nbuf, argv[1]); 310 p = newstr(nbuf); 311 argv += 2; 312 } 313 } 314 sendto(p, 0); 315 } 316 } 317