1*4174Seric # include <stdio.h> 2*4174Seric # include <pwd.h> 3*4174Seric # include <signal.h> 4*4174Seric # include <ctype.h> 5*4174Seric # include <errno.h> 6*4174Seric # include "sendmail.h" 7*4174Seric # ifdef LOG 8*4174Seric # include <syslog.h> 9*4174Seric # endif LOG 10*4174Seric 11*4174Seric static char SccsId[] = "@(#)recipient.c 3.1 08/20/81"; 12*4174Seric 13*4174Seric /* 14*4174Seric ** SENDTO -- Designate a send list. 15*4174Seric ** 16*4174Seric ** The parameter is a comma-separated list of people to send to. 17*4174Seric ** This routine arranges to send to all of them. 18*4174Seric ** 19*4174Seric ** Parameters: 20*4174Seric ** list -- the send list. 21*4174Seric ** copyf -- the copy flag; passed to parse. 22*4174Seric ** 23*4174Seric ** Returns: 24*4174Seric ** none 25*4174Seric ** 26*4174Seric ** Side Effects: 27*4174Seric ** none. 28*4174Seric */ 29*4174Seric 30*4174Seric # define MAXRCRSN 10 31*4174Seric 32*4174Seric sendto(list, copyf) 33*4174Seric char *list; 34*4174Seric int copyf; 35*4174Seric { 36*4174Seric register char *p; 37*4174Seric register char *q; 38*4174Seric register char c; 39*4174Seric ADDRESS *a; 40*4174Seric bool more; 41*4174Seric 42*4174Seric /* more keeps track of what the previous delimiter was */ 43*4174Seric more = TRUE; 44*4174Seric for (p = list; more; ) 45*4174Seric { 46*4174Seric /* find the end of this address */ 47*4174Seric while (*p == ' ' || *p == '\t') 48*4174Seric p++; 49*4174Seric q = p; 50*4174Seric while ((c = *p++) != '\0' && c != ',' && c != '\n') 51*4174Seric continue; 52*4174Seric more = c != '\0'; 53*4174Seric *--p = '\0'; 54*4174Seric if (more) 55*4174Seric p++; 56*4174Seric 57*4174Seric /* parse the address */ 58*4174Seric if ((a = parse(q, (ADDRESS *) NULL, copyf)) == NULL) 59*4174Seric continue; 60*4174Seric 61*4174Seric /* arrange to send to this person */ 62*4174Seric recipient(a); 63*4174Seric } 64*4174Seric To = NULL; 65*4174Seric } 66*4174Seric /* 67*4174Seric ** RECIPIENT -- Designate a message recipient 68*4174Seric ** 69*4174Seric ** Saves the named person for future mailing. 70*4174Seric ** 71*4174Seric ** Parameters: 72*4174Seric ** a -- the (preparsed) address header for the recipient. 73*4174Seric ** 74*4174Seric ** Returns: 75*4174Seric ** none. 76*4174Seric ** 77*4174Seric ** Side Effects: 78*4174Seric ** none. 79*4174Seric */ 80*4174Seric 81*4174Seric recipient(a) 82*4174Seric register ADDRESS *a; 83*4174Seric { 84*4174Seric register ADDRESS *q; 85*4174Seric register struct mailer *m; 86*4174Seric char buf[MAXNAME]; 87*4174Seric 88*4174Seric To = a->q_paddr; 89*4174Seric m = Mailer[a->q_mailer]; 90*4174Seric errno = 0; 91*4174Seric # ifdef DEBUG 92*4174Seric if (Debug) 93*4174Seric printf("recipient(%s)\n", To); 94*4174Seric # endif DEBUG 95*4174Seric 96*4174Seric /* break aliasing loops */ 97*4174Seric if (AliasLevel > MAXRCRSN) 98*4174Seric { 99*4174Seric usrerr("aliasing/forwarding loop broken"); 100*4174Seric return; 101*4174Seric } 102*4174Seric 103*4174Seric /* 104*4174Seric ** Do sickly crude mapping for program mailing, etc. 105*4174Seric */ 106*4174Seric 107*4174Seric if (a->q_mailer == M_LOCAL) 108*4174Seric { 109*4174Seric if (a->q_user[0] == '|') 110*4174Seric { 111*4174Seric a->q_mailer = M_PROG; 112*4174Seric m = Mailer[M_PROG]; 113*4174Seric a->q_user++; 114*4174Seric } 115*4174Seric } 116*4174Seric 117*4174Seric /* 118*4174Seric ** Look up this person in the recipient list. If they 119*4174Seric ** are there already, return, otherwise continue. 120*4174Seric ** If the list is empty, just add it. 121*4174Seric */ 122*4174Seric 123*4174Seric if (m->m_sendq == NULL) 124*4174Seric { 125*4174Seric m->m_sendq = a; 126*4174Seric } 127*4174Seric else 128*4174Seric { 129*4174Seric ADDRESS *pq; 130*4174Seric 131*4174Seric for (q = m->m_sendq; q != NULL; pq = q, q = q->q_next) 132*4174Seric { 133*4174Seric if (!ForceMail && sameaddr(q, a, FALSE)) 134*4174Seric { 135*4174Seric # ifdef DEBUG 136*4174Seric if (Debug) 137*4174Seric printf("(%s in sendq)\n", a->q_paddr); 138*4174Seric # endif DEBUG 139*4174Seric if (Verbose && !bitset(QDONTSEND, a->q_flags)) 140*4174Seric message(Arpa_Info, "duplicate supressed"); 141*4174Seric return; 142*4174Seric } 143*4174Seric } 144*4174Seric 145*4174Seric /* add address on list */ 146*4174Seric q = pq; 147*4174Seric q->q_next = a; 148*4174Seric } 149*4174Seric a->q_next = NULL; 150*4174Seric 151*4174Seric /* 152*4174Seric ** Alias the name and handle :include: specs. 153*4174Seric */ 154*4174Seric 155*4174Seric if (a->q_mailer == M_LOCAL) 156*4174Seric { 157*4174Seric if (strncmp(a->q_user, ":include:", 9) == 0) 158*4174Seric { 159*4174Seric a->q_flags |= QDONTSEND; 160*4174Seric include(&a->q_user[9]); 161*4174Seric } 162*4174Seric else 163*4174Seric alias(a); 164*4174Seric } 165*4174Seric 166*4174Seric /* 167*4174Seric ** If the user is local and still being sent, verify that 168*4174Seric ** the address is good. If it is, try to forward. 169*4174Seric ** If the address is already good, we have a forwarding 170*4174Seric ** loop. This can be broken by just sending directly to 171*4174Seric ** the user (which is probably correct anyway). 172*4174Seric */ 173*4174Seric 174*4174Seric if (!bitset(QDONTSEND, a->q_flags) && a->q_mailer == M_LOCAL) 175*4174Seric { 176*4174Seric char buf[MAXNAME]; 177*4174Seric 178*4174Seric strcpy(buf, a->q_user); 179*4174Seric stripquotes(buf, TRUE); 180*4174Seric 181*4174Seric /* see if this is to a file */ 182*4174Seric if (index(buf, '/') != NULL) 183*4174Seric { 184*4174Seric if (access(buf, 2) < 0) 185*4174Seric { 186*4174Seric a->q_flags |= QBADADDR; 187*4174Seric giveresponse(EX_CANTCREAT, TRUE, m); 188*4174Seric } 189*4174Seric } 190*4174Seric else 191*4174Seric { 192*4174Seric register struct passwd *pw; 193*4174Seric extern struct passwd *getpwnam(); 194*4174Seric pw = getpwnam(buf); 195*4174Seric if (pw == NULL) 196*4174Seric { 197*4174Seric a->q_flags |= QBADADDR; 198*4174Seric giveresponse(EX_NOUSER, TRUE, m); 199*4174Seric } 200*4174Seric else 201*4174Seric { 202*4174Seric a->q_home = newstr(pw->pw_dir); 203*4174Seric if (strcmp(buf, a->q_user) == 0) 204*4174Seric forward(a); 205*4174Seric } 206*4174Seric } 207*4174Seric } 208*4174Seric } 209*4174Seric /* 210*4174Seric ** INCLUDE -- handle :include: specification. 211*4174Seric ** 212*4174Seric ** Parameters: 213*4174Seric ** fname -- filename to include. 214*4174Seric ** 215*4174Seric ** Returns: 216*4174Seric ** none. 217*4174Seric ** 218*4174Seric ** Side Effects: 219*4174Seric ** reads the :include: file and sends to everyone 220*4174Seric ** listed in that file. 221*4174Seric */ 222*4174Seric 223*4174Seric include(fname) 224*4174Seric char *fname; 225*4174Seric { 226*4174Seric char buf[MAXLINE]; 227*4174Seric register FILE *fp; 228*4174Seric 229*4174Seric if (Verbose) 230*4174Seric message(Arpa_Info, "Including file %s", fname); 231*4174Seric fp = fopen(fname, "r"); 232*4174Seric if (fp == NULL) 233*4174Seric { 234*4174Seric usrerr("Cannot open %s", fname); 235*4174Seric return; 236*4174Seric } 237*4174Seric 238*4174Seric /* read the file -- each line is a comma-separated list. */ 239*4174Seric while (fgets(buf, sizeof buf, fp) != NULL) 240*4174Seric { 241*4174Seric register char *p = index(buf, '\n'); 242*4174Seric 243*4174Seric if (p != NULL) 244*4174Seric *p = '\0'; 245*4174Seric if (buf[0] == '\0') 246*4174Seric continue; 247*4174Seric To = fname; 248*4174Seric if (Verbose) 249*4174Seric message(Arpa_Info, " >> %s", buf); 250*4174Seric sendto(buf, 1); 251*4174Seric } 252*4174Seric 253*4174Seric fclose(fp); 254*4174Seric } 255