1: /* 2: * Copyright (c) 1989 Regents of the University of California. 3: * All rights reserved. The Berkeley software License Agreement 4: * specifies the terms and conditions for redistribution. 5: */ 6: 7: #if !defined(lint) && defined(lint) 8: static char copyright[] = "Copyright (c) 1990 Regents of the University of California.\nAll rights reserved.\n"; 9: static char SccsId[] = "@(#)@(#)pop_updt.c 2.3.1 (2.11BSD) 1996/3/21"; 10: #endif not lint 11: 12: #include <errno.h> 13: #include <stdio.h> 14: #include <sys/types.h> 15: #include <strings.h> 16: #include <sys/stat.h> 17: #include <sys/file.h> 18: #include "popper.h" 19: 20: static char standard_error[] = 21: "Error error updating primary drop. Mailbox unchanged"; 22: 23: /* 24: * updt: Apply changes to a user's POP maildrop 25: */ 26: 27: int pop_updt (p) 28: POP * p; 29: { 30: FILE * md; /* Stream pointer for 31: the user's maildrop */ 32: int mfd; /* File descriptor for 33: above */ 34: char buffer[BUFSIZ]; /* Read buffer */ 35: 36: MsgInfoList * mp; /* Pointer to message 37: info list */ 38: register int msg_num; /* Current message 39: counter */ 40: register int status_written; /* Status header field 41: written */ 42: int nchar; /* Bytes read/written */ 43: 44: long offset; /* New mail offset */ 45: 46: #ifdef DEBUG 47: if (p->debug) { 48: pop_log(p,POP_DEBUG,"Performing maildrop update..."); 49: pop_log(p,POP_DEBUG,"Checking to see if all messages were deleted"); 50: } 51: #endif DEBUG 52: 53: if (p->msgs_deleted == p->msg_count) { 54: /* Truncate before close, to avoid race condition, DO NOT UNLINK! 55: Another process may have opened, and not yet tried to lock */ 56: (void)ftruncate ((int)fileno(p->drop),0L); 57: (void)fclose(p->drop) ; 58: return (POP_SUCCESS); 59: } 60: 61: #ifdef DEBUG 62: if (p->debug) 63: pop_log(p,POP_DEBUG,"Opening mail drop \"%s\"",p->drop_name); 64: #endif DEBUG 65: 66: /* Open the user's real maildrop */ 67: if ((mfd = open(p->drop_name,O_RDWR|O_CREAT,0600)) == -1 || 68: (md = fdopen(mfd,"r+")) == NULL) { 69: return pop_msg(p,POP_FAILURE,standard_error); 70: } 71: 72: /* Lock the user's real mail drop */ 73: if ( flock(mfd,LOCK_EX) == -1 ) { 74: (void)fclose(md) ; 75: return pop_msg(p,POP_FAILURE, "flock: '%s': %s", p->temp_drop, 76: strerror(errno)); 77: } 78: 79: /* Go to the right places */ 80: offset = lseek((int)fileno(p->drop),0L,L_XTND) ; 81: 82: /* Append any messages that may have arrived during the session 83: to the temporary maildrop */ 84: while ((nchar=read(mfd,buffer,BUFSIZ)) > 0) 85: if ( nchar != write((int)fileno(p->drop),buffer,nchar) ) { 86: nchar = -1; 87: break ; 88: } 89: if ( nchar != 0 ) { 90: (void)fclose(md) ; 91: (void)ftruncate((int)fileno(p->drop),offset) ; 92: (void)fclose(p->drop) ; 93: return pop_msg(p,POP_FAILURE,standard_error); 94: } 95: 96: rewind(md); 97: (void)ftruncate(mfd,0L) ; 98: 99: /* Synch stdio and the kernel for the POP drop */ 100: rewind(p->drop); 101: (void)lseek((int)fileno(p->drop),0L,L_SET); 102: 103: /* Transfer messages not flagged for deletion from the temporary 104: maildrop to the new maildrop */ 105: #ifdef DEBUG 106: if (p->debug) 107: pop_log(p,POP_DEBUG,"Creating new maildrop \"%s\" from \"%s\"", 108: p->drop_name,p->temp_drop); 109: #endif DEBUG 110: 111: for (msg_num = 0; msg_num < p->msg_count; ++msg_num) { 112: 113: int doing_body; 114: 115: /* Get a pointer to the message information list */ 116: mp = &p->mlp[msg_num]; 117: 118: if (mp->del_flag) { 119: #ifdef DEBUG 120: if(p->debug) 121: pop_log(p,POP_DEBUG, 122: "Message %u flagged for deletion.",mp->number); 123: #endif DEBUG 124: continue; 125: } 126: 127: (void)fseek(p->drop,mp->offset,0); 128: 129: #ifdef DEBUG 130: if(p->debug) 131: pop_log(p,POP_DEBUG,"Copying message %u.",mp->number); 132: #endif DEBUG 133: for(status_written = doing_body = 0 ; 134: fgets(buffer,MAXMSGLINELEN,p->drop);) { 135: 136: if (doing_body == 0) { /* Header */ 137: 138: /* Update the message status */ 139: if (strncasecmp(buffer,"Status:",7) == 0) { 140: if (mp->retr_flag) 141: (void)fputs("Status: RO\n",md); 142: else 143: (void)fputs(buffer, md); 144: status_written++; 145: continue; 146: } 147: /* A blank line signals the end of the header. */ 148: if (*buffer == '\n') { 149: doing_body = 1; 150: if (status_written == 0) { 151: if (mp->retr_flag) 152: (void)fputs("Status: RO\n\n",md); 153: else 154: (void)fputs("Status: U\n\n",md); 155: } 156: else (void)fputs ("\n", md); 157: continue; 158: } 159: /* Save another header line */ 160: (void)fputs (buffer, md); 161: } 162: else { /* Body */ 163: if (strncmp(buffer,"From ",5) == 0) break; 164: (void)fputs (buffer, md); 165: } 166: } 167: } 168: 169: /* flush and check for errors now! The new mail will writen 170: without stdio, since we need not separate messages */ 171: 172: (void)fflush(md) ; 173: if (ferror(md)) { 174: (void)ftruncate(mfd,0L) ; 175: (void)fclose(md) ; 176: (void)fclose(p->drop) ; 177: return pop_msg(p,POP_FAILURE,standard_error); 178: } 179: 180: /* Go to start of new mail if any */ 181: (void)lseek((int)fileno(p->drop),offset,L_SET); 182: 183: while((nchar=read((int)fileno(p->drop),buffer,BUFSIZ)) > 0) 184: if ( nchar != write(mfd,buffer,nchar) ) { 185: nchar = -1; 186: break ; 187: } 188: if ( nchar != 0 ) { 189: (void)ftruncate(mfd,0L) ; 190: (void)fclose(md) ; 191: (void)fclose(p->drop) ; 192: return pop_msg(p,POP_FAILURE,standard_error); 193: } 194: 195: /* Close the maildrop and empty temporary maildrop */ 196: (void)fclose(md); 197: (void)ftruncate((int)fileno(p->drop),0L); 198: (void)fclose(p->drop); 199: 200: return(pop_quit(p)); 201: }