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