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