rsalz@bbn.com (Rich Salz) (05/31/90)
Submitted-by: Syd Weinstein <syd@dsinc.dsi.com> Posting-number: Volume 22, Issue 71 Archive-name: elm2.3/part12 ---- Cut Here and unpack ---- #!/bin/sh # this is part 12 of a multipart archive # do not concatenate these parts, unpack them in order with /bin/sh # file src/aliasdb.c continued # CurArch=12 if test ! -r s2_seq_.tmp then echo "Please unpack part 1 first!" exit 1; fi ( read Scheck if test "$Scheck" != $CurArch then echo "Please unpack part $Scheck next!" exit 1; else exit 0; fi ) < s2_seq_.tmp || exit 1 echo "x - Continuing file src/aliasdb.c" sed 's/^X//' << 'SHAR_EOF' >> src/aliasdb.c X#ifndef USE_DBM X get_connections(); X open_domain_file(); X#endif X init_findnode(); X clear_error(); X findnode_has_been_initialized = TRUE; X } X X strcpy(old_name, name); /* save what we were given */ X X if (expand_site(name, address) == -1) { X if (display_error && name[0] != '!') { X dprint(3, (debugfile, "Couldn't expand host %s in address.\n", X name)); X if (! check_only && warnings) { X error1("Couldn't expand system %s.", name); X sleep(1); X } X } X strcpy(name, old_name); /* and restore... */ X } X else X strcpy(name, address); X#endif X return; X} X X#if defined(OPTIMIZE_RETURN) || !defined(DONT_TOUCH_ADDRESSES) Xint Xexpand_site(cryptic, expanded) Xchar *cryptic, *expanded; X{ X X /** Given an address of the form 'xyz@site' or 'site!xyz' X return an address of the form <expanded address for site> X with 'xyz' embedded according to the path database entry. X Note that 'xyz' can be eiher a simple address (as in "joe") X or a complex address (as in "joe%xerox.parc@Xerox.ARPA")! X 0 = found, -1 return means unknown site code X X Modified to strip out parenthetical comments... X **/ X X#ifdef ACSNET X X strcpy(expanded, cryptic); /* fast and simple */ X return(0); X X#else X# ifdef USE_DBM X datum key, contents; X# endif X X char name[VERY_LONG_STRING], sitename[VERY_LONG_STRING], X temp[VERY_LONG_STRING], old_name[VERY_LONG_STRING], X comment[LONG_STRING]; X char *expand_domain(), *addr; X register int i = 0, j = 0, in_parens = 0, domain_name; X X strcpy(old_name, cryptic); /* remember what we were given */ X X /** break down **/ X X /** first, rip out the comment, if any, noting nested parens **/ X X if ((i = chloc(cryptic, '(')) > -1) { X comment[j++] = ' '; /* leading space */ X do { X switch(comment[j++] = cryptic[i++]) { X case '(': in_parens++; X break; X case ')': in_parens--; X break; X } X } while(in_parens && cryptic[i] != '\0'); X comment[j] = '\0'; X X /* and remove this from cryptic string too... */ X if (cryptic[(j = chloc(cryptic,'('))-1] == ' ') X cryptic[j-1] = '\0'; X else X cryptic[j] = '\0'; X } X else X comment[0] = '\0'; X X i = j = 0; /* reset */ X X while (cryptic[i] != AT_SIGN && cryptic[i] != BANG && X cryptic[i] != '\0' && cryptic[i] != '(') X sitename[j++] = cryptic[i++]; X X sitename[j++] = '\0'; X X j = 0; X X if (cryptic[i] == '\0') return(-1); /* nothing to expand! */ X X domain_name = (cryptic[i] == AT_SIGN); X X i++; X X while (cryptic[i] != '\0' && cryptic[i] != '(' && X ! whitespace(cryptic[i])) X name[j++] = cryptic[i++]; X X name[j] = '\0'; X X if (domain_name) { X strcpy(temp, name); X strcpy(name, sitename); X strcpy(sitename, temp); X } X X dprint(5, (debugfile, "\nBroke address into '%s' @ '%s' '%s'\n\n", X name, sitename, comment)); X X#ifdef USE_DBM X X if (size_of_pathfd == 0) X return(-1); X X key.dptr = sitename; X key.dsize = strlen(sitename) + 1; X X contents = fetch(key); X X if (contents.dptr == 0) X return(-1); /* can't find it! */ X X sprintf(expanded, contents.dptr, name); X strcat(expanded, " "); /* add a single space... */ X strcat(expanded, comment); /* ...and add comment */ X return(0); X#else X X#ifndef LOOK_CLOSE_AFTER_SEARCH X X if (talk_to(sitename)) { X strcpy(expanded, old_name); /* restore! */ X return(0); X } X#endif X X if ((addr = find_path_to(sitename, TRUE)) == NULL) { X X#ifdef LOOK_CLOSE_AFTER_SEARCH X X if (talk_to(sitename)) { X strcpy(expanded, old_name); /* restore! */ X return(0); X } X else X#endif X if ((addr = expand_domain(cryptic)) != NULL) { X strcpy(expanded, addr); /* into THIS buffer */ X strcat(expanded, comment); /* patch in comment */ X return(0); X } X else if (size_of_pathfd == 0) { /* no path database! */ X strcpy(expanded, old_name); /* restore! */ X return(0); X } X else { /* We just can't get there! */ X strcpy(expanded, old_name); /* restore! */ X return(-1); X } X } X else { /* search succeeded */ X sprintf(expanded, addr, name); X strcat(expanded, comment); /* add comment */ X return(0); X } X#endif X#endif X} X#endif /* defined(OPTIMIZE_RETURN) || !defined(DONT_TOUCH_ADDRESSES) */ X Xint Xbinary_search(name, address) Xchar *name, *address; X{ X /* binary search file for name. Return 0 if found, -1 if not */ X X char machine[40]; X register long first = 0, last, middle; X register int compare; X X address[0] = '\0'; X X last = size_of_pathfd; X X do { X X middle = (long) ((first+last) / 2); X X get_entry(machine, address, pathfd, middle); X X compare = strcmp(name, machine); X X if (compare < 0) X last = middle - 1; X else if (compare == 0) X return(0); X else /* greater */ X first = middle + 1; X } while (absolute(last) - absolute(first) > FIND_DELTA); X X /* It could be that our target entry lies exactly at `first'. X * Since get_entry() compares at the entry beginning after X * the passed offset (unless it's 0), we need to decrement it X * (unless it's 0), and give it one more try. X */ X get_entry(machine, address, pathfd, (first == 0L ? first : --first)); X compare = strcmp(name, machine); X return(compare == 0 ? 0 : -1); X} X Xget_entry(machine, address, fileid, offset) Xchar *machine, *address; XFILE *fileid; Xlong offset; X{ X /** get entry...return machine and address immediately X following given offset in fileid. **/ X X (void) fseek(fileid, offset, 0); X X /* To get to the beginning of a record, if we are not at offset 0, X * read until we hit an end-of-line */ X X if(offset != 0L) X while (getc(fileid) != '\n') X ; X X fscanf(fileid, "%s\t%s", machine, address); X} X X#ifndef DONT_TOUCH_ADDRESSES Xinit_findnode() X{ X /** Initialize the FILE and 'size_of_file' values for the X findnode procedure **/ X X struct stat buffer; X char *path_filename; X X#ifdef USE_DBM X char buf[BUFSIZ]; X X sprintf(buf,"%s.pag", pathfile); X path_filename = buf; X#else X path_filename = pathfile; X#endif X X if (stat(path_filename, &buffer) == -1) { X dprint(2, (debugfile, X "Warning: pathalias file \"%s\" wasn't found by %s\n", X path_filename, "init_findnode")); X size_of_pathfd = 0; X return; X } X X size_of_pathfd = (long) buffer.st_size; X X#ifdef USE_DBM X X if (dbminit(pathfile) != 0) { X dprint(2, (debugfile, X "Warning: couldn't initialize DBM database %s\n", X pathfile)); X dprint(2, (debugfile, "** %s - %s **\n\n", error_name(errno), X error_description(errno))); X size_of_pathfd = 0; /* error flag, in this case */ X return; X } X X return; X#else X X if ((pathfd = fopen(pathfile,"r")) == NULL) { X dprint(2, (debugfile, X "Warning: Can't read pathalias file \"%s\" within %s\n", X pathfile, "init_findnode")); X size_of_pathfd = 0; X } X else X dprint(3, (debugfile, "\nOpened '%s' as pathalias database.\n\n", X pathfile)); X#endif X} X#endif /* DONT_TOUCH_ADDRESSES */ X Xchar *find_path_to(machine, printf_format) Xchar *machine; Xint printf_format; X{ X /** Returns either the path to the specified machine or NULL if X not found. If "printf_format" is TRUE, then it leaves the X '%s' intact, otherwise it assumes that the address is a uucp X address for the domain expansion program and removes the X last three characters of the expanded name ("!%s") since X they're redundant with the expansion! X **/ X X static char buffer[SLEN]; /* space for path */ X X if (size_of_pathfd > 0) X if (binary_search(machine, buffer) != -1) { /* found it! */ X if (! printf_format && strlen(buffer) > 3) X buffer[strlen(buffer)-3] = '\0'; X return( (char *) buffer); X } X X return(NULL); /* failed if it's here! */ X} SHAR_EOF echo "File src/aliasdb.c is complete" chmod 0444 src/aliasdb.c || echo "restore of src/aliasdb.c fails" echo "x - extracting src/aliaslib.c (Text)" sed 's/^X//' << 'SHAR_EOF' > src/aliaslib.c && X Xstatic char rcsid[] = "@(#)$Id: aliaslib.c,v 4.1 90/04/28 22:42:29 syd Exp $"; X X/******************************************************************************* X * The Elm Mail System - $Revision: 4.1 $ $State: Exp $ X * X * Copyright (c) 1986, 1987 Dave Taylor X * Copyright (c) 1988, 1989, 1990 USENET Community Trust X ******************************************************************************* X * Bug reports, patches, comments, suggestions should be sent to: X * X * Syd Weinstein, Elm Coordinator X * elm@DSI.COM dsinc!elm X * X ******************************************************************************* X * $Log: aliaslib.c,v $ X * Revision 4.1 90/04/28 22:42:29 syd X * checkin of Elm 2.3 as of Release PL0 X * X * X ******************************************************************************/ X X/** Library of functions dealing with the alias system... X X **/ X X#include "headers.h" X#include <ctype.h> X Xchar *get_alias_address(), *get_token(), *strpbrk(), *index(); Xlong lseek(); X X#ifdef DONT_TOUCH_ADDRESSES Xchar *expand_system(); X#endif X X/* X * Expand "name" as an alias and return a pointer to static data containing X * the expansion. If "name" is not an alias, then NULL is returned. X */ Xchar *get_alias_address(name, mailing) Xchar *name; /* name to expand as an alias */ Xint mailing; /* TRUE to fully expand group names & recursive aliases */ X{ X static char buffer[VERY_LONG_STRING]; X char *bufptr; X int bufsize; X X /* reads files iff changed since last read */ X read_alias_files(); X X /* if name is an alias then return its expansion */ X bufptr = buffer; X bufsize = sizeof(buffer); X if ( do_get_alias(name, &bufptr, &bufsize, mailing, FALSE, 0) ) X return buffer+2; /* skip comma/space from add_name_to_list() */ X X /* nope...not an alias */ X return (char *) NULL; X} X X X/* X * Determine if "name" is an alias, and if so expand it and store the result in X * "*bufptr". TRUE returned if any expansion occurs, else FALSE is returned. X */ Xint do_get_alias(name, bufptr, bufsizep, mailing, sysalias, depth) Xchar *name; /* name to expand as an alias */ Xchar **bufptr; /* place to store result of expansion */ Xint *bufsizep; /* available space in the buffer */ Xint mailing; /* TRUE to fully expand group names & recursive aliases */ Xint sysalias; /* TRUE to suppress checks of the user's aliases */ Xint depth; /* recursion depth - initially call at depth=0 */ X{ X char abuf[LONG_STRING]; X int loc; X X /* update the recursion depth counter */ X ++depth; X X dprint(6, (debugfile, "%*s->attempting alias expansion on \"%s\"\n", X (depth*2), "", name)); X X /* strip out (comments) and leading/trailing whitespace */ X remove_possible_trailing_spaces( name = strip_parens(name) ); X for ( ; isspace(*name) ; ++name ) ; X X /* throw back empty addresses */ X if ( *name == '\0' ) X return FALSE; X X /* check for a user alias, unless in the midst of sys alias expansion */ X if ( !sysalias && user_data != -1 ) { X if ( (loc = find(name, user_hash_table, MAX_UALIASES)) >= 0 ) { X lseek(user_data, ntohl(user_hash_table[loc].byte), 0L); X get_line(user_data, abuf); X goto do_expand; X } X } X X /* check for a system alias */ X if ( system_data != -1 ) { X if ( (loc = find(name, system_hash_table, MAX_SALIASES)) >= 0 ) { X lseek(system_data, ntohl(system_hash_table[loc].byte), 0L); X get_line(system_data, abuf); X sysalias = TRUE; X goto do_expand; X } X } X X /* nope...this name wasn't an alias */ X return FALSE; X Xdo_expand: X X /* at this point, alias is expanded into "abuf" - now what to do... */ X X dprint(7, (debugfile, "%*s ->expanded alias to \"%s\"\n", X (depth*2), "", abuf)); X X /* check for an exact match */ X loc = strlen(name); X if (strncmp(name, abuf, loc) == 0 && (abuf[loc] == ' ' || abuf[loc] == '\0')) X#ifdef DONT_TOUCH_ADDRESSES X return add_name_to_list(abuf, bufptr, bufsizep); X#else X return add_name_to_list(expand_system(abuf, TRUE), bufptr, bufsizep); X#endif X X /* see if we are stuck in a loop */ X if ( depth > 12 ) { X dprint(2, (debugfile, X "alias expansion loop detected at \"%s\" - bailing out\n", name)); X error1("Error expanding \"%s\" - probable alias definition loop.", X name); X return FALSE; X } X X /* see if the alias equivalence is a group name */ X if ( mailing && abuf[0] == '!' ) X return do_expand_group(abuf+1, bufptr, bufsizep, sysalias, depth); X X /* see if the alias equivalence is an email address */ X if ( strpbrk(abuf,"!@:") != NULL ) { X#ifdef DONT_TOUCH_ADDRESSES X return add_name_to_list(abuf, bufptr, bufsizep); X#else X return add_name_to_list(expand_system(abuf, TRUE), bufptr, bufsizep); X#endif X } X X /* see if the alias equivalence is itself an alias */ X if ( mailing && do_get_alias(abuf,bufptr,bufsizep,TRUE,sysalias,depth) ) X return TRUE; X X /* the alias equivalence must just be a local address */ X return add_name_to_list(abuf, bufptr, bufsizep); X} X X X/* X * Expand the comma-delimited group of names in "group", storing the result X * in "*bufptr". Returns TRUE if expansion occurs OK, else FALSE in the X * event of errors. X */ Xint do_expand_group(group, bufptr, bufsizep, sysalias, depth) Xchar *group; /* group list to expand */ Xchar **bufptr; /* place to store result of expansion */ Xint *bufsizep; /* available space in the buffer */ Xint sysalias; /* TRUE to suppress checks of the user's aliases */ Xint depth; /* nesting depth */ X{ X char *name; X X /* go through each comma-delimited name in the group */ X while ( group != NULL ) { X X /* extract the next name from the list */ X for ( name = group ; isspace(*name) ; ++name ) ; X if ( (group = index(name,',')) != NULL ) X *group++ = '\0'; X remove_possible_trailing_spaces(name); X if ( *name == '\0' ) X continue; X X /* see if this name is really an alias */ X if ( do_get_alias(name, bufptr, bufsizep, TRUE, sysalias, depth) ) X continue; X X /* verify it is a valid address */ X if ( !valid_name(name) ) { X dprint(3, (debugfile, X "Illegal address %s during list expansion in %s\n", X name, "do_get_alias")); X error1("%s is an illegal address!", name); X return FALSE; X } X X /* add it to the list */ X if ( !add_name_to_list(name, bufptr, bufsizep) ) X return FALSE; X X } X X return TRUE; X} X X X/* X * Append "<comma><space>name" to the list, checking to ensure the buffer X * does not overflow. Upon return, *bufptr and *bufsizep will be updated to X * reflect the stuff added to the buffer. If a buffer overflow would occur, X * an error message is printed and FALSE is returned, else TRUE is returned. X */ Xint add_name_to_list(name,bufptr,bufsizep) Xregister char *name; /* name to append to buffer */ Xchar **bufptr; /* pointer to pointer to end of buffer */ Xint *bufsizep; /* pointer to space remaining in buffer */ X{ X register char *dest = *bufptr; X register int bufsize = *bufsizep; X X if ( bufsize < 2 ) X return FALSE; X *dest++ = ','; --bufsize; X *dest++ = ' '; --bufsize; X X while ( *name != '\0' && --bufsize > 0 ) X *dest++ = *name++ ; X *dest = '\0'; X X *bufptr = dest; X *bufsizep = bufsize; X if ( bufsize <= 0 ) { X error("Alias expansion is too long."); X return FALSE; X } X X return TRUE; X} X X X X#ifndef DONT_TOUCH_ADDRESSES Xchar *expand_system(buffer, show_errors) Xchar *buffer; Xint show_errors; X{ X /** This routine will check the first machine name in the given path X (if any) and expand it out if it is an alias...if not, it will X return what it was given. If show_errors is false, it won't X display errors encountered... X **/ X X dprint(6, (debugfile, "expand_system(%s, show-errors=%s)\n", buffer, X onoff(show_errors))); X findnode(buffer, show_errors); X X return( (char *) buffer); X} X#endif X Xint Xfind(word, table, size) Xchar *word; Xstruct alias_rec table[]; Xint size; X{ X /** find word and return loc, or -1 **/ X register int loc; X X if (strlen(word) > 20) { X dprint(3, (debugfile, "Overly long alias name entered: %s\n", word)); X error1("Bad alias name: %s. Too long.\n", word); X return(-1); X } X X loc = hash_it(word, size); X X while (stricmp(word, table[loc].name) != 0) { X if (table[loc].name[0] == '\0') X return(-1); X loc = (loc + 1) % size; X } X X return(loc); X} X Xint Xstricmp(s1,s2) Xregister char *s1, *s2; X{ X /* case insensitive comparison */ X register int d; X for (;;) { X d = ( isupper(*s1) ? tolower(*s1) : *s1 ) X - ( isupper(*s2) ? tolower(*s2) : *s2 ) ; X if ( d != 0 || *s1 == '\0' || *s2 == '\0' ) X return d; X ++s1; X ++s2; X } X /*NOTREACHED*/ X} X Xint Xhash_it(string, table_size) Xregister char *string; Xint table_size; X{ X /** compute the hash function of the string, returning X it (mod table_size) **/ X X register int sum = 0; X for ( ; *string != '\0' ; ++string ) X sum += (int) ( isupper(*string) ? tolower(*string) : *string ); X X return(sum % table_size); X} X Xget_line(fd, buffer) Xint fd; Xchar *buffer; X{ X /* Read from file fd. End read upon reading either X EOF or '\n' character (this is where it differs X from a straight 'read' command!) */ X X register int i= 0; X char ch; X X while (read(fd, &ch, 1) > 0) X if (ch == '\n' || ch == '\r') { X buffer[i] = 0; X return; X } X else X buffer[i++] = ch; X} SHAR_EOF chmod 0444 src/aliaslib.c || echo "restore of src/aliaslib.c fails" echo "x - extracting src/args.c (Text)" sed 's/^X//' << 'SHAR_EOF' > src/args.c && X Xstatic char rcsid[] = "@(#)$Id: args.c,v 4.1 90/04/28 22:42:31 syd Exp $"; X X/******************************************************************************* X * The Elm Mail System - $Revision: 4.1 $ $State: Exp $ X * X * Copyright (c) 1986, 1987 Dave Taylor X * Copyright (c) 1988, 1989, 1990 USENET Community Trust X ******************************************************************************* X * Bug reports, patches, comments, suggestions should be sent to: X * X * Syd Weinstein, Elm Coordinator X * elm@DSI.COM dsinc!elm X * X ******************************************************************************* X * $Log: args.c,v $ X * Revision 4.1 90/04/28 22:42:31 syd X * checkin of Elm 2.3 as of Release PL0 X * X * X ******************************************************************************/ X X/** starting argument parsing routines for ELM system... X X**/ X X#include "headers.h" X#include "patchlevel.h" X Xextern char *optarg; /* optional argument as we go */ Xextern int optind; /* argnum + 1 when we leave */ X Xvoid exit(); /* just keeping lint happy.... */ X Xchar * Xparse_arguments(argc, argv, to_whom) Xint argc; Xchar *argv[], *to_whom; X{ X /** Set flags according to what was given to program. If we are X fed a name or series of names, put them into the 'to_whom' buffer X and if the check_only flag wasn't presented, set mail_only to ON, X and if stdin is not a tty, set batch_only to ON; X Return req_mfile, which points to a named mail file or is empty. X **/ X X register int c = 0; X char *strcpy(); X static char req_mfile[SLEN]; X X to_whom[0] = '\0'; X batch_subject[0] = '\0'; X X while ((c = getopt(argc, argv, "?acd:f:hkKms:Vvwz")) != EOF) { X switch (c) { X case 'a' : arrow_cursor++; break; X case 'c' : check_only++; break; X case 'd' : debug = atoi(optarg); break; X case 'f' : strcpy(req_mfile, optarg); break; X case '?' : X case 'h' : args_help(); X case 'k' : hp_terminal++; break; X case 'K' : hp_terminal++; hp_softkeys++; break; X case 'm' : mini_menu = 0; break; X case 's' : strcpy(batch_subject, optarg); break; X case 'V' : sendmail_verbose++; break; X case 'v' : args_version(); X case 'w' : warnings = 0; break; X case 'z' : check_size++; break; X } X } X X X#ifndef DEBUG X if (debug) X printf( X "Warning: system created without debugging enabled - request ignored\n"); X debug = 0; X#endif X X if (optind < argc) { X while (optind < argc) { X if (strlen(to_whom) + strlen(to_whom[0] != '\0'? " " : "") + X strlen(argv[optind]) > SLEN) X exit(printf("\n\rToo many addresses, or addresses too long!\n\r")); X X sprintf(to_whom, "%s%s%s", to_whom, X to_whom[0] != '\0'? " " : "", argv[optind]); X if(!check_only) X mail_only++; X optind++; X } X check_size = 0; /* NEVER do this if we're mailing!! */ X } X X if (strlen(batch_subject) > 0 && ! mail_only) X exit(printf( X "\n\rDon't understand specifying a subject and no-one to send to!\n\r")); X X if (!isatty(fileno(stdin)) && !check_only) { X batch_only = ON; X if(*batch_subject == '\0') X strcpy(batch_subject, DEFAULT_BATCH_SUBJECT); X } X return(req_mfile); X X X} X Xargs_help() X{ X /** print out possible starting arguments... **/ X X printf("\nPossible Starting Arguments for ELM program:\n\n"); X printf("\targ\t\t\tMeaning\n"); X printf("\t -a \t\tArrow - use the arrow pointer regardless\n"); X printf("\t -c \t\tCheckalias - check the given aliases only\n"); X printf("\t -dn\t\tDebug - set debug level to 'n'\n"); X printf( X "\t -fx\t\tFolder - read folder 'x' rather than incoming mailbox\n"); X printf("\t -h \t\tHelp - give this list of options\n"); X printf("\t -k \t\tKeypad - enable HP 2622 terminal keyboard\n"); X printf("\t -K \t\tKeypad&softkeys - enable use of softkeys + \"-k\"\n"); X printf("\t -m \t\tMenu - Turn off menu, using more of the screen\n"); X printf("\t -sx\t\tSubject 'x' - for batchmailing\n"); X printf("\t -V \t\tEnable sendmail voyeur mode.\n"); X printf("\t -v \t\tPrint out ELM version information.\n"); X printf("\t -w \t\tSupress warning messages...\n"); X printf("\t -z \t\tZero - don't enter ELM if no mail is pending\n"); X printf("\n"); X printf("\n"); X exit(1); X} X Xargs_version() X{ X /** print out version information **/ X X printf("\nElm Version and Identification Information:\n\n"); X printf("\tElm %s PL%d, of %s\n",VERSION,PATCHLEVEL,VERS_DATE); X printf("\t(C) Copyright 1986, 1987 Dave Taylor\n"); X printf("\t(C) Copyright 1988, 1989, 1990 USENET Community Trust\n"); X printf("\t----------------------------------\n"); X printf("\tConfigured %s\n", CONFIGURE_DATE); X printf("\t----------------------------------\n"); X X#ifdef USE_EMBEDDED_ADDRESSES X printf("\tFrom: and Reply-To: addresses are good: USE_EMBEDDED_ADDRESSES\n"); X#else /* USE_EMBEDDED_ADDRESSES */ X printf("\tFrom: and Reply-To: addresses ignored: not USE_EMBEDDED_ADDRESSES\n"); X#endif /* USE_EMBEDDED_ADDRESSES */ X X#ifdef OPTIMIZE_RETURN X printf("\tReturn addresses will be optimized: OPTIMIZE_RETURN\n"); X#else /* OPTIMIZE_RETURN */ X printf("\tReturn addresses will not be optimized: not OPTIMIZE_RETURN\n"); X#endif X X#ifdef INTERNET X printf("\tPrefers Internet address formats: INTERNET\n"); X#else /* INTERNET */ X printf("\tInternet address formats not used: not INTERNET\n"); X#endif /* INTERNET */ X X#ifdef DEBUG X printf("\tDebug options are available: DEBUG\n"); X#else /* DEBUG */ X printf("\tNo debug options are available: not DEBUG\n"); X#endif /* DEBUG */ X X#ifdef CRYPT X printf("\tCrypt function enabled: CRYPT\n"); X#else /* CRYPT */ X printf("\tCrypt function disabled: not CRYPT\n"); X#endif /* CRYPT */ X X#ifdef ALLOW_MAILBOX_EDITING X printf("\tMailbox editing included: ALLOW_MAILBOX_EDITING\n"); X#else /* ALLOW_MAILBOX_EDITING */ X printf("\tMailbox editing not included: not ALLOW_MAILBOX_EDITING\n"); X#endif /* ALLOW_MAILBOX_EDITING */ X X#ifdef ENABLE_CALENDAR X printf("\tCalendar file feature enabled: ENABLE_CALENDAR\n"); X printf("\t\t(Default calendar file is %s)\n",dflt_calendar_file); X#else /* ENABLE_CALENDAR */ X printf("\tCalendar file feature disabled: not ENABLE_CALENDAR\n"); X#endif /* ENABLE_CALENDAR */ X X printf("\n\n"); X exit(1); X X} X SHAR_EOF chmod 0444 src/args.c || echo "restore of src/args.c fails" echo "x - extracting src/bouncebk.c (Text)" sed 's/^X//' << 'SHAR_EOF' > src/bouncebk.c && X Xstatic char rcsid[] = "@(#)$Id: bouncebk.c,v 4.1 90/04/28 22:42:33 syd Exp $"; X X/******************************************************************************* X * The Elm Mail System - $Revision: 4.1 $ $State: Exp $ X * X * Copyright (c) 1986, 1987 Dave Taylor X * Copyright (c) 1988, 1989, 1990 USENET Community Trust X ******************************************************************************* X * Bug reports, patches, comments, suggestions should be sent to: X * X * Syd Weinstein, Elm Coordinator X * elm@DSI.COM dsinc!elm X * X ******************************************************************************* X * $Log: bouncebk.c,v $ X * Revision 4.1 90/04/28 22:42:33 syd X * checkin of Elm 2.3 as of Release PL0 X * X * X ******************************************************************************/ X X/** This set of routines implement the bounceback feature of the mailer. X This feature allows mail greater than 'n' hops away (n specified by X the user) to have a 'cc' to the user through the remote machine. X X Due to the vagaries of the Internet addressing (uucp -> internet -> uucp) X this will NOT generate bounceback copies with mail to an internet host! X X**/ X X#include "headers.h" X Xchar *bounce_off_remote(), /* forward declaration */ X *strcat(), *strcpy(); X Xint Xuucp_hops(to) Xchar *to; X{ X /** Given the entire "To:" list, return the number of hops in the X first address (a hop = a '!') or ZERO iff the address is to a X non uucp address. X **/ X X register int hopcount = 0, iindex; X X for (iindex = 0; ! whitespace(to[iindex]) && to[iindex] != '\0'; iindex++) { X if (to[iindex] == '!') X hopcount++; X else if (to[iindex] == '@' || to[iindex] == '%' || to[iindex] == ':') X return(0); /* don't continue! */ X } X X return(hopcount); X} X Xchar *bounce_off_remote(to) Xchar *to; X{ X /** Return an address suitable for framing (no, that's not it...) X Er, suitable for including in a 'cc' line so that it ends up X with the bounceback address. The method is to take the first X address in the To: entry and break it into machines, then X build a message up from that. For example, consider the X following address: X a!b!c!d!e!joe X the bounceback address would be; X a!b!c!d!e!d!c!b!a!ourmachine!ourname X simple, eh? X **/ X X static char address[LONG_STRING]; /* BEEG address buffer! */ X X char host[MAX_HOPS][NLEN]; /* for breaking up addr */ X register int hostcount = 0, hindex = 0, X iindex; X X for (iindex = 0; !whitespace(to[iindex]) && to[iindex] != '\0'; iindex++) { X if (to[iindex] == '!') { X host[hostcount][hindex] = '\0'; X hostcount++; X hindex = 0; X } X else X host[hostcount][hindex++] = to[iindex]; X } X X /* we have hostcount hosts... */ X X strcpy(address, host[0]); /* initialize it! */ X X for (iindex=1; iindex < hostcount; iindex++) { X strcat(address, "!"); X strcat(address, host[iindex]); X } X X /* and now the same thing backwards... */ X X for (iindex = hostcount -2; iindex > -1; iindex--) { X strcat(address, "!"); X strcat(address, host[iindex]); X } X X /* and finally, let's tack on our machine and login name */ X X strcat(address, "!"); X strcat(address, hostname); X strcat(address, "!"); X strcat(address, username); X X /* and we're done!! */ X X return( (char *) address ); X} SHAR_EOF chmod 0444 src/bouncebk.c || echo "restore of src/bouncebk.c fails" echo "x - extracting src/builtin.c (Text)" sed 's/^X//' << 'SHAR_EOF' > src/builtin.c && X Xstatic char rcsid[] = "@(#)$Id: builtin.c,v 4.1 90/04/28 22:42:34 syd Exp $"; X X/******************************************************************************* X * The Elm Mail System - $Revision: 4.1 $ $State: Exp $ X * X * Copyright (c) 1986, 1987 Dave Taylor X * Copyright (c) 1988, 1989, 1990 USENET Community Trust X ******************************************************************************* X * Bug reports, patches, comments, suggestions should be sent to: X * X * Syd Weinstein, Elm Coordinator X * elm@DSI.COM dsinc!elm X * X ******************************************************************************* X * $Log: builtin.c,v $ X * Revision 4.1 90/04/28 22:42:34 syd X * checkin of Elm 2.3 as of Release PL0 X * X * X ******************************************************************************/ X X/** This is the built-in pager for displaying messages while in the Elm X program. It's a bare-bones pager with precious few options. The idea X is that those systems that are sufficiently slow that using an external X pager such as 'more' is too slow, then they can use this! X X Also added support for the "builtin+" pager (clears the screen for X each new page) including a two-line overlap for context... X X**/ X X#include "headers.h" X#include <ctype.h> X X#define BEEP 007 /* ASCII Bell character */ X Xstatic unfilled_lines, X form_title; X Xint lines_displayed, /* total number of lines displayed */ X total_lines_to_display, /* total number of lines in message */ X pages_displayed; /* for the nth page titles and all */ X Xstart_builtin(lines_in_message) Xint lines_in_message; X{ X /** clears the screen and resets the internal counters... **/ X X dprint(8,(debugfile, X "displaying %d lines from message using internal pager\n", X lines_in_message)); X X unfilled_lines = LINES; X form_title = 1; X lines_displayed = 0; X pages_displayed = 1; X X total_lines_to_display = lines_in_message; X} X Xextern int tabspacing; X Xint Xnext_line(inputptr, output, width) Xchar **inputptr, *output; Xregister unsigned width; X{ X /* Copy characters from input to output and copy X * remainder of output to output. In copying use ^X notation for X * control characters, '?' non-ascii characters, expand tabs X * to correct number of spaces till next tab stop. X * Column zero of the next line is considered to be the tab stop X * that follows the last one that fits on a line. X * Copy until newline/return encountered, null char encountered, X * width characters producted in output buffer. X * Formfeed is handled exceptionally. If encountered it X * is removed from input and 1 is returned. Otherwise 0 is returned. X */ X X register char *optr, *iptr; X register unsigned chars_output, nt; X int ret_val; X X optr = output; X iptr = *inputptr; X chars_output = 0; X X ret_val = 0; /* presume no formfeed */ X while(1) { X X if(chars_output >= width) { /* no more room on line */ X *optr++ = '\n'; X *optr++ = '\r'; X /* if next input character is newline or return, X * we can skip over it since we are outputing a newline anyway */ X if((*iptr == '\n') || (*iptr == '\r')) X iptr++; X break; X } else if (*iptr == '\n' || *iptr == '\r') { /*newline or return */ X *optr++ = '\n'; X *optr++ = '\r'; X iptr++; X break; /* end of line */ X } else if(*iptr == '\f') { /* formfeed */ X /* if next input character is newline or return, X * we can skip over it since we are outputing a formfeed anyway */ X if((*++iptr == '\n') || (*iptr == '\r')) X iptr++; X ret_val = 1; X break; /* leave rest of screen clear */ X } else if(*iptr == '\0') { /* none left in input string */ X break; X } else if(*iptr == '\t') { /* tab stop */ X if((nt=next_tab(chars_output+1)) > width) { X *optr++ = '\n'; /* won't fit on this line - autowrap */ X *optr++ = '\r'; /* tab by tabbing so-to-speak to 1st */ X iptr++; /* column of next line */ X break; X } else { /* will fit - output proper num of spaces */ X while(chars_output < nt-1) { X chars_output++; X *optr++ = ' '; X } X iptr++; X } X } else if(isprint(*iptr)) { X *optr++ = *iptr++; /* printing character */ X chars_output++; X } else { /* non-white space control character */ X if(chars_output + 2 <= width) { X *optr++ = '^'; X *optr++ = (*iptr == '\177' ? '?' : (*iptr&0177) + 'A' - 1); X iptr++; X chars_output += 2; X } else { /* no space on line for both chars */ X break; X } X } X } X *optr = '\0'; X *inputptr = iptr; X return(ret_val); X} X X Xint Xdisplay_line(input_line) Xchar *input_line; X{ X /** Display the given line on the screen, taking into account such X dumbness as wraparound and such. If displaying this would put X us at the end of the screen, put out the "MORE" prompt and wait X for some input. Return non-zero if the user terminates the X paging (e.g. 'i') or zero if we should continue. Also, X this will pass back the value of any character the user types in X at the prompt instead, if needed... (e.g. if it can't deal with X it at this point) X **/ X X char *pending, footer[SLEN], display_buffer[SLEN], ch; X int formfeed, lines_more; X X#ifdef MMDF X if (strcmp(input_line, MSG_SEPERATOR) == 0) X strcpy(input_line," "); X#endif /* MMDF */ X pending = input_line; X CarriageReturn(); X X do { X X /* while there is more space on the screen - leave prompt line free */ X while(unfilled_lines > 0) { X X /* display a screen's lineful of the input line X * and reset pending to point to remainder of input line */ X formfeed = next_line(&pending, display_buffer, COLUMNS); X X if(*display_buffer == '\0') { /* no line to display */ X if(!formfeed) /* no "formfeed" to display X * need more lines for screen */ X return(FALSE); X } else X Write_to_screen(display_buffer, 0); X X /* if formfeed, clear remainder of screen */ X if(formfeed) { X CleartoEOS(); X unfilled_lines=0; X } X else X unfilled_lines--; X X /* if screen is not full (leave room for prompt) X * but we've used up input line, return */ X X if(unfilled_lines > 0 && *pending == '\0') X return(FALSE); /* we need more lines to fill screen */ X X /* otherwise continue to display next part of input line */ X } X X /* screen is now full - prompt for user input */ X lines_more = total_lines_to_display - lines_displayed; X sprintf(footer, X ( (user_level == 0) ? X " There %s %d line%s left (%d%%). Press <space> for more, or 'i' to return. " X : (user_level == 1) ? X " %s%d line%s more (%d%%). Press <space> for more, 'i' to return. " X : X " %s%d line%s more (you've seen %d%%) "), X (user_level == 0 ? X (lines_more == 1 ? "is" : "are") : ""), X lines_more, plural(lines_more), X (int)((100L * lines_displayed) / total_lines_to_display)); X X MoveCursor(LINES, 0); X StartBold(); X Write_to_screen(footer, 0); X EndBold(); X X switch(ch = ReadCh()) { X X case '\n': X case '\r': /* scroll down a line */ X unfilled_lines = 1; X ClearLine(LINES); X break; X X case ' ': /* scroll a screenful */ X unfilled_lines = LINES; X if(clear_pages) { X ClearScreen(); X MoveCursor(0,0); X CarriageReturn(); X X /* output title */ X if(title_messages && filter) { X title_for_page(++pages_displayed); X unfilled_lines -= 2; X } X } else ClearLine(LINES); X X /* and keep last line to be first line of next X * screenful unless we had a formfeed */ X if(!formfeed) { X if(clear_pages) X Write_to_screen(display_buffer, 0); X unfilled_lines--; X } X break; X X default: return(ch); X } X CarriageReturn(); X } while(*pending); X return(FALSE); X} X Xtitle_for_page(page) Xint page; X{ X /** Output a nice title for the second thru last pages of the message X we're currently reading. Note - this code is very similar to X that which produces the title for the first page, except that X page number replaces the date and the method by which it X gets to the screen **/ X X static char title1[SLEN], title2[SLEN]; X char titlebuf[SLEN], title3[SLEN], who[SLEN]; X static t1_len, t2_len; X register int padding, showing_to; X X /* format those parts of the title that are constant for a message */ X if(form_title) { X X showing_to = tail_of(headers[current-1]->from, who, X headers[current-1]->to); X X sprintf(title1, "%s %d/%d ", X headers[current-1]->status & DELETED ? "[deleted]" : X headers[current-1]->status & FORM_LETTER ? "Form": "Message", X current, message_count); X t1_len = strlen(title1); X sprintf(title2, "%s %s", showing_to? "To" : "From", who); X t2_len = strlen(title2); X } X /* format those parts of the title that vary between pages of a mesg */ X sprintf(title3, " Page %d", page); X X /* truncate or pad title2 portion on the right X * so that line fits exactly to the rightmost column */ X padding = COLUMNS - (t1_len + t2_len + strlen(title3)); X X sprintf(titlebuf, "%s%-*.*s%s\n\r\n\r", title1, t2_len+padding, X t2_len+padding, title2, title3); X /* extra newline is to give a blank line after title */ X X Write_to_screen(titlebuf, 0); X form_title = 0; X} SHAR_EOF chmod 0444 src/builtin.c || echo "restore of src/builtin.c fails" echo "x - extracting src/calendar.c (Text)" sed 's/^X//' << 'SHAR_EOF' > src/calendar.c && X Xstatic char rcsid[] = "@(#)$Id: calendar.c,v 4.1 90/04/28 22:42:36 syd Exp $"; X X/******************************************************************************* X * The Elm Mail System - $Revision: 4.1 $ $State: Exp $ X * X * Copyright (c) 1986, 1987 Dave Taylor X * Copyright (c) 1988, 1989, 1990 USENET Community Trust X ******************************************************************************* X * Bug reports, patches, comments, suggestions should be sent to: X * X * Syd Weinstein, Elm Coordinator X * elm@DSI.COM dsinc!elm X * X ******************************************************************************* X * $Log: calendar.c,v $ X * Revision 4.1 90/04/28 22:42:36 syd X * checkin of Elm 2.3 as of Release PL0 X * X * X ******************************************************************************/ X X/** This routine implements a rather snazzy idea suggested by Warren X Carithers of the Rochester Institute of Technology that allows X mail to contain entries formatted in a manner that will allow direct X copying into a users calendar program. X X All lines in the current message beginning with "->", e.g. X X -> Mon 04/21 1:00p meet with chairman candidate X X get copied into the user's calendar file. X X**/ X X#include "headers.h" X X#ifdef ENABLE_CALENDAR /* if not defined, this will be an empty file */ X X#include <errno.h> X Xextern int errno; X Xchar *error_name(), *error_description(), *strcpy(); X Xscan_calendar() X{ X FILE *calendar; X int count; X X /* First step is to open the calendar file for appending... **/ X X if (can_open(calendar_file, "a") != 0) { X dprint(2, (debugfile, X "Error: wrong permissions to append to calendar %s\n", X calendar_file)); X dprint(2, (debugfile, "** %s - %s **\n", X error_name(errno), error_description(errno))); X error1("Not able to append to file %s!", calendar_file); X return; X } X X save_file_stats(calendar_file); X X if ((calendar = fopen(calendar_file,"a")) == NULL) { X dprint(2, (debugfile, X "Error: couldn't append to calendar file %s (scan)\n", X calendar_file)); X dprint(2, (debugfile, "** %s - %s **\n", X error_name(errno), error_description(errno))); X error1("Couldn't append to file %s!", calendar_file); X return; X } X X count = extract_info(calendar); X X fclose(calendar); X X restore_file_stats(calendar_file); X X if (count > 0) X error2("%d entr%s saved in calendar file.", X count, count > 1 ? "ies" : "y"); X else X error("No calendar entries found in that message."); X X return; X} X Xint Xextract_info(save_to_fd) XFILE *save_to_fd; X{ X /** Save the relevant parts of the current message to the given X calendar file. The only parameter is an opened file X descriptor, positioned at the end of the existing file **/ X X register int entries = 0, lines; X char buffer[SLEN], *cp, *is_cal_entry(); X X /** get to the first line of the message desired **/ X X if (fseek(mailfile, headers[current-1]->offset, 0) == -1) { X dprint(1,(debugfile, X "ERROR: Attempt to seek %d bytes into file failed (%s)", X headers[current-1]->offset, "extract_info")); X error1("ELM [seek] failed trying to read %d bytes into file.", X headers[current-1]->offset); X return(0); X } X X /* how many lines in message? */ X X lines = headers[current-1]->lines; X X /* now while not EOF & still in message... scan it! */ X X while (lines) { X X if(fgets(buffer, SLEN, mailfile) == NULL) X break; X X if(buffer[strlen(buffer)-1] == '\n') X lines--; /* got a full line */ X X if((cp = is_cal_entry(buffer)) != NULL) { X entries++; X fprintf(save_to_fd,"%s", cp); X } X X } X dprint(4,(debugfile, X "Got %d calender entr%s.\n", entries, entries > 1? "ies":"y")); X X return(entries); X} X Xchar * Xis_cal_entry(string) Xregister char *string; X{ X /* If string is of the form X * ->{optional white space} {stuff} X * return a pointer to stuff, otherwise return NULL. X */ X X if(strncmp(string, "->", 2) == 0) { X for(string +=2 ; whitespace(*string); string++) X ; X return(string); X } X return(NULL); X} X X#endif SHAR_EOF chmod 0444 src/calendar.c || echo "restore of src/calendar.c fails" echo "x - extracting src/conn_to.c (Text)" sed 's/^X//' << 'SHAR_EOF' > src/conn_to.c && X Xstatic char rcsid[] = "@(#)$Id: conn_to.c,v 4.1 90/04/28 22:42:37 syd Exp $"; X X/******************************************************************************* X * The Elm Mail System - $Revision: 4.1 $ $State: Exp $ X * X * Copyright (c) 1986, 1987 Dave Taylor X * Copyright (c) 1988, 1989, 1990 USENET Community Trust X ******************************************************************************* X * Bug reports, patches, comments, suggestions should be sent to: X * X * Syd Weinstein, Elm Coordinator X * elm@DSI.COM dsinc!elm X * X ******************************************************************************* X * $Log: conn_to.c,v $ X * Revision 4.1 90/04/28 22:42:37 syd X * checkin of Elm 2.3 as of Release PL0 X * X * X ******************************************************************************/ X X/** This contains the routine(s) needed to have the Elm mailer figure X out what machines the current machine can talk to. X It will invoke uuname to a file, then read the file in! X**/ X X#include "headers.h" X Xchar *strcpy(); X X#ifndef DONT_TOUCH_ADDRESSES Xget_connections() X{ X X /** get the direct connections that this machine has X using the uuname routine to get the names. X **/ X X FILE *fd; X char buffer[SLEN], filename[SLEN]; X struct lsys_rec *system_record, *previous_record; X int loc_on_line; X X X if (! warnings) { /* skip this - they don't care! */ X talk_to_sys = NULL; X return; X } X X if (strlen(uuname) == 0) { /* skip this - no way to get connections */ X warnings = NO; X talk_to_sys = NULL; X dprint(1, (debugfile, "No uuname - clearing warnings\n")); X error("Warning: no uuname command, clearing option warnings"); X return; X } X X sprintf(filename, "%s%s%d", temp_dir, temp_uuname, getpid()); X sprintf(buffer,"%s > %s", uuname, filename); X X if (system_call(buffer, SH, FALSE, FALSE) != 0) { X dprint(1, (debugfile, "Can't get uuname info - system() failed!\n")); X goto unable_to_get; X } X X if ((fd = fopen(filename, "r")) == NULL) { X dprint(1, (debugfile, X "Can't get uuname info - can't open file %s for reading\n", X filename)); X goto unable_to_get; X } X X previous_record = NULL; X X while (fgets(buffer, SLEN, fd) != NULL) { X no_ret(buffer); X if (previous_record == NULL) { X dprint(2, (debugfile, "uuname\tdirect connection to %s, ", buffer)); X loc_on_line = 30 + strlen(buffer); X previous_record = (struct lsys_rec *) pmalloc(sizeof *talk_to_sys); X X strcpy(previous_record->name, buffer); X previous_record->next = NULL; X talk_to_sys = previous_record; X } X else { /* don't have to check uniqueness - uuname does that! */ X if (loc_on_line + strlen(buffer) > 80) { X dprint(2, (debugfile, "\n\t")); X loc_on_line = 8; X } X dprint(2, (debugfile, "%s, ", buffer)); X loc_on_line += (strlen(buffer) + 2); X system_record = (struct lsys_rec *) pmalloc(sizeof *talk_to_sys); X X strcpy(system_record->name, buffer); X system_record->next = NULL; X previous_record->next = system_record; X previous_record = system_record; X } X } X X fclose(fd); X X (void) unlink(filename); /* kill da temp file!! */ X X dprint(2, (debugfile, "\n")); /* for a nice format! Yeah! */ X X return; /* it all went okay... */ X Xunable_to_get: X unlink(filename); /* insurance */ X error("Warning: couldn't figure out system connections..."); X talk_to_sys = NULL; X} X#endif SHAR_EOF chmod 0444 src/conn_to.c || echo "restore of src/conn_to.c fails" echo "x - extracting src/curses.c (Text)" sed 's/^X//' << 'SHAR_EOF' > src/curses.c && X Xstatic char rcsid[] = "@(#)$Id: curses.c,v 4.1 90/04/28 22:42:39 syd Exp $"; X X/******************************************************************************* X * The Elm Mail System - $Revision: 4.1 $ $State: Exp $ X * X * Copyright (c) 1986, 1987 Dave Taylor X * Copyright (c) 1988, 1989, 1990 USENET Community Trust X ******************************************************************************* X * Bug reports, patches, comments, suggestions should be sent to: X * X * Syd Weinstein, Elm Coordinator X * elm@DSI.COM dsinc!elm X * X ******************************************************************************* X * $Log: curses.c,v $ X * Revision 4.1 90/04/28 22:42:39 syd X * checkin of Elm 2.3 as of Release PL0 X * X * X ******************************************************************************/ X X/** This library gives programs the ability to easily access the X termcap information and write screen oriented and raw input X programs. The routines can be called as needed, except that X to use the cursor / screen routines there must be a call to X InitScreen() first. The 'Raw' input routine can be used X independently, however. X X**/ X X/** NOTE THE ADDITION OF: the #ifndef ELM stuff around routines that X we don't use. This is for code size and compile time speed... X**/ X X#include "headers.h" X X#ifdef TERMIOS X# include <termios.h> X# if __convex__ X# include <sys/ioctl.h> /* non-standard, for TIOCGWINSZ */ X# endif X#else X# ifdef TERMIO X# include <termio.h> X# else X# include <sgtty.h> X# endif X#endif X X#include <ctype.h> X X#ifdef PTEM X# include <sys/types.h> X# include <sys/stream.h> X# include <sys/ptem.h> X#endif X X#ifdef BSD X#undef tolower X#endif X X#define TTYIN 0 X X#ifdef SHORTNAMES X# define _clearinverse _clrinv X# define _cleartoeoln _clrtoeoln X# define _cleartoeos _clr2eos X# define _transmit_off xmit_off X# define _transmit_on xmit_on X#endif X X#ifdef TERMIOS Xstruct termios _raw_tty, X _original_tty; X#define ttgetattr(fd,where) tcgetattr((fd),(where)) X#define ttsetattr(fd,where) tcsetattr((fd),TCSADRAIN,(where)) X#else /*TERMIOS*/ X# ifdef TERMIO Xstruct termio _raw_tty, X _original_tty; X#define ttgetattr(fd,where) ioctl((fd),TCGETA,(where)) X#define ttsetattr(fd,where) ioctl((fd),TCSETAW,(where)) X# else Xstruct sgttyb _raw_tty, X _original_tty; X#define ttgetattr(fd,where) ioctl((fd),TIOCGETP,(where)) X#define ttsetattr(fd,where) ioctl((fd),TIOCSETP,(where)) X# endif /*TERMIO*/ X#endif /*TERMIOS*/ X Xstatic int _inraw = 0; /* are we IN rawmode? */ X X#define DEFAULT_LINES_ON_TERMINAL 24 X#define DEFAULT_COLUMNS_ON_TERMINAL 80 X Xstatic int _memory_locked = 0; /* are we IN memlock?? */ Xstatic int _line = -1, /* initialize to "trash" */ X _col = -1; X Xstatic int _intransmit; /* are we transmitting keys? */ X Xstatic Xchar *_clearscreen, *_moveto, *_up, *_down, *_right, *_left, X *_setbold, *_clearbold, *_setunderline, *_clearunderline, X *_sethalfbright, *_clearhalfbright, *_setinverse, *_clearinverse, X *_cleartoeoln, *_cleartoeos, *_transmit_on, *_transmit_off, X *_set_memlock, *_clear_memlock; X Xstatic int _lines, _columns, _automargin, _eatnewlineglitch; Xint tabspacing; X Xstatic char _terminal[1024]; /* Storage for terminal entry */ Xstatic char _capabilities[1024]; /* String for cursor motion */ X Xstatic char *ptr = _capabilities; /* for buffering */ X Xint outchar(); /* char output for tputs */ Xchar *tgetstr(), /* Get termcap capability */ X *tgoto(); /* and the goto stuff */ X XInitScreen() X{ X /* Set up all this fun stuff: returns zero if all okay, or; X -1 indicating no terminal name associated with this shell, X -2..-n No termcap for this terminal type known X */ X X int tgetent(), /* get termcap entry */ X err; X char termname[40]; X char *strcpy(), *getenv(); X X if (getenv("TERM") == NULL) return(-1); SHAR_EOF echo "End of part 12" echo "File src/curses.c is continued in part 13" echo "13" > s2_seq_.tmp exit 0 exit 0 # Just in case... -- Please send comp.sources.unix-related mail to rsalz@uunet.uu.net. Use a domain-based address or give alternate paths, or you may lose out.