This is pop_bull.c in view mode; [Download] [Up]
/*
* Copyright (c) 1997 by Qualcomm Incorporated.
*/
/*
* bullcopy
*
*/
#if HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdio.h>
#include <pwd.h>
#if HAVE_DIRENT_H
# include <dirent.h>
# define NAMLEN(dirent) strlen((dirent)->d_name)
#else
# define dirent direct
# define NAMLEN(dirent) (dirent)->d_namlen
# if HAVE_SYS_NDIR_H
# include <sys/ndir.h>
# endif
# if HAVE_SYS_DIR_H
# include <sys/dir.h>
# endif
# if HAVE_NDIR_H
# include <ndir.h>
# endif
#endif
#ifndef HAVE_BCOPY
# define bcopy(src,dest,len) (void) (memcpy(dest,src,len))
#endif
#include <ctype.h>
#include <popper.h>
#include <flock.h>
static int sequence = 0;
static long timestamp;
static char *errmesg = "Unable to copy Bulletin %s to pop dropbox %s (%d)";
typedef struct _file_list file_list;
struct _file_list {
char *bull_name;
long bull_value;
file_list *next;
};
file_list *
insert_list(p, head, name)
POP *p;
file_list *head;
char *name;
{
long new_bull;
file_list *new_rec, *current;
new_bull = atol(name);
new_rec = (file_list *)malloc(sizeof(file_list));
new_rec->next = NULL;
new_rec->bull_value = new_bull;
new_rec->bull_name = (char *)malloc(strlen(name) + 1);
strcpy(new_rec->bull_name, name);
current = head;
if (!head) {
return(new_rec);
} else {
if (head->bull_value > new_bull) {
new_rec->next = head;
head = new_rec;
return(head);
}
}
while (current->next) {
if (current->bull_value > new_bull)
break;
current = current->next;
}
new_rec->next = current->next;
current->next = new_rec;
return(head);
}
/*
* pop_bull: Append any new bulletins to the end of the user's
* temporary maildrop.
*/
pop_bull (p, pwp)
POP *p;
struct passwd *pwp;
{
char popBullName[256];
FILE *popBull;
DIR *dirp;
file_list *list = NULL;
struct dirent *dp;
long maxBullNumber = 0;
long bullNumber;
long lastBullSent;
char buffer[MAXMSGLINELEN];
int res;
int bullcount = 0;
int save_count;
#ifdef BULLDB
datum bull_count;
datum name;
#endif
/* Construct full path name of .popbull file. */
sprintf(popBullName, "%s/.popbull", pwp->pw_dir);
/* Scan bulletin directory and compute the maximum current
bulletin number. */
dirp = opendir(p->bulldir);
if (dirp == NULL) {
pop_log(p, POP_PRIORITY,
"Unable to open bulletin directory '%s'. (%d)", p->bulldir, errno);
return POP_FAILURE;
}
while ((dp = readdir(dirp)) != NULL) {
if (!isdigit(*dp->d_name)) continue;
bullNumber = atol(dp->d_name);
if (bullNumber > maxBullNumber) maxBullNumber = bullNumber;
list = insert_list(p, list, dp->d_name);
}
closedir(dirp);
timestamp = time(0);
/* Open the user's .popbull file and read the number of the last
bulletin sent to this user. If the file doesn't exist, create
it and seed it with the current max bulletin number. Note that
new users do not get sent old bulletins. */
#ifdef BULLDB
name.dptr = p->user;
name.dsize = strlen(p->user) + 1;
#ifdef GDBM
bull_count = gdbm_fetch(p->bull_db, name);
#else
bull_count = dbm_fetch(p->bull_db, name);
#endif
if (bull_count.dptr == NULL) {
/* If the database does not have a value, check the users .popbull
* file. If it's not empty, then use the value there, otherwise,
* create a new value.
*/
popBull = fopen(popBullName, "r");
if ((popBull == NULL) || (fgets(buffer,MAXMSGLINELEN,popBull) == NULL) ||
!isdigit(*buffer)) {
if ((lastBullSent = (maxBullNumber - NEWBULLCNT)) < 0)
lastBullSent = 0;
} else {
lastBullSent = atol(buffer);
}
if (popBull)
fclose(popBull);
bull_count.dptr = (char *)&lastBullSent;
bull_count.dsize = sizeof(lastBullSent);
/* Block while waiting for a lock to update the entry */
if (flock(dbm_dirfno(p->bull_db), LOCK_EX) == -1)
return(pop_msg(p, POP_FAILURE, "Bulletin database lock failed"));
#ifdef GDBM
gdbm_store(p->bull_db, name, bull_count, GDBM_REPLACE);
#else
dbm_store(p->bull_db, name, bull_count, DBM_REPLACE);
#endif
flock(dbm_dirfno(p->bull_db), LOCK_UN);
if (NEWBULLCNT <= 0)
{
#ifdef GDBM
gdbm_close(p->bull_db);
#else
dbm_close(p->bull_db);
#endif
return POP_SUCCESS;
}
} else {
bcopy(bull_count.dptr, &lastBullSent, bull_count.dsize);
#else
popBull = fopen(popBullName, "r");
if ((popBull == NULL) || (fgets(buffer, MAXMSGLINELEN, popBull) == NULL) ||
!isdigit(*buffer)) {
if (popBull != NULL) fclose(popBull);
popBull = fopen(popBullName, "w");
if (popBull == NULL) {
pop_log(p, POP_PRIORITY, "Unable to create .popbull file (%d)", errno);
return POP_FAILURE;
}
if ((lastBullSent = (maxBullNumber - NEWBULLCNT)) < 0)
lastBullSent = 0;
fprintf(popBull, "%ld\n", lastBullSent);
fclose(popBull);
if (NEWBULLCNT <= 0)
return POP_SUCCESS;
} else {
lastBullSent = atol(buffer);
#endif /* BULLDB */
}
/* If there aren't any new bulletins for this user, return. */
if (lastBullSent >= maxBullNumber)
{
#ifdef BULLDB
#ifdef GDBM
gdbm_close(p->bull_db);
#else
dbm_close(p->bull_db);
#endif
#endif
return POP_SUCCESS;
}
(void) chmod(popBullName, 0600); /* Only needs to be read by me */
/* Append the new bulletins to the end of the user's temporary
mail drop. */
res = POP_SUCCESS;
save_count = p->msg_count;
while (list) {
if (list->bull_value > lastBullSent)
if ((res = CopyOneBull(list->bull_name, p)) != POP_SUCCESS) {
p->msg_count = save_count;
break;
}
list = list->next;
}
if (res == POP_SUCCESS) {
#ifdef BULLDB
bull_count.dptr = (char *)&maxBullNumber;
bull_count.dsize = sizeof(maxBullNumber);
if (flock(dbm_dirfno(p->bull_db), LOCK_EX) == -1)
return(pop_msg(p, POP_FAILURE, "Bulletin database lock failed"));
#ifdef GDBM
gdbm_store(p->bull_db, name, bull_count, GDBM_REPLACE);
gdbm_close(p->bull_db);
#else
dbm_store(p->bull_db, name, bull_count, DBM_REPLACE);
dbm_close(p->bull_db);
#endif
flock(dbm_dirfno(p->bull_db), LOCK_UN);
#else
/* Update the user's .popbull file. */
popBull = fopen(popBullName, "w");
if (popBull == NULL) {
pop_log(p, POP_PRIORITY, "Unable to open .popbull file. (%d)", errno);
return POP_FAILURE;
}
fprintf(popBull, "%ld\n", maxBullNumber);
fclose(popBull);
#endif
}
#ifdef BULLDB
#ifdef GDBM
gdbm_close(p->bull_db);
#else
dbm_close(p->bull_db);
#endif
pop_log(p,POP_PRIORITY, "LOGGING THE CLOSE OF BULLDB");
#endif
return(res);
}
extern int newline;
/*
* CopyOneBull: Append a single bulletin file to the end of the
* temporary maildrop file.
*/
CopyOneBull(name, p)
char *name;
POP *p;
{
FILE *bull;
char buffer[MAXMSGLINELEN];
int in_header = 1;
int first_line = 1;
int nchar;
int msg_num;
int receivedhdrs = 0;
char bullName[256];
MsgInfoList *mp; /* Pointer to message info list */
msg_num = p->msg_count;
p->msg_count = (((p->msg_count - 1) / ALLOC_MSGS) + 1) * ALLOC_MSGS;
sprintf(bullName, "%s/%s", p->bulldir, name);
bull = fopen(bullName, "r");
if (bull == NULL) {
pop_log(p, POP_PRIORITY,
"Unable to open bulletin file %s (%d)", name, errno);
return POP_FAILURE;
}
newline = 1;
if ((fgets(buffer, MAXMSGLINELEN, bull) != NULL) && !(isfromline(buffer))) {
pop_log(p, POP_PRIORITY,
"Bulletin %s does not start with a valid \"From \" separator",name);
fclose(bull);
return POP_FAILURE;
}
/* Just and appended message, no Status or UIDL updates here */
#ifndef NO_STATUS
p->dirty = 1;
#endif
mp = p->mlp + msg_num - 1;
if (++msg_num > p->msg_count) {
p->mlp=(MsgInfoList *) realloc(p->mlp,
(p->msg_count += ALLOC_MSGS)*sizeof(MsgInfoList));
if (p->mlp == NULL) {
p->msg_count = 0;
return pop_msg (p,POP_FAILURE,
"Bull: Can't build message list for '%s': Out of memory",
p->user);
}
mp = p->mlp + msg_num - 2;
}
++mp;
mp->number = msg_num;
mp->length = 0;
mp->lines = 0;
mp->body_lines = 0;
mp->offset = ftell(p->drop);
mp->del_flag = FALSE;
mp->retr_flag = FALSE;
if (fputs(buffer, p->drop) == EOF) {
return(pop_msg(p, POP_FAILURE, errmesg, name, p->temp_drop, errno));
}
p->drop_size += strlen(buffer);
mp->lines++;
sprintf(buffer, "X-UIDL: %ld.%03d\n", timestamp, sequence);
if (fputs(buffer, p->drop) == EOF) {
return(pop_msg(p, POP_FAILURE, errmesg, name, p->temp_drop, errno));
}
mp->length += strlen(buffer);
p->drop_size += strlen(buffer);
mp->lines++;
#ifdef DEBUG
if(p->debug)
pop_log(p,POP_DEBUG,
"Bull msg %d being added to list, offset %d",
mp->number, mp->offset);
#endif
sprintf(buffer, "%ld.%03d\n", timestamp, sequence++);
mp->uidl_str = (char *)strdup(buffer);
first_line = 0;
while (fgets(buffer, MAXMSGLINELEN, bull) != NULL) {
nchar = strlen(buffer);
if (in_header) { /* Header */
if (!strncasecmp(buffer, "X-UIDL:", 7)) {
continue; /* Skip any UIDLs */
} else if (strncasecmp(buffer, "To:", 3) == 0) {
sprintf(buffer,"To: %s@%s\n", p->user, p->myhost);
nchar = strlen(buffer);
} else if (strncasecmp(buffer, "Status:", 7) == 0) {
continue;
} else if (*buffer == '\n') {
in_header = 0;
mp->body_lines = 0; /* Reset to zero when in the body */
}
}
mp->length += nchar;
p->drop_size += nchar;
mp->lines++;
mp->body_lines++;
if (fputs(buffer, p->drop) == EOF) {
return(pop_msg(p,POP_FAILURE,errmesg,name,p->temp_drop, errno));
}
}
fflush(p->drop);
p->msg_count = msg_num;
fclose(bull);
#ifdef DEBUG
if(p->debug && msg_num != 1)
pop_log(p,POP_DEBUG,
"Bull msg %d uidl %s at offset %d is %d octets long and has %u lines.",
mp->number,mp->uidl_str,mp->offset,mp->length,mp->lines);
#endif
return POP_SUCCESS;
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.