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