|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T l
Length: 12961 (0x32a1)
Types: TextFile
Names: »leavembox.c«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki
└─⟦this⟧ »EUUGD11/euug-87hel/sec1/elm/src/leavembox.c«
/** leavembox.c **/
/** leave current mailbox, updating etc. as needed...
(C) Copyright 1985, Dave Taylor
**/
#include "headers.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#define ECHOIT 1 /* echo on for prompting! */
/** added due to a bug in the 2.1 OS **/
struct utimbuf {
time_t actime; /** access time **/
time_t modtime; /** modification */
};
extern int errno;
char *error_name(), *error_description(), *strcpy();
unsigned short getegid();
unsigned long sleep();
int
leave_mbox(quitting)
int quitting;
{
/** Exit, saving files into mbox and deleting specified, or simply
delete specified mail... If "quitting" is true, then output status
regardless of what happens. Returns 1 iff mailfile was
changed (ie messages deleted from file), 0 if not, and -1 if new
mail has arrived in the meantime...
**/
FILE *temp;
char outfile[SLEN], buffer[SLEN];
struct stat buf; /* stat command */
struct utimbuf times; /* utime command */
register int to_delete = 0, to_save = 0, i, mode = 00644,
pending = 0, number_saved = 0, last_sortby;
char dflt;
long bytes();
dprint0(1,"\n\n-- leaving_mailbox --\n\n");
if (message_count == 0)
return(FALSE); /* nothing changed */
for (i = 0; i < message_count; i++)
if (ison(header_table[i].status, DELETED)) to_delete++;
else to_save++;
dprint2(2,"Count: %d to delete and %d to save\n", to_delete, to_save);
if (mbox_specified == 0)
update_mailtime();
if (hp_softkeys && question_me) {
define_softkeys(YESNO); /* YES or NO on softkeys */
softkeys_on();
}
if (always_del) /* set up the default answer... */
dflt = 'y';
else
dflt = 'n';
if (question_me && to_delete)
if (to_save) {
fflush(stdin);
sprintf(buffer, "Delete message%s? (y/n) ", plural(to_delete));
if (want_to(buffer, dflt, ECHOIT) != 'y') {
if (mbox_specified == 0) unlock(); /* remove lock! */
dprint1(3,"\tDelete message%s? - answer was NO\n",
plural(to_delete));
error("Nothing deleted");
return(FALSE); /* nothing was deleted! */
}
}
else if (! to_save) { /* nothing to save!! */
fflush(stdin);
if (want_to("Delete all mail? (y/n) ", dflt, ECHOIT)!='y') {
if (mbox_specified == 0) unlock(); /* remove lock! */
dprint0(3,"Delete all mail? - answer was NO\n");
error("Nothing deleted");
return(FALSE); /* nothing was deleted */
}
}
if (always_leave)
dflt = 'y';
else
dflt = 'n';
/** we have to check to see what the sorting order was...so that
the order of saved messages is the same as the order of the
messages originally (a subtle point...) **/
if (sortby != RECEIVED_DATE) { /* what we want anyway! */
last_sortby = sortby;
sortby = RECEIVED_DATE;
sort_mailbox(message_count, FALSE);
sortby = last_sortby;
}
if (question_me && to_save && mbox_specified == 0) {
fflush(stdin);
if (want_to("Keep mail in incoming mailbox? (y/n) ",dflt, ECHOIT)
== 'y')
if (to_delete) /* okay - keep undeleted as pending! */
pending++;
else { /* gag! nothing to delete, don't save! */
unlock(); /* remove mailfile lock! */
dprint0(3,"Keep mail in incoming mailbox? -- answer was YES\n");
error("Mailbox unchanged");
return(FALSE); /* nothing changed! */
}
}
/** okay...now lets do it! **/
if (to_save > 0) {
if (to_delete > 0)
sprintf(buffer ,"[%s %d message%s, and deleting %d]",
pending? "keeping" : "storing",
to_save, plural(to_save), to_delete);
else if (quitting)
sprintf(buffer,"[%s %s]",
pending? "keeping" : "storing",
to_save > 1? "all messages" : "message");
else
buffer[0] = '\0'; /* no string! */
}
else {
if (to_delete > 0)
sprintf(buffer, "[deleting all messages]");
else if (quitting)
sprintf(buffer, "[no messages to %s, and none to delete]",
pending? "keep" : "save");
else
buffer[0] = '\0';
}
dprint1(2,"Action: %s\n", buffer);
error(buffer);
if (! mbox_specified) {
if (pending) { /* keep some messages pending! */
sprintf(outfile,"%s%d", temp_mbox, getpid());
unlink(outfile);
}
else if (mailbox_defined) /* save to specified mailbox */
strcpy(outfile, mailbox);
else /* save to $home/mbox */
sprintf(outfile,"%s/mbox", home);
}
else {
if (! to_delete) return(FALSE); /* no work to do! */
sprintf(outfile, "%s%d", temp_file, getpid());
unlink(outfile); /* ensure it's empty! */
}
if (to_save) {
if ((errno = can_open(outfile, "a"))) {
error1(
"Permission to append to %s denied! Leaving mailbox intact\n",
outfile);
dprint2(1,
"Error: Permission to append to outfile %s denied!! (%s)\n",
outfile, "leavembox");
dprint2(1,"** %s - %s **\n", error_name(errno),
error_description(errno));
unlock();
return(0);
}
if ((temp = fopen(outfile,"a")) == NULL) {
if (mbox_specified == 0)
unlock(); /* remove mailfile lock! */
dprint1(1,"Error: could not append to file %s\n",
outfile);
dprint2(1,"** %s - %s **\n", error_name(errno),
error_description(errno));
sprintf(buffer, " Could not append to file %s! ",
outfile);
Centerline(LINES-1, buffer);
emergency_exit();
}
for (i = 0; i < message_count; i++)
if (! (header_table[i].status & DELETED)) {
current = i+1;
if (! number_saved++) {
dprint2(2,"Saving message%s #%d, ", plural(to_save), current);
}
else {
dprint1(2,"#%d, ", current);
}
copy_message("", temp, FALSE, FALSE);
}
fclose(temp);
dprint0(2,"\n\n");
}
/* remove source file...either default mailbox or original copy of
specified one! */
/** let's grab the original mode and date/time of the mailfile
before removing it **/
if (stat(infile, &buf) == 0)
mode = buf.st_mode & 00777;
else {
dprint2(1,"Error: errno %s attempting to stat file %s\n",
error_name(errno), infile);
error3("Error %s (%s) on stat(%s)", error_name(errno),
error_description(errno), infile);
}
fclose(mailfile); /* close the baby... */
if (mailfile_size != bytes(infile)) {
sort_mailbox(message_count, FALSE); /* display sorting order! */
unlock();
error("New mail has just arrived - resyncing...");
return(-1);
}
unlink(infile); /* and BLAMO! */
if (to_save && (mbox_specified || pending)) {
if (link(outfile, infile) != 0)
if (errno == EXDEV) { /** different file devices! Use copy! **/
if (copy(outfile, infile) != 0) {
dprint2(1,"leavembox: copy(%s, %s) failed;",
outfile, infile);
dprint2(1,"** %s - %s **\n", error_name(errno),
error_description(errno));
error("couldn't modify mail file!");
sleep(1);
sprintf(infile,"%s/%s", home, unedited_mail);
if (copy(outfile, infile) != 0) {
dprint1(1,"leavembox: couldn't copy to %s either!! Help;",
infile);
dprint2(1,"** %s - %s **\n", error_name(errno),
error_description(errno));
error("something godawful is happening to me!!!");
emergency_exit();
}
else {
dprint1(1,"\nWoah! Confused - Saved mail in %s (leavembox)\n",
infile);
error1("saved mail in %s", infile);
}
}
}
else {
dprint2(1,"link(%s, %s) failed (leavembox)\n", outfile, infile);
dprint2(1,"** %s - %s **\n", error_name(errno),
error_description(errno));
error2("link failed! %s - %s", error_name(errno),
error_description(errno));
emergency_exit();
}
unlink(outfile);
}
else if (keep_empty_files) {
sleep(1);
error1("..keeping empty mail file '%s'..", infile);
temp = fopen(infile, "w");
fclose(temp);
chmod(infile, mode);
chown(infile, userid, groupid);
}
if (mbox_specified == 0) {
if (mode != 00644) { /* if not the default mail access mode... */
if (! pending) { /* if none still being saved */
temp = fopen(infile, "w");
fclose(temp);
}
chmod(infile,mode);
/* let's set the access times of the new mail file to be
the same as the OLD one (still sitting in 'buf') ! */
times.actime = buf.st_atime;
times.modtime= buf.st_mtime;
if (utime(infile, ×) != 0) {
dprint0(1,"Error: encountered error doing utime (leavmbox)\n");
dprint2(1,"** %s - %s **\n", error_name(errno),
error_description(errno));
error2("Error %s trying to change file %s access time",
error_name(errno), infile);
}
}
unlock(); /* remove the lock on the file ASAP! */
/** finally, let's change the ownership of the default
outgoing mailbox, if needed **/
if (to_save)
chown(outfile, userid, groupid);
}
#ifdef SAVE_GROUP_MAILBOX_ID
chown(infile, userid, getegid()); /** see the Config Guide **/
#else
chown(infile, userid, groupid); /** file owned by user **/
#endif
return(to_delete);
}
char lock_name[SLEN];
lock(direction)
int direction;
{
/** Create lock file to ensure that we don't get any mail
while altering the mailbox contents!
If it already exists sit and spin until
either the lock file is removed...indicating new mail
or
we have iterated MAX_ATTEMPTS times, in which case we
either fail or remove it and make our own (determined
by if REMOVE_AT_LAST is defined in header file
If direction == INCOMING then DON'T remove the lock file
on the way out! (It'd mess up whatever created it!).
**/
register int iteration = 0, access_val, lock_fd;
sprintf(lock_name,"%s%s.lock", mailhome, username);
access_val = access(lock_name, ACCESS_EXISTS);
while (access_val != -1 && iteration++ < MAX_ATTEMPTS) {
dprint1(2,"File '%s' currently exists! Waiting...(lock)\n",
lock_name);
if (direction == INCOMING)
PutLine0(LINES, 0, "\nMail being received!\twaiting...");
else
error1("Attempt %d: Mail being received...waiting",
iteration);
sleep(5);
access_val = access(lock_name, ACCESS_EXISTS);
}
if (access_val != -1) {
#ifdef REMOVE_AT_LAST
/** time to waste the lock file! Must be there in error! **/
dprint0(2,
"Warning: I'm giving up waiting - removing lock file(lock)\n");
if (direction == INCOMING)
PutLine0(LINES, 0,"\nTimed out - removing current lock file...");
else
error("Throwing away the current lock file!");
if (unlink(lock_name) != 0) {
dprint3(1,"Error %s (%s)\n\ttrying to unlink file %s (%s)\n",
error_name(errno), error_description(errno), lock_name);
PutLine1(LINES, 0,
"\n\rI couldn't remove the current lock file %s\n\r",
lock_name);
PutLine2(LINES, 0, "** %s - %s **\n\r", error_name(errno),
error_description(errno));
if (direction == INCOMING)
leave();
else
emergency_exit();
}
/* everything is okay, so lets act as if nothing had happened... */
#else
/* okay...we die and leave, not updating the mailfile mbox or
any of those! */
if (direction == INCOMING) {
PutLine1(LINES, 0, "\nGiving up after %d iterations...", iteration);
PutLine0(LINES, 0,
"Please try to read your mail again in a few minutes.\n");
dprint1(2,"Warning:bailing out after %d iterations...(lock)\n",
iteration);
leave_locked(0);
}
else {
dprint1(2,"Warning: after %d iterations, timed out! (lock)\n",
iteration);
leave(error("Timed out on lock file reads. Leaving program"));
}
#endif
}
/* if we get here we can create the lock file, so lets do it! */
if ((lock_fd = creat(lock_name, 0)) == -1) {
dprint2(1,"Can't create lock file: creat(%s) raises error %s (lock)\n",
lock_name, error_name(errno));
if (errno == EACCES)
leave(error1(
"Can't create lock file! I need write permission in %s!\n\r",
mailhome));
else {
dprint1(1,"Error encountered attempting to create lock %s\n",
lock_name);
dprint2(1,"** %s - %s **\n", error_name(errno),
error_description(errno));
PutLine1(LINES, 0,
"\n\rError encountered while attempting to create lock file %s;\n\r",
lock_name);
PutLine2(LINES, 0, "** %s - %s **\n\r", error_name(errno),
error_description(errno));
leave();
}
}
close(lock_fd); /* close it. We don't want to KEEP the thing! */
}
unlock()
{
/** Remove the lock file! This must be part of the interrupt
processing routine to ensure that the lock file is NEVER
left sitting in the mailhome directory! **/
(void) unlink(lock_name);
}