int pop_updt (POP *p) { FILE * md; /* Stream pointer for the user's maildrop */ int mfd; /* File descriptor for above */ char buffer[BUFSIZ]; /* Read buffer */ MsgInfoList * mp; /* Pointer to message info list */ int msg_num; /* Current message counter */ int status_written; /* Status header field written */ int nchar; /* Bytes read/written */ long offset; /* New mail offset */ int blank_line; #ifdef DEBUG if (p->debug) { pop_log(p,POP_DEBUG,"Performing maildrop update..."); pop_log(p,POP_DEBUG,"Checking to see if all messages were deleted"); } #endif /* DEBUG */ if(IS_MAILDIR(p)) return pop_maildir_update(p); if (p->msgs_deleted == p->msg_count) { /* Truncate before close, to avoid race condition, DO NOT UNLINK! Another process may have opened, and not yet tried to lock */ ftruncate ((int)fileno(p->drop),0); fclose(p->drop) ; return (POP_SUCCESS); } #ifdef DEBUG if (p->debug) pop_log(p,POP_DEBUG,"Opening mail drop \"%s\"",p->drop_name); #endif /* DEBUG */ /* Open the user's real maildrop */ if ((mfd = open(p->drop_name,O_RDWR|O_CREAT,0600)) == -1 || (md = fdopen(mfd,"r+")) == NULL) { return pop_msg(p,POP_FAILURE,standard_error); } /* Lock the user's real mail drop */ if ( flock(mfd, LOCK_EX) == -1 ) { fclose(md) ; return pop_msg(p,POP_FAILURE, "flock: '%s': %s", p->temp_drop, strerror(errno)); } /* Go to the right places */ offset = lseek((int)fileno(p->drop),0,SEEK_END) ; /* Append any messages that may have arrived during the session to the temporary maildrop */ while ((nchar=read(mfd,buffer,BUFSIZ)) > 0) if ( nchar != write((int)fileno(p->drop),buffer,nchar) ) { nchar = -1; break ; } if ( nchar != 0 ) { fclose(md) ; ftruncate((int)fileno(p->drop),(int)offset) ; fclose(p->drop) ; return pop_msg(p,POP_FAILURE,standard_error); } rewind(md); lseek(mfd,0,SEEK_SET); ftruncate(mfd,0) ; /* Synch stdio and the kernel for the POP drop */ rewind(p->drop); lseek((int)fileno(p->drop),0,SEEK_SET); /* Transfer messages not flagged for deletion from the temporary maildrop to the new maildrop */ #ifdef DEBUG if (p->debug) pop_log(p,POP_DEBUG,"Creating new maildrop \"%s\" from \"%s\"", p->drop_name,p->temp_drop); #endif /* DEBUG */ for (msg_num = 0; msg_num < p->msg_count; ++msg_num) { int doing_body; /* Get a pointer to the message information list */ mp = &p->mlp[msg_num]; if (mp->flags & DEL_FLAG) { #ifdef DEBUG if(p->debug) pop_log(p,POP_DEBUG, "Message %d flagged for deletion.",mp->number); #endif /* DEBUG */ continue; } fseek(p->drop,mp->offset,0); #ifdef DEBUG if(p->debug) pop_log(p,POP_DEBUG,"Copying message %d.",mp->number); #endif /* DEBUG */ blank_line = 1; for(status_written = doing_body = 0 ; fgets(buffer,MAXMSGLINELEN,p->drop);) { if (doing_body == 0) { /* Header */ /* Update the message status */ if (strncasecmp(buffer,"Status:",7) == 0) { if (mp->flags & RETR_FLAG) fputs("Status: RO\n",md); else fputs(buffer, md); status_written++; continue; } /* A blank line signals the end of the header. */ if (*buffer == '\n') { doing_body = 1; if (status_written == 0) { if (mp->flags & RETR_FLAG) fputs("Status: RO\n\n",md); else fputs("Status: U\n\n",md); } else fputs ("\n", md); continue; } /* Save another header line */ fputs (buffer, md); } else { /* Body */ if (blank_line && strncmp(buffer,"From ",5) == 0) break; fputs (buffer, md); blank_line = (*buffer == '\n'); } } } /* flush and check for errors now! The new mail will writen without stdio, since we need not separate messages */ fflush(md) ; if (ferror(md)) { ftruncate(mfd,0) ; fclose(md) ; fclose(p->drop) ; return pop_msg(p,POP_FAILURE,standard_error); } /* Go to start of new mail if any */ lseek((int)fileno(p->drop),offset,SEEK_SET); while((nchar=read((int)fileno(p->drop),buffer,BUFSIZ)) > 0) if ( nchar != write(mfd,buffer,nchar) ) { nchar = -1; break ; } if ( nchar != 0 ) { ftruncate(mfd,0) ; fclose(md) ; fclose(p->drop) ; return pop_msg(p,POP_FAILURE,standard_error); } /* Close the maildrop and empty temporary maildrop */ fclose(md); ftruncate((int)fileno(p->drop),0); fclose(p->drop); return(pop_quit(p)); }
static int popmail (char *mailbox, char *outfile, int preserve, char *password, int reverse_order) { int nmsgs, nbytes; register int i; int mbfi; FILE *mbf; char *getenv (const char *); popserver server; int start, end, increment; char *user, *hostname; user = mailbox; if ((hostname = strchr (mailbox, ':'))) *hostname++ = '\0'; server = pop_open (hostname, user, password, POP_NO_GETPASS); if (! server) { error ("Error connecting to POP server: %s", pop_error, 0); return EXIT_FAILURE; } if (pop_stat (server, &nmsgs, &nbytes)) { error ("Error getting message count from POP server: %s", pop_error, 0); return EXIT_FAILURE; } if (!nmsgs) { pop_close (server); return EXIT_SUCCESS; } mbfi = open (outfile, O_WRONLY | O_CREAT | O_EXCL, 0666); if (mbfi < 0) { pop_close (server); error ("Error in open: %s, %s", strerror (errno), outfile); return EXIT_FAILURE; } if (fchown (mbfi, getuid (), -1) != 0) { int fchown_errno = errno; struct stat st; if (fstat (mbfi, &st) != 0 || st.st_uid != getuid ()) { pop_close (server); error ("Error in fchown: %s, %s", strerror (fchown_errno), outfile); return EXIT_FAILURE; } } if ((mbf = fdopen (mbfi, "wb")) == NULL) { pop_close (server); error ("Error in fdopen: %s", strerror (errno), 0); close (mbfi); unlink (outfile); return EXIT_FAILURE; } if (reverse_order) { start = nmsgs; end = 1; increment = -1; } else { start = 1; end = nmsgs; increment = 1; } for (i = start; i * increment <= end * increment; i += increment) { mbx_delimit_begin (mbf); if (pop_retr (server, i, mbf) != OK) { error ("%s", Errmsg, 0); close (mbfi); return EXIT_FAILURE; } mbx_delimit_end (mbf); fflush (mbf); if (ferror (mbf)) { error ("Error in fflush: %s", strerror (errno), 0); pop_close (server); close (mbfi); return EXIT_FAILURE; } } /* On AFS, a call to write only modifies the file in the local * workstation's AFS cache. The changes are not written to the server * until a call to fsync or close is made. Users with AFS home * directories have lost mail when over quota because these checks were * not made in previous versions of movemail. */ #ifdef BSD_SYSTEM if (fsync (mbfi) < 0) { error ("Error in fsync: %s", strerror (errno), 0); return EXIT_FAILURE; } #endif if (close (mbfi) == -1) { error ("Error in close: %s", strerror (errno), 0); return EXIT_FAILURE; } if (! preserve) for (i = 1; i <= nmsgs; i++) { if (pop_delete (server, i)) { error ("Error from POP server: %s", pop_error, 0); pop_close (server); return EXIT_FAILURE; } } if (pop_quit (server)) { error ("Error from POP server: %s", pop_error, 0); return EXIT_FAILURE; } return EXIT_SUCCESS; }
static int popmail (char *mailbox, char *outfile, int preserve, char *password, int reverse_order) { int nmsgs, nbytes; register int i; int mbfi; FILE *mbf; popserver server; int start, end, increment; char *user, *hostname; user = mailbox; if ((hostname = strchr (mailbox, ':'))) *hostname++ = '\0'; server = pop_open (hostname, user, password, POP_NO_GETPASS); if (! server) { error ("Error connecting to POP server: %s", pop_error, 0); return EXIT_FAILURE; } if (pop_stat (server, &nmsgs, &nbytes)) { error ("Error getting message count from POP server: %s", pop_error, 0); return EXIT_FAILURE; } if (!nmsgs) { pop_close (server); return EXIT_SUCCESS; } mbfi = open (outfile, O_WRONLY | O_BINARY | O_CREAT | O_EXCL, 0666); if (mbfi < 0) { pop_close (server); error ("Error in open: %s, %s", strerror (errno), outfile); return EXIT_FAILURE; } if (fchown (mbfi, getuid (), -1) != 0) { int fchown_errno = errno; struct stat st; if (fstat (mbfi, &st) != 0 || st.st_uid != getuid ()) { pop_close (server); error ("Error in fchown: %s, %s", strerror (fchown_errno), outfile); return EXIT_FAILURE; } } if ((mbf = fdopen (mbfi, "wb")) == NULL) { pop_close (server); error ("Error in fdopen: %s", strerror (errno), 0); close (mbfi); unlink (outfile); return EXIT_FAILURE; } if (reverse_order) { start = nmsgs; end = 1; increment = -1; } else { start = 1; end = nmsgs; increment = 1; } for (i = start; i * increment <= end * increment; i += increment) { mbx_delimit_begin (mbf); if (pop_retr (server, i, mbf) != OK) { error ("%s", Errmsg, 0); close (mbfi); return EXIT_FAILURE; } mbx_delimit_end (mbf); fflush (mbf); if (ferror (mbf)) { error ("Error in fflush: %s", strerror (errno), 0); pop_close (server); close (mbfi); return EXIT_FAILURE; } } if (fsync (mbfi) != 0 && errno != EINVAL) { error ("Error in fsync: %s", strerror (errno), 0); close (mbfi); return EXIT_FAILURE; } if (close (mbfi) != 0) { error ("Error in close: %s", strerror (errno), 0); return EXIT_FAILURE; } if (! preserve) for (i = 1; i <= nmsgs; i++) { if (pop_delete (server, i)) { error ("Error from POP server: %s", pop_error, 0); pop_close (server); return EXIT_FAILURE; } } if (pop_quit (server)) { error ("Error from POP server: %s", pop_error, 0); return EXIT_FAILURE; } return EXIT_SUCCESS; }