14174Seric # include <pwd.h> 24174Seric # include "sendmail.h" 34174Seric 4*4324Seric static char SccsId[] = "@(#)recipient.c 3.11 09/07/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; 304319Seric bool more; /* set if more addresses to send to */ 31*4324Seric ADDRESS *al; /* list of addresses to send to */ 324174Seric 33*4324Seric # ifdef DEBUG 34*4324Seric if (Debug > 1) 35*4324Seric printf("sendto: %s\n", list); 36*4324Seric # endif DEBUG 37*4324Seric 384174Seric more = TRUE; 39*4324Seric al = NULL; 404174Seric for (p = list; more; ) 414174Seric { 424319Seric register char *q; 434319Seric register char c; 444319Seric ADDRESS *a; 454319Seric 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++; 56*4324Seric if (*q == '\0') 57*4324Seric continue; 584174Seric 594174Seric /* parse the address */ 604174Seric if ((a = parse(q, (ADDRESS *) NULL, copyf)) == NULL) 614174Seric continue; 624174Seric 63*4324Seric /* put it on the local send list */ 64*4324Seric a->q_next = al; 65*4324Seric al = a; 66*4324Seric } 67*4324Seric 68*4324Seric /* arrange to send to everyone on the local send list */ 69*4324Seric while (al != NULL) 70*4324Seric { 71*4324Seric register ADDRESS *a = al; 72*4324Seric 73*4324Seric al = a->q_next; 744174Seric recipient(a); 754174Seric } 76*4324Seric 774174Seric To = NULL; 784174Seric } 794174Seric /* 804174Seric ** RECIPIENT -- Designate a message recipient 814174Seric ** 824174Seric ** Saves the named person for future mailing. 834174Seric ** 844174Seric ** Parameters: 854174Seric ** a -- the (preparsed) address header for the recipient. 864174Seric ** 874174Seric ** Returns: 884174Seric ** none. 894174Seric ** 904174Seric ** Side Effects: 914174Seric ** none. 924174Seric */ 934174Seric 944174Seric recipient(a) 954174Seric register ADDRESS *a; 964174Seric { 974174Seric register ADDRESS *q; 984319Seric ADDRESS **pq; 994174Seric register struct mailer *m; 1004174Seric 1014174Seric To = a->q_paddr; 1024174Seric m = Mailer[a->q_mailer]; 1034174Seric errno = 0; 1044174Seric # ifdef DEBUG 1054174Seric if (Debug) 1064174Seric printf("recipient(%s)\n", To); 1074174Seric # endif DEBUG 1084174Seric 1094174Seric /* break aliasing loops */ 1104174Seric if (AliasLevel > MAXRCRSN) 1114174Seric { 1124174Seric usrerr("aliasing/forwarding loop broken"); 1134174Seric return; 1144174Seric } 1154174Seric 1164174Seric /* 1174174Seric ** Do sickly crude mapping for program mailing, etc. 1184174Seric */ 1194174Seric 1204197Seric if (a->q_mailer == MN_LOCAL) 1214174Seric { 1224174Seric if (a->q_user[0] == '|') 1234174Seric { 1244197Seric a->q_mailer = MN_PROG; 1254197Seric m = Mailer[MN_PROG]; 1264174Seric a->q_user++; 1274217Seric # ifdef PARANOID 1284217Seric if (AliasLevel <= 0) 1294217Seric { 1304217Seric usrerr("Cannot mail directly to programs"); 1314217Seric a->q_flags |= QDONTSEND; 1324217Seric } 1334217Seric # endif PARANOID 1344174Seric } 1354174Seric } 1364174Seric 1374174Seric /* 1384174Seric ** Look up this person in the recipient list. If they 1394174Seric ** are there already, return, otherwise continue. 1404174Seric ** If the list is empty, just add it. 1414174Seric */ 1424174Seric 1434319Seric for (pq = &m->m_sendq; (q = *pq) != NULL; pq = &q->q_next) 1444174Seric { 1454319Seric if (!ForceMail && sameaddr(q, a, FALSE)) 1464174Seric { 1474174Seric # ifdef DEBUG 1484319Seric if (Debug) 1494319Seric printf("(%s in sendq)\n", a->q_paddr); 1504174Seric # endif DEBUG 1514319Seric if (Verbose && !bitset(QDONTSEND, a->q_flags)) 152*4324Seric message(Arpa_Info, "duplicate suppressed"); 1534319Seric return; 1544174Seric } 1554319Seric } 1564174Seric 1574319Seric /* add address on list */ 1584319Seric *pq = a; 1594174Seric a->q_next = NULL; 1604247Seric if (DontSend) 1614247Seric a->q_flags |= QDONTSEND; 1624174Seric 1634174Seric /* 1644174Seric ** Alias the name and handle :include: specs. 1654174Seric */ 1664174Seric 1674197Seric if (a->q_mailer == MN_LOCAL) 1684174Seric { 1694174Seric if (strncmp(a->q_user, ":include:", 9) == 0) 1704174Seric { 1714174Seric a->q_flags |= QDONTSEND; 1724176Seric if (Verbose) 1734176Seric message(Arpa_Info, "including file %s", &a->q_user[9]); 1744176Seric include(&a->q_user[9], " sending"); 1754174Seric } 1764174Seric else 1774174Seric alias(a); 1784174Seric } 1794174Seric 1804174Seric /* 1814174Seric ** If the user is local and still being sent, verify that 1824174Seric ** the address is good. If it is, try to forward. 1834174Seric ** If the address is already good, we have a forwarding 1844174Seric ** loop. This can be broken by just sending directly to 1854174Seric ** the user (which is probably correct anyway). 1864174Seric */ 1874174Seric 1884197Seric if (!bitset(QDONTSEND, a->q_flags) && a->q_mailer == MN_LOCAL) 1894174Seric { 1904174Seric char buf[MAXNAME]; 1914201Seric register char *p; 1924174Seric 1934174Seric strcpy(buf, a->q_user); 1944174Seric stripquotes(buf, TRUE); 1954174Seric 1964174Seric /* see if this is to a file */ 1974201Seric if ((p = rindex(buf, '/')) != NULL) 1984174Seric { 1994201Seric /* check if writable or creatable */ 2004201Seric if ((access(buf, 0) >= 0) ? 2014201Seric (access(buf, 2) < 0) : 2024201Seric (*p = '\0', access(buf, 3) < 0)) 2034174Seric { 2044174Seric a->q_flags |= QBADADDR; 2054174Seric giveresponse(EX_CANTCREAT, TRUE, m); 2064174Seric } 2074174Seric } 2084174Seric else 2094174Seric { 2104174Seric register struct passwd *pw; 2114174Seric extern struct passwd *getpwnam(); 2124174Seric pw = getpwnam(buf); 2134174Seric if (pw == NULL) 2144174Seric { 2154174Seric a->q_flags |= QBADADDR; 2164174Seric giveresponse(EX_NOUSER, TRUE, m); 2174174Seric } 2184174Seric else 2194174Seric { 2204174Seric a->q_home = newstr(pw->pw_dir); 2214213Seric a->q_uid = pw->pw_uid; 2224174Seric if (strcmp(buf, a->q_user) == 0) 2234174Seric forward(a); 2244174Seric } 2254174Seric } 2264174Seric } 2274174Seric } 2284174Seric /* 2294174Seric ** INCLUDE -- handle :include: specification. 2304174Seric ** 2314174Seric ** Parameters: 2324174Seric ** fname -- filename to include. 2334176Seric ** msg -- message to print in verbose mode. 2344174Seric ** 2354174Seric ** Returns: 2364174Seric ** none. 2374174Seric ** 2384174Seric ** Side Effects: 2394174Seric ** reads the :include: file and sends to everyone 2404174Seric ** listed in that file. 2414174Seric */ 2424174Seric 2434176Seric include(fname, msg) 2444174Seric char *fname; 2454176Seric char *msg; 2464174Seric { 2474174Seric char buf[MAXLINE]; 2484174Seric register FILE *fp; 2494178Seric char *oldto = To; 2504174Seric 2514174Seric fp = fopen(fname, "r"); 2524174Seric if (fp == NULL) 2534174Seric { 2544174Seric usrerr("Cannot open %s", fname); 2554174Seric return; 2564174Seric } 2574174Seric 2584174Seric /* read the file -- each line is a comma-separated list. */ 2594174Seric while (fgets(buf, sizeof buf, fp) != NULL) 2604174Seric { 2614174Seric register char *p = index(buf, '\n'); 2624174Seric 2634174Seric if (p != NULL) 2644174Seric *p = '\0'; 2654174Seric if (buf[0] == '\0') 2664174Seric continue; 2674178Seric To = oldto; 2684174Seric if (Verbose) 2694176Seric message(Arpa_Info, "%s to %s", msg, buf); 2704176Seric AliasLevel++; 2714174Seric sendto(buf, 1); 2724176Seric AliasLevel--; 2734174Seric } 2744174Seric 2754319Seric (void) fclose(fp); 2764174Seric } 277*4324Seric /* 278*4324Seric ** SENDTOARGV -- send to an argument vector. 279*4324Seric ** 280*4324Seric ** Parameters: 281*4324Seric ** argv -- argument vector to send to. 282*4324Seric ** 283*4324Seric ** Returns: 284*4324Seric ** none. 285*4324Seric ** 286*4324Seric ** Side Effects: 287*4324Seric ** puts all addresses on the argument vector onto the 288*4324Seric ** send queue. 289*4324Seric */ 290*4324Seric 291*4324Seric sendtoargv(argv) 292*4324Seric register char **argv; 293*4324Seric { 294*4324Seric register char *p; 295*4324Seric extern bool sameword(); 296*4324Seric 297*4324Seric while ((p = *argv++) != NULL) 298*4324Seric { 299*4324Seric if (argv[0] != NULL && argv[1] != NULL && sameword(argv[0], "at")) 300*4324Seric { 301*4324Seric char nbuf[MAXNAME]; 302*4324Seric 303*4324Seric if (strlen(p) + strlen(argv[1]) + 2 > sizeof nbuf) 304*4324Seric usrerr("address overflow"); 305*4324Seric else 306*4324Seric { 307*4324Seric (void) strcpy(nbuf, p); 308*4324Seric (void) strcat(nbuf, "@"); 309*4324Seric (void) strcat(nbuf, argv[1]); 310*4324Seric p = newstr(nbuf); 311*4324Seric argv += 2; 312*4324Seric } 313*4324Seric } 314*4324Seric sendto(p, 0); 315*4324Seric } 316*4324Seric } 317