14174Seric # include <stdio.h> 24174Seric # include <pwd.h> 34174Seric # include <signal.h> 44174Seric # include <ctype.h> 54174Seric # include <errno.h> 64174Seric # include "sendmail.h" 74174Seric # ifdef LOG 84174Seric # include <syslog.h> 94174Seric # endif LOG 104174Seric 11*4178Seric static char SccsId[] = "@(#)recipient.c 3.3 08/20/81"; 124174Seric 134174Seric /* 144174Seric ** SENDTO -- Designate a send list. 154174Seric ** 164174Seric ** The parameter is a comma-separated list of people to send to. 174174Seric ** This routine arranges to send to all of them. 184174Seric ** 194174Seric ** Parameters: 204174Seric ** list -- the send list. 214174Seric ** copyf -- the copy flag; passed to parse. 224174Seric ** 234174Seric ** Returns: 244174Seric ** none 254174Seric ** 264174Seric ** Side Effects: 274174Seric ** none. 284174Seric */ 294174Seric 304174Seric # define MAXRCRSN 10 314174Seric 324174Seric sendto(list, copyf) 334174Seric char *list; 344174Seric int copyf; 354174Seric { 364174Seric register char *p; 374174Seric register char *q; 384174Seric register char c; 394174Seric ADDRESS *a; 404174Seric bool more; 414174Seric 424174Seric /* more keeps track of what the previous delimiter was */ 434174Seric more = TRUE; 444174Seric for (p = list; more; ) 454174Seric { 464174Seric /* find the end of this address */ 474174Seric while (*p == ' ' || *p == '\t') 484174Seric p++; 494174Seric q = p; 504174Seric while ((c = *p++) != '\0' && c != ',' && c != '\n') 514174Seric continue; 524174Seric more = c != '\0'; 534174Seric *--p = '\0'; 544174Seric if (more) 554174Seric p++; 564174Seric 574174Seric /* parse the address */ 584174Seric if ((a = parse(q, (ADDRESS *) NULL, copyf)) == NULL) 594174Seric continue; 604174Seric 614174Seric /* arrange to send to this person */ 624174Seric recipient(a); 634174Seric } 644174Seric To = NULL; 654174Seric } 664174Seric /* 674174Seric ** RECIPIENT -- Designate a message recipient 684174Seric ** 694174Seric ** Saves the named person for future mailing. 704174Seric ** 714174Seric ** Parameters: 724174Seric ** a -- the (preparsed) address header for the recipient. 734174Seric ** 744174Seric ** Returns: 754174Seric ** none. 764174Seric ** 774174Seric ** Side Effects: 784174Seric ** none. 794174Seric */ 804174Seric 814174Seric recipient(a) 824174Seric register ADDRESS *a; 834174Seric { 844174Seric register ADDRESS *q; 854174Seric register struct mailer *m; 864174Seric char buf[MAXNAME]; 874174Seric 884174Seric To = a->q_paddr; 894174Seric m = Mailer[a->q_mailer]; 904174Seric errno = 0; 914174Seric # ifdef DEBUG 924174Seric if (Debug) 934174Seric printf("recipient(%s)\n", To); 944174Seric # endif DEBUG 954174Seric 964174Seric /* break aliasing loops */ 974174Seric if (AliasLevel > MAXRCRSN) 984174Seric { 994174Seric usrerr("aliasing/forwarding loop broken"); 1004174Seric return; 1014174Seric } 1024174Seric 1034174Seric /* 1044174Seric ** Do sickly crude mapping for program mailing, etc. 1054174Seric */ 1064174Seric 1074174Seric if (a->q_mailer == M_LOCAL) 1084174Seric { 1094174Seric if (a->q_user[0] == '|') 1104174Seric { 1114174Seric a->q_mailer = M_PROG; 1124174Seric m = Mailer[M_PROG]; 1134174Seric a->q_user++; 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 1554174Seric if (a->q_mailer == M_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 1764174Seric if (!bitset(QDONTSEND, a->q_flags) && a->q_mailer == M_LOCAL) 1774174Seric { 1784174Seric char buf[MAXNAME]; 1794174Seric 1804174Seric strcpy(buf, a->q_user); 1814174Seric stripquotes(buf, TRUE); 1824174Seric 1834174Seric /* see if this is to a file */ 1844174Seric if (index(buf, '/') != NULL) 1854174Seric { 1864174Seric if (access(buf, 2) < 0) 1874174Seric { 1884174Seric a->q_flags |= QBADADDR; 1894174Seric giveresponse(EX_CANTCREAT, TRUE, m); 1904174Seric } 1914174Seric } 1924174Seric else 1934174Seric { 1944174Seric register struct passwd *pw; 1954174Seric extern struct passwd *getpwnam(); 1964174Seric pw = getpwnam(buf); 1974174Seric if (pw == NULL) 1984174Seric { 1994174Seric a->q_flags |= QBADADDR; 2004174Seric giveresponse(EX_NOUSER, TRUE, m); 2014174Seric } 2024174Seric else 2034174Seric { 2044174Seric a->q_home = newstr(pw->pw_dir); 2054174Seric if (strcmp(buf, a->q_user) == 0) 2064174Seric forward(a); 2074174Seric } 2084174Seric } 2094174Seric } 2104174Seric } 2114174Seric /* 2124174Seric ** INCLUDE -- handle :include: specification. 2134174Seric ** 2144174Seric ** Parameters: 2154174Seric ** fname -- filename to include. 2164176Seric ** msg -- message to print in verbose mode. 2174174Seric ** 2184174Seric ** Returns: 2194174Seric ** none. 2204174Seric ** 2214174Seric ** Side Effects: 2224174Seric ** reads the :include: file and sends to everyone 2234174Seric ** listed in that file. 2244174Seric */ 2254174Seric 2264176Seric include(fname, msg) 2274174Seric char *fname; 2284176Seric char *msg; 2294174Seric { 2304174Seric char buf[MAXLINE]; 2314174Seric register FILE *fp; 232*4178Seric char *oldto = To; 2334174Seric 2344174Seric fp = fopen(fname, "r"); 2354174Seric if (fp == NULL) 2364174Seric { 2374174Seric usrerr("Cannot open %s", fname); 2384174Seric return; 2394174Seric } 2404174Seric 2414174Seric /* read the file -- each line is a comma-separated list. */ 2424174Seric while (fgets(buf, sizeof buf, fp) != NULL) 2434174Seric { 2444174Seric register char *p = index(buf, '\n'); 2454174Seric 2464174Seric if (p != NULL) 2474174Seric *p = '\0'; 2484174Seric if (buf[0] == '\0') 2494174Seric continue; 250*4178Seric To = oldto; 2514174Seric if (Verbose) 2524176Seric message(Arpa_Info, "%s to %s", msg, buf); 2534176Seric AliasLevel++; 2544174Seric sendto(buf, 1); 2554176Seric AliasLevel--; 2564174Seric } 2574174Seric 2584174Seric fclose(fp); 2594174Seric } 260