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