14174Seric # include <pwd.h> 24174Seric # include "sendmail.h" 34174Seric 4*4217Seric static char SccsId[] = "@(#)recipient.c 3.8 08/23/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; 304174Seric register char *q; 314174Seric register char c; 324174Seric ADDRESS *a; 334174Seric bool more; 344174Seric 354174Seric /* more keeps track of what the previous delimiter was */ 364174Seric more = TRUE; 374174Seric for (p = list; more; ) 384174Seric { 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; 784174Seric register struct mailer *m; 794174Seric char buf[MAXNAME]; 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++; 107*4217Seric # ifdef PARANOID 108*4217Seric if (AliasLevel <= 0) 109*4217Seric { 110*4217Seric usrerr("Cannot mail directly to programs"); 111*4217Seric a->q_flags |= QDONTSEND; 112*4217Seric } 113*4217Seric # 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 1234174Seric if (m->m_sendq == NULL) 1244174Seric { 1254174Seric m->m_sendq = a; 1264174Seric } 1274174Seric else 1284174Seric { 1294174Seric ADDRESS *pq; 1304174Seric 1314174Seric for (q = m->m_sendq; q != NULL; pq = q, q = q->q_next) 1324174Seric { 1334174Seric if (!ForceMail && sameaddr(q, a, FALSE)) 1344174Seric { 1354174Seric # ifdef DEBUG 1364174Seric if (Debug) 1374174Seric printf("(%s in sendq)\n", a->q_paddr); 1384174Seric # endif DEBUG 1394174Seric if (Verbose && !bitset(QDONTSEND, a->q_flags)) 1404174Seric message(Arpa_Info, "duplicate supressed"); 1414174Seric return; 1424174Seric } 1434174Seric } 1444174Seric 1454174Seric /* add address on list */ 1464174Seric q = pq; 1474174Seric q->q_next = a; 1484174Seric } 1494174Seric a->q_next = NULL; 1504174Seric 1514174Seric /* 1524174Seric ** Alias the name and handle :include: specs. 1534174Seric */ 1544174Seric 1554197Seric if (a->q_mailer == MN_LOCAL) 1564174Seric { 1574174Seric if (strncmp(a->q_user, ":include:", 9) == 0) 1584174Seric { 1594174Seric a->q_flags |= QDONTSEND; 1604176Seric if (Verbose) 1614176Seric message(Arpa_Info, "including file %s", &a->q_user[9]); 1624176Seric include(&a->q_user[9], " sending"); 1634174Seric } 1644174Seric else 1654174Seric alias(a); 1664174Seric } 1674174Seric 1684174Seric /* 1694174Seric ** If the user is local and still being sent, verify that 1704174Seric ** the address is good. If it is, try to forward. 1714174Seric ** If the address is already good, we have a forwarding 1724174Seric ** loop. This can be broken by just sending directly to 1734174Seric ** the user (which is probably correct anyway). 1744174Seric */ 1754174Seric 1764197Seric if (!bitset(QDONTSEND, a->q_flags) && a->q_mailer == MN_LOCAL) 1774174Seric { 1784174Seric char buf[MAXNAME]; 1794201Seric register char *p; 1804174Seric 1814174Seric strcpy(buf, a->q_user); 1824174Seric stripquotes(buf, TRUE); 1834174Seric 1844174Seric /* see if this is to a file */ 1854201Seric if ((p = rindex(buf, '/')) != NULL) 1864174Seric { 1874201Seric /* check if writable or creatable */ 1884201Seric if ((access(buf, 0) >= 0) ? 1894201Seric (access(buf, 2) < 0) : 1904201Seric (*p = '\0', access(buf, 3) < 0)) 1914174Seric { 1924174Seric a->q_flags |= QBADADDR; 1934174Seric giveresponse(EX_CANTCREAT, TRUE, m); 1944174Seric } 1954174Seric } 1964174Seric else 1974174Seric { 1984174Seric register struct passwd *pw; 1994174Seric extern struct passwd *getpwnam(); 2004174Seric pw = getpwnam(buf); 2014174Seric if (pw == NULL) 2024174Seric { 2034174Seric a->q_flags |= QBADADDR; 2044174Seric giveresponse(EX_NOUSER, TRUE, m); 2054174Seric } 2064174Seric else 2074174Seric { 2084174Seric a->q_home = newstr(pw->pw_dir); 2094213Seric a->q_uid = pw->pw_uid; 2104174Seric if (strcmp(buf, a->q_user) == 0) 2114174Seric forward(a); 2124174Seric } 2134174Seric } 2144174Seric } 2154174Seric } 2164174Seric /* 2174174Seric ** INCLUDE -- handle :include: specification. 2184174Seric ** 2194174Seric ** Parameters: 2204174Seric ** fname -- filename to include. 2214176Seric ** msg -- message to print in verbose mode. 2224174Seric ** 2234174Seric ** Returns: 2244174Seric ** none. 2254174Seric ** 2264174Seric ** Side Effects: 2274174Seric ** reads the :include: file and sends to everyone 2284174Seric ** listed in that file. 2294174Seric */ 2304174Seric 2314176Seric include(fname, msg) 2324174Seric char *fname; 2334176Seric char *msg; 2344174Seric { 2354174Seric char buf[MAXLINE]; 2364174Seric register FILE *fp; 2374178Seric char *oldto = To; 2384174Seric 2394174Seric fp = fopen(fname, "r"); 2404174Seric if (fp == NULL) 2414174Seric { 2424174Seric usrerr("Cannot open %s", fname); 2434174Seric return; 2444174Seric } 2454174Seric 2464174Seric /* read the file -- each line is a comma-separated list. */ 2474174Seric while (fgets(buf, sizeof buf, fp) != NULL) 2484174Seric { 2494174Seric register char *p = index(buf, '\n'); 2504174Seric 2514174Seric if (p != NULL) 2524174Seric *p = '\0'; 2534174Seric if (buf[0] == '\0') 2544174Seric continue; 2554178Seric To = oldto; 2564174Seric if (Verbose) 2574176Seric message(Arpa_Info, "%s to %s", msg, buf); 2584176Seric AliasLevel++; 2594174Seric sendto(buf, 1); 2604176Seric AliasLevel--; 2614174Seric } 2624174Seric 2634174Seric fclose(fp); 2644174Seric } 265