14174Seric # include <pwd.h> 24174Seric # include "sendmail.h" 34174Seric 4*4201Seric static char SccsId[] = "@(#)recipient.c 3.6 08/22/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++; 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 1484197Seric 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 1694197Seric if (!bitset(QDONTSEND, a->q_flags) && a->q_mailer == MN_LOCAL) 1704174Seric { 1714174Seric char buf[MAXNAME]; 172*4201Seric register char *p; 1734174Seric 1744174Seric strcpy(buf, a->q_user); 1754174Seric stripquotes(buf, TRUE); 1764174Seric 1774174Seric /* see if this is to a file */ 178*4201Seric if ((p = rindex(buf, '/')) != NULL) 1794174Seric { 180*4201Seric /* check if writable or creatable */ 181*4201Seric if ((access(buf, 0) >= 0) ? 182*4201Seric (access(buf, 2) < 0) : 183*4201Seric (*p = '\0', access(buf, 3) < 0)) 1844174Seric { 1854174Seric a->q_flags |= QBADADDR; 1864174Seric giveresponse(EX_CANTCREAT, TRUE, m); 1874174Seric } 1884174Seric } 1894174Seric else 1904174Seric { 1914174Seric register struct passwd *pw; 1924174Seric extern struct passwd *getpwnam(); 1934174Seric pw = getpwnam(buf); 1944174Seric if (pw == NULL) 1954174Seric { 1964174Seric a->q_flags |= QBADADDR; 1974174Seric giveresponse(EX_NOUSER, TRUE, m); 1984174Seric } 1994174Seric else 2004174Seric { 2014174Seric a->q_home = newstr(pw->pw_dir); 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 2554174Seric fclose(fp); 2564174Seric } 257