Xref: utzoo alt.sources:98 comp.unix.xenix:1354 Path: utzoo!hoptoad!cpsc6a!codas!ateng!chip From: chip@ateng.UUCP (Chip Salzenberg) Newsgroups: alt.sources,comp.unix.xenix Subject: Elm 1.7 beta: patches for Xenix (2 of 7) Message-ID: <169@ateng.UUCP> Date: 27 Jan 88 00:26:04 GMT Organization: A T Engineering, Tampa, FL Lines: 601 I am enclosing newmbox.c whole -- I modified it so heavily that its diffs were larger than the source code. #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the "#! /bin/sh" line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create the files: # newmbox.c # This archive created: Tue Jan 26 19:14:19 1988 export PATH; PATH=/bin:$PATH : echo 'shar: extracting "newmbox.c" (16430 characters) ' if test -f 'newmbox.c' then echo 'shar: will not overwrite existing file "newmbox.c" ' else sed 's/^X//' << \SHAR_EOF > 'newmbox.c' X/** newmbox.c **/ X X/** read new mailbox file, (C) Copyright 1986 by Dave Taylor **/ X X#include "headers.h" X X#include X#include X#include X X#ifdef BSD /* Berkeley has library elsewhere... */ X# ifndef BSD4_1 X# include X# else X# include X# endif X#else X# include X#endif X Xextern int errno; X Xchar *error_name(), *error_description(), *strcpy(), *strncpy(); Xunsigned long sleep(); Xvoid rewind(); Xvoid exit(); Xlong bytes(); /* size of file NSM */ X Xstruct header_rec *realloc(); X Xint Xnewmbox(stat, resync, main_screen) Xint stat, resync, main_screen; X{ X /** Read a new mailbox file or resync on current file. X X Values of stat and what they mean; X X stat = 0 - changing mailboxes from within program X stat = 1 - read default mailbox or infile for the X first time X stat = 2 - read existing mailbox, new mail arrived X stat = 3 - resync on existing mailbox... X X resync is TRUE iff we know the current mailbox has changed. If X it's set to true this means that we MUST READ SOMETHING, even X if it's the current mailbox again!! X X main_screen simply tells where the counting line should be. X X **/ X X int switching_to_default = 0, switching_from_default = 0; X int did_list = 0, redraw = 0; /* for dealing with the '?' answer */ X char buff[SLEN]; X X if (mbox_specified == 0 && stat == 0) X switching_from_default++; X X if (stat > 0) { X if (stat == 1 && strlen(infile) == 0) { X X /* Subtlety - check to see if there's another instantiation X of Elm (e.g. if the /tmp file is in use). If so, DIE! */ X X sprintf(infile, "%s%s", temp_mbox, username); X if (access(infile, ACCESS_EXISTS) != -1) { X error( X "Hey! An instantiation of Elm is already reading this mail!\n\r"); X fprintf(stderr, X"\n\r [if this is in error then you'll need to remove '/tmp/mbox.%s']\n\r", X username); X exit(1); X } X sprintf(infile, "%s%s", mailhome, username); X } X if (strlen(infile) == 0) /* no filename yet?? */ X sprintf(infile,"%s%s", mailhome, username); X if (user_access(infile, READ_ACCESS) != 0) { X int err = errno; X if (first_word(infile, mailhome)) { /* a mail file! */ X /* oh wow. incoming mailbox with no messages... */ X return(1); X } X error2("Can't open mailbox %s! (%s)", X infile, error_description(err)); X exit(1); X } X } X else { /* get name of new mailbox! */ X MoveCursor(LINES-3, 30); X CleartoEOS(); X PutLine0(LINES-3, 40, "(Use '?' to list your folders)"); X show_last_error(); X Xask_again: X buff[0] = '\0'; X if (did_list == 0) { X PutLine0(LINES-2,0,"Name of new mailbox: "); X (void) optionally_enter(buff, LINES-2, 21, FALSE); X ClearLine(LINES-2); X } X else { X printf("\n\rName of new mailbox: "); X (void) optionally_enter(buff, -1, -1, FALSE); X } X X if (strlen(buff) == 0) { X strcpy(buff, infile); X#if 0 X /* Old code for hitting ENTER at mailbox prompt */ X if (resync && file_changed) X strcpy(buff, infile); X else X return(redraw); X#endif X } X X if (strcmp(buff, "?") == 0) { X Raw(OFF); X list_folders(); X Raw(ON); X did_list = 1; /* ask for name differently */ X redraw = 1; /* we'll need to clean the screen */ X goto ask_again; X } X X if (strcmp(buff, "!") == 0 || strcmp(buff, "%") == 0) /* mailbox */ X sprintf(buff,"%s%s", mailhome, username); X else if (! expand_filename(buff)) { X error1("can't expand file %s", buff); X goto ask_again; X } X X if (strcmp(buff, infile) == 0 && !resync) { X dprint(3, (debugfile, X "User requested change to current mailbox! (newmbox)\n")); X error("already reading that mailbox!"); X return(FALSE); X } X X if (user_access(buff, READ_ACCESS) != 0) { X int err = errno; X dprint(2, (debugfile, X "Error: Can't open mailbox %s (newmbox)\n", buff)); X dprint(2, (debugfile, "** %s - %s **\n", X error_name(err), error_description(err))); X error2("Can't open file %s! (%s)", X buff, error_description(err)); X goto ask_again; X } X X if (first_word(buff, mailhome)) { /* a mail file! */ X mbox_specified = 0; /* fake program to think that */ X stat = 1; /* we're the default file */ X switching_to_default++; /* remember this act! */ X } X else if (!is_mailbox(buff)) { X dprint(2, (debugfile, X "Error: File %s is not a mailbox (newmbox)\n", buff)); X error1("Sorry, %s is not a mailbox!", buff); X goto ask_again; X } X X if (resync && file_changed && strcmp(buff, infile) == 0) X PutLine0(LINES-3,COLUMNS-40,"Resynchronizing file"); X else X PutLine1(LINES-3,COLUMNS-40,"Mailbox: %s", buff); X CleartoEOLN(); X strcpy(infile,buff); X if (! switching_to_default) X mbox_specified = 1; X } X X if (stat == 3) X switching_from_default = TRUE; X X if (switching_from_default) { /* we need to remove the tmp file */ X sprintf(buff, "%s%s", temp_mbox, username); X if (access(buff, ACCESS_EXISTS) != -1) /* is it there at all? */ X if (unlink(buff) != 0) { X error1( X "Sorry, but I can't seem to unlink your temp mail file [%s]\n\r", X error_name(errno)); X silently_exit(); X } X } X X clear_error(); X clear_central_message(); X X header_page = 0; X X if (mailfile != NULL) X (void) fclose(mailfile); /* close it first, to avoid too many open */ X X if ((mailfile = fopen(infile,"r")) == NULL) X message_count = 0; X else if (stat != 2) { /* new mail file! */ X current = 1; X save_file_stats(infile); X message_count = read_headers(FALSE, main_screen); X if (! message_count) X current = 0; X } X else { /* resync with current mail file */ X save_file_stats(infile); X message_count = read_headers(TRUE, main_screen); X } X X if (stat != 2) X selected = 0; /* we don't preselect new mailboxes, boss! */ X X return(TRUE); X} X Xint Xis_mailbox(filename) Xchar *filename; X{ X int fd, rd; X char buf[8]; X X if ((fd = open(filename, O_RDONLY)) == -1) X return (FALSE); X X rd = read(fd, buf, 5); X close(fd); X switch (rd) { X case 0: return (TRUE); X case 5: if (strncmp(buf, "From ", 5) == 0) X return (TRUE); X else X return (FALSE); X default: return (FALSE); X } X} X Xint Xread_headers(rereading, main_screen) Xint rereading, main_screen; X{ X /** Reads the headers into the header_table structure and leaves X the file rewound for further I/O requests. If the file being X read is the default mailbox (ie incoming) then it is copied to X a temp file and closed, to allow more mail to arrive during X the elm session. If 'rereading' is set, the program will copy X the status flags from the previous data structure to the new X one if possible. This is (obviously) for re-reading a mailfile! X **/ X X FILE *temp; X char buffer[LONG_STRING], temp_filename[SLEN]; X long f_bytes = 0L, line_bytes = 0L; X int count = 0, copyit = 0, in_header = 1; X int count_x, count_y = 17, new_messages = 0, err; X int in_to_list = FALSE, forwarding_mail = FALSE, first_line = TRUE; X X static int first_read = 0; X X if (! first_read++) { X ClearLine(LINES-1); X ClearLine(LINES); X if (rereading) X PutLine2(LINES, 0, "Reading in %s, message: %d", infile, X message_count); X else X PutLine1(LINES, 0, "Reading in %s, message: 0", infile); X count_x = LINES; X count_y = 22 + strlen(infile); X } X else { X count_x = LINES-2; X if (main_screen) X PutLine0(LINES-2, 0, "Reading message: 0"); X else { X PutLine0(LINES, 0, "\n"); X PutLine0(LINES, 0, "Reading message: 0"); X count_x = LINES; X } X } X X if (mbox_specified == 0) { X lock(INCOMING); /* ensure no mail arrives while we do this! */ X sprintf(temp_filename,"%s%s",temp_mbox, username); X if (! rereading) { X if (access(temp_filename, ACCESS_EXISTS) != -1) { X /* Hey! What the hell is this? The temp file already exists? */ X /* Looks like a potential clash of processes on the same file! */ X unlock(); /* so remove lock file! */ X error("What's this? The temp mailbox already exists??"); X sleep(2); X error("Ahhhh.....I give up"); X silently_exit(); /* leave without tampering with it! */ X } X if ((temp = fopen(temp_filename,"w")) == NULL) { X err = errno; X unlock(); /* remove lock file! */ X Raw(OFF); X Write_to_screen( X "\nCouldn't open file %s for use as temp mailbox;\n", 1, X temp_filename); X Write_to_screen("** %s - %s **\n", 2, X error_name(err), error_description(err)); X dprint(1, (debugfile, X "Error: Couldn't open file %s as temp mbox. errno %s (%s)\n", X temp_filename, error_name(err), "read_headers")); X leave(); X } X get_mailtime(); X copyit++; X chown(temp_filename, userid, groupid); X chmod(temp_filename, 0700); /* shut off file for other people! */ X } X else { X if ((temp = fopen(temp_filename,"a")) == NULL) { X err = errno; X unlock(); /* remove lock file! */ X Raw(OFF); X Write_to_screen( X "\nCouldn't reopen file %s for use as temp mailbox;\n", 1, X temp_filename); X Write_to_screen("** %s - %s **\n", 2, X error_name(err), error_description(err)); X dprint(1, (debugfile, X "Error: Couldn't reopen file %s as temp mbox. errno %s (%s)\n", X temp_filename, error_name(err), "read_headers")); X emergency_exit(); X } X copyit++; X } X } X X if (rereading) { X if (fseek(mailfile, mailfile_size, 0) == -1) { X err = errno; X Write_to_screen( X "\nCouldn't seek to %ld (end of mailbox) in %s!\n", 2, X mailfile_size, infile); X Write_to_screen("** %s - %s **\n", 2, X error_name(err), error_description(err)); X dprint(1, (debugfile, X "Error: Couldn't seek to end of mailbox %s: (offset %ld) Errno %s (%s)\n", X infile, mailfile_size, error_name(err), "read_headers")); X emergency_exit(); X } X X count = message_count; /* next available */ X f_bytes = mailfile_size; /* start correctly */ X } X X /* find size of mailfile and then unlock file */ X mailfile_size = bytes(infile); X unlock(); /* close that mailfile */ X X for (; f_bytes < mailfile_size; f_bytes += line_bytes) { X X if (fgets(buffer, LONG_STRING, mailfile) == NULL) { X /* SOMETHING IS VERY WRONG */ X PutLine0(LINES, 0, "\n\rI can't read the mail file!?\n\r\n\r"); X fflush(stdout); X dprint(1, (debugfile, "\n\n**** Mail file truncated!! ****\n\n")); X mail_only++; /* to avoid leave() cursor motion */ X leave(); X } X X line_bytes = (long) strlen(buffer); X if (copyit) X fputs(buffer, temp); X X if (first_line) { /** looking for first new line... **/ X X dprint(9, (debugfile, X "newmbox: count=%d f_bytes=%ld\n\tbuffer=%s\n", X count, f_bytes, buffer)); X X /** Skip blank lines until a header is found **/ X if (buffer[0] == '\n' && buffer[1] == '\0') { X if (count) X header_table[count-1].lines++; X continue; X } X X if (!mbox_specified && first_word(buffer, "Forward to ")) { X set_central_message("Mail being forwarded to %s", X (char *) (buffer + 11)); X forwarding_mail = TRUE; X } X else if (first_word(buffer, "From ")) { X forwarding_mail = FALSE; X } X else { X /** Blech! This is a scrambled mailbox file! */ X PutLine0(LINES, 0, X "\n\rMail file is corrupt!! I can't read it!!\n\r\n\r"); X fflush(stdout); X dprint(1, (debugfile, X "\n\n**** First mail header is corrupt!! ****\n\n")); X dprint(1, (debugfile, "Line is;\n\t%s\n\n", buffer)); X mail_only++; /* to avoid leave() cursor motion */ X leave(); X } X X first_line = FALSE; X } X X if (first_word(buffer,"From ")) { X X /** try to allocate new headers, if needed... **/ X X if (count >= max_headers) X more_headers(); X X /** iff this is a valid From line, start a new message... **/ X X if (real_from(buffer, &header_table[count])) { X ++count; X PutLine1(count_x, count_y, "%d", count); X in_header = TRUE; X X header_table[count-1].index_number = count; X header_table[count-1].subject[0] = '\0'; X header_table[count-1].offset = f_bytes; X header_table[count-1].lines = 0; X X /** If we've never seen this msg before, make it visible. **/ X X if (!rereading || count > message_count) X header_table[count - 1].status = VISIBLE; X X if (new_msg(header_table[count - 1])) { X X /** Mark a new message as such. **/ X X header_table[count - 1].status |= NEW; X X /** X We want to move the current pointer to the first new X message IF this is the first of the new messages, the X user requested this feature, we're not rereading the X mailbox (imagine how THAT could screw the user up!), X and we're not in some funky sorting mode (received-date is X the default). As always, I'm open to suggestions on X other ways to have this work intelligently. X **/ X X if (! new_messages++ X && point_to_new X && ! rereading X && sortby == RECEIVED_DATE) { X current = count; X get_page(current); /* make sure we're ON that page! */ X } X } X } X } X else if (in_header) { X X /** empty line means end of header... **/ X X if (buffer[0] == '\n' && buffer[1] == '\0') { X if (in_header) { X in_header = 0; /* in body of message! */ X fix_date(&header_table[count-1]); X } X } X X /** >From contains return address... **/ X X else if (first_word(buffer,">From")) X forwarded(buffer, &header_table[count-1]); X X /** subject of message... **/ X X else if (first_word(buffer,"Subject:") || X first_word(buffer,"Subj:") || X first_word(buffer,"Re:")) { X char *s = header_table[count-1].subject; X if (*s == '\0') { X remove_first_word(buffer); X strncpy(s, buffer, STRING); X } X } X X /** who it's from... **/ X X else if (first_word(buffer,"From:")) X parse_arpa_from(buffer, header_table[count-1].from); X X /** when it was sent... **/ X X else if (first_word(buffer, "Date:")) X parse_arpa_date(buffer, &header_table[count-1]); X X /** some status things about the message... **/ X X else if (first_word(buffer, "Priority:")) X header_table[count-1].status |= PRIORITY; X else if (first_word(buffer, "Content-Type: mailform")) X header_table[count-1].status |= FORM_LETTER; X else if (first_word(buffer, "Action:")) X header_table[count-1].status |= ACTION; X X /** next let's see if it's to us or not... **/ X X else if (first_word(buffer, "To:")) { X in_to_list = TRUE; X header_table[count-1].to[0] = '\0'; /* nothing yet */ X figure_out_addressee((char *) buffer +3, X header_table[count-1].to); X } X X /** continuation of a To: list... **/ X X else if (in_to_list == TRUE) { X if (whitespace(buffer[0])) X figure_out_addressee(buffer, header_table[count-1].to); X else X in_to_list = FALSE; X } X } X X header_table[count-1].lines++; X } X X if (mbox_specified == 0) { X unlock(); /* remove lock file! */ X fclose(mailfile); X fclose(temp); X if ((mailfile = fopen(temp_filename,"r")) == NULL) { X err = errno; X MoveCursor(LINES,0); X Raw(OFF); X Write_to_screen("\nAugh! Couldn't reopen %s as temp mail file;\n", X 1, temp_filename); X Write_to_screen("** %s - %s **\n", 2, error_name(err), X error_description(err)); X dprint(1, (debugfile, X "Error: Reopening %s as temp mail file failed! errno %s (%s)\n", X temp_filename, error_name(errno), "read_headers")); X leave(); X } X } X else X rewind(mailfile); X X sort_mailbox(count, 1); /* let's sort this baby now! */ X X return(count); X} X Xmore_headers() X{ X /** Allocate more message headers **/ X X struct header_rec *temp_struct; X X max_headers += KLICK; X dprint(3, (debugfile, X "\n\nAbout to allocate headers, max_headers=%d\n", max_headers)); X if ((temp_struct = realloc(header_table, max_headers * X sizeof(struct header_rec))) == NULL) { X error1( X "\n\r\n\rCouldn't allocate enough memory! Failed on message #%d\n\r\n\r", X max_headers + 1); X leave(); X } X header_table = temp_struct; X dprint(7, (debugfile, "\tallocated %d more headers!\n\n",KLICK)); X} SHAR_EOF if test 16430 -ne `wc -c < 'newmbox.c'` then echo 'shar: error transmitting "newmbox.c" (should have been 16430 characters) ' fi chmod 664 'newmbox.c' fi # end of overwriting check # End of shell archive exit 0 -- Chip Salzenberg UUCP: "{codas,uunet}!ateng!chip" A T Engineering My employer's opinions are a trade secret. "Anything that works is better than anything that doesn't."