This is pop_updt.c in view mode; [Download] [Up]
/*
* Copyright (c) 1989 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
*/
/*
* Copyright (c) 1997 by Qualcomm Incorporated.
*/
#include <config.h>
#include <errno.h>
#include <stdio.h>
#include <sys/types.h>
# include <string.h>
#if HAVE_UNISTD_H
# include <unistd.h>
#endif
#include <flock.h>
#if HAVE_STRINGS_H
# include <strings.h>
#endif
#include <sys/stat.h>
#include <sys/file.h>
#include <popper.h>
#ifdef MAILOCK
# include <maillock.h>
#endif
#if !defined(L_XTND)
#define L_XTND SEEK_END
#endif
#ifndef L_SET
#define L_SET SEEK_SET
#endif
#if defined(HAVE_UNISTD_H)
#include <unistd.h>
#endif
extern int errno;
#define BBSIZE 4096
static char standard_error[] =
"Error updating primary drop. Mail left in temporary maildrop (%d)";
/*
* updt: Apply changes to a user's POP maildrop
*/
int pop_updt (p)
POP * p;
{
FILE * md; /* Stream pointer for
the user's maildrop */
int mfd; /* File descriptor for
above */
char buffer[BBSIZE]; /* Read buffer */
char uidl_buf[128]; /* UIDL header */
MsgInfoList * mp; /* Pointer to message
info list */
register int msg_num; /* Current message
counter */
register int status_written; /* Status header field
written */
int nchar; /* Bytes read/written */
long offset; /* New mail offset */
char * result; /* fget and fputs status */
int save_errno; /* Save the error value we
are trying to print. */
struct stat mybuf; /* For fstat() */
#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
if (p->stats) {
pop_log(p,POP_PRIORITY,"Stats: %s %d %d %d %d",
p->user, p->msgs_deleted, p->bytes_deleted,
p->msg_count - p->msgs_deleted,
p->drop_size - p->bytes_deleted);
}
if (p->server_mode) {
if (!p->dirty) {
#ifndef KEEP_TEMP_DROP
/* Added code in pop_dropcopy.c makes unlink ok now. */
/* s-dorner@uiuc.edu, 12/91 */
(void)unlink(p->temp_drop);
#endif
return(POP_SUCCESS);
}
#ifdef MAILOCK
/* Use SVR4 mail locking */
if (maillock(p->user, 1) != 0)
return(pop_msg(p,POP_FAILURE,"maillock: '%s' (%d)",p->temp_drop,errno));
#endif
}
if (p->server_mode)
fstat(fileno(p->drop), &mybuf);
if ((p->msgs_deleted == p->msg_count) &&
(!p->server_mode || (mybuf.st_size == p->spool_end))) {
/* Truncate before close, to avoid race condition. */
(void)ftruncate (fileno(p->drop), (OFF_T)0);
#ifndef KEEP_TEMP_DROP
/* Added code in pop_dropcopy.c makes unlink ok now. */
/* s-dorner@uiuc.edu, 12/91 */
(void)unlink(p->temp_drop);
#endif
(void)fclose(p->drop);
if (p->server_mode) {
(void)fclose(p->hold);
#ifdef MAILOCK
mailunlock();
#endif
}
return (POP_SUCCESS);
}
if (!p->server_mode) {
#ifdef DEBUG
if (p->debug)
pop_log(p,POP_DEBUG,"Opening mail drop \"%s\"", p->drop_name);
#endif
#ifdef MAILOCK
/* Use SVR4 mail locking */
if (maillock(p->user, 1) != 0)
return(pop_msg(p,POP_FAILURE,"maillock: '%s' (%d)",
p->drop_name, errno));
#endif
/* Open the user's real maildrop */
if ((mfd = open(p->drop_name,O_RDWR|O_CREAT,0660)) == -1 ||
(md = fdopen(mfd,"r+")) == NULL) {
#ifdef MAILOCK
mailunlock();
#endif
return pop_msg(p,POP_FAILURE, standard_error, errno);
}
} else {
#ifdef MAILOCK
/* Use SVR4 mail locking */
if (maillock(p->user, 1) != 0)
return(pop_msg(p,POP_FAILURE,"maillock: '%s' (%d)",
p->drop_name, errno));
#endif
mfd = fileno(p->drop);
}
/* Lock the user's real mail drop */
if ( flock(mfd,LOCK_EX) == -1 )
{
(void)fclose(md) ;
#ifdef MAILOCK
mailunlock();
#endif
return pop_msg(p,POP_FAILURE, "flock: '%s': %s (%d)", p->drop_name,
(errno < sys_nerr) ? sys_errlist[errno] : "", errno);
}
if (!p->server_mode) {
/* Go to the right places */
(void)fseek(p->drop, 0, SEEK_END);
offset = ftell(p->drop);
/* Append any messages that may have arrived during the session
to the temporary maildrop */
while ((nchar = read(mfd, buffer, BBSIZE)) > 0)
if ( nchar != write(fileno(p->drop), buffer, nchar) ) {
nchar = -1;
break ;
}
if ( nchar != 0 ) {
save_errno = errno;
(void)fclose(md) ;
#ifdef MAILOCK
mailunlock();
#endif
(void)ftruncate(fileno(p->drop), (OFF_T)offset);
(void)fclose(p->drop) ;
#ifdef EDQUOT
if (save_errno == EDQUOT) {
pop_msg(p, POP_FAILURE,
"Overquota: appending messages from mailspool to temporary drop (%d)",
errno);
} else
#endif
pop_msg(p, POP_FAILURE,
"Error appending messages from mailspool to temporary drop (%d)",
errno);
}
fflush(md);
rewind(md);
(void)ftruncate(mfd, (OFF_T)0) ;
(void)lseek(mfd, (OFF_T)0, L_SET);
/* Synch stdio and the kernel for the POP drop */
rewind(p->drop);
(void)lseek(fileno(p->drop), (OFF_T)0, L_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
} else {
/* Move this stuff later */
fstat(fileno(p->drop), &mybuf);
md = p->hold; /* Really the temp drop */
mfd = fileno(md);
}
if (!p->server_mode || (p->msgs_deleted != p->msg_count)) {
for (msg_num = 0; msg_num < p->msg_count; ++msg_num) {
int inheader;
int body_lines;
/* Get a pointer to the message information list */
mp = &p->mlp[msg_num];
if (mp->del_flag) {
#ifdef DEBUG
if(p->debug)
pop_log(p,POP_DEBUG,
"Message %d flagged for deletion.",mp->number);
#endif
continue;
}
(void)fseek(p->drop, mp->offset, SEEK_SET);
#ifdef DEBUG
if(p->debug)
pop_log(p,POP_DEBUG,"Copying message %d.",mp->number);
#endif
/* Put the From line separator */
fgets(buffer, MAXMSGLINELEN, p->drop);
if (fputs(buffer, md) == EOF)
break;
sprintf(buffer, "%s %s", "X-UIDL:", mp->uidl_str);
if (fputs(buffer, md) == EOF)
break;
for(status_written=0,inheader=1;
fgets(buffer,MAXMSGLINELEN,p->drop);) {
if (inheader) { /* Header */
/* A blank line signals the end of the header. */
if (*buffer == '\n') {
#ifndef NO_STATUS
if (status_written == 0) {
if (mp->retr_flag) {
(void)sprintf(buffer, "Status: RO\n\n");
} else {
(void)sprintf(buffer, "Status: U\n\n");
}
}
#endif
inheader = 0;
body_lines = 1;
status_written = 0;
} else if (!strncasecmp(buffer, "X-UIDL:", 7)) {
continue; /* Skip all existing UIDL lines */
} else if (!strncasecmp(buffer,"Status:", 7)) {
/* Update the message status */
if (mp->retr_flag)
sprintf(buffer, "Status: RO\n");
status_written++;
}
/* Save another header line */
if (fputs(buffer, md) == EOF)
break;
} else { /* Body */
if (++body_lines > mp->body_lines)
break;
if (fputs(buffer, md) == EOF)
break;
}
}
if (ferror(md)) {
break;
}
if (p->mmdf_separator) {
fputs(p->mmdf_separator, md);
}
}
/* flush and check for errors now! The new mail will writen
without stdio, since we need not separate messages */
if (ferror(md)) {
save_errno = errno;
(void)ftruncate(mfd, (OFF_T)0) ;
(void)fclose(md) ;
#ifdef MAILOCK
mailunlock();
#endif
(void)fclose(p->drop) ;
#ifdef EDQUOT
if (save_errno == EDQUOT)
return pop_msg(p, POP_FAILURE,
"Overquota copying messages to Mailspool. Temp drop unchanged (%d)",
save_errno);
else
#endif
return pop_msg(p,POP_FAILURE, standard_error, errno);
}
(void)fflush(md) ;
if (ferror(md)) {
int save_error = errno;
(void)ftruncate(mfd, (OFF_T)0) ;
(void)close(mfd) ;
#ifdef MAILOCK
mailunlock();
#endif
(void)fclose(p->drop);
#ifdef EDQUOT
if (save_errno == EDQUOT)
return pop_msg(p, POP_FAILURE,
"Overquota copying messages to Mailspool. Temp drop unchanged (%d)",
save_errno);
else
#endif
return pop_msg(p,POP_FAILURE, standard_error, errno);
}
} /* p->msgs_deleted != p->msg_count */
if (p->server_mode) {
if (mybuf.st_size > p->spool_end) {
/* Go to the right places */
(void)lseek(fileno(p->drop), (OFF_T)p->spool_end, L_SET);
/* Append any messages that may have arrived during the session
to the temporary maildrop */
while ((nchar = read(fileno(p->drop), buffer, BBSIZE)) > 0)
if ( nchar != write(mfd, buffer, nchar) ) {
nchar = -1;
break ;
}
if ( nchar != 0 ) {
#ifdef MAILOCK
mailunlock();
#endif
(void)ftruncate(mfd, (OFF_T)0) ;
(void)close(mfd) ;
#ifdef EDQUOT
if (errno == EDQUOT) {
pop_msg(p, POP_FAILURE,
"Overquota: appending messages from mailspool to temporary drop (%d)",
errno);
} else
#endif
pop_msg(p, POP_FAILURE,
"Error appending messages from mailspool to temporary drop (%d)",
errno);
}
}
rewind(p->drop);
(void)ftruncate(fileno(p->drop), (OFF_T)0);
(void)lseek(fileno(p->drop), (OFF_T)0, L_SET);
(void)lseek(mfd, (OFF_T)0, L_SET);
while ((nchar = read(mfd, buffer, BBSIZE)) > 0)
if (nchar != write(fileno(p->drop), buffer, nchar)) {
nchar = -1;
break ;
}
if ( nchar != 0 ) {
(void)ftruncate(fileno(p->drop), (OFF_T)0);
(void)fclose(p->drop);
#ifdef MAILOCK
mailunlock();
#endif
(void)fclose(md);
#ifdef EDQUOT
if (errno == EDQUOT) {
pop_msg(p, POP_FAILURE,
"Overquota: copying messages back to mailspool (%d)", errno);
} else
#endif
pop_msg(p, POP_FAILURE,
"Error appending messages from temporary drop to mailspool (%d)",
errno);
}
(void)fclose(md);
#ifdef MAILOCK
mailunlock();
#endif
(void)ftruncate(mfd, (OFF_T)0);
#ifndef KEEP_TEMP_DROP
/* Added code in pop_dropcopy.c makes unlink ok now. */
/* s-dorner@uiuc.edu, 12/91 */
(void)fclose(p->drop);
#endif
(void)unlink(p->temp_drop);
} else {
/* Go to start of new mail if any */
(void)lseek(fileno(p->drop), (OFF_T)offset, L_SET);
/* Copy over any new mail that arrived while processing the pop drop */
while((nchar = read(fileno(p->drop), buffer, BBSIZE)) > 0)
if ( nchar != write(mfd, buffer, nchar) ) {
nchar = -1;
break ;
}
if ( nchar != 0 ) {
int save_error = errno;
(void)ftruncate(mfd, (OFF_T)0) ;
(void)fclose(md) ;
#ifdef MAILOCK
mailunlock();
#endif
(void)fclose(p->drop) ;
#ifdef EDQUOT
if (save_errno == EDQUOT)
return pop_msg(p, POP_FAILURE,
"Overquota copying messages to Mailspool. Temp drop unchanged (%d)",
save_errno);
else
#endif
return pop_msg(p,POP_FAILURE, standard_error, errno);
}
/* Close the maildrop and empty temporary maildrop */
(void)fclose(md);
#ifdef MAILOCK
mailunlock();
#endif
(void)ftruncate(fileno(p->drop), (OFF_T)0);
#ifndef KEEP_TEMP_DROP
/* Added code in pop_dropcopy.c makes unlink ok now. */
/* s-dorner@uiuc.edu, 12/91 */
(void)unlink(p->temp_drop);
#endif
(void)fclose(p->drop);
}
return(pop_quit(p));
}
int pop_restore (p)
POP *p;
{
FILE *md;
int mfd;
char buffer[BBSIZE];
int nchar;
long offset;
int save_errno;
#ifdef DEBUG
if (p->debug)
pop_log(p,POP_DEBUG,"Performing maildrop restoration...");
#endif
if (p->server_mode)
{
#ifndef KEEP_TEMP_DROP
(void) unlink(p->temp_drop);
#endif
return(POP_SUCCESS);
}
#ifdef DEBUG
if (p->debug)
pop_log(p,POP_DEBUG,"Opening mail drop \"%s\"", p->drop_name);
#endif
#ifdef MAILOCK
if (maillock(p->user, 1))
return pop_msg(p,POP_FAILURE,"maillock: '%s' (%d)",p->drop_name, errno);
#endif
if ((mfd = open(p->drop_name,O_RDWR | O_CREAT,0660)) == -1 ||
(md = fdopen(mfd, "r+")) == NULL)
{
#ifdef MAILOCK
mailunlock();
#endif
return pop_msg(p,POP_FAILURE, standard_error, errno);
}
if (flock(mfd, LOCK_EX) == -1)
{
(void) fclose(md);
#ifdef MAILOCK
mailunlock();
#endif
return pop_msg(p,POP_FAILURE, "flock: '%s': %s (%d)", p->drop_name,
(errno < sys_nerr) ? sys_errlist[errno]: "", errno);
}
(void)fseek(p->drop, 0, SEEK_END);
offset = ftell(p->drop);
/* Append any messages that may have arrived during the session
to the temporary mail drop */
while ((nchar = read(mfd,buffer, BBSIZE)) > 0)
if ( nchar != write(fileno(p->drop), buffer, nchar))
{
nchar = -1;
break;
}
if ( nchar != 0)
{
save_errno = errno;
(void) fclose(md);
#ifdef MAILOCK
mailunlock();
#endif
(void)ftruncate(fileno(p->drop), (OFF_T)offset);
(void)fclose(p->drop);
#ifdef EDQUOT
if (save_errno == EDQUOT)
{
pop_msg(p, POP_FAILURE,
"Overquota: appending messages to temporary drop (%d)",
errno);
}
else
#endif
pop_msg(p, POP_FAILURE,
"Error appending messages from mailspool to temporary drop (%d)",
errno);
}
fflush(md);
rewind(md);
(void)ftruncate(mfd, (OFF_T)0);
(void)lseek(mfd, (OFF_T)0, L_SET);
rewind(p->drop);
(void)lseek(fileno(p->drop), (OFF_T)0, L_SET);
while((nchar = read(fileno(p->drop), buffer, BBSIZE)) > 0)
if (nchar != write(mfd, buffer, nchar))
{
nchar = -1;
break;
}
if (nchar != 0)
{
save_errno = errno;
(void) ftruncate(mfd, (OFF_T)0);
(void) fclose(md);
#ifdef MAILOCK
mailunlock();
#endif
(void)fclose(p->drop);
#ifdef EDQUOT
if (save_errno == EDQUOT)
return pop_msg(p, POP_FAILURE,
"Overquota copying messages to Mailspool. Temp drop unchanged (%d)",
save_errno);
else
#endif
return pop_msg(p,POP_FAILURE, standard_error, errno);
}
(void) fclose(md);
#ifdef MAILOCK
mailunlock();
#endif
(void) ftruncate(fileno(p->drop), (OFF_T)0);
#ifndef KEEP_TEMP_DROP
(void) unlink(p->temp_drop);
#endif
(void) fclose(p->drop);
return pop_quit(p);
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.