1 # include <stdio.h> 2 # include <pwd.h> 3 # include <signal.h> 4 # include <ctype.h> 5 # include <errno.h> 6 # include "sendmail.h" 7 # ifdef LOG 8 # include <syslog.h> 9 # endif LOG 10 11 static char SccsId[] = "@(#)recipient.c 3.2 08/20/81"; 12 13 /* 14 ** SENDTO -- Designate a send list. 15 ** 16 ** The parameter is a comma-separated list of people to send to. 17 ** This routine arranges to send to all of them. 18 ** 19 ** Parameters: 20 ** list -- the send list. 21 ** copyf -- the copy flag; passed to parse. 22 ** 23 ** Returns: 24 ** none 25 ** 26 ** Side Effects: 27 ** none. 28 */ 29 30 # define MAXRCRSN 10 31 32 sendto(list, copyf) 33 char *list; 34 int copyf; 35 { 36 register char *p; 37 register char *q; 38 register char c; 39 ADDRESS *a; 40 bool more; 41 42 /* more keeps track of what the previous delimiter was */ 43 more = TRUE; 44 for (p = list; more; ) 45 { 46 /* find the end of this address */ 47 while (*p == ' ' || *p == '\t') 48 p++; 49 q = p; 50 while ((c = *p++) != '\0' && c != ',' && c != '\n') 51 continue; 52 more = c != '\0'; 53 *--p = '\0'; 54 if (more) 55 p++; 56 57 /* parse the address */ 58 if ((a = parse(q, (ADDRESS *) NULL, copyf)) == NULL) 59 continue; 60 61 /* arrange to send to this person */ 62 recipient(a); 63 } 64 To = NULL; 65 } 66 /* 67 ** RECIPIENT -- Designate a message recipient 68 ** 69 ** Saves the named person for future mailing. 70 ** 71 ** Parameters: 72 ** a -- the (preparsed) address header for the recipient. 73 ** 74 ** Returns: 75 ** none. 76 ** 77 ** Side Effects: 78 ** none. 79 */ 80 81 recipient(a) 82 register ADDRESS *a; 83 { 84 register ADDRESS *q; 85 register struct mailer *m; 86 char buf[MAXNAME]; 87 88 To = a->q_paddr; 89 m = Mailer[a->q_mailer]; 90 errno = 0; 91 # ifdef DEBUG 92 if (Debug) 93 printf("recipient(%s)\n", To); 94 # endif DEBUG 95 96 /* break aliasing loops */ 97 if (AliasLevel > MAXRCRSN) 98 { 99 usrerr("aliasing/forwarding loop broken"); 100 return; 101 } 102 103 /* 104 ** Do sickly crude mapping for program mailing, etc. 105 */ 106 107 if (a->q_mailer == M_LOCAL) 108 { 109 if (a->q_user[0] == '|') 110 { 111 a->q_mailer = M_PROG; 112 m = Mailer[M_PROG]; 113 a->q_user++; 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 == M_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 == M_LOCAL) 177 { 178 char buf[MAXNAME]; 179 180 strcpy(buf, a->q_user); 181 stripquotes(buf, TRUE); 182 183 /* see if this is to a file */ 184 if (index(buf, '/') != NULL) 185 { 186 if (access(buf, 2) < 0) 187 { 188 a->q_flags |= QBADADDR; 189 giveresponse(EX_CANTCREAT, TRUE, m); 190 } 191 } 192 else 193 { 194 register struct passwd *pw; 195 extern struct passwd *getpwnam(); 196 pw = getpwnam(buf); 197 if (pw == NULL) 198 { 199 a->q_flags |= QBADADDR; 200 giveresponse(EX_NOUSER, TRUE, m); 201 } 202 else 203 { 204 a->q_home = newstr(pw->pw_dir); 205 if (strcmp(buf, a->q_user) == 0) 206 forward(a); 207 } 208 } 209 } 210 } 211 /* 212 ** INCLUDE -- handle :include: specification. 213 ** 214 ** Parameters: 215 ** fname -- filename to include. 216 ** msg -- message to print in verbose mode. 217 ** 218 ** Returns: 219 ** none. 220 ** 221 ** Side Effects: 222 ** reads the :include: file and sends to everyone 223 ** listed in that file. 224 */ 225 226 include(fname, msg) 227 char *fname; 228 char *msg; 229 { 230 char buf[MAXLINE]; 231 register FILE *fp; 232 233 fp = fopen(fname, "r"); 234 if (fp == NULL) 235 { 236 usrerr("Cannot open %s", fname); 237 return; 238 } 239 240 /* read the file -- each line is a comma-separated list. */ 241 while (fgets(buf, sizeof buf, fp) != NULL) 242 { 243 register char *p = index(buf, '\n'); 244 245 if (p != NULL) 246 *p = '\0'; 247 if (buf[0] == '\0') 248 continue; 249 To = fname; 250 if (Verbose) 251 message(Arpa_Info, "%s to %s", msg, buf); 252 AliasLevel++; 253 sendto(buf, 1); 254 AliasLevel--; 255 } 256 257 fclose(fp); 258 } 259