1 /* 2 * Copyright (c) 1980 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that the above copyright notice and this paragraph are 7 * duplicated in all such forms and that any documentation, 8 * advertising materials, and other materials related to such 9 * distribution and use acknowledge that the software was developed 10 * by the University of California, Berkeley. The name of the 11 * University may not be used to endorse or promote products derived 12 * from this software without specific prior written permission. 13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16 */ 17 18 #ifndef lint 19 static char sccsid[] = "@(#)quit.c 5.10 (Berkeley) 07/07/88"; 20 #endif /* not lint */ 21 22 #include "rcv.h" 23 #include <sys/stat.h> 24 #include <sys/file.h> 25 26 /* 27 * Rcv -- receive mail rationally. 28 * 29 * Termination processing. 30 */ 31 32 /* 33 * Save all of the undetermined messages at the top of "mbox" 34 * Save all untouched messages back in the system mailbox. 35 * Remove the system mailbox, if none saved there. 36 */ 37 38 quit() 39 { 40 int mcount, p, modify, autohold, anystat, holdbit, nohold; 41 FILE *ibuf, *obuf, *fbuf, *rbuf, *readstat, *abuf; 42 register struct message *mp; 43 register int c; 44 extern char tempQuit[], tempResid[]; 45 struct stat minfo; 46 char *mbox; 47 48 /* 49 * If we are read only, we can't do anything, 50 * so just return quickly. 51 */ 52 53 if (readonly) 54 return; 55 /* 56 * See if there any messages to save in mbox. If no, we 57 * can save copying mbox to /tmp and back. 58 * 59 * Check also to see if any files need to be preserved. 60 * Delete all untouched messages to keep them out of mbox. 61 * If all the messages are to be preserved, just exit with 62 * a message. 63 */ 64 65 fbuf = fopen(mailname, "r"); 66 if (fbuf == NULL) 67 goto newmail; 68 flock(fileno(fbuf), LOCK_EX); 69 rbuf = NULL; 70 if (fstat(fileno(fbuf), &minfo) >= 0 && minfo.st_size > mailsize) { 71 printf("New mail has arrived.\n"); 72 rbuf = fopen(tempResid, "w"); 73 if (rbuf == NULL || fbuf == NULL) 74 goto newmail; 75 #ifdef APPEND 76 fseek(fbuf, mailsize, 0); 77 while ((c = getc(fbuf)) != EOF) 78 putc(c, rbuf); 79 #else 80 p = minfo.st_size - mailsize; 81 while (p-- > 0) { 82 c = getc(fbuf); 83 if (c == EOF) 84 goto newmail; 85 putc(c, rbuf); 86 } 87 #endif 88 fclose(rbuf); 89 if ((rbuf = fopen(tempResid, "r")) == NULL) 90 goto newmail; 91 remove(tempResid); 92 } 93 94 /* 95 * Adjust the message flags in each message. 96 */ 97 98 anystat = 0; 99 autohold = value("hold") != NOSTR; 100 holdbit = autohold ? MPRESERVE : MBOX; 101 nohold = MBOX|MSAVED|MDELETED|MPRESERVE; 102 if (value("keepsave") != NOSTR) 103 nohold &= ~MSAVED; 104 for (mp = &message[0]; mp < &message[msgCount]; mp++) { 105 if (mp->m_flag & MNEW) { 106 mp->m_flag &= ~MNEW; 107 mp->m_flag |= MSTATUS; 108 } 109 if (mp->m_flag & MSTATUS) 110 anystat++; 111 if ((mp->m_flag & MTOUCH) == 0) 112 mp->m_flag |= MPRESERVE; 113 if ((mp->m_flag & nohold) == 0) 114 mp->m_flag |= holdbit; 115 } 116 modify = 0; 117 if (Tflag != NOSTR) { 118 if ((readstat = fopen(Tflag, "w")) == NULL) 119 Tflag = NOSTR; 120 } 121 for (c = 0, p = 0, mp = &message[0]; mp < &message[msgCount]; mp++) { 122 if (mp->m_flag & MBOX) 123 c++; 124 if (mp->m_flag & MPRESERVE) 125 p++; 126 if (mp->m_flag & MODIFY) 127 modify++; 128 if (Tflag != NOSTR && (mp->m_flag & (MREAD|MDELETED)) != 0) { 129 char *id; 130 131 if ((id = hfield("article-id", mp)) != NOSTR) 132 fprintf(readstat, "%s\n", id); 133 } 134 } 135 if (Tflag != NOSTR) 136 fclose(readstat); 137 if (p == msgCount && !modify && !anystat) { 138 printf("Held %d message%s in %s\n", 139 p, p == 1 ? "" : "s", mailname); 140 fclose(fbuf); 141 return; 142 } 143 if (c == 0) { 144 if (p != 0) { 145 writeback(rbuf); 146 fclose(fbuf); 147 return; 148 } 149 goto cream; 150 } 151 152 /* 153 * Create another temporary file and copy user's mbox file 154 * darin. If there is no mbox, copy nothing. 155 * If he has specified "append" don't copy his mailbox, 156 * just copy saveable entries at the end. 157 */ 158 159 mbox = expand("&"); 160 mcount = c; 161 if (value("append") == NOSTR) { 162 if ((obuf = fopen(tempQuit, "w")) == NULL) { 163 perror(tempQuit); 164 fclose(fbuf); 165 return; 166 } 167 if ((ibuf = fopen(tempQuit, "r")) == NULL) { 168 perror(tempQuit); 169 remove(tempQuit); 170 fclose(obuf); 171 fclose(fbuf); 172 return; 173 } 174 remove(tempQuit); 175 if ((abuf = fopen(mbox, "r")) != NULL) { 176 while ((c = getc(abuf)) != EOF) 177 putc(c, obuf); 178 fclose(abuf); 179 } 180 if (ferror(obuf)) { 181 perror(tempQuit); 182 fclose(ibuf); 183 fclose(obuf); 184 fclose(fbuf); 185 return; 186 } 187 fclose(obuf); 188 close(creat(mbox, 0600)); 189 if ((obuf = fopen(mbox, "r+")) == NULL) { 190 perror(mbox); 191 fclose(ibuf); 192 fclose(fbuf); 193 return; 194 } 195 } 196 if (value("append") != NOSTR) { 197 if ((obuf = fopen(mbox, "a")) == NULL) { 198 perror(mbox); 199 fclose(fbuf); 200 return; 201 } 202 fchmod(fileno(obuf), 0600); 203 } 204 for (mp = &message[0]; mp < &message[msgCount]; mp++) 205 if (mp->m_flag & MBOX) 206 if (send(mp, obuf, saveignore, NOSTR) < 0) { 207 perror(mbox); 208 fclose(ibuf); 209 fclose(obuf); 210 fclose(fbuf); 211 return; 212 } 213 214 /* 215 * Copy the user's old mbox contents back 216 * to the end of the stuff we just saved. 217 * If we are appending, this is unnecessary. 218 */ 219 220 if (value("append") == NOSTR) { 221 rewind(ibuf); 222 c = getc(ibuf); 223 while (c != EOF) { 224 putc(c, obuf); 225 if (ferror(obuf)) 226 break; 227 c = getc(ibuf); 228 } 229 fclose(ibuf); 230 fflush(obuf); 231 } 232 trunc(obuf); 233 if (ferror(obuf)) { 234 perror(mbox); 235 fclose(obuf); 236 fclose(fbuf); 237 return; 238 } 239 fclose(obuf); 240 if (mcount == 1) 241 printf("Saved 1 message in mbox\n"); 242 else 243 printf("Saved %d messages in mbox\n", mcount); 244 245 /* 246 * Now we are ready to copy back preserved files to 247 * the system mailbox, if any were requested. 248 */ 249 250 if (p != 0) { 251 writeback(rbuf); 252 fclose(fbuf); 253 return; 254 } 255 256 /* 257 * Finally, remove his /usr/mail file. 258 * If new mail has arrived, copy it back. 259 */ 260 261 cream: 262 if (rbuf != NULL) { 263 abuf = fopen(mailname, "r+"); 264 if (abuf == NULL) 265 goto newmail; 266 while ((c = getc(rbuf)) != EOF) 267 putc(c, abuf); 268 fclose(rbuf); 269 trunc(abuf); 270 fclose(abuf); 271 alter(mailname); 272 fclose(fbuf); 273 return; 274 } 275 demail(); 276 fclose(fbuf); 277 return; 278 279 newmail: 280 printf("Thou hast new mail.\n"); 281 if (fbuf != NULL) 282 fclose(fbuf); 283 } 284 285 /* 286 * Preserve all the appropriate messages back in the system 287 * mailbox, and print a nice message indicated how many were 288 * saved. On any error, just return -1. Else return 0. 289 * Incorporate the any new mail that we found. 290 */ 291 writeback(res) 292 register FILE *res; 293 { 294 register struct message *mp; 295 register int p, c; 296 FILE *obuf; 297 298 p = 0; 299 if ((obuf = fopen(mailname, "r+")) == NULL) { 300 perror(mailname); 301 return(-1); 302 } 303 #ifndef APPEND 304 if (res != NULL) 305 while ((c = getc(res)) != EOF) 306 putc(c, obuf); 307 #endif 308 for (mp = &message[0]; mp < &message[msgCount]; mp++) 309 if ((mp->m_flag&MPRESERVE)||(mp->m_flag&MTOUCH)==0) { 310 p++; 311 if (send(mp, obuf, (struct ignoretab *)0, NOSTR) < 0) { 312 perror(mailname); 313 fclose(obuf); 314 return(-1); 315 } 316 } 317 #ifdef APPEND 318 if (res != NULL) 319 while ((c = getc(res)) != EOF) 320 putc(c, obuf); 321 #endif 322 fflush(obuf); 323 trunc(obuf); 324 if (ferror(obuf)) { 325 perror(mailname); 326 fclose(obuf); 327 return(-1); 328 } 329 if (res != NULL) 330 fclose(res); 331 fclose(obuf); 332 alter(mailname); 333 if (p == 1) 334 printf("Held 1 message in %s\n", mailname); 335 else 336 printf("Held %d messages in %s\n", p, mailname); 337 return(0); 338 } 339