14174Seric # include <pwd.h> 24174Seric # include "sendmail.h" 34174Seric 4*4247Seric static char SccsId[] = "@(#)recipient.c 3.9 08/27/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++; 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 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; 150*4247Seric if (DontSend) 151*4247Seric a->q_flags |= QDONTSEND; 1524174Seric 1534174Seric /* 1544174Seric ** Alias the name and handle :include: specs. 1554174Seric */ 1564174Seric 1574197Seric if (a->q_mailer == MN_LOCAL) 1584174Seric { 1594174Seric if (strncmp(a->q_user, ":include:", 9) == 0) 1604174Seric { 1614174Seric a->q_flags |= QDONTSEND; 1624176Seric if (Verbose) 1634176Seric message(Arpa_Info, "including file %s", &a->q_user[9]); 1644176Seric include(&a->q_user[9], " sending"); 1654174Seric } 1664174Seric else 1674174Seric alias(a); 1684174Seric } 1694174Seric 1704174Seric /* 1714174Seric ** If the user is local and still being sent, verify that 1724174Seric ** the address is good. If it is, try to forward. 1734174Seric ** If the address is already good, we have a forwarding 1744174Seric ** loop. This can be broken by just sending directly to 1754174Seric ** the user (which is probably correct anyway). 1764174Seric */ 1774174Seric 1784197Seric if (!bitset(QDONTSEND, a->q_flags) && a->q_mailer == MN_LOCAL) 1794174Seric { 1804174Seric char buf[MAXNAME]; 1814201Seric register char *p; 1824174Seric 1834174Seric strcpy(buf, a->q_user); 1844174Seric stripquotes(buf, TRUE); 1854174Seric 1864174Seric /* see if this is to a file */ 1874201Seric if ((p = rindex(buf, '/')) != NULL) 1884174Seric { 1894201Seric /* check if writable or creatable */ 1904201Seric if ((access(buf, 0) >= 0) ? 1914201Seric (access(buf, 2) < 0) : 1924201Seric (*p = '\0', access(buf, 3) < 0)) 1934174Seric { 1944174Seric a->q_flags |= QBADADDR; 1954174Seric giveresponse(EX_CANTCREAT, TRUE, m); 1964174Seric } 1974174Seric } 1984174Seric else 1994174Seric { 2004174Seric register struct passwd *pw; 2014174Seric extern struct passwd *getpwnam(); 2024174Seric pw = getpwnam(buf); 2034174Seric if (pw == NULL) 2044174Seric { 2054174Seric a->q_flags |= QBADADDR; 2064174Seric giveresponse(EX_NOUSER, TRUE, m); 2074174Seric } 2084174Seric else 2094174Seric { 2104174Seric a->q_home = newstr(pw->pw_dir); 2114213Seric a->q_uid = pw->pw_uid; 2124174Seric if (strcmp(buf, a->q_user) == 0) 2134174Seric forward(a); 2144174Seric } 2154174Seric } 2164174Seric } 2174174Seric } 2184174Seric /* 2194174Seric ** INCLUDE -- handle :include: specification. 2204174Seric ** 2214174Seric ** Parameters: 2224174Seric ** fname -- filename to include. 2234176Seric ** msg -- message to print in verbose mode. 2244174Seric ** 2254174Seric ** Returns: 2264174Seric ** none. 2274174Seric ** 2284174Seric ** Side Effects: 2294174Seric ** reads the :include: file and sends to everyone 2304174Seric ** listed in that file. 2314174Seric */ 2324174Seric 2334176Seric include(fname, msg) 2344174Seric char *fname; 2354176Seric char *msg; 2364174Seric { 2374174Seric char buf[MAXLINE]; 2384174Seric register FILE *fp; 2394178Seric char *oldto = To; 2404174Seric 2414174Seric fp = fopen(fname, "r"); 2424174Seric if (fp == NULL) 2434174Seric { 2444174Seric usrerr("Cannot open %s", fname); 2454174Seric return; 2464174Seric } 2474174Seric 2484174Seric /* read the file -- each line is a comma-separated list. */ 2494174Seric while (fgets(buf, sizeof buf, fp) != NULL) 2504174Seric { 2514174Seric register char *p = index(buf, '\n'); 2524174Seric 2534174Seric if (p != NULL) 2544174Seric *p = '\0'; 2554174Seric if (buf[0] == '\0') 2564174Seric continue; 2574178Seric To = oldto; 2584174Seric if (Verbose) 2594176Seric message(Arpa_Info, "%s to %s", msg, buf); 2604176Seric AliasLevel++; 2614174Seric sendto(buf, 1); 2624176Seric AliasLevel--; 2634174Seric } 2644174Seric 2654174Seric fclose(fp); 2664174Seric } 267