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, with or without 6: * modification, are permitted provided that the following conditions 7: * are met: 8: * 1. Redistributions of source code must retain the above copyright 9: * notice, this list of conditions and the following disclaimer. 10: * 2. Redistributions in binary form must reproduce the above copyright 11: * notice, this list of conditions and the following disclaimer in the 12: * documentation and/or other materials provided with the distribution. 13: * 3. All advertising materials mentioning features or use of this software 14: * must display the following acknowledgement: 15: * This product includes software developed by the University of 16: * California, Berkeley and its contributors. 17: * 4. Neither the name of the University nor the names of its contributors 18: * may be used to endorse or promote products derived from this software 19: * without specific prior written permission. 20: * 21: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31: * SUCH DAMAGE. 32: */ 33: 34: #if !defined(lint) && defined(DOSCCS) 35: static char sccsid[] = "@(#)quit.c 5.16 (Berkeley) 2/9/91"; 36: #endif 37: 38: #include "rcv.h" 39: #include <sys/stat.h> 40: #include <sys/file.h> 41: 42: /* 43: * Rcv -- receive mail rationally. 44: * 45: * Termination processing. 46: */ 47: 48: /* 49: * The "quit" command. 50: */ 51: quitcmd() 52: { 53: /* 54: * If we are sourcing, then return 1 so execute() can handle it. 55: * Otherwise, return -1 to abort command loop. 56: */ 57: if (sourcing) 58: return 1; 59: return -1; 60: } 61: 62: /* 63: * Save all of the undetermined messages at the top of "mbox" 64: * Save all untouched messages back in the system mailbox. 65: * Remove the system mailbox, if none saved there. 66: */ 67: 68: quit() 69: { 70: int mcount, p, modify, autohold, anystat, holdbit, nohold; 71: FILE *ibuf, *obuf, *fbuf, *rbuf, *readstat, *abuf; 72: register struct message *mp; 73: register int c; 74: extern char tempQuit[], tempResid[]; 75: struct stat minfo; 76: char *mbox; 77: 78: /* 79: * If we are read only, we can't do anything, 80: * so just return quickly. 81: */ 82: if (readonly) 83: return; 84: /* 85: * If editing (not reading system mail box), then do the work 86: * in edstop() 87: */ 88: if (edit) { 89: edstop(); 90: return; 91: } 92: 93: /* 94: * See if there any messages to save in mbox. If no, we 95: * can save copying mbox to /tmp and back. 96: * 97: * Check also to see if any files need to be preserved. 98: * Delete all untouched messages to keep them out of mbox. 99: * If all the messages are to be preserved, just exit with 100: * a message. 101: */ 102: 103: fbuf = Fopen(mailname, "r"); 104: if (fbuf == NULL) 105: goto newmail; 106: flock(fileno(fbuf), LOCK_EX); 107: rbuf = NULL; 108: if (fstat(fileno(fbuf), &minfo) >= 0 && minfo.st_size > mailsize) { 109: printf("New mail has arrived.\n"); 110: rbuf = Fopen(tempResid, "w"); 111: if (rbuf == NULL || fbuf == NULL) 112: goto newmail; 113: #ifdef APPEND 114: fseek(fbuf, mailsize, 0); 115: while ((c = getc(fbuf)) != EOF) 116: (void) putc(c, rbuf); 117: #else 118: p = minfo.st_size - mailsize; 119: while (p-- > 0) { 120: c = getc(fbuf); 121: if (c == EOF) 122: goto newmail; 123: (void) putc(c, rbuf); 124: } 125: #endif 126: Fclose(rbuf); 127: if ((rbuf = Fopen(tempResid, "r")) == NULL) 128: goto newmail; 129: rm(tempResid); 130: } 131: 132: /* 133: * Adjust the message flags in each message. 134: */ 135: 136: anystat = 0; 137: autohold = value("hold") != NOSTR; 138: holdbit = autohold ? MPRESERVE : MBOX; 139: nohold = MBOX|MSAVED|MDELETED|MPRESERVE; 140: if (value("keepsave") != NOSTR) 141: nohold &= ~MSAVED; 142: for (mp = &message[0]; mp < &message[msgCount]; mp++) { 143: if (mp->m_flag & MNEW) { 144: mp->m_flag &= ~MNEW; 145: mp->m_flag |= MSTATUS; 146: } 147: if (mp->m_flag & MSTATUS) 148: anystat++; 149: if ((mp->m_flag & MTOUCH) == 0) 150: mp->m_flag |= MPRESERVE; 151: if ((mp->m_flag & nohold) == 0) 152: mp->m_flag |= holdbit; 153: } 154: modify = 0; 155: if (Tflag != NOSTR) { 156: if ((readstat = Fopen(Tflag, "w")) == NULL) 157: Tflag = NOSTR; 158: } 159: for (c = 0, p = 0, mp = &message[0]; mp < &message[msgCount]; mp++) { 160: if (mp->m_flag & MBOX) 161: c++; 162: if (mp->m_flag & MPRESERVE) 163: p++; 164: if (mp->m_flag & MODIFY) 165: modify++; 166: if (Tflag != NOSTR && (mp->m_flag & (MREAD|MDELETED)) != 0) { 167: char *id; 168: 169: if ((id = hfield("article-id", mp)) != NOSTR) 170: fprintf(readstat, "%s\n", id); 171: } 172: } 173: if (Tflag != NOSTR) 174: Fclose(readstat); 175: if (p == msgCount && !modify && !anystat) { 176: printf("Held %d message%s in %s\n", 177: p, p == 1 ? "" : "s", mailname); 178: Fclose(fbuf); 179: return; 180: } 181: if (c == 0) { 182: if (p != 0) { 183: writeback(rbuf); 184: Fclose(fbuf); 185: return; 186: } 187: goto cream; 188: } 189: 190: /* 191: * Create another temporary file and copy user's mbox file 192: * darin. If there is no mbox, copy nothing. 193: * If he has specified "append" don't copy his mailbox, 194: * just copy saveable entries at the end. 195: */ 196: 197: mbox = expand("&"); 198: mcount = c; 199: if (value("append") == NOSTR) { 200: if ((obuf = Fopen(tempQuit, "w")) == NULL) { 201: perror(tempQuit); 202: Fclose(fbuf); 203: return; 204: } 205: if ((ibuf = Fopen(tempQuit, "r")) == NULL) { 206: perror(tempQuit); 207: rm(tempQuit); 208: Fclose(obuf); 209: Fclose(fbuf); 210: return; 211: } 212: rm(tempQuit); 213: if ((abuf = Fopen(mbox, "r")) != NULL) { 214: while ((c = getc(abuf)) != EOF) 215: (void) putc(c, obuf); 216: Fclose(abuf); 217: } 218: if (ferror(obuf)) { 219: perror(tempQuit); 220: Fclose(ibuf); 221: Fclose(obuf); 222: Fclose(fbuf); 223: return; 224: } 225: Fclose(obuf); 226: close(creat(mbox, 0600)); 227: if ((obuf = Fopen(mbox, "r+")) == NULL) { 228: perror(mbox); 229: Fclose(ibuf); 230: Fclose(fbuf); 231: return; 232: } 233: } 234: if (value("append") != NOSTR) { 235: if ((obuf = Fopen(mbox, "a")) == NULL) { 236: perror(mbox); 237: Fclose(fbuf); 238: return; 239: } 240: fchmod(fileno(obuf), 0600); 241: } 242: for (mp = &message[0]; mp < &message[msgCount]; mp++) 243: if (mp->m_flag & MBOX) 244: if (send(mp, obuf, saveignore, NOSTR) < 0) { 245: perror(mbox); 246: Fclose(ibuf); 247: Fclose(obuf); 248: Fclose(fbuf); 249: return; 250: } 251: 252: /* 253: * Copy the user's old mbox contents back 254: * to the end of the stuff we just saved. 255: * If we are appending, this is unnecessary. 256: */ 257: 258: if (value("append") == NOSTR) { 259: rewind(ibuf); 260: c = getc(ibuf); 261: while (c != EOF) { 262: (void) putc(c, obuf); 263: if (ferror(obuf)) 264: break; 265: c = getc(ibuf); 266: } 267: Fclose(ibuf); 268: fflush(obuf); 269: } 270: trunc(obuf); 271: if (ferror(obuf)) { 272: perror(mbox); 273: Fclose(obuf); 274: Fclose(fbuf); 275: return; 276: } 277: Fclose(obuf); 278: if (mcount == 1) 279: printf("Saved 1 message in mbox\n"); 280: else 281: printf("Saved %d messages in mbox\n", mcount); 282: 283: /* 284: * Now we are ready to copy back preserved files to 285: * the system mailbox, if any were requested. 286: */ 287: 288: if (p != 0) { 289: writeback(rbuf); 290: Fclose(fbuf); 291: return; 292: } 293: 294: /* 295: * Finally, remove his /usr/mail file. 296: * If new mail has arrived, copy it back. 297: */ 298: 299: cream: 300: if (rbuf != NULL) { 301: abuf = Fopen(mailname, "r+"); 302: if (abuf == NULL) 303: goto newmail; 304: while ((c = getc(rbuf)) != EOF) 305: (void) putc(c, abuf); 306: Fclose(rbuf); 307: trunc(abuf); 308: Fclose(abuf); 309: alter(mailname); 310: Fclose(fbuf); 311: return; 312: } 313: demail(); 314: Fclose(fbuf); 315: return; 316: 317: newmail: 318: printf("Thou hast new mail.\n"); 319: if (fbuf != NULL) 320: Fclose(fbuf); 321: } 322: 323: /* 324: * Preserve all the appropriate messages back in the system 325: * mailbox, and print a nice message indicated how many were 326: * saved. On any error, just return -1. Else return 0. 327: * Incorporate the any new mail that we found. 328: */ 329: writeback(res) 330: register FILE *res; 331: { 332: register struct message *mp; 333: register int p, c; 334: FILE *obuf; 335: 336: p = 0; 337: if ((obuf = Fopen(mailname, "r+")) == NULL) { 338: perror(mailname); 339: return(-1); 340: } 341: #ifndef APPEND 342: if (res != NULL) 343: while ((c = getc(res)) != EOF) 344: (void) putc(c, obuf); 345: #endif 346: for (mp = &message[0]; mp < &message[msgCount]; mp++) 347: if ((mp->m_flag&MPRESERVE)||(mp->m_flag&MTOUCH)==0) { 348: p++; 349: if (send(mp, obuf, (struct ignoretab *)0, NOSTR) < 0) { 350: perror(mailname); 351: Fclose(obuf); 352: return(-1); 353: } 354: } 355: #ifdef APPEND 356: if (res != NULL) 357: while ((c = getc(res)) != EOF) 358: (void) putc(c, obuf); 359: #endif 360: fflush(obuf); 361: trunc(obuf); 362: if (ferror(obuf)) { 363: perror(mailname); 364: Fclose(obuf); 365: return(-1); 366: } 367: if (res != NULL) 368: Fclose(res); 369: Fclose(obuf); 370: alter(mailname); 371: if (p == 1) 372: printf("Held 1 message in %s\n", mailname); 373: else 374: printf("Held %d messages in %s\n", p, mailname); 375: return(0); 376: } 377: 378: /* 379: * Terminate an editing session by attempting to write out the user's 380: * file from the temporary. Save any new stuff appended to the file. 381: */ 382: edstop() 383: { 384: register int gotcha, c; 385: register struct message *mp; 386: FILE *obuf, *ibuf, *readstat; 387: struct stat statb; 388: char tempname[30]; 389: char *mktemp(); 390: 391: if (readonly) 392: return; 393: holdsigs(); 394: if (Tflag != NOSTR) { 395: if ((readstat = Fopen(Tflag, "w")) == NULL) 396: Tflag = NOSTR; 397: } 398: for (mp = &message[0], gotcha = 0; mp < &message[msgCount]; mp++) { 399: if (mp->m_flag & MNEW) { 400: mp->m_flag &= ~MNEW; 401: mp->m_flag |= MSTATUS; 402: } 403: if (mp->m_flag & (MODIFY|MDELETED|MSTATUS)) 404: gotcha++; 405: if (Tflag != NOSTR && (mp->m_flag & (MREAD|MDELETED)) != 0) { 406: char *id; 407: 408: if ((id = hfield("article-id", mp)) != NOSTR) 409: fprintf(readstat, "%s\n", id); 410: } 411: } 412: if (Tflag != NOSTR) 413: Fclose(readstat); 414: if (!gotcha || Tflag != NOSTR) 415: goto done; 416: ibuf = NULL; 417: if (stat(mailname, &statb) >= 0 && statb.st_size > mailsize) { 418: strcpy(tempname, _PATH_TMP); 419: strcat(tempname, "mboxXXXXXX"); 420: mktemp(tempname); 421: if ((obuf = Fopen(tempname, "w")) == NULL) { 422: perror(tempname); 423: relsesigs(); 424: reset(0); 425: } 426: if ((ibuf = Fopen(mailname, "r")) == NULL) { 427: perror(mailname); 428: Fclose(obuf); 429: rm(tempname); 430: relsesigs(); 431: reset(0); 432: } 433: fseek(ibuf, mailsize, 0); 434: while ((c = getc(ibuf)) != EOF) 435: (void) putc(c, obuf); 436: Fclose(ibuf); 437: Fclose(obuf); 438: if ((ibuf = Fopen(tempname, "r")) == NULL) { 439: perror(tempname); 440: rm(tempname); 441: relsesigs(); 442: reset(0); 443: } 444: rm(tempname); 445: } 446: printf("\"%s\" ", mailname); 447: fflush(stdout); 448: if ((obuf = Fopen(mailname, "r+")) == NULL) { 449: perror(mailname); 450: relsesigs(); 451: reset(0); 452: } 453: trunc(obuf); 454: c = 0; 455: for (mp = &message[0]; mp < &message[msgCount]; mp++) { 456: if ((mp->m_flag & MDELETED) != 0) 457: continue; 458: c++; 459: if (send(mp, obuf, (struct ignoretab *) NULL, NOSTR) < 0) { 460: perror(mailname); 461: relsesigs(); 462: reset(0); 463: } 464: } 465: gotcha = (c == 0 && ibuf == NULL); 466: if (ibuf != NULL) { 467: while ((c = getc(ibuf)) != EOF) 468: (void) putc(c, obuf); 469: Fclose(ibuf); 470: } 471: fflush(obuf); 472: if (ferror(obuf)) { 473: perror(mailname); 474: relsesigs(); 475: reset(0); 476: } 477: Fclose(obuf); 478: if (gotcha) { 479: rm(mailname); 480: printf("removed\n"); 481: } else 482: printf("complete\n"); 483: fflush(stdout); 484: 485: done: 486: relsesigs(); 487: }