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 * Copyright (c) 2016 by Delphix. All rights reserved. 26 */ 27 28 /* 29 * University Copyright- Copyright (c) 1982, 1986, 1988 30 * The Regents of the University of California 31 * All Rights Reserved 32 * 33 * University Acknowledgment- Portions of this document are derived from 34 * software developed by the University of California, Berkeley, and its 35 * contributors. 36 */ 37 38 #include "rcv.h" 39 #include <locale.h> 40 41 /* 42 * mailx -- a modified version of a University of California at Berkeley 43 * mail program 44 * 45 * Rcv -- receive mail rationally. 46 * 47 * Termination processing. 48 */ 49 50 static void writeback(int noremove); 51 52 #define PRIV(x) setgid(myegid), (x), setgid(myrgid); 53 54 /* 55 * Save all of the undetermined messages at the top of "mbox" 56 * Save all untouched messages back in the system mailbox. 57 * Remove the system mailbox, if none saved there. 58 */ 59 60 void 61 quit( 62 int noremove /* don't remove system mailbox, trunc it instead */ 63 ) 64 { 65 int mcount, p, modify, autohold, anystat, holdbit, nohold, fd; 66 FILE *ibuf, *obuf, *fbuf, *readstat; 67 register struct message *mp; 68 register int c; 69 char *id; 70 int appending; 71 char *mbox = Getf("MBOX"); 72 73 /* 74 * If we are read only, we can't do anything, 75 * so just return quickly. 76 */ 77 78 mcount = 0; 79 if (readonly) 80 return; 81 /* 82 * See if there any messages to save in mbox. If no, we 83 * can save copying mbox to /tmp and back. 84 * 85 * Check also to see if any files need to be preserved. 86 * Delete all untouched messages to keep them out of mbox. 87 * If all the messages are to be preserved, just exit with 88 * a message. 89 * 90 * If the luser has sent mail to himself, refuse to do 91 * anything with the mailbox, unless mail locking works. 92 */ 93 94 #ifndef CANLOCK 95 if (selfsent) { 96 printf(gettext("You have new mail.\n")); 97 return; 98 } 99 #endif 100 101 /* 102 * Adjust the message flags in each message. 103 */ 104 105 anystat = 0; 106 autohold = value("hold") != NOSTR; 107 appending = value("append") != NOSTR; 108 holdbit = autohold ? MPRESERVE : MBOX; 109 nohold = MBOXED|MBOX|MSAVED|MDELETED|MPRESERVE; 110 if (value("keepsave") != NOSTR) 111 nohold &= ~MSAVED; 112 for (mp = &message[0]; mp < &message[msgCount]; mp++) { 113 if (mp->m_flag & MNEW) { 114 receipt(mp); 115 mp->m_flag &= ~MNEW; 116 mp->m_flag |= MSTATUS; 117 } 118 if (mp->m_flag & MSTATUS) 119 anystat++; 120 if ((mp->m_flag & MTOUCH) == 0) 121 mp->m_flag |= MPRESERVE; 122 if ((mp->m_flag & nohold) == 0) 123 mp->m_flag |= holdbit; 124 } 125 modify = 0; 126 if (Tflag != NOSTR) { 127 if ((readstat = fopen(Tflag, "w")) == NULL) 128 Tflag = NOSTR; 129 } 130 for (c = 0, p = 0, mp = &message[0]; mp < &message[msgCount]; mp++) { 131 if (mp->m_flag & MBOX) 132 c++; 133 if (mp->m_flag & MPRESERVE) 134 p++; 135 if (mp->m_flag & MODIFY) 136 modify++; 137 if (Tflag != NOSTR && (mp->m_flag & (MREAD|MDELETED)) != 0) { 138 id = hfield("message-id", mp, addone); 139 if (id != NOSTR) 140 fprintf(readstat, "%s\n", id); 141 else { 142 id = hfield("article-id", mp, addone); 143 if (id != NOSTR) 144 fprintf(readstat, "%s\n", id); 145 } 146 } 147 } 148 if (Tflag != NOSTR) 149 fclose(readstat); 150 if (p == msgCount && !modify && !anystat) { 151 if (p == 1) 152 printf(gettext("Held 1 message in %s\n"), mailname); 153 else 154 printf(gettext("Held %d messages in %s\n"), p, 155 mailname); 156 return; 157 } 158 if (c == 0) { 159 writeback(noremove); 160 return; 161 } 162 163 /* 164 * Create another temporary file and copy user's mbox file 165 * therein. If there is no mbox, copy nothing. 166 * If they have specified "append" don't copy the mailbox, 167 * just copy saveable entries at the end. 168 */ 169 170 mcount = c; 171 if (!appending) { 172 if ((fd = open(tempQuit, O_RDWR|O_CREAT|O_EXCL, 0600)) < 0 || 173 (obuf = fdopen(fd, "w")) == NULL) { 174 perror(tempQuit); 175 return; 176 } 177 if ((ibuf = fopen(tempQuit, "r")) == NULL) { 178 perror(tempQuit); 179 removefile(tempQuit); 180 fclose(obuf); 181 return; 182 } 183 removefile(tempQuit); 184 if ((fbuf = fopen(mbox, "r")) != NULL) { 185 while ((c = getc(fbuf)) != EOF) 186 putc(c, obuf); 187 fclose(fbuf); 188 } 189 fflush(obuf); 190 if (fferror(obuf)) { 191 perror(tempQuit); 192 fclose(ibuf); 193 fclose(obuf); 194 return; 195 } 196 fclose(obuf); 197 if ((fd = open(mbox, O_RDWR|O_CREAT|O_TRUNC, MBOXPERM)) < 0 || 198 (obuf = fdopen(fd, "r+")) == NULL) { 199 perror(mbox); 200 fclose(ibuf); 201 return; 202 } 203 if (issysmbox) 204 touchlock(); 205 } else { /* we are appending */ 206 if ((fd = open(mbox, O_RDWR|O_CREAT, MBOXPERM)) < 0 || 207 (obuf = fdopen(fd, "a")) == NULL) { 208 perror(mbox); 209 return; 210 } 211 } 212 for (mp = &message[0]; mp < &message[msgCount]; mp++) 213 if (mp->m_flag & MBOX) { 214 if (msend(mp, obuf, (int)value("alwaysignore") ? 215 M_IGNORE|M_SAVING : M_SAVING, fputs) < 0) { 216 perror(mbox); 217 if (!appending) 218 fclose(ibuf); 219 fclose(obuf); 220 return; 221 } 222 mp->m_flag &= ~MBOX; 223 mp->m_flag |= MBOXED; 224 if (issysmbox) 225 touchlock(); 226 } 227 228 /* 229 * Copy the user's old mbox contents back 230 * to the end of the stuff we just saved. 231 * If we are appending, this is unnecessary. 232 */ 233 234 if (!appending) { 235 rewind(ibuf); 236 c = getc(ibuf); 237 while (c != EOF) { 238 putc(c, obuf); 239 if (ferror(obuf)) 240 break; 241 c = getc(ibuf); 242 } 243 fclose(ibuf); 244 fflush(obuf); 245 } 246 trunc(obuf); 247 if (fferror(obuf)) { 248 perror(mbox); 249 fclose(obuf); 250 return; 251 } 252 fclose(obuf); 253 if (mcount == 1) 254 printf(gettext("Saved 1 message in %s\n"), mbox); 255 else 256 printf(gettext("Saved %d messages in %s\n"), mcount, mbox); 257 258 /* 259 * Now we are ready to copy back preserved files to 260 * the system mailbox, if any were requested. 261 */ 262 writeback(noremove); 263 } 264 265 /* 266 * Preserve all the appropriate messages back in the system 267 * mailbox, and print a nice message indicating how many were 268 * saved. Incorporate any new mail that we found. 269 */ 270 static void 271 writeback(int noremove) 272 { 273 register struct message *mp; 274 register int p, c; 275 struct stat st; 276 FILE *obuf = 0, *fbuf = 0, *rbuf = 0; 277 void (*fhup)(int), (*fint)(int), (*fquit)(int); 278 int fd = -1; 279 280 fhup = sigset(SIGHUP, SIG_IGN); 281 fint = sigset(SIGINT, SIG_IGN); 282 fquit = sigset(SIGQUIT, SIG_IGN); 283 284 if (issysmbox) 285 lockmail(); 286 if ((fbuf = fopen(mailname, "r+")) == NULL) { 287 perror(mailname); 288 goto die; 289 } 290 if (!issysmbox) 291 lock(fbuf, "r+", 1); 292 fstat(fileno(fbuf), &st); 293 if (st.st_size > mailsize) { 294 printf(gettext("New mail has arrived.\n")); 295 snprintf(tempResid, PATHSIZE, "%s/:saved/%s", maildir, myname); 296 PRIV(rbuf = fopen(tempResid, "w+")); 297 if (rbuf == NULL) { 298 snprintf(tempResid, PATHSIZE, "/tmp/Rq%-ld", mypid); 299 fd = open(tempResid,O_RDWR|O_CREAT|O_EXCL, 0600); 300 PRIV(rbuf = fdopen(fd, "w+")); 301 if (rbuf == NULL) { 302 snprintf(tempResid, PATHSIZE, 303 "%s/:saved/%s", maildir, 304 myname); 305 perror(tempResid); 306 fclose(fbuf); 307 goto die; 308 } 309 } 310 #ifdef APPEND 311 fseek(fbuf, mailsize, 0); 312 while ((c = getc(fbuf)) != EOF) 313 putc(c, rbuf); 314 #else 315 p = st.st_size - mailsize; 316 while (p-- > 0) { 317 c = getc(fbuf); 318 if (c == EOF) { 319 perror(mailname); 320 fclose(fbuf); 321 goto die; 322 } 323 putc(c, rbuf); 324 } 325 #endif 326 fclose(fbuf); 327 fseek(rbuf, 0L, 0); 328 if (issysmbox) 329 touchlock(); 330 } 331 332 if ((obuf = fopen(mailname, "r+")) == NULL) { 333 perror(mailname); 334 goto die; 335 } 336 #ifndef APPEND 337 if (rbuf != NULL) 338 while ((c = getc(rbuf)) != EOF) 339 putc(c, obuf); 340 #endif 341 p = 0; 342 for (mp = &message[0]; mp < &message[msgCount]; mp++) 343 if ((mp->m_flag&MPRESERVE)||(mp->m_flag&MTOUCH)==0) { 344 p++; 345 if (msend(mp, obuf, 0, fputs) < 0) { 346 perror(mailname); 347 goto die; 348 } 349 if (issysmbox) 350 touchlock(); 351 } 352 #ifdef APPEND 353 if (rbuf != NULL) 354 while ((c = getc(rbuf)) != EOF) 355 putc(c, obuf); 356 #endif 357 fflush(obuf); 358 trunc(obuf); 359 if (fferror(obuf)) { 360 perror(mailname); 361 goto die; 362 } 363 alter(mailname); 364 if (p) { 365 if (p == 1) 366 printf(gettext("Held 1 message in %s\n"), mailname); 367 else 368 printf(gettext("Held %d messages in %s\n"), p, 369 mailname); 370 } 371 372 if (!noremove && (fsize(obuf) == 0) && (value("keep") == NOSTR)) { 373 if (stat(mailname, &st) >= 0) 374 PRIV(delempty(st.st_mode, mailname)); 375 } 376 377 die: 378 if (rbuf) { 379 fclose(rbuf); 380 PRIV(removefile(tempResid)); 381 } 382 if (obuf) 383 fclose(obuf); 384 if (issysmbox) 385 unlockmail(); 386 sigset(SIGHUP, fhup); 387 sigset(SIGINT, fint); 388 sigset(SIGQUIT, fquit); 389 } 390 391 void 392 lockmail(void) 393 { 394 PRIV(maillock(lockname,10)); 395 } 396 397 void 398 unlockmail(void) 399 { 400 PRIV(mailunlock()); 401 } 402