1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 23 /* All Rights Reserved */ 24 25 #include "mail.h" 26 /* 27 * generate delivery notification if required. 28 */ 29 void gendeliv(fp, rc, name) 30 FILE *fp; 31 int rc; 32 char *name; 33 { 34 static char pn[] = "gendeliv"; 35 register char *p; 36 char buf[1024], cbuf[256], ybuf[10]; 37 register int i; 38 int didafflines = 0, didrcvlines = 0, suppress = 0, svopts = 0; 39 time_t ltmp; 40 register struct hdrs *hptr; 41 FILE *outfile; 42 43 Dout(pn, 0, "at entry, fp = o%lo, rc = %d,name = '%s'\n", (long)fp, rc, name); 44 if (fp == (FILE *)NULL) { 45 /* Want to send Positive delivery notification. Need to */ 46 /* put selected header info from orig. msg aside to */ 47 /* avoid confusion with header info in Delivery Rpt. */ 48 Daffbytecnt = affbytecnt; affbytecnt = 0; 49 Daffcnt = affcnt; affcnt = 0; 50 Drcvbytecnt = rcvbytecnt; rcvbytecnt = 0; 51 52 hdrlines[H_DAFWDFROM].head = hdrlines[H_AFWDFROM].head; 53 hdrlines[H_DAFWDFROM].tail = hdrlines[H_AFWDFROM].tail; 54 hdrlines[H_AFWDFROM].head = (struct hdrs *)NULL; 55 hdrlines[H_AFWDFROM].tail = (struct hdrs *)NULL; 56 hdrlines[H_DRECEIVED].head = hdrlines[H_RECEIVED].head; 57 hdrlines[H_DRECEIVED].tail = hdrlines[H_RECEIVED].tail; 58 hdrlines[H_RECEIVED].head = (struct hdrs *)NULL; 59 hdrlines[H_RECEIVED].tail = (struct hdrs *)NULL; 60 hdrlines[H_DTCOPY].head = hdrlines[H_TCOPY].head; 61 hdrlines[H_DTCOPY].tail = hdrlines[H_TCOPY].tail; 62 hdrlines[H_TCOPY].head = (struct hdrs *)NULL; 63 hdrlines[H_TCOPY].tail = (struct hdrs *)NULL; 64 65 pushlist (H_TCOPY, HEAD, Rpath, FALSE); 66 } 67 if (rc == 0) { 68 /* Verify that positive delivery notification requested */ 69 if (ckdlivopts(H_DTCOPY, &svopts) & NODELIVERY) { 70 Dout(pn, 0, "pos. notif. not requested\n"); 71 goto rtrn; 72 } 73 } else { 74 /* Verify that negative delivery notification requested */ 75 if (ckdlivopts(H_DTCOPY, &svopts) & IGNORE) { 76 Dout(pn, 0, "neg. notif. not requested\n"); 77 goto rtrn; 78 } 79 } 80 if (fp == (FILE *)NULL) { 81 char *pargs[3]; 82 pargs[0] = "mail"; 83 pargs[1] = Rpath; 84 pargs[2] = 0; 85 if ((outfile = popenvp(pargs[0], pargs, "w", 1)) == (FILE *)NULL) { 86 /* Can't get pipe to mail. Just forget it..... */ 87 Dout(pn, 0,"popenvp() failed\n"); 88 goto rtrn; 89 } 90 } else { 91 outfile = fp; 92 } 93 94 /* get date string into buf for later...*/ 95 ltmp = time((time_t)0); 96 strcpy(buf, asctime(gmtime(<mp))); 97 /* strip year out of date string, insert 'GMT', and put year back... */ 98 p = strrchr(buf,' '); 99 strcpy(ybuf,++p); 100 *p = '\0'; 101 strcat(buf,"GMT "); 102 strcat(buf, ybuf); 103 trimnl(buf); 104 105 fprintf(outfile,"%s 2\n", header[H_RVERS].tag); 106 fprintf(outfile,"%s %s\n", header[H_TCOPY].tag, 107 hdrlines[H_TCOPY].head->value); 108 fprintf(outfile,"%s %s\n", header[H_DATE].tag, buf); 109 dumprcv(ORDINARY, -1,&didrcvlines,&suppress,outfile); 110 dumpaff(ORDINARY, -1,&didafflines,&suppress,outfile); 111 fprintf(outfile,"Original-%s ", header[H_DATE].tag); 112 if ((hptr = hdrlines[H_DATE].head) != (struct hdrs *)NULL) { 113 Dout(pn, 0,"date from H_DATE = '%s'\n", hptr->value); 114 fprintf(outfile,"%s\n", hptr->value); 115 } else { 116 /* If no H_DATE line in original message, use date */ 117 /* in last UNIX H_FROM1 or H_FROM line */ 118 if ((hptr = hdrlines[H_FROM1].tail) == (struct hdrs *)NULL) { 119 hptr = hdrlines[H_FROM].tail; 120 } 121 Dout(pn, 0,"date from H_FROM = '%s'\n", hptr->value); 122 (void) strlcpy(buf, hptr->value, sizeof (buf)); 123 /* Find date portion of line. */ 124 /* Assumes line is of form - */ 125 /* 'name_date_[remote_from_sys|forwarded_by_name]' */ 126 if ((p = strchr(buf,' ')) == (char *)NULL) { 127 strcpy(buf, "No valid datestamp in original."); 128 } else { 129 (void) strlcpy(buf, p++, sizeof (buf)); 130 /* Walk backwards from end of string to 3rd blank, */ 131 /* and then check for 'remote from' or 'forwarded by' */ 132 /* If either found, truncate there, else use entire */ 133 /* string. */ 134 p = buf + strlen(buf) - 1; 135 i = 0; 136 while (p > buf) { 137 if (*p == ' ') { 138 if (++i == 3) { 139 break; 140 } 141 } 142 p--; 143 } 144 if ((i != 3) || (p <= buf)) { 145 strcpy(buf, "No valid datestamp in original."); 146 } else { 147 if ((strncmp((p+1),"remote from", 11) == 0) || 148 (strncmp((p+1),"forwarded by", 12) == 0)) { 149 *p = '\0'; 150 } 151 } 152 } 153 fprintf(outfile,"%s\n", buf); 154 } 155 if ((hptr = hdrlines[H_SUBJ].head) != (struct hdrs *)NULL) { 156 fprintf(outfile,"Original-%s %s\n", 157 header[H_SUBJ].tag, hptr->value); 158 } 159 if ((hptr = hdrlines[H_MSVC].head) != (struct hdrs *)NULL) { 160 if ((strlen(hptr->value) != 4) || 161 (casncmp("mail", hptr->value, 4) != 0)) { 162 fprintf(outfile,"Original-%s %s\n", 163 header[H_MSVC].tag, hptr->value); 164 } 165 } 166 if ((hptr = hdrlines[H_MTSID].head) != (struct hdrs *)NULL) { 167 fprintf(outfile,"Confirming-%s <%s>\n", 168 header[H_MTSID].tag, hptr->value); 169 } 170 if ((hptr = hdrlines[H_UAID].head) != (struct hdrs *)NULL) { 171 fprintf(outfile,"Confirming-%s <%s>\n", 172 header[H_UAID].tag, hptr->value); 173 } 174 cbuf[0] = '\0'; 175 if ((hptr = hdrlines[H_DTCOPY].head) != (struct hdrs *)NULL) { 176 /* Pick comment field off of ">To:" line and put into cbuf */ 177 getcomment(hptr->value, cbuf); 178 } 179 if (rc == 0) { 180 fprintf(outfile,"Delivered-To: %s!%s %s on %s\n", 181 thissys, name, cbuf, buf); 182 } else { 183 (void) strlcpy (buf, name, sizeof (buf)); 184 if ((p = strchr(buf,'!')) != (char *)NULL) { 185 *p = '\0'; 186 } 187 fprintf(outfile,"Not-Delivered-To: %s!%s %s due to ", 188 thissys, buf, 189 /* if en-route-to, put comment there, else put it here*/ 190 ((p == (char *)NULL) ? cbuf : "")); 191 mta_ercode(outfile); 192 if (ckdlivopts(H_DTCOPY, &svopts) & RETURN) { 193 fprintf(outfile," ORIGINAL MESSAGE ATTACHED\n"); 194 } 195 196 if (error == E_FRWL) { 197 fprintf(outfile, frwlmsg, program, uval); 198 } else { 199 fprintf(outfile, " (%s: Error # %d '%s'", 200 program,error,errlist[error]); 201 if (error == E_SURG) { 202 fprintf(outfile,", rc = %d)\n",surg_rc); 203 fprintf(outfile, 204 " ======= Surrogate command =======\n"); 205 fprintf(outfile," %s\n", 206 ((SURRcmdstr == (char *)NULL) ? 207 "" : SURRcmdstr)); 208 /* Include stderr from surrogate, if any */ 209 if (SURRerrfile) { 210 fprintf(outfile, 211 " ==== Start of stdout & stderr ===\n"); 212 rewind (SURRerrfile); 213 while (fgets(buf, sizeof(buf), SURRerrfile) != 214 (char *)NULL) { 215 fprintf(outfile," %s", buf); 216 } 217 if (buf[strlen(buf)-1] != '\n') { 218 fprintf(outfile,"\n"); 219 } 220 fprintf(outfile, 221 " ==== End of stdout & stderr ===\n"); 222 } else 223 fprintf(outfile, 224 " ==== stdout & stderr unavailable ===\n"); 225 } else { 226 fprintf(outfile,")\n"); 227 } 228 } 229 if (p != (char *)NULL) { 230 fprintf(outfile, "En-Route-To: %s %s\n", name, cbuf); 231 } 232 } 233 if ((hptr = hdrlines[H_DAFWDFROM].head) != (struct hdrs *)NULL) { 234 while (hptr != (struct hdrs *)NULL) { 235 fprintf(outfile,"Original-%s %s\n", 236 header[H_DAFWDFROM].tag, hptr->value); 237 hptr = hptr->next; 238 } 239 } 240 fprintf(outfile,"%s\n", header[H_EOH].tag); 241 if (fp == (FILE *)NULL) { 242 pclosevp(outfile); 243 } 244 Dout(pn, 5, "notification sent.\n"); 245 246 rtrn: 247 /* Restore header info from original message. (see above and also */ 248 /* goback()). */ 249 clrhdr(H_TCOPY); 250 clrhdr(H_AFWDFROM); 251 clrhdr(H_RECEIVED); 252 affbytecnt = Daffbytecnt; Daffbytecnt = 0; 253 affcnt = Daffcnt; Daffcnt = 0; 254 rcvbytecnt = Drcvbytecnt; Drcvbytecnt = 0; 255 256 hdrlines[H_AFWDFROM].head = hdrlines[H_DAFWDFROM].head; 257 hdrlines[H_AFWDFROM].tail = hdrlines[H_DAFWDFROM].tail; 258 hdrlines[H_DAFWDFROM].head = (struct hdrs *)NULL; 259 hdrlines[H_DAFWDFROM].tail = (struct hdrs *)NULL; 260 hdrlines[H_RECEIVED].head = hdrlines[H_DRECEIVED].head; 261 hdrlines[H_RECEIVED].tail = hdrlines[H_DRECEIVED].tail; 262 hdrlines[H_DRECEIVED].head = (struct hdrs *)NULL; 263 hdrlines[H_DRECEIVED].tail = (struct hdrs *)NULL; 264 hdrlines[H_TCOPY].head = hdrlines[H_DTCOPY].head; 265 hdrlines[H_TCOPY].tail = hdrlines[H_DTCOPY].tail; 266 hdrlines[H_DTCOPY].head = (struct hdrs *)NULL; 267 hdrlines[H_DTCOPY].tail = (struct hdrs *)NULL; 268 269 return; 270 } 271