home *** CD-ROM | disk | FTP | other *** search
- From: decvax!hplabs!hpcnou!dat (Dave Taylor)
- Subject: Msg Shar.part.6
- Newsgroups: mod.sources
- Approved: jpn@panda.UUCP
-
- Mod.sources: Volume 4, Issue 10
- Submitted by: decvax!hplabs!hpcnou!dat (Dave Taylor)
-
- # Msg Shar part 6 of 7
-
- # Shell Archive created by hpcnou!dat at Wed Feb 26 15:56:49 1986
-
- # To unpack the enclosed files, please use this file as input to the
- # Bourne (sh) shell. This can be most easily done by the command;
- # sh < thisfilename
-
- # This archive contains;
- # src/newmbox.c src/strings.c src/syscall.c src/utils.c
- # src/validname.c src/Makefile utils/answer.c utils/arepdaemon.c
- # utils/autoreply.c
-
-
- if [ ! -d src ]
- then
- echo creating directory src
- mkdir src
- fi
-
- # ---------- file src/newmbox.c ----------
-
-
- if [ -f src/newmbox.c ]
- then
- echo File 'src/newmbox.c' already exists\!
- exit 1
- fi
-
- echo extracting file src/newmbox.c...
- cat << 'END-OF-FILE' > src/newmbox.c
- /** newmbox.c **/
-
- /** read new mbox file
-
- (C) Copyright 1986 Dave Taylor
- **/
-
- #include <ctype.h>
-
- #ifdef BSD
- #undef tolower
- #endif
-
- #include "headers.h"
-
- #include <sys/types.h>
- #include <sys/stat.h>
- #ifdef BSD
- # include <sys/time.h>
- #else
- # include <time.h>
- #endif
-
- int
- newmbox(stat, resync)
- int stat, resync;
- {
- /** 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 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!!
- **/
-
- int switching_to_default = 0;
- char buff[SLEN];
-
- dprint2("newmbox(stat=%d, resync=%d)\n", stat, resync);
-
- dprint1("\tfile-changed = %s\n\n", onoff(file_changed));
-
- if (stat > 0) {
- if (strlen(infile) == 0) /* no filename yet?? */
- sprintf(infile,"%s%s",mailhome, username);
- }
- else { /* get name of new mailbox! */
- MoveCursor(LINES-3, 30);
- CleartoEOS();
- show_last_error();
- if (mbox_specified != 2) {
- PutLine(LINES-2,0,"Name of new mailbox: ");
- buff[0] = '\0';
- (void) optionally_enter(buff, LINES-2, 21, FALSE);
- ClearLine(LINES-2);
- if (strlen(buff) == 0) {
- if (resync && file_changed)
- strcpy(buff, infile);
- else
- return(FALSE);
- }
- if (strcmp(buff, infile) == 0 && ! resync) {
- error("already reading that mailbox!");
- return(FALSE);
- }
- if (first_word(buff, mailhome) && ! resync) {
- mbox_specified = 0; /* fake program to think that */
- stat = 1; /* we're the default file */
- switching_to_default++; /* remember this act! */
- }
- else if (strcmp(buff, "!") == 0) { /* go to mailbox */
- sprintf(buff,"%s%s", mailhome, username);
- if (! resync || (resync && ! file_changed)) {
- if (strcmp(buff, infile) == 0) { /* are we reading it? */
- error("already reading your incoming mailbox!");
- return(FALSE);
- }
- }
- if (! resync || (resync && ! file_changed)) {
- mbox_specified = 0; /* fake program to think that */
- stat = 1; /* we're the default file */
- switching_to_default++; /* remember this act! */
- }
- }
-
- if (! expand_filename(buff)) {
- error1("cannot expand file %s", buff);
- if (resync && file_changed)
- strcpy(buff, infile);
- else
- return(FALSE);
- }
-
- if (! can_access(buff,"r")) {
- error1("cannot open file %s", buff);
- if (resync && file_changed)
- strcpy(buff, infile);
- else
- return(FALSE);
- }
-
- if (resync && file_changed && strcmp(buff, infile) == 0)
- PutLine(20,40,"Resynchronizing file");
- else
- PutLine(20,40,"Mailbox: %s", buff);
- CleartoEOLN();
- strcpy(infile,buff);
- if (! switching_to_default) mbox_specified = 1;
- }
- else { /* starting filename given to routine */
- if (! can_access(infile,"r"))
- exit(PutLine(LINES, 0, "Could not open file %s!\n", infile));
- mbox_specified = 1;
- }
- }
-
- clear_error();
- clear_central_message();
-
- if ((mailfile = fopen(infile,"r")) == NULL)
- message_count = 0;
- else if (stat < 2) { /* new mail file! */
- if (notesfile)
- message_count = read_notesfile(); /* can't get new notes! */
- else
- message_count = read_headers(FALSE);
- }
- else /* resync with current mail file */
- message_count = read_headers(TRUE);
-
- if (message_count && stat < 2) current = 1;
-
- header_page = 0;
-
- return(TRUE);
- }
-
- int
- read_headers(stat)
- int stat;
- {
- /** 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 msg session. If stat is set, the program will then copy
- the delete flag from the previous data structure value to the
- new one if possible. This is for re-reading the mailfile!
- Added: reads and formats the date from the first 'From' line
- **/
-
- FILE *temp;
- char buffer[LONG_STRING], temp_filename[SLEN];
- register int line = 0, count = 0, subj = 0, copyit = 0, in_header = 1;
- long bytes = 0L, line_bytes = 0L;
- static int first_read = 0;
- int count_x, count_y = 17;
-
- dprint1("read_headers(stat=%d)\n", stat);
-
- if (! first_read++) {
- MoveCursor(LINES-2, 0);
- CleartoEOS();
- PutLine(LINES-1, 0, "Reading in %s, message: 0", infile);
- count_x = LINES-1;
- count_y = 22 + strlen(infile);
- }
- else {
- PutLine(LINES-2, 0, "Reading message: 0");
- count_x = LINES-2;
- }
-
- if (mbox_specified == 0) {
- lock(INCOMING); /* ensure no mail arrives while we do this! */
- sprintf(temp_filename,"%s%s",temp_mbox, username);
- if ((temp = fopen(temp_filename,"w")) == NULL) {
- unlock(); /* remove lock file! */
- Raw(OFF);
- printf("Could not open file %s for writing (uid=%d)...\n",
- temp_filename, getuid());
- system_call("/bin/ls -l /tmp/*", SH);
- leave(error1("could not open file %s for writing!",
- temp_filename));
- }
- get_mailtime();
- copyit++;
- chown(temp_filename, userid, getgid());
- }
-
- while (fgets(buffer, LONG_STRING, mailfile) != NULL) {
- if (line == 0) { /* first line of file... */
-
- if (! mbox_specified) {
- if (first_word(buffer, "Forward to "))
- set_central_message("Mail being forwarded to %s",
- (char *) (buffer + 11));
- }
-
- /* Are we reading in a notesfile file without the flag
- turned on??? */
-
- if (first_word(buffer, NOTES_HEADER)) { /* if so... */
- rewind(mailfile);
- notesfile++; /* set da flag, boss-man */
- return(read_notesfile()); /* hop over to notes */
- }
- }
-
- if (copyit) fputs(buffer, temp);
- line_bytes = (long) strlen(buffer);
- line++;
- if (first_word(buffer,"From ")) {
- if (real_from(buffer, &header_table[count])) {
- header_table[count].offset = (long) bytes;
- if (! stat || count > message_count)
- header_table[count].delete = 0; /* clear flag! */
- strcpy(header_table[count].subject, ""); /* clear subj */
- header_table[count++].lines = line;
- header_table[count].priority = 0;
- subj = 0;
- in_header = 1;
- PutLine(count_x, count_y, "%d", count);
- if (count > 1)
- header_table[count-2].lines = header_table[count-1].lines -
- header_table[count-2].lines;
- }
- }
- 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, SLEN);
- }
- }
- else if (first_word(buffer,"From:"))
- parse_arpa_from(buffer, header_table[count-1].from);
- else if (first_word(buffer, "Date:"))
- parse_arpa_date(buffer, &header_table[count-1]);
- else if (first_word(buffer, "Priority:"))
- header_table[count-1].priority++;
- 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]);
- }
- }
- }
- bytes += (long) line_bytes;
- }
-
- total_lines_in_file = line;
- header_table[count-1].lines = line - header_table[count-1].lines + 1;
-
- if (mbox_specified == 0) {
- unlock(); /* remove lock file! */
- fclose(mailfile);
- fclose(temp);
- if ((mailfile = fopen(temp_filename,"r")) == NULL) {
- MoveCursor(LINES,0);
- Raw(OFF);
- printf("Fatal error: could not reopen %s as temp mail file!\n",
- temp_filename);
- leave();
- }
- }
- else
- rewind(mailfile);
-
- return(count);
- }
- END-OF-FILE
-
- size=`wc -c < src/newmbox.c`
-
- if [ $size != 8124 ]
- then
- echo Warning: src/newmbox.c changed - should be 8124 bytes, not $size bytes
- fi
-
- chmod 644 src/newmbox.c
-
- # ---------- file src/strings.c ----------
-
-
- if [ -f src/strings.c ]
- then
- echo File 'src/strings.c' already exists\!
- exit 1
- fi
-
- echo extracting file src/strings.c...
- cat << 'END-OF-FILE' > src/strings.c
- /** strings.c **/
-
- /** This file contains all the string oriented functions for the
- MSG Mailer, and lots of other generally useful string functions!
-
- For BSD systems, this file also includes the function "tolower"
- to translate the given character from upper case to lower case.
-
- (C) Copyright 1985, Dave Taylor
- **/
-
- #include <stdio.h>
- #include "headers.h"
- #include <ctype.h>
-
- #ifdef BSD
- #undef tolower
- #undef toupper
- #endif
-
- /** forward declarations **/
-
- char *format_long(), *strip_commas(), *tail_of_string(), *shift_lower(),
- *get_token(), *strip_parens(), *argv_zero();
-
- #ifdef BSD
-
- int
- tolower(ch)
- char ch;
- {
- /** This should be a macro call, but if you use this as a macro
- calls to 'tolower' where the argument is a function call will
- cause the function to be called TWICE which is obviously the
- wrong behaviour. On the other hand, to just blindly translate
- assuming the character is always uppercase can cause BIG
- problems, so...
- **/
-
- return ( isupper(ch) ? ch - 'A' + 'a' : ch );
- }
-
- int
- toupper(ch)
- char ch;
- {
- /** see comment for above routine - tolower() **/
-
- return ( islower(ch) ? ch - 'a' + 'A' : ch );
- }
-
- #endif
-
- int
- in_string(buffer, pattern)
- char *buffer, *pattern;
- {
- /** Returns TRUE iff pattern occurs IN IT'S ENTIRETY in buffer. **/
-
- register int i = 0, j = 0;
-
- while (buffer[i] != '\0') {
- while (buffer[i++] == pattern[j++])
- if (pattern[j] == '\0')
- return(TRUE);
- i = i - j + 1;
- j = 0;
- }
- return(FALSE);
- }
-
- tail_of(from, buffer, header_line)
- char *from, *buffer;
- int header_line;
- {
- /** Return last two words of 'from'. This is to allow
- painless display of long return addresses as simply the
- machine!username. Alternatively, if the first three
- characters of the 'from' address are 'To:' and 'header_line'
- is TRUE, then return the buffer value prepended with 'To '.
- **/
-
- /** Note: '!' delimits Usenet nodes, '@' delimits ARPA nodes,
- ':' delimits CSNet & Bitnet nodes, and '%' delimits
- multiple stage ARPA hops... **/
-
- register int loc, i = 0, cnt = 0;
- char tempbuffer[SLEN];
-
-
- for (loc = strlen(from)-1; loc >= 0 && cnt < 2; loc--) {
- if (from[loc] == '!' || from[loc] == '@' ||
- from[loc] == ':') cnt++;
- if (cnt < 2) buffer[i++] = from[loc];
- }
-
- buffer[i] = '\0';
-
- reverse(buffer);
-
- if ((strncmp(buffer,"To:", 3) == 0) && header_line)
- buffer[2] = ' ';
- else if ((strncmp(from, "To:", 3) == 0) && header_line) {
- sprintf(tempbuffer,"To %s", buffer);
- strcpy(buffer, tempbuffer);
- }
- else if (strncmp(buffer, "To:", 3) == 0) {
- for (i=3; i < strlen(buffer); i++)
- tempbuffer[i-3] = buffer[i];
- tempbuffer[i-3] = '\0';
- strcpy(buffer, tempbuffer);
- }
- }
-
- char *format_long(inbuff, init_len)
- char *inbuff;
- int init_len;
- {
- /** Return buffer with \n\t sequences added at each point
- where it would be more than 80 chars long. It only
- allows the breaks at legal points (ie white spaces).
- init-len is the characters already on the first line...
- Changed so that if this is called while mailing without
- the overhead of "msg", it'll include "\r\n\t" instead.
- **/
-
- static char ret_buffer[VERY_LONG_STRING];
- register int index = 0, current_length = 0, depth=15, i;
- char buffer[VERY_LONG_STRING];
- char *word, *bufptr;
-
- strcpy(buffer, inbuff);
-
- bufptr = (char *) buffer;
-
- current_length = init_len + 2; /* for luck */
-
- while ((word = get_token(bufptr," ", depth)) != NULL) {
- if (strlen(word) + current_length > 80) {
- if (index > 0) {
- if (mail_only)
- ret_buffer[index++] = '\r';
- ret_buffer[index++] = '\n';
- ret_buffer[index++] = '\t';
- }
- for (i=0; i<strlen(word); i++)
- ret_buffer[index++] = word[i];
- current_length = strlen(word) + 8; /* 8 = TAB */
- }
- else {
- if (index > 0)
- ret_buffer[index++] = ' ';
- for (i=0; i<strlen(word); i++)
- ret_buffer[index++] = word[i];
- current_length += strlen(word) + 1;
- }
-
- bufptr = NULL;
- }
-
- ret_buffer[index] = '\0';
-
- return( (char *) ret_buffer);
- }
-
- char *strip_commas(string)
- char *string;
- {
- /** return string with all commas changed to spaces. This IS
- destructive and will permanently change the input string.. **/
-
- register int i;
-
- for (i=0; i < strlen(string); i++)
- if (string[i] == COMMA)
- string[i] = SPACE;
-
- return( (char *) string);
- }
-
- char *strip_parens(string)
- char *string;
- {
- /** Return string with all parenthesized information removed.
- This is a non-destructive algorithm... **/
-
- static char buffer[VERY_LONG_STRING];
- register int i, depth = 0, buffer_index = 0;
-
- for (i=0; i < strlen(string); i++) {
- if (string[i] == '(')
- depth++;
- else if (string[i] == ')')
- depth--;
- else if (depth == 0)
- buffer[buffer_index++] = string[i];
- }
-
- buffer[buffer_index] = '\0';
-
- return( (char *) buffer);
- }
-
- move_left(string, chars)
- char string[];
- int chars;
- {
- /** moves string chars characters to the left DESTRUCTIVELY **/
-
- register int i;
-
- chars--; /* index starting at zero! */
-
- for (i=chars; string[i] != '\0' && string[i] != '\n'; i++)
- string[i-chars] = string[i];
-
- string[i-chars] = '\0';
- }
-
- remove_first_word(string)
- char *string;
- { /** removes first word of string, ie up to first non-white space
- following a white space! **/
-
- register int loc;
-
- for (loc = 0; string[loc] != ' ' && string[loc] != '\0'; loc++)
- ;
-
- while (string[loc] == ' ' || string[loc] == '\t')
- loc++;
-
- move_left(string, ++loc);
- }
-
- char *tail_of_string(string, maxchars)
- char *string;
- int maxchars;
- {
- /** Return a string that is the last 'maxchars' characters of the
- given string. This is only used if the first word of the string
- is longer than maxchars, else it will return what is given to
- it...
- **/
-
- static char buffer[SLEN];
- register int index, i;
-
- for (index=0;! whitespace(string[index]) && index < strlen(string);
- index++)
- ;
-
- if (index < maxchars) {
- strncpy(buffer, string, maxchars-2); /* word too short */
- buffer[maxchars-2] = '.';
- buffer[maxchars-1] = '.';
- buffer[maxchars] = '.';
- buffer[maxchars+1] = '\0';
- }
- else {
- i = maxchars;
- buffer[i--] = '\0';
- while (i > 1)
- buffer[i--] = string[index--];
- buffer[2] = '.';
- buffer[1] = '.';
- buffer[0] = '.';
- }
-
- return( (char *) buffer);
- }
-
- reverse(string)
- char *string;
- {
- /** reverse string... pretty trivial routine, actually! **/
-
- char buffer[SLEN];
- register int i, j = 0;
-
- for (i = strlen(string)-1; i >= 0; i--)
- buffer[j++] = string[i];
-
- buffer[j] = '\0';
-
- strcpy(string, buffer);
- }
-
- int
- get_word(buffer, start, word)
- char *buffer, *word;
- int start;
- {
- /** return next word in buffer, starting at 'start'.
- delimiter is space or end-of-line. Returns the
- location of the next word, or -1 if returning
- the last word in the buffer. -2 indicates empty
- buffer! **/
-
- register int loc = 0;
-
- while (buffer[start] == ' ' && buffer[start] != '\0')
- start++;
-
- if (buffer[start] == '\0') return(-2); /* nothing IN buffer! */
-
- while (buffer[start] != ' ' && buffer[start] != '\0')
- word[loc++] = buffer[start++];
-
- word[loc] = '\0';
- return(start);
- }
-
- int
- chloc(string, ch)
- char *string, ch;
- {
- /** returns the index of ch in string, or -1 if not in string **/
- register int i;
-
- for (i=0; i<strlen(string); i++)
- if (string[i] == ch) return(i);
- return(-1);
- }
-
- int
- two_words(string)
- char *string;
- {
- /** is 'string' exactly two words? Return TRUE or FALSE **/
-
- return( words_in_string(string) == 2 );
-
- }
-
- char *shift_lower(string)
- char *string;
- {
- /** return 'string' shifted to lower case. Do NOT touch the
- actual string handed to us! **/
-
- static char buffer[LONG_SLEN];
- register int i;
-
- for (i=0; i < strlen(string); i++)
- if (isupper(string[i]))
- buffer[i] = tolower(string[i]);
- else
- buffer[i] = string[i];
-
- buffer[strlen(string)] = 0;
-
- return( (char *) buffer);
- }
-
- int
- words_in_string(buffer)
- char *buffer;
- {
- /** This routine returns the number of words in the given line.
- A word is defined as a series of characters surrounded by
- either the beginning of the string, the end of the string,
- or white space.
- For example, the following line has 8 words:
- "This is a test of the program, okay?"
- **/
-
- register int count = 0, i = 0;
-
- while (buffer[i] != '\0') {
-
- while (whitespace(buffer[i])) i++;
-
- if (buffer[i] != '\0')
- count++;
-
- while (! whitespace(buffer[i]) && buffer[i] != '\0') i++;
- }
- return(count);
- }
-
- clean_up(buffer)
- char *buffer;
- {
- /** This routine takes a string of the form "a:b" and returns it
- as just "b"... **/
-
- char mybuffer[SLEN];
- register int loc, myloc = 0;
-
- for (loc=0; buffer[loc] != ':'; loc++)
- ;
-
- while (buffer[++loc] != '\0')
- mybuffer[myloc++] = buffer[loc];
-
- mybuffer[myloc] = '\0';
-
- strcpy(buffer, mybuffer);
- }
-
- Centerline(line, string)
- int line;
- char *string;
- {
- /** Output 'string' on the given line, centered. **/
-
- register int length, col;
-
- length = strlen(string);
-
- if (length > COLUMNS)
- col = 0;
- else
- col = (COLUMNS - length) / 2;
-
- PutLine(line, col, string);
- }
-
- char *argv_zero(string)
- char *string;
- {
- /** given a string of the form "/something/name" return a
- string of the form "name"... **/
-
- static char buffer[NLEN];
- register int i, j=0;
-
- for (i=strlen(string)-1; string[i] != '/'; i--)
- buffer[j++] = string[i];
- buffer[j] = '\0';
-
- reverse(buffer);
-
- return( (char *) buffer);
- }
-
- #define MAX_RECURSION 20 /* up to 20 deep recursion */
-
- char *get_token(source, keys, depth)
- char *source, *keys;
- int depth;
- {
- /** This function is similar to strtok() (see "opt_utils")
- but allows nesting of calls via pointers...
- **/
-
- register int last_ch;
- static char *buffers[MAX_RECURSION];
- char *return_value, *sourceptr;
-
- if (depth > MAX_RECURSION) {
- error1("get_token calls nested greater than %d deep!",
- MAX_RECURSION);
- emergency_exit();
- }
-
- if (source != NULL)
- buffers[depth] = source;
-
- sourceptr = buffers[depth];
-
- if (*sourceptr == '\0')
- return(NULL); /* we hit end-of-string last time!? */
-
- sourceptr += strspn(sourceptr, keys); /* skip the bad.. */
-
- if (*sourceptr == '\0') {
- buffers[depth] = sourceptr;
- return(NULL); /* we've hit end-of-string */
- }
-
- last_ch = strcspn(sourceptr, keys); /* end of good stuff */
-
- return_value = sourceptr; /* and get the ret */
-
- sourceptr += last_ch; /* ...value */
-
- if (*sourceptr != '\0') /** don't forget if we're at end! **/
- sourceptr++;
-
- return_value[last_ch] = '\0'; /* ..ending right */
-
- buffers[depth] = sourceptr; /* save this, mate! */
-
- return((char *) return_value); /* and we're outta here! */
- }
- END-OF-FILE
-
- size=`wc -c < src/strings.c`
-
- if [ $size != 10790 ]
- then
- echo Warning: src/strings.c changed - should be 10790 bytes, not $size bytes
- fi
-
- chmod 644 src/strings.c
-
- # ---------- file src/syscall.c ----------
-
-
- if [ -f src/syscall.c ]
- then
- echo File 'src/syscall.c' already exists\!
- exit 1
- fi
-
- echo extracting file src/syscall.c...
- cat << 'END-OF-FILE' > src/syscall.c
- /** syscall.c **/
-
- /** These routines are used for user-level system calls, including the
- '!' command and the '|' commands...
-
- (C) Copyright 1986 Dave Taylor
- **/
-
- #include "headers.h"
-
- #include <signal.h>
-
- char *argv_zero();
-
- int
- subshell()
- {
- /** spawn a subshell with either the specified command
- returns non-zero if screen rewrite needed
- **/
-
- char command[SLEN];
- int ret;
-
- PutLine(LINES-3,COLUMNS-40,"(use 'sh' or 'csh' for a shell)");
- PutLine(LINES-2,0,"Shell Command: ");
- command[0] = '\0';
- (void) optionally_enter(command, LINES-2, 15, FALSE);
- if (strlen(command) == 0) {
- MoveCursor(LINES-2,0); CleartoEOLN();
- return(0);
- }
-
- MoveCursor(LINES,0); CleartoEOLN();
- Raw(OFF);
- if (cursor_control) transmit_functions(OFF);
-
- ret = system_call(command, USER_SHELL);
-
- printf("\nPress <return> to return to MSG: ");
- Raw(ON);
- (void) getchar();
- if (cursor_control) transmit_functions(ON);
-
- if (ret != 0) error1("Return code was %d", ret);
- return(1);
- }
-
- system_call(string, shell_type)
- char *string;
- int shell_type;
- {
- /** execute 'string', setting uid to userid... **/
- /** if shell-type is "SH" /bin/sh is used regardless of the
- users shell setting. Otherwise, "USER_SHELL" is sent **/
-
- int status, pid, w;
- register int (*istat)(), (*qstat)();
-
- dprint2("system_call('%s', %s)\n", string,
- shell_type == SH? "SH" : "USER-SHELL");
-
- if ((pid = fork()) == 0) {
- setuid(userid); /* back to the normal user! */
- if (strlen(shell) > 0 && shell_type == USER_SHELL) {
- execl(shell, argv_zero(shell), "-c", string, 0);
- }
- else
- execl("/bin/sh", "sh", "-c", string, 0);
- _exit(127);
- }
-
- istat = signal(SIGINT, SIG_IGN);
- qstat = signal(SIGQUIT, SIG_IGN);
-
- while ((w = wait(&status)) != pid && w != -1)
- ;
-
- if (w == -1) status = -1;
-
- signal(SIGINT, istat);
- signal(SIGQUIT, qstat);
-
- return(status);
- }
-
- int
- pipe()
- {
- /** pipe the current message to the specified sequence.. **/
-
- char command[SLEN], buffer[LONG_SLEN];
- int ret, lines;
-
- PutLine(LINES-2,0,"Pipe current msg to: ");
- command[0] = '\0';
- (void) optionally_enter(command, LINES-2, 21, FALSE);
- if (strlen(command) == 0) {
- MoveCursor(LINES-2,0); CleartoEOLN();
- return(0);
- }
-
- MoveCursor(LINES,0); CleartoEOLN();
- Raw(OFF);
-
- lines = header_table[current-1].lines;
-
- if (cursor_control) transmit_functions(OFF);
-
- sprintf(buffer, "%s %s %d %d - | %s", cutfile,
- infile, header_table[current-1].offset,
- lines, command);
-
- ret = system_call(buffer, USER_SHELL);
-
- printf("\nPress <return> to return to MSG: ");
- Raw(ON);
- (void) getchar();
- if (cursor_control) transmit_functions(ON);
-
- if (ret != 0) error1("Return code was %d", ret);
- return(1);
- }
-
- printmsg()
- {
- /** print specified message using 'printout' variable.
- Error message iff printout not defined! **/
-
- FILE *temp;
- char buffer[LONG_SLEN], filename[SLEN], printbuffer[LONG_SLEN];
- int retcode;
-
- dprint1("printmsg()\n\tprintout = %s\n", printout);
- dprint1("\tcurrent message = %d\n", current);
-
- if (strlen(printout) == 0) {
- error("PRINTMAIL not defined! Don't know how to print message");
- return;
- }
-
- if (current == 0) {
- error("No mail to print!");
- return;
- }
-
- sprintf(filename,"%s%d", temp_print, getpid());
-
- if ((temp = fopen(filename,"w")) == NULL) {
- error1("Could not open file %s as a temporary file", filename);
- return;
- }
-
- copy_message("", temp, FALSE);
-
- fclose(temp);
-
- if (in_string(printout, "%s"))
- sprintf(printbuffer, printout, filename);
- else
- sprintf(printbuffer, "%s %s", printout, filename);
-
- sprintf(buffer,"(%s 2>&1 ) > /dev/null",
- printbuffer, filename);
-
- error("working...");
-
- if ((retcode = system_call(buffer, SH)) == 0)
- error("Message queued up to print");
- else
- error1("Printout failed with return code %d", retcode);
-
- unlink(filename); /* remove da temp file! */
- }
- END-OF-FILE
-
- size=`wc -c < src/syscall.c`
-
- if [ $size != 3869 ]
- then
- echo Warning: src/syscall.c changed - should be 3869 bytes, not $size bytes
- fi
-
- chmod 644 src/syscall.c
-
- # ---------- file src/utils.c ----------
-
-
- if [ -f src/utils.c ]
- then
- echo File 'src/utils.c' already exists\!
- exit 1
- fi
-
- echo extracting file src/utils.c...
- cat << 'END-OF-FILE' > src/utils.c
- /** utils.c **/
-
- /** Utility routines for MSG
-
- All routines herein: (C) Copyright 1985 Dave Taylor
- **/
-
- #include "headers.h"
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <ctype.h>
-
- #ifdef BSD
- #undef tolower
- #endif
-
- #include <signal.h>
- #include <errno.h>
-
- emergency_exit()
- {
- /** used in dramatic cases when we must leave without altering
- ANYTHING about the system... **/
-
- Raw(OFF);
- if (cursor_control) transmit_functions(OFF);
- if (hp_terminal) softkeys_off();
-
- if (cursor_control)
- MoveCursor(LINES, 0);
-
- printf("\n\rEmergency Exit taken! All temp files intact!\n\r\n\r");
-
- exit(1);
- }
-
- leave(val)
- int val; /* not used, placeholder for signal catching! */
- {
- char buffer[SLEN];
-
- dprint1("leave(%d)\n", val);
-
- Raw(OFF);
- if (cursor_control) transmit_functions(OFF);
- if (hp_terminal) softkeys_off();
-
- sprintf(buffer,"%s%d",temp_file, getpid()); /* editor buffer */
- (void) unlink(buffer);
-
- if (! mail_only) {
- sprintf(buffer,"%s%d",temp_file, getpid()+1); /* editor buffer */
- (void) unlink(buffer);
- }
-
- sprintf(buffer,"%s%s",temp_mbox, username); /* temp mailbox */
- (void) unlink(buffer);
-
- sprintf(buffer,"%s%s.lock",mailhome, username); /* lock file */
- (void) unlink(buffer);
-
- if (! mail_only)
- MoveCursor(LINES-1,0);
- putchar('\n');
-
- exit(0);
- }
-
- leave_locked(val)
- int val; /* not used, placeholder for signal catching! */
- {
- /** same as leave routine, but don't disturb lock file **/
-
- char buffer[SLEN];
-
- dprint1("leave_locked(%d)\n", val);
-
- Raw(OFF);
- if (cursor_control) transmit_functions(OFF);
- if (hp_terminal) softkeys_off();
-
- sprintf(buffer,"%s%d",temp_file, getpid()); /* editor buffer */
- (void) unlink(buffer);
-
- sprintf(buffer,"%s%d",temp_file, getpid()+1); /* editor buffer */
- (void) unlink(buffer);
-
- sprintf(buffer,"%s%s",temp_mbox, username); /* temp mailbox */
- (void) unlink(buffer);
-
- MoveCursor(LINES-1,0);
- putchar('\n');
-
- exit(0);
- }
-
- int
- get_page(current)
- int current;
- {
- /** ensure that 'current' is on the displayed page,
- returning non-zero iff the page changed! **/
-
- register int first_on_page, last_on_page;
-
- first_on_page = (header_page * headers_per_page) + 1;
-
- last_on_page = first_on_page + headers_per_page - 1;
-
- if (current > last_on_page) {
- header_page = (int) (current-1) / headers_per_page;
- return(1);
- }
- else if (current < first_on_page) {
- header_page = (int) (current-1) / headers_per_page;
- return(1);
- }
- else
- return(0);
- }
-
- int
- copy_to_self(buffer)
- char *buffer;
- {
- /** returns true iff buffer = 'Cc: username' where username
- is the account name of the person sending the message.
- Used for weeding out 'Cc:' lines from the messages if
- 'weed' is turned on. **/
-
- /** note: tail_of() is located in file "strings.c" **/
-
- char name[SLEN], buf[SLEN];
- register int i=0, j=0;
-
- dprint1("copy_to_self(%s)\n", buffer);
-
- tail_of(header_table[current-1].from, name, FALSE);
-
- while (name[i] != '!' && i < strlen(name))
- i++;
-
- if (name[i] == '!') {
- for (i++; i < strlen(name); i++)
- name[j++] = name[i];
-
- name[j] = 0;
- }
-
- sprintf(buf, "Cc: %s\n", name);
-
- return( strcmp(buf, buffer) == 0 );
- }
- END-OF-FILE
-
- size=`wc -c < src/utils.c`
-
- if [ $size != 3154 ]
- then
- echo Warning: src/utils.c changed - should be 3154 bytes, not $size bytes
- fi
-
- chmod 644 src/utils.c
-
- # ---------- file src/validname.c ----------
-
-
- if [ -f src/validname.c ]
- then
- echo File 'src/validname.c' already exists\!
- exit 1
- fi
-
- echo extracting file src/validname.c...
- cat << 'END-OF-FILE' > src/validname.c
- /** validname.c **/
-
- /** This routine takes a single address, no machine hops or
- anything, and returns 1 if it's valid and 0 if not. The
- algorithm it uses is the same one that uux uses, namely:
-
- 1. Is there a file '/usr/mail/%s'?
- 2. Is there a password entry for %s?
-
- (C) Copyright 1986 Dave Taylor
- **/
-
- #include <stdio.h>
-
- #include "defs.h"
-
- int
- valid_name(name)
- char *name;
- {
- /** does what it says above, boss! **/
-
- char filebuf[SLEN];
-
- #ifdef NOCHECK_VALIDNAME
-
- return(1); /* always say it's okay! */
-
- #else
-
- sprintf(filebuf,"%s/%s", mailhome, name);
-
- if (access(filebuf, ACCESS_EXISTS) == 0)
- return(1);
-
- if (getpwnam(name) != NULL)
- return(1);
-
- return(0);
-
- #endif
-
- }
- END-OF-FILE
-
- size=`wc -c < src/validname.c`
-
- if [ $size != 707 ]
- then
- echo Warning: src/validname.c changed - should be 707 bytes, not $size bytes
- fi
-
- chmod 644 src/validname.c
-
- # ---------- file src/Makefile ----------
-
-
- if [ -f src/Makefile ]
- then
- echo File 'src/Makefile' already exists\!
- exit 1
- fi
-
- echo extracting file src/Makefile...
- cat << 'END-OF-FILE' > src/Makefile
- #
- # Makefile for the MSG mail program.
- #
- # (C) Copyright 1986, Dave Taylor
- #
- # Last modification: January 23rd, 1986
-
- CFILES= addr_utils.c alias.c aliasdb.c aliaslib.c args.c curses.c date.c \
- delete.c encode.c file.c file_utils.c fileio.c hdrconfg.c help.c \
- initialize.c input_utils.c mailout.c mailtime.c mkhdrs.c msg.c \
- newmbox.c notesfile.c output_utils.c pattern.c quit.c savecopy.c \
- read_rc.c reply.c return_addr.c screen.c showmsg.c strings.c \
- syscall.c utils.c validname.c softkeys.c opt_utils.c leavembox.c
-
- HEADERS=../hdrs/curses.h ../hdrs/defs.h ../hdrs/headers.h ../hdrs/msg.h
-
- OBJS= addr_utils.o alias.o aliasdb.o aliaslib.o args.o curses.o date.o \
- delete.o encode.o file.o file_utils.o fileio.o hdrconfg.o help.o \
- initialize.o input_utils.o mailout.o mailtime.o mkhdrs.o msg.o \
- newmbox.o notesfile.o output_utils.o pattern.o quit.o savecopy.o \
- read_rc.o reply.o return_addr.o screen.o showmsg.o strings.o \
- syscall.o utils.o validname.o softkeys.o opt_utils.o leavembox.o
-
- # if on BSD use
- # DEFINE=-DBSD
- # else if on UTS use
- # DEFINE=-DUTS
- # else
- DEFINE=
-
- BIN= ../bin
- LIBS= -ltermcap
- CFLAGS= -O -I../hdrs
- CC= /bin/cc
- RM= /bin/rm -f
-
- .c.o: ${HEADERS}
- ${CC} -c ${CFLAGS} ${DEFINE} $*.c
-
- ../bin/msg: ${OBJS} ${EXTRA} ${HEADERS} ../hdrs/msg.h
- ${CC} -o ${BIN}/msg -n ${OBJS} ${LIBS}
-
- curses.o: curses.c ../hdrs/curses.h
- ${CC} -c -O -DRAWMODE ${DEFINE} -I../hdrs curses.c
-
- clean:
- ${RM} ${OBJS} LINT.OUT
-
- lint: LINT.OUT
-
- LINT.OUT: ${CFILES}
- lint -p -I../hdrs ${CFILES} > LINT.OUT
-
- listing:
- @../bin/makelisting Makefile ${HEADERS} ${CFILES}
- @echo LISTING generated.
- END-OF-FILE
-
- size=`wc -c < src/Makefile`
-
- if [ $size != 1647 ]
- then
- echo Warning: src/Makefile changed - should be 1647 bytes, not $size bytes
- fi
-
- chmod 644 src/Makefile
-
- if [ ! -d utils ]
- then
- echo creating directory utils
- mkdir utils
- fi
-
- # ---------- file utils/answer.c ----------
-
-
- if [ -f utils/answer.c ]
- then
- echo File 'utils/answer.c' already exists\!
- exit 1
- fi
-
- echo extracting file utils/answer.c...
- cat << 'END-OF-FILE' > utils/answer.c
- /** answer.c **/
-
- /** This program is a phone message transcription system, and
- is designed for secretaries and the like, to allow them to
- painlessly generate electronic mail instead of paper forms.
-
- Note: this program ONLY uses the local alias file, and does not
- even read in the system alias file at all.
-
- (C) Copyright 1986, Dave Taylor
-
- **/
-
- #include <stdio.h>
- #include <fcntl.h>
- #include <ctype.h>
-
- #include "defs.h" /* MSG system definitions */
-
- struct alias_rec user_hash_table [MAX_UALIASES];
-
- int user_data; /* fileno of user data file */
-
- char *expand_group(), *get_alias_address(), *get_token();
-
- main()
- {
- FILE *fd;
- char *address, buffer[LONG_STRING], tempfile[SLEN];
- char name[SLEN], user_name[SLEN];
- int msgnum = 0, eof;
-
- read_alias_files();
-
- while (1) {
- if (msgnum > 9999) msgnum = 0;
-
- printf("\n-------------------------------------------------------------------------------\n");
-
- prompt: printf("\nMessage to: ");
- gets(user_name, SLEN);
-
- if ((strcmp(user_name,"quit") == 0) ||
- (strcmp(user_name,"exit") == 0) ||
- (strcmp(user_name,"done") == 0) ||
- (strcmp(user_name,"bye") == 0))
- exit(0);
-
- if (translate(user_name, name) == 0)
- goto prompt;
-
- address = get_alias_address(name, 1, 0);
-
- if (strlen(address) == 0) {
- printf("Sorry, could not find '%s' [%s] in list!\n", user_name,
- name);
- goto prompt;
- }
-
- sprintf(tempfile, "%s%d", temp_file, msgnum++);
-
- if ((fd = fopen(tempfile,"w")) == NULL)
- exit(printf("** Fatal Error: could not open %s to write\n",
- tempfile));
-
-
- printf("\nEnter message for %s ending with a blank line.\n\n",
- user_name);
-
- fprintf(fd,"\n\n");
-
- do {
- printf("> ");
- if (! (eof = (gets(buffer, SLEN) == NULL)))
- fprintf(fd, "%s\n", buffer);
- } while (! eof && strlen(buffer) > 0);
-
- fclose(fd);
-
- sprintf(buffer, "(%s -s \"While You Were Out\" %s < %s ; %s %s) &",
- mailx, address, tempfile, remove, tempfile);
-
- system(buffer);
- }
- }
-
- int
- translate(fullname, name)
- char *fullname, *name;
- {
- /** translate fullname into name..
- 'first last' translated to first_initial - underline - last
- 'initial last' translated to initial - underline - last
- Return 0 if error.
- **/
- register int i, lastname = 0;
-
- for (i=0; i < strlen(fullname); i++) {
-
- if (isupper(fullname[i]))
- fullname[i] = fullname[i] - 'A' + 'a';
-
- if (fullname[i] == ' ')
- if (lastname) {
- printf(
- "** Can't have more than 'FirstName LastName' as address!\n");
- return(0);
- }
- else
- lastname = i+1;
-
- }
-
- if (lastname)
- sprintf(name, "%c_%s", fullname[0], (char *) fullname + lastname);
- else
- strcpy(name, fullname);
-
- return(1);
- }
-
-
- read_alias_files()
- {
- /** read the user alias file **/
-
- char fname[SLEN];
- int hash;
-
- sprintf(fname, "%s/.alias_hash", getenv("HOME"));
-
- if ((hash = open(fname, O_RDONLY)) == -1)
- exit(printf("** Fatal Error: Could not open %s!\n", fname));
-
- read(hash, user_hash_table, sizeof user_hash_table);
- close(hash);
-
- sprintf(fname, "%s/.alias_data", getenv("HOME"));
-
- if ((user_data = open(fname, O_RDONLY)) == -1)
- return;
- }
-
- char *get_alias_address(name, mailing, depth)
- char *name;
- int mailing, depth;
- {
- /** return the line from either datafile that corresponds
- to the specified name. If 'mailing' specified, then
- fully expand group names. Returns NULL if not found.
- Depth is the nesting depth, and varies according to the
- nesting level of the routine. **/
-
- static char buffer[VERY_LONG_STRING];
- int loc;
-
- if ((loc = find(name, user_hash_table, MAX_UALIASES)) >= 0) {
- lseek(user_data, user_hash_table[loc].byte, 0L);
- get_line(user_data, buffer, LONG_STRING);
- if (buffer[0] == '!' && mailing)
- return( (char *) expand_group(buffer, depth));
- else
- return( (char *) buffer);
- }
-
- return( (char *) NULL);
- }
-
- char *expand_group(members, depth)
- char *members;
- int depth;
- {
- /** given a group of names separated by commas, this routine
- will return a string that is the full addresses of each
- member separated by spaces. Depth is the current recursion
- depth of the expansion (for the 'get_token' routine) **/
-
- char buffer[VERY_LONG_STRING];
- char buf[LONG_STRING], *word, *address, *bufptr;
-
- strcpy(buf, members); /* parameter safety! */
- buffer[0] = '\0'; /* nothing in yet! */
- bufptr = (char *) buf; /* grab the address */
- depth++; /* one more deeply into stack */
-
- while ((word = (char *) get_token(bufptr, "!, ", depth)) != NULL) {
- if ((address = (char *) get_alias_address(word, 1, depth)) == NULL) {
- fprintf(stderr, "Alias %s not found for group expansion!", word);
- return( (char *) NULL);
- }
- else if (strcmp(buffer,address) != 0) {
- sprintf(buffer,"%s %s", buffer, address);
- }
-
- bufptr = NULL;
- }
-
- return( (char *) buffer);
- }
-
- int
- find(word, table, size)
- char *word;
- struct alias_rec table[];
- int size;
- {
- /** find word and return loc, or -1 **/
- register int loc;
-
- if (strlen(word) > 20)
- exit(printf("Bad alias name: %s. Too long.\n", word));
-
- loc = hash_it(word, size);
-
- while (strcmp(word, table[loc].name) != 0) {
- if (table[loc].name[0] == '\0')
- return(-1);
- loc = (loc + 1) % size;
- }
-
- return(loc);
- }
-
- int
- hash_it(string, table_size)
- char *string;
- int table_size;
- {
- /** compute the hash function of the string, returning
- it (mod table_size) **/
-
- register int i, sum = 0;
-
- for (i=0; string[i] != '\0'; i++)
- sum += (int) string[i];
-
- return(sum % table_size);
- }
-
- get_line(fd, buffer)
- int fd;
- char *buffer;
- {
- /* read from file fd. End read upon reading either
- EOF or '\n' character (this is where it differs
- from a straight 'read' command!) */
-
- register int i= 0;
- char ch;
-
- while (read(fd, &ch, 1) > 0)
- if (ch == '\n' || ch == '\r') {
- buffer[i] = 0;
- return;
- }
- else
- buffer[i++] = ch;
- }
-
- print_long(buffer, init_len)
- char *buffer;
- int init_len;
- {
- /** print buffer out, 80 characters (or less) per line, for
- as many lines as needed. If 'init_len' is specified,
- it is the length that the first line can be.
- **/
-
- register int i, loc=0, space, length;
-
- /* In general, go to 80 characters beyond current character
- being processed, and then work backwards until space found! */
-
- length = init_len;
-
- do {
- if (strlen(buffer) > loc + length) {
- space = loc + length;
- while (buffer[space] != ' ' && space > loc + 50) space--;
- for (i=loc;i <= space;i++)
- putchar(buffer[i]);
- putchar('\n');
- loc = space;
- }
- else {
- for (i=loc;i < strlen(buffer);i++)
- putchar(buffer[i]);
- putchar('\n');
- loc = strlen(buffer);
- }
- length = 80;
- } while (loc < strlen(buffer));
- }
-
- /****
- The following is a newly chopped version of the 'strtok' routine
- that can work in a recursive way (up to 20 levels of recursion) by
- changing the character buffer to an array of character buffers....
- ****/
-
- #define MAX_RECURSION 20 /* up to 20 deep recursion */
-
- #undef NULL
- #define NULL (char *) 0 /* for this routine only */
-
- extern int strspn();
- extern char *strpbrk();
-
- char *get_token(string, sepset, depth)
- char *string, *sepset;
- int depth;
- {
-
- /** string is the string pointer to break up, sepstr are the
- list of characters that can break the line up and depth
- is the current nesting/recursion depth of the call **/
-
- register char *p, *q, *r;
- static char *savept[MAX_RECURSION];
-
- /** is there space on the recursion stack? **/
-
- if (depth >= MAX_RECURSION) {
- fprintf(stderr,"Error: Get_token calls nested greated than %d deep!\n",
- MAX_RECURSION);
- exit(1);
- }
-
- /* set up the pointer for the first or subsequent call */
- p = (string == NULL)? savept[depth]: string;
-
- if(p == 0) /* return if no tokens remaining */
- return(NULL);
-
- q = p + strspn(p, sepset); /* skip leading separators */
-
- if (*q == '\0') /* return if no tokens remaining */
- return(NULL);
-
- if ((r = strpbrk(q, sepset)) == NULL) /* move past token */
- savept[depth] = 0; /* indicate this is last token */
- else {
- *r = '\0';
- savept[depth] = ++r;
- }
- return(q);
- }
- END-OF-FILE
-
- size=`wc -c < utils/answer.c`
-
- if [ $size != 8207 ]
- then
- echo Warning: utils/answer.c changed - should be 8207 bytes, not $size bytes
- fi
-
- chmod 644 utils/answer.c
-
- # ---------- file utils/arepdaemon.c ----------
-
-
- if [ -f utils/arepdaemon.c ]
- then
- echo File 'utils/arepdaemon.c' already exists\!
- exit 1
- fi
-
- echo extracting file utils/arepdaemon.c...
- cat << 'END-OF-FILE' > utils/arepdaemon.c
- /** arepdaemon.c **/
-
- /** (C) Copyright 1986 Dave Taylor **/
-
- /** Keep track of mail as it arrives, and respond by sending a 'recording'
- file to the sender as new mail is received.
-
- Note: the user program that interacts with this program is the
- 'autoreply' program and that should be consulted for further
- usage information.
-
- This program is part of the 'autoreply' system, and is designed
- to run every hour and check all mailboxes listed in the file
- "/etc/autoreply.data", where the data is in the form:
-
- username replyfile current-mailfile-size
-
- To avoid a flood of autoreplies, this program will NOT reply to mail
- that contains header "X-Mailer: fastmail". Further, each time the
- program responds to mail, the 'mailfile size' entry is updated in
- the file /etc/autoreply.data to allow the system to be brought
- down and rebooted without any loss of data or duplicate messages.
-
- This daemon also uses a lock semaphore file, /usr/spool/uucp/LCK..arep,
- to ensure that more than one copy of itself is never running. For this
- reason, it is recommended that this daemon be started up each morning
- from cron, since it will either start since it's needed or simply see
- that the file is there and disappear.
-
- Since this particular program is the main daemon answering any
- number of different users, it must be run with uid root.
-
- (C) 1985, Dave Taylor, HP Colorado Networks Operation
- **/
-
- #include <stdio.h>
- #include <time.h>
- #include <sys/types.h>
- #include <sys/stat.h>
-
- #include "defs.h"
-
- #define arep_lock_file "/usr/spool/uucp/LCK..arep"
-
- #define autoreply_file "/etc/autoreply.data"
- #define fastmail "/usr/local/bin/fastmail"
-
- #define logfile "/etc/autoreply.log" /* first choice */
- #define logfile2 "/tmp/autoreply.log" /* second choice */
-
- #define BEGINNING 0 /* see fseek(3S) for info */
- #define SLEEP_TIME 3600 /* run once an hour */
- #define MAX_PEOPLE 20 /* max number in program */
-
- #define EXISTS 00 /* lock file exists?? */
- #define MODE 0777 /* lockfile creation mode */
-
- #define NLEN 20
-
- #define remove_return(s) if (strlen(s) > 0) { \
- if (s[strlen(s)-1] == '\n') \
- s[strlen(s)-1] = '\0'; \
- }
-
- struct replyrec {
- char username[NLEN]; /* login name of user */
- char mailfile[SLEN]; /* name of mail file */
- char replyfile[SLEN]; /* name of reply file */
- long mailsize; /* mail file size */
- int in_list; /* for new replies */
- } reply_table[MAX_PEOPLE];
-
- FILE *logfd; /* logfile (log action) */
- long autoreply_size = 0L; /* size of autoreply file */
- int active = 0; /* # of people 'enrolled' */
-
- FILE *open_logfile(); /* forward declaration */
-
- long bytes(); /* ditto */
-
- main()
- {
- long size;
- int person, data_changed;
-
- if (! lock())
- exit(0); /* already running! */
-
- while (1) {
-
- logfd = open_logfile(); /* open the log */
-
- /* 1. check to see if autoreply table has changed.. */
-
- if ((size = bytes(autoreply_file)) != autoreply_size) {
- read_autoreply_file();
- autoreply_size = size;
- }
-
- /* 2. now for each active person... */
-
- data_changed = 0;
-
- for (person = 0; person < active; person++) {
- if ((size = bytes(reply_table[person].mailfile)) !=
- reply_table[person].mailsize) {
- if (size > reply_table[person].mailsize)
- read_newmail(person);
- /* else mail removed - resync */
- reply_table[person].mailsize = size;
- data_changed++;
- }
- }
-
- /* 3. if data changed, update autoreply file */
-
- if (data_changed)
- update_autoreply_file();
-
- close_logfile(); /* close the logfile again */
-
- /* 4. Go to sleep... */
-
- sleep(SLEEP_TIME);
- }
- }
-
- int
- read_autoreply_file()
- {
- /** We're here because the autoreply file has changed size!! It
- could either be because someone has been added or because
- someone has been removed...since the list will always be in
- order (nice, eh?) we should have a pretty easy time of it...
- **/
-
- FILE *file;
- char username[SLEN], replyfile[SLEN];
- int person;
- long size;
-
- log("Autoreply data file has changed! Reading...");
-
- if ((file = fopen(autoreply_file,"r")) == NULL) {
- log("No-one is using autoreply...");
- return(0);
- }
-
- for (person = 0; person < active; person++)
- reply_table[person].in_list = 0;
-
- while (fscanf(file, "%s %s %dl", username, replyfile, &size) != EOF) {
- /* check to see if this person is already in the list */
- if ((person = in_list(username)) != -1) {
- reply_table[person].in_list = 1;
- reply_table[person].mailsize = size; /* sync */
- }
- else { /* if not, add them */
- if (active == MAX_PEOPLE) {
- unlock();
- exit(log("Couldn't add %s - already at max people!",
- username));
- }
- log("adding %s to the active list", username);
- strcpy(reply_table[active].username, username);
- sprintf(reply_table[active].mailfile, "/usr/mail/%s", username);
- strcpy(reply_table[active].replyfile, replyfile);
- reply_table[active].mailsize = size;
- reply_table[active].in_list = 1; /* obviously! */
- active++;
- }
- }
-
- /** now check to see if anyone has been removed... **/
-
- for (person = 0; person < active; person++)
- if (reply_table[person].in_list == 0) {
- log("removing %s from the active list",
- reply_table[person].username);
- strcpy(reply_table[person].username,
- reply_table[active-1].username);
- strcpy(reply_table[person].mailfile,
- reply_table[active-1].mailfile);
- strcpy(reply_table[person].replyfile,
- reply_table[active-1].replyfile);
- reply_table[person].mailsize = reply_table[active-1].mailsize;
- active--;
- }
- }
-
- update_autoreply_file()
- {
- /** update the entries in the autoreply file... **/
-
- FILE *file;
- register int person;
-
- if ((file = fopen(autoreply_file,"w")) == NULL) {
- log("Couldn't update autoreply file!");
- return;
- }
-
- for (person = 0; person < active; person++)
- fprintf(file, "%s %s %ld\n",
- reply_table[person].username,
- reply_table[person].replyfile,
- reply_table[person].mailsize);
-
- fclose(file);
-
- printf("updated autoreply file\n");
- autoreply_size = bytes(autoreply_file);
- }
-
- int
- in_list(name)
- char *name;
- {
- /** search the current active reply list for the specified username.
- return the index if found, or '-1' if not. **/
-
- register int index;
-
- for (index = 0; index < active; index++)
- if (strcmp(name, reply_table[index].username) == 0)
- return(index);
-
- return(-1);
- }
-
- read_newmail(person)
- int person;
- {
- /** Read the new mail for the specified person. **/
-
-
- FILE *mailfile;
- char from_whom[LONG_SLEN], subject[SLEN];
- int sendit;
-
- log("New mail for %s", reply_table[person].username);
-
- if ((mailfile = fopen(reply_table[person].mailfile,"r")) == NULL)
- return(log("can't open mailfile for user %s",
- reply_table[person].username));
-
- if (fseek(mailfile, reply_table[person].mailsize, BEGINNING) == -1)
- return(log("couldn't seek to %ld in mail file!",
- reply_table[person].mailsize));
-
- while (get_return(mailfile, person, from_whom, subject, &sendit) != -1)
- if (sendit)
- reply_to_mail(person, from_whom, subject);
-
- return;
- }
-
- int
- get_return(file, person, from, subject, sendit)
- FILE *file;
- int person, *sendit;
- char *from, *subject;
- {
- /** Reads the new message and return the from and subject lines.
- sendit is set to true iff it isn't a machine generated msg
- **/
-
- char name1[SLEN], name2[SLEN], lastname[SLEN];
- char buffer[LONG_SLEN], hold_return[NLEN];
- int done = 0, in_header = 0;
-
- from[0] = '\0';
- *sendit = 1;
-
- while (! done) {
-
- if (fgets(buffer, LONG_SLEN, file) == NULL)
- return(-1);
-
- if (first_word(buffer, "From ")) {
- in_header++;
- sscanf(buffer, "%*s %s", hold_return);
- }
- else if (in_header) {
- if (first_word(buffer, ">From")) {
- sscanf(buffer,"%*s %s %*s %*s %*s %*s %*s %*s %*s %s", name1, name2);
- add_site(from, name2, lastname);
- }
- else if (first_word(buffer,"Subject:")) {
- remove_return(buffer);
- strcpy(subject, (char *) (buffer + 8));
- }
- else if (first_word(buffer,"X-Mailer: fastmail"))
- *sendit = 0;
- else if (strlen(buffer) == 1)
- done = 1;
- }
- }
-
- if (from[0] == '\0')
- strcpy(from, hold_return); /* default address! */
- else
- add_site(from, name1, lastname); /* get the user name too! */
-
- return(0);
- }
-
- add_site(buffer, site, lastsite)
- char *buffer, *site, *lastsite;
- {
- /** add site to buffer, unless site is 'uucp', or the same as
- lastsite. If not, set lastsite to site.
- **/
-
- char local_buffer[LONG_SLEN], *strip_parens();
-
- if (strcmp(site, "uucp") != 0)
- if (strcmp(site, lastsite) != 0) {
- if (buffer[0] == '\0')
- strcpy(buffer, strip_parens(site)); /* first in list! */
- else {
- sprintf(local_buffer,"%s!%s", buffer, strip_parens(site));
- strcpy(buffer, local_buffer);
- }
- strcpy(lastsite, strip_parens(site)); /* don't want THIS twice! */
- }
- }
-
- remove_first_word(string)
- char *string;
- { /** removes first word of string, ie up to first non-white space
- following a white space! **/
-
- register int loc;
-
- for (loc = 0; string[loc] != ' ' && string[loc] != '\0'; loc++)
- ;
-
- while (string[loc] == ' ' || string[loc] == '\t')
- loc++;
-
- move_left(string, loc);
- }
-
- move_left(string, chars)
- char string[];
- int chars;
- {
- /** moves string chars characters to the left DESTRUCTIVELY **/
-
- register int i;
-
- chars--; /* index starting at zero! */
-
- for (i=chars; string[i] != '\0' && string[i] != '\n'; i++)
- string[i-chars] = string[i];
-
- string[i-chars] = '\0';
- }
-
- reply_to_mail(person, from, subject)
- int person;
- char *from, *subject;
- {
- /** Respond to the message from the specified person with the
- specified subject... **/
-
- char buffer[SLEN];
-
- if (strlen(subject) == 0)
- strcpy(subject, "Auto-reply Mail");
- else if (! first_word(subject,"Auto-reply")) {
- sprintf(buffer, "Auto-reply to:%s", subject);
- strcpy(subject, buffer);
- }
-
- log("auto-replying to '%s'", from);
-
- mail(from, subject, reply_table[person].replyfile, person);
- }
-
- reverse(string)
- char *string;
- {
- /** reverse string... pretty trivial routine, actually! **/
-
- char buffer[SLEN];
- register int i, j = 0;
-
- for (i = strlen(string)-1; i >= 0; i--)
- buffer[j++] = string[i];
-
- buffer[j] = '\0';
-
- strcpy(string, buffer);
- }
-
- long
- bytes(name)
- char *name;
- {
- /** return the number of bytes in the specified file. This
- is to check to see if new mail has arrived.... **/
-
- int ok = 1;
- extern int errno; /* system error number! */
- struct stat buffer;
-
- if (stat(name, &buffer) != 0)
- if (errno != 2) {
- unlock();
- exit(fprintf(stderr,"Error %d attempting fstat on %s", errno, name));
- }
- else
- ok = 0;
-
- return(ok ? buffer.st_size : 0);
- }
-
- mail(to, subject, filename, person)
- char *to, *subject, *filename;
- int person;
- {
- /** Mail 'file' to the user from person... **/
-
- char buffer[VERY_LONG_STRING];
-
- sprintf(buffer, "%s -f '%s [autoreply]' -s '%s' %s %s",
- fastmail, reply_table[person].username,
- subject, filename, to);
-
- system(buffer);
- }
-
- log(message, arg)
- char *message;
- char *arg;
- {
- /** Put log entry into log file. Use the format:
- date-time: <message>
- **/
-
- struct tm *localtime(), *thetime;
- long time(), clock;
- char buffer[SLEN];
-
- /** first off, get the time and date **/
-
- clock = time((long *) 0); /* seconds since ??? */
- thetime = localtime(&clock); /* and NOW the time... */
-
- /** then put the message out! **/
-
- sprintf(buffer, message, arg);
-
- fprintf(logfd,"%d/%d-%d:%02d: %s\n",
- thetime->tm_mon+1, thetime->tm_mday,
- thetime->tm_hour, thetime->tm_min,
- buffer);
- }
-
- FILE *open_logfile()
- {
- /** open the logfile. returns a valid file descriptor **/
-
- FILE *fd;
-
- if ((fd = fopen(logfile, "a")) == 0)
- if ((fd = fopen(logfile2, "a")) == 0) {
- unlock();
- exit(1); /* give up! */
- }
-
- return( (FILE *) fd);
- }
-
- close_logfile()
- {
- /** Close the logfile until needed again. **/
-
- fclose(logfd);
- }
-
- char *strip_parens(string)
- char *string;
- {
- /** Return string with all parenthesized information removed.
- This is a non-destructive algorithm... **/
-
- static char buffer[LONG_SLEN];
- register int i, depth = 0, buffer_index = 0;
-
- for (i=0; i < strlen(string); i++) {
- if (string[i] == '(')
- depth++;
- else if (string[i] == ')')
- depth--;
- else if (depth == 0)
- buffer[buffer_index++] = string[i];
- }
-
- buffer[buffer_index] = '\0';
-
- return( (char *) buffer);
- }
-
- /*** LOCK and UNLOCK - ensure only one copy of this daemon running at any
- given time by using a file existance semaphore (wonderful stuff!) ***/
-
- lock()
- {
- /** Try to create the lock file. If it's there, or we can't
- create it for some stupid reason, return zero, otherwise,
- a non-zero return code indicates success in locking this
- process in. **/
-
- if (access(arep_lock_file, EXISTS) == 0)
- return(0); /* file already exists!! */
-
- if (creat(arep_lock_file, MODE) == -1)
- return(0); /* can't create file!! */
-
- return(1);
- }
-
- unlock()
- {
- /** remove lock file if it's there! **/
-
- (void) unlink(arep_lock_file);
- }
- END-OF-FILE
-
- size=`wc -c < utils/arepdaemon.c`
-
- if [ $size != 13340 ]
- then
- echo Warning: utils/arepdaemon.c changed - should be 13340 bytes, not $size bytes
- fi
-
- chmod 644 utils/arepdaemon.c
-
- # ---------- file utils/autoreply.c ----------
-
-
- if [ -f utils/autoreply.c ]
- then
- echo File 'utils/autoreply.c' already exists\!
- exit 1
- fi
-
- echo extracting file utils/autoreply.c...
- cat << 'END-OF-FILE' > utils/autoreply.c
- /** autoreply.c **/
-
- /** This is the front-end for the autoreply system, and performs two
- functions: it either adds the user to the list of people using the
- autoreply function (starting the daemon if no-one else) or removes
- a user from the list of people.
-
- Usage: autoreply filename
- autoreply "off"
- or autoreply [to find current status]
-
- (C) 1986, Dave Taylor
- **/
-
- #include <stdio.h>
- #include <errno.h>
- #include <sys/types.h>
- #include <sys/stat.h>
-
- #define SLEN 80 /* a normal string */
- #define NLEN 20 /* a short string */
-
- #define READ_ACCESS 04 /* is file readable? */
-
- #define mailhome "/usr/mail" /* where new mail lives */
- #define tempdir "/tmp/arep" /* file prefix */
- #define autoreply_file "/etc/autoreply.data" /* autoreply data file */
-
- extern int errno; /* system error code */
- char username[NLEN]; /* login name of user */
-
- main(argc, argv)
- int argc;
- char *argv[];
- {
- char filename[SLEN];
-
- if (argc > 2) {
- printf("Usage: %s <filename>\tto start autoreply,\n", argv[0]);
- printf(" %s off\t\tto turn off autoreply\n", argv[0]);
- printf(" or %s \t\tto check current status\n", argv[0]);
- exit(1);
- }
-
- (void) cuserid(username);
-
- if (strcmp(argv[1], "off") == 0 || argc == 1)
- remove_user((argc == 1));
- else {
- strcpy(filename, argv[1]);
- if (access(filename,READ_ACCESS) != 0) {
- printf("Error: Can't read file '%s'\n", filename);
- exit(1);
- }
-
- if (filename[0] != '/') /* prefix home directory */
- sprintf(filename,"%s/%s", getenv("HOME"), argv[1]);
-
- add_user(filename);
- }
-
- exit(0);
- }
-
- remove_user(stat_only)
- int stat_only;
- {
- /** Remove the user from the list of currently active autoreply
- people. If 'stat_only' is set, then just list the name of
- the file being used to autoreply with, if any. **/
-
- FILE *temp, *repfile;
- char tempfile[SLEN], user[SLEN], filename[SLEN];
- int c, copied = 0, found = 0;
- long filesize, bytes();
-
- if (! stat_only) {
- sprintf(tempfile, "%s.%06d", tempdir, getpid());
-
- if ((temp = fopen(tempfile, "w")) == NULL) {
- printf("Error: couldn't open tempfile '%s'. Not removed\n",
- tempfile);
- exit(1);
- }
- }
-
- if ((repfile = fopen(autoreply_file, "r")) == NULL) {
- if (stat_only) {
- printf("You're not currently autoreplying to mail.\n");
- exit(0);
- }
- printf("No-one is autoreplying to their mail!\n");
- exit(0);
- }
-
- /** copy out of real replyfile... **/
-
- while (fscanf(repfile, "%s %s %ld", user, filename, &filesize) != EOF)
-
- if (strcmp(user, username) != 0) {
- if (! stat_only) {
- copied++;
- fprintf(tempfile, "%s %s %ld\n", user, filename, filesize);
- }
- }
- else {
- if (stat_only) {
- printf("You're currently autoreplying to mail with the file %s\n", filename);
- exit(0);
- }
- found++;
- }
-
- fclose(temp);
- fclose(repfile);
-
- if (! found) {
- printf("You're not currently autoreplying to mail%s\n",
- stat_only? "." : "!");
- if (! stat_only)
- unlink(tempfile);
- exit(! stat_only);
- }
-
- /** now copy tempfile back into replyfile **/
-
- if (copied == 0) { /* removed the only person! */
- unlink(autoreply_file);
- }
- else { /* save everyone else */
-
- if ((temp = fopen(tempfile,"r")) == NULL) {
- printf("Error: couldn't reopen tempfile '%s'. Not removed.\n",
- tempfile);
- unlink(tempfile);
- exit(1);
- }
-
- if ((repfile = fopen(autoreply_file, "w")) == NULL) {
- printf(
- "Error: couldn't reopen autoreply file for writing! Not removed.\n");
- unlink(tempfile);
- exit(1);
- }
-
- while ((c = getc(temp)) != EOF)
- putc(c, repfile);
-
- fclose(temp);
- fclose(repfile);
-
- }
- unlink(tempfile);
-
- if (found > 1)
- printf("Warning: your username appeared %d times!! Removed all\n",
- found);
- else
- printf("You've been removed from the autoreply table.\n");
- }
-
- add_user(filename)
- char *filename;
- {
- /** add the user to the autoreply file... **/
-
- FILE *repfile;
- char mailfile[SLEN];
- long bytes();
-
- if ((repfile = fopen(autoreply_file, "a")) == NULL) {
- printf("Error: couldn't open the autoreply file! Not added\n");
- exit(1);
- }
-
- sprintf(mailfile,"%s/%s", mailhome, username);
-
- fprintf(repfile,"%s %s %ld\n", username, filename, bytes(mailfile));
-
- fclose(repfile);
-
- printf("You've been added to the autoreply system.\n");
- }
-
-
- long
- bytes(name)
- char *name;
- {
- /** return the number of bytes in the specified file. This
- is to check to see if new mail has arrived.... **/
-
- int ok = 1;
- extern int errno; /* system error number! */
- struct stat buffer;
-
- if (stat(name, &buffer) != 0)
- if (errno != 2)
- exit(fprintf(stderr,"Error %d attempting fstat on %s", errno, name));
- else
- ok = 0;
-
- return(ok ? buffer.st_size : 0L);
- }
- END-OF-FILE
-
- size=`wc -c < utils/autoreply.c`
-
- if [ $size != 4840 ]
- then
- echo Warning: utils/autoreply.c changed - should be 4840 bytes, not $size bytes
- fi
-
- chmod 644 utils/autoreply.c
-
- echo done
-
- exit 0
-
-
-
-
-