|
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 n
Length: 14549 (0x38d5) Types: TextFile Names: »newmbox.c«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki └─⟦this⟧ »EUUGD11/euug-87hel/sec1/elm/src/newmbox.c«
/** newmbox.c **/ /** read new mailbox file, (C) Copyright 1986 by Dave Taylor **/ #include <ctype.h> #ifdef BSD #undef tolower /* we have our own "tolower" routine instead! */ #endif #include "headers.h" #include <sys/types.h> #include <sys/stat.h> #include <errno.h> #ifdef BSD /* Berkeley has library elsewhere... */ # ifndef BSD4.1 # include <sys/time.h> # else # include <time.h> # endif #else # include <time.h> #endif extern int errno; char *error_name(), *error_description(), *strcpy(), *strncpy(); unsigned long sleep(); void rewind(); void exit(); struct header_rec *realloc(); int newmbox(stat, resync, main_screen) int stat, resync, main_screen; { /** Read a new mailbox file or resync on current file. Values of stat and what they mean; stat = 0 - changing mailboxes from within program stat = 1 - read default mailbox or infile for the first time stat = 2 - read existing mailbox, new mail arrived resync is TRUE iff we know the current mailbox has changed. If it's set to true this means that we MUST READ SOMETHING, even if it's the current mailbox again!! main_screen simply tells where the counting line should be. **/ int switching_to_default = 0, switching_from_default = 0; int iterations = 0, redraw = 0; /* for dealing with the '?' answer */ char buff[SLEN]; if (mbox_specified == 0 && stat == 0) switching_from_default++; if (stat > 0) { if (stat == 1 && strlen(infile) == 0) { /* Subtlety - check to see if there's another instantiation of Elm (e.g. if the /tmp file is in use). If so, DIE! */ sprintf(infile, "%s%s", temp_mbox, username); if (access(infile, ACCESS_EXISTS) != -1) { error( "Hey! An instantiation of Elm is already reading this mail!\n\r"); fprintf(stderr, "\n\r [if this is in error then you'll need to remove '/tmp/mbox.%s']\n\r", username); exit(1); } sprintf(infile, "%s%s", mailhome, username); } if (strlen(infile) == 0) /* no filename yet?? */ sprintf(infile,"%s%s",mailhome, username); if ((errno = can_access(infile, READ_ACCESS))) { if (strncmp(infile, mailhome, strlen(mailhome)) == 0) { /* oh wow. incoming mailbox with no messages... */ return(1); } error2("Can't open mailbox '%s' for reading [%s]", infile, error_name(errno)); exit(1); } } else { /* get name of new mailbox! */ MoveCursor(LINES-3, 30); CleartoEOS(); PutLine0(LINES-3, 40, "(Use '?' to list your folders)"); show_last_error(); ask_again: buff[0] = '\0'; if (iterations++ == 0) { PutLine0(LINES-2,0,"Name of new mailbox: "); (void) optionally_enter(buff, LINES-2, 21, FALSE); ClearLine(LINES-2); } else { printf("\n\rName of new mailbox: "); (void) optionally_enter(buff, -1, -1, FALSE); } if (strlen(buff) == 0) { if (resync && file_changed) strcpy(buff, infile); else return(redraw); } if (strcmp(buff, "?") == 0) { redraw = 1; /* we'll need to clean the screen */ dprint0(1,"*** setting redraw to 1 ***\n"); list_folders(); goto ask_again; } if (strcmp(buff, "!") == 0 || strcmp(buff, "%") == 0) /* go to mailbox */ sprintf(buff,"%s%s", mailhome, username); else if (! expand_filename(buff)) { error1("can't expand file %s", buff); if (resync && file_changed) strcpy(buff, infile); else return(FALSE); } if (strcmp(buff, infile) == 0 && ! resync) { dprint0(3,"User requested change to current mailbox! (newmbox)\n"); error("already reading that mailbox!"); return(FALSE); } if ((errno = can_access(buff, READ_ACCESS))) { dprint2(2,"Error: attempt to open %s as mailbox denied (%s)!\n", buff, "newmbox"); error1("Permission to open file %s denied", buff); if (resync && file_changed) strcpy(buff, infile); else return(FALSE); } if (first_word(buff, mailhome)) { /* a mail file! */ mbox_specified = 0; /* fake program to think that */ stat = 1; /* we're the default file */ switching_to_default++; /* remember this act! */ } if (resync && file_changed && strcmp(buff, infile) == 0) PutLine0(LINES-3,COLUMNS-40,"Resynchronizing file"); else PutLine1(LINES-3,COLUMNS-40,"Mailbox: %s", buff); CleartoEOLN(); strcpy(infile,buff); if (! switching_to_default) mbox_specified = 1; } if (switching_from_default) { /* we need to remove the tmp file */ sprintf(buff, "%s%s", temp_mbox, username); if (unlink(buff) != 0) { error1( "Sorry, but I can't seem to unlink your temp mail file [%s]\n\r", error_name(errno)); silently_exit(); } } clear_error(); clear_central_message(); header_page = 0; if (mailfile != NULL) (void) fclose(mailfile); /* close it first, to avoid too many open */ if ((mailfile = fopen(infile,"r")) == NULL) message_count = 0; else if (stat < 2) { /* new mail file! */ current = 1; message_count = read_headers(FALSE, main_screen); if (! message_count) current = 0; } else /* resync with current mail file */ message_count = read_headers(TRUE, main_screen); if (stat < 2) selected = 0; /* we don't preselect new mailboxes, boss! */ return(TRUE); } int read_headers(rereading, main_screen) int rereading, main_screen; { /** Reads the headers into the header_table structure and leaves the file rewound for further I/O requests. If the file being read is the default mailbox (ie incoming) then it is copied to a temp file and closed, to allow more mail to arrive during the elm session. If 'rereading' is set, the program will copy the status flags from the previous data structure to the new one if possible. This is (obviously) for re-reading a mailfile! **/ FILE *temp; struct header_rec *temp_struct; char buffer[LONG_STRING], temp_filename[SLEN]; long bytes = 0L, line_bytes = 0L; register int line = 0, count = 0, subj = 0, copyit = 0, in_header = 1; int count_x, count_y = 17, new_messages = 0, err; int in_to_list = FALSE, forwarding_mail = FALSE; static int first_read = 0; if (! first_read++) { ClearLine(LINES-1); ClearLine(LINES); if (rereading) PutLine2(LINES, 0, "Reading in %s, message: %d", infile, message_count); else PutLine1(LINES, 0, "Reading in %s, message: 0", infile); count_x = LINES; count_y = 22 + strlen(infile); } else { count_x = LINES-2; if (main_screen) PutLine0(LINES-2, 0, "Reading message: 0"); else { PutLine0(LINES, 0, "\n"); PutLine0(LINES, 0, "Reading message: 0"); count_x = LINES; } } if (mbox_specified == 0) { lock(INCOMING); /* ensure no mail arrives while we do this! */ sprintf(temp_filename,"%s%s",temp_mbox, username); if (! rereading) { if (access(temp_filename, ACCESS_EXISTS) != -1) { /* Hey! What the hell is this? The temp file already exists? */ /* Looks like a potential clash of processes on the same file! */ unlock(); /* so remove lock file! */ error("What's this? The temp mailbox already exists??"); sleep(2); error("Ahhhh.....I give up"); silently_exit(); /* leave without tampering with it! */ } if ((temp = fopen(temp_filename,"w")) == NULL) { err = errno; unlock(); /* remove lock file! */ Raw(OFF); Write_to_screen( "\nCouldn't open file %s for use as temp mailbox;\n", 1, temp_filename); Write_to_screen("** %s - %s **\n", 2, error_name(err), error_description(err)); dprint3(1, "Error: Couldn't open file %s as temp mbox. errno %s (%s)\n", temp_filename, error_name(err), "read_headers"); leave(); } get_mailtime(); copyit++; chown(temp_filename, userid, groupid); chmod(temp_filename, 0700); /* shut off file for other people! */ } else { if ((temp = fopen(temp_filename,"a")) == NULL) { err = errno; unlock(); /* remove lock file! */ Raw(OFF); Write_to_screen( "\nCouldn't reopen file %s for use as temp mailbox;\n", 1, temp_filename); Write_to_screen("** %s - %s **\n", 2, error_name(err), error_description(err)); dprint3(1, "Error: Couldn't reopen file %s as temp mbox. errno %s (%s)\n", temp_filename, error_name(err), "read_headers"); emergency_exit(); } copyit++; } } if (rereading) { if (fseek(mailfile, mailfile_size, 0)) { err = errno; Write_to_screen( "\nCouldn't seek to %ld (end of mailbox) in %s!\n", 2, mailfile_size, infile); Write_to_screen("** %s - %s **\n", 2, error_name(err), error_description(err)); dprint4(1, "Error: Couldn't seek to end of mailbox %s: (offset %ld) Errno %s (%s)\n", infile, mailfile_size, error_name(err), "read_headers"); emergency_exit(); } count = message_count; /* next available */ bytes = mailfile_size; /* start correctly */ if (message_count > 0) line = header_table[message_count - 1].lines; else line = 0; } while (fgets(buffer, LONG_STRING, mailfile) != NULL) { if (bytes == 0L) { /* first line of file... */ if (! mbox_specified) { if (first_word(buffer, "Forward to ")) { set_central_message("Mail being forwarded to %s", (char *) (buffer + 11)); forwarding_mail = TRUE; } } if (! first_word(buffer, "From ") && !forwarding_mail) { PutLine0(LINES, 0, "\n\rMail file is corrupt!! I can't read it!!\n\r\n\r"); fflush(stderr); dprint0(1, "\n\n**** First mail header is corrupt!! ****\n\n"); dprint1(1, "Line is;\n\t%s\n\n", buffer); mail_only++; /* to avoid leave() cursor motion */ leave(); } } if (copyit) fputs(buffer, temp); line_bytes = (long) strlen(buffer); line++; if (first_word(buffer,"From ")) { /** try to allocate new headers, if needed... **/ if (count >= max_headers) { max_headers += KLICK; dprint2(3, "\n\nAbout to allocate headers, count = %d, max_headers=%d\n", count, max_headers); if ((temp_struct = realloc(header_table, max_headers * sizeof(struct header_rec))) == NULL) { error1( "\n\r\n\rCouldn't allocate enough memory! Failed on message #%d\n\r\n\r", count); leave(); } header_table = temp_struct; dprint1(7,"\tallocated %d more headers!\n\n", KLICK); } if (real_from(buffer, &header_table[count])) { header_table[count].offset = (long) bytes; header_table[count].index_number = count+1; if (! rereading || count > message_count) header_table[count].status = VISIBLE; /* default status! */ strcpy(header_table[count].subject, ""); /* clear subj */ header_table[count-1].lines = line; if (new_msg(header_table[count])) { header_table[count].status |= NEW; /* new message! */ if (! new_messages++ && point_to_new && ! rereading && sortby == RECEIVED_DATE) { current = count+1; get_page(current); /* make sure we're ON that page! */ } /* Quick comment on that last conditional test... We want to move the current pointer to the first new message IF this is the first of the new messages, the user requested this feature, we're not rereading the mailbox (imagine how THAT could screw the user up!), and we're not in some funky sorting mode (received-date is the default). As always, I'm open to suggestions on other ways to have this work intelligently. */ } count++; subj = 0; line = 0; in_header = 1; PutLine1(count_x, count_y, "%d", count); } } else if (in_header) { if (first_word(buffer,">From")) forwarded(buffer, &header_table[count-1]); /* return address */ else if (first_word(buffer,"Subject:") || first_word(buffer,"Subj:") || first_word(buffer,"Re:")) { if (! subj++) { remove_first_word(buffer); strncpy(header_table[count-1].subject, buffer, STRING); } } else if (first_word(buffer,"From:")) parse_arpa_from(buffer, header_table[count-1].from); /** when it was sent... **/ else if (first_word(buffer, "Date:")) parse_arpa_date(buffer, &header_table[count-1]); /** some status things about the message... **/ else if (first_word(buffer, "Priority:")) header_table[count-1].status |= PRIORITY; else if (first_word(buffer, "Content-Type: mailform")) header_table[count-1].status |= FORM_LETTER; else if (first_word(buffer, "Action:")) header_table[count-1].status |= ACTION; /** next let's see if it's to us or not... **/ else if (first_word(buffer, "To:")) { in_to_list = TRUE; header_table[count-1].to[0] = '\0'; /* nothing yet */ figure_out_addressee((char *) buffer +3, header_table[count-1].to); } else if (buffer[0] == LINE_FEED || buffer[0] == '\0') { if (in_header) { in_header = 0; /* in body of message! */ fix_date(&header_table[count-1]); } } else if (in_to_list == TRUE) { if (whitespace(buffer[0])) figure_out_addressee(buffer, header_table[count-1].to); else in_to_list = FALSE; } } bytes += (long) line_bytes; } header_table[count > 0? count-1:count].lines = line + 1; if (mbox_specified == 0) { unlock(); /* remove lock file! */ fclose(mailfile); fclose(temp); if ((mailfile = fopen(temp_filename,"r")) == NULL) { err = errno; MoveCursor(LINES,0); Raw(OFF); Write_to_screen("\nAugh! Couldn't reopen %s as temp mail file;\n", 1, temp_filename); Write_to_screen("** %s - %s **\n", 2, error_name(err), error_description(err)); dprint3(1, "Error: Reopening %s as temp mail file failed! errno %s (%s)\n", temp_filename, error_name(errno), "read_headers"); leave(); } } else rewind(mailfile); sort_mailbox(count, 1); /* let's sort this baby now! */ return(count); }