14174Seric # include <pwd.h> 24174Seric # include "sendmail.h" 34174Seric 4*4197Seric static char SccsId[] = "@(#)recipient.c 3.5 08/21/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 100*4197Seric if (a->q_mailer == MN_LOCAL) 1014174Seric { 1024174Seric if (a->q_user[0] == '|') 1034174Seric { 104*4197Seric a->q_mailer = MN_PROG; 105*4197Seric m = Mailer[MN_PROG]; 1064174Seric a->q_user++; 1074174Seric } 1084174Seric } 1094174Seric 1104174Seric /* 1114174Seric ** Look up this person in the recipient list. If they 1124174Seric ** are there already, return, otherwise continue. 1134174Seric ** If the list is empty, just add it. 1144174Seric */ 1154174Seric 1164174Seric if (m->m_sendq == NULL) 1174174Seric { 1184174Seric m->m_sendq = a; 1194174Seric } 1204174Seric else 1214174Seric { 1224174Seric ADDRESS *pq; 1234174Seric 1244174Seric for (q = m->m_sendq; q != NULL; pq = q, q = q->q_next) 1254174Seric { 1264174Seric if (!ForceMail && sameaddr(q, a, FALSE)) 1274174Seric { 1284174Seric # ifdef DEBUG 1294174Seric if (Debug) 1304174Seric printf("(%s in sendq)\n", a->q_paddr); 1314174Seric # endif DEBUG 1324174Seric if (Verbose && !bitset(QDONTSEND, a->q_flags)) 1334174Seric message(Arpa_Info, "duplicate supressed"); 1344174Seric return; 1354174Seric } 1364174Seric } 1374174Seric 1384174Seric /* add address on list */ 1394174Seric q = pq; 1404174Seric q->q_next = a; 1414174Seric } 1424174Seric a->q_next = NULL; 1434174Seric 1444174Seric /* 1454174Seric ** Alias the name and handle :include: specs. 1464174Seric */ 1474174Seric 148*4197Seric if (a->q_mailer == MN_LOCAL) 1494174Seric { 1504174Seric if (strncmp(a->q_user, ":include:", 9) == 0) 1514174Seric { 1524174Seric a->q_flags |= QDONTSEND; 1534176Seric if (Verbose) 1544176Seric message(Arpa_Info, "including file %s", &a->q_user[9]); 1554176Seric include(&a->q_user[9], " sending"); 1564174Seric } 1574174Seric else 1584174Seric alias(a); 1594174Seric } 1604174Seric 1614174Seric /* 1624174Seric ** If the user is local and still being sent, verify that 1634174Seric ** the address is good. If it is, try to forward. 1644174Seric ** If the address is already good, we have a forwarding 1654174Seric ** loop. This can be broken by just sending directly to 1664174Seric ** the user (which is probably correct anyway). 1674174Seric */ 1684174Seric 169*4197Seric if (!bitset(QDONTSEND, a->q_flags) && a->q_mailer == MN_LOCAL) 1704174Seric { 1714174Seric char buf[MAXNAME]; 1724174Seric 1734174Seric strcpy(buf, a->q_user); 1744174Seric stripquotes(buf, TRUE); 1754174Seric 1764174Seric /* see if this is to a file */ 1774174Seric if (index(buf, '/') != NULL) 1784174Seric { 1794174Seric if (access(buf, 2) < 0) 1804174Seric { 1814174Seric a->q_flags |= QBADADDR; 1824174Seric giveresponse(EX_CANTCREAT, TRUE, m); 1834174Seric } 1844174Seric } 1854174Seric else 1864174Seric { 1874174Seric register struct passwd *pw; 1884174Seric extern struct passwd *getpwnam(); 1894174Seric pw = getpwnam(buf); 1904174Seric if (pw == NULL) 1914174Seric { 1924174Seric a->q_flags |= QBADADDR; 1934174Seric giveresponse(EX_NOUSER, TRUE, m); 1944174Seric } 1954174Seric else 1964174Seric { 1974174Seric a->q_home = newstr(pw->pw_dir); 1984174Seric if (strcmp(buf, a->q_user) == 0) 1994174Seric forward(a); 2004174Seric } 2014174Seric } 2024174Seric } 2034174Seric } 2044174Seric /* 2054174Seric ** INCLUDE -- handle :include: specification. 2064174Seric ** 2074174Seric ** Parameters: 2084174Seric ** fname -- filename to include. 2094176Seric ** msg -- message to print in verbose mode. 2104174Seric ** 2114174Seric ** Returns: 2124174Seric ** none. 2134174Seric ** 2144174Seric ** Side Effects: 2154174Seric ** reads the :include: file and sends to everyone 2164174Seric ** listed in that file. 2174174Seric */ 2184174Seric 2194176Seric include(fname, msg) 2204174Seric char *fname; 2214176Seric char *msg; 2224174Seric { 2234174Seric char buf[MAXLINE]; 2244174Seric register FILE *fp; 2254178Seric char *oldto = To; 2264174Seric 2274174Seric fp = fopen(fname, "r"); 2284174Seric if (fp == NULL) 2294174Seric { 2304174Seric usrerr("Cannot open %s", fname); 2314174Seric return; 2324174Seric } 2334174Seric 2344174Seric /* read the file -- each line is a comma-separated list. */ 2354174Seric while (fgets(buf, sizeof buf, fp) != NULL) 2364174Seric { 2374174Seric register char *p = index(buf, '\n'); 2384174Seric 2394174Seric if (p != NULL) 2404174Seric *p = '\0'; 2414174Seric if (buf[0] == '\0') 2424174Seric continue; 2434178Seric To = oldto; 2444174Seric if (Verbose) 2454176Seric message(Arpa_Info, "%s to %s", msg, buf); 2464176Seric AliasLevel++; 2474174Seric sendto(buf, 1); 2484176Seric AliasLevel--; 2494174Seric } 2504174Seric 2514174Seric fclose(fp); 2524174Seric } 253