14174Seric # include <pwd.h> 24174Seric # include "sendmail.h" 34174Seric 4*4319Seric static char SccsId[] = "@(#)recipient.c 3.10 09/06/81"; 54174Seric 64174Seric /* 74174Seric ** SENDTO -- Designate a send list. 84174Seric ** 94174Seric ** The parameter is a comma-separated list of people to send to. 104174Seric ** This routine arranges to send to all of them. 114174Seric ** 124174Seric ** Parameters: 134174Seric ** list -- the send list. 144174Seric ** copyf -- the copy flag; passed to parse. 154174Seric ** 164174Seric ** Returns: 174174Seric ** none 184174Seric ** 194174Seric ** Side Effects: 204174Seric ** none. 214174Seric */ 224174Seric 234174Seric # define MAXRCRSN 10 244174Seric 254174Seric sendto(list, copyf) 264174Seric char *list; 274174Seric int copyf; 284174Seric { 294174Seric register char *p; 30*4319Seric bool more; /* set if more addresses to send to */ 314174Seric 324174Seric more = TRUE; 334174Seric for (p = list; more; ) 344174Seric { 35*4319Seric register char *q; 36*4319Seric register char c; 37*4319Seric ADDRESS *a; 38*4319Seric 394174Seric /* find the end of this address */ 404174Seric while (*p == ' ' || *p == '\t') 414174Seric p++; 424174Seric q = p; 434174Seric while ((c = *p++) != '\0' && c != ',' && c != '\n') 444174Seric continue; 454174Seric more = c != '\0'; 464174Seric *--p = '\0'; 474174Seric if (more) 484174Seric p++; 494174Seric 504174Seric /* parse the address */ 514174Seric if ((a = parse(q, (ADDRESS *) NULL, copyf)) == NULL) 524174Seric continue; 534174Seric 544174Seric /* arrange to send to this person */ 554174Seric recipient(a); 564174Seric } 574174Seric To = NULL; 584174Seric } 594174Seric /* 604174Seric ** RECIPIENT -- Designate a message recipient 614174Seric ** 624174Seric ** Saves the named person for future mailing. 634174Seric ** 644174Seric ** Parameters: 654174Seric ** a -- the (preparsed) address header for the recipient. 664174Seric ** 674174Seric ** Returns: 684174Seric ** none. 694174Seric ** 704174Seric ** Side Effects: 714174Seric ** none. 724174Seric */ 734174Seric 744174Seric recipient(a) 754174Seric register ADDRESS *a; 764174Seric { 774174Seric register ADDRESS *q; 78*4319Seric ADDRESS **pq; 794174Seric register struct mailer *m; 804174Seric 814174Seric To = a->q_paddr; 824174Seric m = Mailer[a->q_mailer]; 834174Seric errno = 0; 844174Seric # ifdef DEBUG 854174Seric if (Debug) 864174Seric printf("recipient(%s)\n", To); 874174Seric # endif DEBUG 884174Seric 894174Seric /* break aliasing loops */ 904174Seric if (AliasLevel > MAXRCRSN) 914174Seric { 924174Seric usrerr("aliasing/forwarding loop broken"); 934174Seric return; 944174Seric } 954174Seric 964174Seric /* 974174Seric ** Do sickly crude mapping for program mailing, etc. 984174Seric */ 994174Seric 1004197Seric if (a->q_mailer == MN_LOCAL) 1014174Seric { 1024174Seric if (a->q_user[0] == '|') 1034174Seric { 1044197Seric a->q_mailer = MN_PROG; 1054197Seric m = Mailer[MN_PROG]; 1064174Seric a->q_user++; 1074217Seric # ifdef PARANOID 1084217Seric if (AliasLevel <= 0) 1094217Seric { 1104217Seric usrerr("Cannot mail directly to programs"); 1114217Seric a->q_flags |= QDONTSEND; 1124217Seric } 1134217Seric # endif PARANOID 1144174Seric } 1154174Seric } 1164174Seric 1174174Seric /* 1184174Seric ** Look up this person in the recipient list. If they 1194174Seric ** are there already, return, otherwise continue. 1204174Seric ** If the list is empty, just add it. 1214174Seric */ 1224174Seric 123*4319Seric for (pq = &m->m_sendq; (q = *pq) != NULL; pq = &q->q_next) 1244174Seric { 125*4319Seric if (!ForceMail && sameaddr(q, a, FALSE)) 1264174Seric { 1274174Seric # ifdef DEBUG 128*4319Seric if (Debug) 129*4319Seric printf("(%s in sendq)\n", a->q_paddr); 1304174Seric # endif DEBUG 131*4319Seric if (Verbose && !bitset(QDONTSEND, a->q_flags)) 132*4319Seric message(Arpa_Info, "duplicate supressed"); 133*4319Seric return; 1344174Seric } 135*4319Seric } 1364174Seric 137*4319Seric /* add address on list */ 138*4319Seric *pq = a; 1394174Seric a->q_next = NULL; 1404247Seric if (DontSend) 1414247Seric a->q_flags |= QDONTSEND; 1424174Seric 1434174Seric /* 1444174Seric ** Alias the name and handle :include: specs. 1454174Seric */ 1464174Seric 1474197Seric if (a->q_mailer == MN_LOCAL) 1484174Seric { 1494174Seric if (strncmp(a->q_user, ":include:", 9) == 0) 1504174Seric { 1514174Seric a->q_flags |= QDONTSEND; 1524176Seric if (Verbose) 1534176Seric message(Arpa_Info, "including file %s", &a->q_user[9]); 1544176Seric include(&a->q_user[9], " sending"); 1554174Seric } 1564174Seric else 1574174Seric alias(a); 1584174Seric } 1594174Seric 1604174Seric /* 1614174Seric ** If the user is local and still being sent, verify that 1624174Seric ** the address is good. If it is, try to forward. 1634174Seric ** If the address is already good, we have a forwarding 1644174Seric ** loop. This can be broken by just sending directly to 1654174Seric ** the user (which is probably correct anyway). 1664174Seric */ 1674174Seric 1684197Seric if (!bitset(QDONTSEND, a->q_flags) && a->q_mailer == MN_LOCAL) 1694174Seric { 1704174Seric char buf[MAXNAME]; 1714201Seric register char *p; 1724174Seric 1734174Seric strcpy(buf, a->q_user); 1744174Seric stripquotes(buf, TRUE); 1754174Seric 1764174Seric /* see if this is to a file */ 1774201Seric if ((p = rindex(buf, '/')) != NULL) 1784174Seric { 1794201Seric /* check if writable or creatable */ 1804201Seric if ((access(buf, 0) >= 0) ? 1814201Seric (access(buf, 2) < 0) : 1824201Seric (*p = '\0', access(buf, 3) < 0)) 1834174Seric { 1844174Seric a->q_flags |= QBADADDR; 1854174Seric giveresponse(EX_CANTCREAT, TRUE, m); 1864174Seric } 1874174Seric } 1884174Seric else 1894174Seric { 1904174Seric register struct passwd *pw; 1914174Seric extern struct passwd *getpwnam(); 1924174Seric pw = getpwnam(buf); 1934174Seric if (pw == NULL) 1944174Seric { 1954174Seric a->q_flags |= QBADADDR; 1964174Seric giveresponse(EX_NOUSER, TRUE, m); 1974174Seric } 1984174Seric else 1994174Seric { 2004174Seric a->q_home = newstr(pw->pw_dir); 2014213Seric a->q_uid = pw->pw_uid; 2024174Seric if (strcmp(buf, a->q_user) == 0) 2034174Seric forward(a); 2044174Seric } 2054174Seric } 2064174Seric } 2074174Seric } 2084174Seric /* 2094174Seric ** INCLUDE -- handle :include: specification. 2104174Seric ** 2114174Seric ** Parameters: 2124174Seric ** fname -- filename to include. 2134176Seric ** msg -- message to print in verbose mode. 2144174Seric ** 2154174Seric ** Returns: 2164174Seric ** none. 2174174Seric ** 2184174Seric ** Side Effects: 2194174Seric ** reads the :include: file and sends to everyone 2204174Seric ** listed in that file. 2214174Seric */ 2224174Seric 2234176Seric include(fname, msg) 2244174Seric char *fname; 2254176Seric char *msg; 2264174Seric { 2274174Seric char buf[MAXLINE]; 2284174Seric register FILE *fp; 2294178Seric char *oldto = To; 2304174Seric 2314174Seric fp = fopen(fname, "r"); 2324174Seric if (fp == NULL) 2334174Seric { 2344174Seric usrerr("Cannot open %s", fname); 2354174Seric return; 2364174Seric } 2374174Seric 2384174Seric /* read the file -- each line is a comma-separated list. */ 2394174Seric while (fgets(buf, sizeof buf, fp) != NULL) 2404174Seric { 2414174Seric register char *p = index(buf, '\n'); 2424174Seric 2434174Seric if (p != NULL) 2444174Seric *p = '\0'; 2454174Seric if (buf[0] == '\0') 2464174Seric continue; 2474178Seric To = oldto; 2484174Seric if (Verbose) 2494176Seric message(Arpa_Info, "%s to %s", msg, buf); 2504176Seric AliasLevel++; 2514174Seric sendto(buf, 1); 2524176Seric AliasLevel--; 2534174Seric } 2544174Seric 255*4319Seric (void) fclose(fp); 2564174Seric } 257