rsalz@bbn.com (Rich Salz) (02/18/88)
Submitted-by: Dave Ihnat <ihnp4!homebru!ignatz> Posting-number: Volume 13, Issue 51 Archive-name: rolodex/part03 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 3 (of 4)." PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f './io.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'./io.c'\" else echo shar: Extracting \"'./io.c'\" \(10740 characters\) sed "s/^X//" >'./io.c' <<'END_OF_FILE' X/* io.c */ X#include <stdio.h> X#ifdef UNIX X#include <sys/types.h> X#include <sys/stat.h> X#ifdef BSD X#include <sys/file.h> X#else X#include <fcntl.h> X#endif X#endif X X#ifdef VMS X#include <types.h> X#include <stat.h> X#include <file.h> X#endif X X#ifdef MSDOS X# ifdef MSC X# include <sys/types.h> X# endif /* MSC */ X#include <sys/stat.h> X#include <fcntl.h> X#endif X X#include <ctype.h> X X#ifdef TMC X#include <ctools.h> X#else X#include "ctools.h" X#endif X X#include "rolofilz.h" X#include "datadef.h" X X Xchar *Field_Names[N_BASIC_FIELDS] = { X X "Name: ", "Work Phone: ", "Home Phone: ", "Company: ", X "Work Address: ", "Home Address: ", "Remarks: ", "Date Updated: " X X }; X XPtr_Rolo_List Begin_Rlist = 0; XPtr_Rolo_List End_Rlist = 0; XPtr_Rolo_List Current_Entry = 0; X Xstatic char *rolofiledata; X X/* X * The following has been added to accomplish two goals: X * X * 1) Document all help files expected in the system, to avoid/identify X * lost elements in distribution. X * X * 2) Allow a flexible, easily-modified way of changing filenames as X * necessary/desired to comply with different operating systems. X */ Xchar *hlpfiles[] = { X "addhelp.hlp", /* ADDHELP */ X "addinfo.hlp", /* ADDINFO */ X "confirm.hlp", /* CONFIRMHELP */ X "entrymnu.hlp", /* ENTRYMENU */ X "escan.hlp", /* ESCANHELP */ X "esearch.hlp", /* ESEARCHHELP */ X "fldsrch.hlp", /* FIELDSEARCHHELP */ X#ifdef UNIX X "lockinfo.unx", /* LOCKINFO */ X#endif X#ifdef VMS X "lockinfo.vms", /* LOCKINFO */ X#endif X#ifdef MSDOS X "lockinfo.dos", /* LOCKINFO */ X#endif X "mainmenu.hlp", /* MAINMENU */ X "mnymtch.hlp", /* MANYMATCHHELP */ X "moption.hlp", /* MOPTIONHELP */ X "moptions.hlp", /* MOPTIONSHELP */ X "moreflds.hlp", /* MOREFIELDSHELP */ X "newadd.hlp", /* NEWADDHELP */ X "otherfmt.hlp", /* OTHERFORMATHELP */ X "pkentry.hlp", /* PICKENTRYHELP */ X "pkntmenu.hlp", /* PICKENTRYMENU */ X "poptmenu.hlp", /* POPTIONMENU */ X "poptions.hlp", /* POPTIONSHELP */ X "srchstr.hlp", /* SEARCHSTRINGHELP */ X "update.hlp", /* UPDATEHELP */ X "updatmnu.hlp", /* UPDATEMENU */ X "usrfld.hlp", /* USERFIELDHELP */ X}; X X Xread_rolodex (fd) int fd; X X{ X struct stat statdata; X long filesize; X int i,j,k,start_of_others,warning_given; X Ptr_Rolo_Entry newentry; X Ptr_Rolo_List newlink,rptr; X char *next_field,*next_other; X char **other_pointers; X int n_entries = 0; X X /* find out how many bytes are in the file */ X X fstat(fd,&statdata); X if ((filesize = statdata.st_size) == 0) { X return(0); X } X X /* create an array of characters that big */ X X rolofiledata = rolo_emalloc(filesize); X X /* read them all in at once for efficiency */ X X#ifdef MSDOS X /* X * Unlike Unix, MS-DOS compilers make a distinction between text and X * binary files. Unfortunately, this means that in text mode, the file X * size is reported by the stat call won't necessarily match the value X * reported by the read, since there is CR/LF character translation. X * So, the best we can hope for here is that a failed read will give a X * zero or negative return value... X */ X if ((filesize = read(fd,rolofiledata,filesize)) <= 0) { X#else X if (filesize != read(fd,rolofiledata,filesize)) { X#endif X fprintf(stderr,"rolodex read failed\n"); X exit(-1); X } X X j = 0; X X /* for each entry in the rolodex file */ X X while (j < filesize) { X X n_entries++; X X /* create the link and space for the data entry */ X X newlink = new_link_with_entry(); X newentry = get_entry(newlink); X if (j == 0) { X Begin_Rlist = newlink; X set_prev_link(newlink,0); X set_next_link(newlink,0); X } X else { X set_next_link(End_Rlist,newlink); X set_prev_link(newlink,End_Rlist); X set_next_link(newlink,0); X } X End_Rlist = newlink; X X /* locate each required field in the character array and change */ X /* the ending line feed to a null. Insert a pointer to the */ X /* beginning of the field into the data entry */ X X for (i = 0; i < N_BASIC_FIELDS; i++) { X next_field = rolofiledata + j; X while (rolofiledata[j] != '\n') { X j++; X } X rolofiledata[j] = '\0'; X j++; X set_basic_rolo_field(i,newentry,next_field); X } X X /* the end of an entry is indicated by two adjacent newlines */ X X if (rolofiledata[j] == '\n') { X j++; X newentry -> other_fields = 0; X continue; X } X X /* there must be additional, user-inserted fields. Find out how many. */ X X start_of_others = j; X while (1) { X while (rolofiledata[j] != '\n') { X j++; X } X incr_n_others(newentry); X j++; X if (rolofiledata[j] == '\n') { X j++; X break; X } X } X X /* allocate an array of character pointers to hold these fields */ X X other_pointers = (char **)rolo_emalloc(get_n_others(newentry)*sizeof(char *)); X X /* separate each field and insert a pointer to it in the char array */ X X k = start_of_others; X for (i = 0; i < get_n_others(newentry); i++) { X next_other = rolofiledata + k; X while (rolofiledata[k] != '\n') { X k++; X } X rolofiledata[k] = '\0'; X other_pointers[i] = next_other; X k++; X } X X /* insert the pointer to this character array into the data entry */ X X newentry -> other_fields = other_pointers; X X } X X /* check that all the entries are in alphabetical order by name */ X X warning_given = 0; X rptr = get_next_link(Begin_Rlist); X while (rptr != 0) { X if (1 == compare_links(get_prev_link(rptr),rptr)) { X if (!warning_given) fprintf(stderr,"Warning, rolodex out of order\n"); X warning_given = 1; X reorder_file = 1; X } X rptr = get_next_link(rptr); X } X X return(n_entries); X X} X X Xwrite_rolo_list (fp) FILE *fp; X X/* write the entire in-core rolodex to a file */ X X{ X X Ptr_Rolo_List rptr; X Ptr_Rolo_Entry lentry; X int j; X X rptr = Begin_Rlist; X X while (rptr != 0) { X lentry = get_entry(rptr); X for (j = 0; j < N_BASIC_FIELDS; j++) { X fprintf(fp,"%s\n",get_basic_rolo_field(j,lentry)); X } X for (j = 0; j < get_n_others(lentry); j++) { X fprintf(fp,"%s\n",get_other_field(j,lentry)); X } X fprintf(fp,"\n"); X rptr = get_next_link(rptr); X } X X} X X Xwrite_rolo (fp1,fp2) FILE *fp1; FILE *fp2; X X{ X write_rolo_list(fp1); X write_rolo_list(fp2); X} X X Xdisplay_basic_field (name,value,show,up) char *name; char *value; int show,up; X{ X int i; X if ((value == (char *)NULL) || (all_whitespace(value) && !show)) return; X printf("%-25s",name); X while (*value != '\0') { X if (*value == ';') { X while (*++value == ' '); X putchar('\n'); X for (i = 0; i < (up ? 28 : 25); i++) putchar(' '); X } X else { X putchar(*value++); X } X } X putchar('\n'); X} X X Xdisplay_other_field (fieldstring) char *fieldstring; X{ X int already_put_sep = 0; X int count = 0; X int i; X while (*fieldstring != '\0') { X if (*fieldstring == ';' && already_put_sep) { X while (*++fieldstring == ' '); X putchar('\n'); X for (i = 0; i < 25; i++) putchar(' '); X continue; X } X putchar(*fieldstring); X count++; X if (*fieldstring == ':' && !already_put_sep) { X for (i = count; i < 24; i++) putchar(' '); X already_put_sep = 1; X } X fieldstring++; X } X putchar('\n'); X} X X Xsummarize_entry_list (rlist,ss) Ptr_Rolo_List rlist; char *ss; X X/* print out the Name field for each entry that is tagged as matched */ X/* and number each entry. */ X X{ X int count = 1; X clear_the_screen(); X printf("Entries that match '%s' :\n\n",ss); X while (rlist != 0) { X if (get_matched(rlist)) { X printf ( X "%d. \t%s\n", X count++, X get_basic_rolo_field((int) R_NAME,get_entry(rlist)) X ); X } X rlist = get_next_link(rlist); X } X putchar('\n'); X} X X Xdisplay_field_names () X X/* display and number each standard field name. */ X X{ X int j; X char *name; X clear_the_screen(); X for (j = 0; j < N_BASIC_FIELDS - 1; j++) { X name = Field_Names[j]; X printf("%d. ",j+1); X while (*name != ':') putchar(*name++); X putchar('\n'); X } X printf("%d. ",N_BASIC_FIELDS); X printf("A user created item name\n\n"); X} X Xdisplay_entry (lentry) Ptr_Rolo_Entry lentry; X{ X int j,n_others; X char *string; X X clear_the_screen(); X X /* display the standard fields other than Date Updated */ X X for (j = 0; j < N_BASIC_FIELDS - 1; j++) { X string = get_basic_rolo_field(j,lentry); X display_basic_field(Field_Names[j],string,0,0); X } X X /* display any additional fields the user has defined for this entry */ X X n_others = get_n_others(lentry); X for (j = 0; j < n_others; j++) { X string = get_other_field(j,lentry); X display_other_field(string); X } X X /* display the Date Updated field */ X X j = N_BASIC_FIELDS - 1; X display_basic_field(Field_Names[j],get_basic_rolo_field(j,lentry),0,0); X fprintf(stdout,"\n"); X X} X X Xdisplay_entry_for_update (lentry) Ptr_Rolo_Entry lentry; X X/* same as display_entry, except each item is numbered and the Date Updated */ X/* item is not displayed */ X X{ X int j,n_others; X char *string; X int count = 1; X X clear_the_screen(); X X for (j = 0; j < N_BASIC_FIELDS - 1; j++) { X string = get_basic_rolo_field(j,lentry); X printf("%d. ",count++); X display_basic_field(Field_Names[j],string,1,1); X } X X n_others = get_n_others(lentry); X for (j = 0; j < n_others; j++) { X string = get_other_field(j,lentry); X printf("%d. ",count++); X display_other_field(string); X } X X printf("%d. Add a new user defined field\n",count); X X fprintf(stdout,"\n"); X X} X X Xint cathelpfile (fileidx,helptopic,clear) X X int fileidx; X char *helptopic; X int clear; X X{ X register char *filepath; X FILE *fp; X char buffer[MAXLINELEN]; X X if(fileidx > LAST_HELP) { X fprintf(stderr, X "INTERNAL ERROR: Error file index, max: %d, requested: %d\n", X LAST_HELP,fileidx); X return; X }else X filepath = libdir(hlpfiles[fileidx]); X X if (clear) clear_the_screen(); X if (NULL == (fp = fopen(filepath,"r"))) { X if (helptopic) { X printf("No help available on %s, sorry.\n\n",helptopic); X } X else { X fprintf(stderr,"Fatal error, can't open %s\n",filepath); X exit(-1); X } X return; X } X while (NULL != fgets(buffer,MAXLINELEN,fp)) printf("%s",buffer); X printf("\n"); X fclose(fp); X return; X} X X Xany_char_to_continue () X{ X char buffer[80]; X printf("RETURN to continue: "); X fgets(buffer,80,stdin); X return; X} END_OF_FILE if test 10740 -ne `wc -c <'./io.c'`; then echo shar: \"'./io.c'\" unpacked with wrong size! fi # end of './io.c' fi if test -f './operatns.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'./operatns.c'\" else echo shar: Extracting \"'./operatns.c'\" \(9950 characters\) sed "s/^X//" >'./operatns.c' <<'END_OF_FILE' X/* operatns.c */ X#include <stdio.h> X#include <ctype.h> X X#ifdef TMC X#include <ctools.h> X#else X#include "ctools.h" X#endif X#include "args.h" X#include "menu.h" X#include "mem.h" X X#include "rolofilz.h" X#include "rolodefs.h" X#include "datadef.h" X#include "choices.h" X X#define index strchr Xchar *index(); X Xextern char *ctime(); X XPtr_Rolo_List create_entry (basicdata,otherdata) char **basicdata, **otherdata; X{ X Ptr_Rolo_List newlink; X Ptr_Rolo_Entry newentry; X int i,j; X newlink = new_link_with_entry(); X newentry = get_entry(newlink); X for (j = 0; j < N_BASIC_FIELDS; j++) { X set_basic_rolo_field(j,newentry,basicdata[j]); X } X j = 0; X while (otherdata[j] != 0) j++; X set_n_others(newentry,j); X if (j > 0) { X newentry -> other_fields = (char **) rolo_emalloc(j*sizeof(char *)); X for (i = 0; i < j; i++) { X set_other_field(i,newentry,otherdata[i]); X } X } X else newentry -> other_fields = 0; X return(newlink); X} X X Xother_fields () X{ X int rval; X rval = rolo_menu_yes_no ( X "Additional fields? ",DEFAULT_NO,1, X MOREFIELDSHELP, "additional fields" X ); X return(rval == MENU_YES); X} X X Xadd_the_entry () X{ X return(MENU_YES == rolo_menu_yes_no ( X "Add new entry to rolodex? ",DEFAULT_YES,1, X NEWADDHELP, "adding newly entered entry" X )); X} X X Xrolo_add () X X{ X int i,j,k,rval,menuval; X char *response; X char *basicdata[N_BASIC_FIELDS], *otherdata[100]; X Ptr_Rolo_List rlink; X X if(read_only) X { X printf("Readonly mode: cannot add entries.\n"); X sleep(2); X return(1); X } X X for (j = 0; j < 100; j++) otherdata[j] = (char *)NULL; X for (j = 0; j < N_BASIC_FIELDS; j++) basicdata[j] = (char *)NULL; X cathelpfile(ADDINFO,(char *)NULL,1); X X /* 'k' and 'kludge' are are kludge to allow us to back up from entering */ X /* user defined fields to go an correct wrong basic field information. */ X X k = 0; X X kludge : X X for (j = k; j < N_BASIC_FIELDS - 1; j++) { X X redo : X X rval = menu_match ( X &menuval,&response, X Field_Names[j], X 0,0,0,1,5, X "\\",A_ABORT_ADD, X "^",A_BACKUP, X "!",A_FILL_IN_REST, X "?",A_HELP, X "",A_NO_DATA X ); X X switch (rval) { X X case MENU_NO_MATCH : X basicdata[j] = copystr(response); X if (j == 0 && strlen(basicdata[j]) == 0) { X printf("Each entry must have a name!\n\n"); X sleep(2); X goto redo; X } X break; X X case MENU_MATCH : X switch (menuval) { X case A_BACKUP : X if (j == 0) return(0); X j--; X goto redo; X /* break; */ X case A_ABORT_ADD : X return(0); X /* break; */ X case A_FILL_IN_REST : X if (j == 0) { X fprintf(stderr,"You must enter at least a name...\n\n"); X sleep(2); X goto redo; X } X goto add_entry; X /* break; */ X case A_HELP : X cathelpfile(ADDHELP,"adding entries",1); X any_char_to_continue(); X clear_the_screen(); X cathelpfile(ADDINFO,(char *)NULL,0); X for (i = 0; i < j; i++) { X printf("%s%s\n",Field_Names[i],basicdata[i]); X } X goto redo; X /* break; */ X case A_NO_DATA : X if (j == 0) { X fprintf(stderr,"You must enter at least a name...\n\n"); X sleep(2); X goto redo; X } X X if (basicdata[j] != (char *)NULL) X basicdata[j][0] = '\0'; X else X basicdata[j] = ""; X break; X default : X fprintf(stderr,"Impossible rval from rolo_add menu_match\n\n"); X save_and_exit(-1); X break; X } X break; X X case MENU_EOF : X user_eof(); X break; X X case MENU_ERROR : X case MENU_AMBIGUOUS : X default : X fprintf(stderr,"Impossible return from rolo_add menu_match\n"); X save_and_exit(-1); X break; X X } X X } X X if (other_fields()) { X for (j = 0; j < 100; j++) { X redo_other : X rval = menu_match ( X &menuval,&response, X "Enter <name>: <data> (type RETURN to quit) : ", X 0,0,0,0,5, X "\\",O_ABORT, X "?",O_HELP, X "Help",O_HELP, X "^",O_BACKUP, X "",O_DONE_OTHERS X ); X switch (rval) { X case MENU_MATCH : X switch (menuval) { X case O_DONE_OTHERS : X goto add_entry; X /* break; */ X case O_BACKUP : X if (j == 0) { X k = N_BASIC_FIELDS - 2; X goto kludge; X } X else { X j--; X printf("Deleting %s\n",otherdata[j]); X goto redo_other; X } X /* break; */ X case O_ABORT : X return(0); X /* break; */ X case O_HELP : X cathelpfile(OTHERFORMATHELP,"user-item format",1); X any_char_to_continue(); X goto redo_other; X } X break; X case MENU_NO_MATCH : X if ((index(response,':') == (char *)NULL) || X (*response == ':')) { X printf("No field name provided -- separate with a ':'.\n"); X goto redo_other; X } X otherdata[j] = copystr(response); X break; X case MENU_EOF : X user_eof(); X break; X case MENU_AMBIGUOUS : X case MENU_ERROR : X default : X fprintf(stderr,"Impossible rval from add_other menu_match\n"); X save_and_exit(-1); X } X } X } X X add_entry : X X basicdata[N_BASIC_FIELDS - 1] = timestring(); X X rlink = create_entry(basicdata,otherdata); X clear_the_screen(); X display_entry(get_entry(rlink)); X if (add_the_entry()) { X printf ( X "Adding entry for %s to rolodex\n", X get_basic_rolo_field((int) R_NAME,get_entry(rlink)) X ); X rolo_insert(rlink,compare_links); X changed = 1; X sleep(2); X } X else { X return(0); X } X return(0); /* Should never hit this... */ X} X X Xentry_action (rlink) Ptr_Rolo_List rlink; X X{ X static entry_menu_displayed = 0; X int rval,menuval; X char *response; X X if (!entry_menu_displayed) cathelpfile(ENTRYMENU,(char *)NULL,0); X#ifdef NEVERDEF X entry_menu_displayed = 1; /* This may be turned off to provide verbose help */ X#endif X X redo : X X rval = menu_match ( X &menuval, &response, X "Action (? for help) : ", X 0,1,1,1,7, X "\\",E_ABORT, X "?",E_HELP, X "",E_CONTINUE, X "-",E_DELETE, X "+",E_UPDATE, X "<",E_PREV, X "%",E_SCAN X ); X X if (rval != MENU_MATCH) { X if (rval == MENU_EOF) user_eof(); X fprintf(stderr,"Impossible return from entry_action menu_match\n"); X save_and_exit(-1); X } X X switch (menuval) { X case E_ABORT : X case E_CONTINUE : X case E_PREV : X break; X case E_SCAN : X rolo_peruse_mode(get_next_link(rlink)); X break; X case E_UPDATE : X rolo_update_mode(rlink); X break; X case E_DELETE : X if(!rolo_delete(rlink)) X printf("Entry deleted\n"); X sleep(1); X changed = 1; X break; X case E_HELP : X cathelpfile ( X (in_search_mode ? ESEARCHHELP : ESCANHELP), X "entry actions", X 1 X ); X any_char_to_continue(); X clear_the_screen(); X display_entry(get_entry(rlink)); X goto redo; X /* break; */ X default : X fprintf(stderr,"Impossible menuval in entry_action\n"); X save_and_exit(-1); X } X X return(menuval); X X} X X Xdisplay_list_of_entries (rlist) Ptr_Rolo_List rlist; X X{ X Ptr_Rolo_List old,hold; X X if(rlist != 0) X hold = get_next_link(rlist); /* In case of change */ X X while (rlist != 0) { X X if (!get_matched(rlist)) goto next; X X loop : X X display_entry(get_entry(rlist)); X X switch (entry_action(rlist)) { X case E_CONTINUE : X break; X case E_ABORT : X return(0); X /* break; */ X case E_PREV : X old = rlist; X find_prev_match : X if (get_prev_link(rlist) == 0) { X rlist = old; X printf("No previous entry in scan list\n"); X sleep(2); X } X else { X rlist = get_prev_link(rlist); X if (!get_matched(rlist)) goto find_prev_match; X } X goto loop; X /* break; */ X case E_UPDATE : X if(name_changed) X { X printf("Continuing scan at next entry in scan list before change...\n"); X sleep(1); X rlist = hold; X X break; X } X /* Deliberate fall-thru */ X default : X printf("Displaying next entry in scan list...\n"); X sleep(1); X break; X } X X next : X X if(!name_changed) X rlist = get_next_link(rlist); X else X name_changed = 0; X X if(rlist != 0) X hold = get_next_link(rlist); /* In case of change */ X X } X X printf("No further entries to scan...\n"); X sleep(2); X return(0); X} X X Xrolo_peruse_mode (first_rlink) Ptr_Rolo_List first_rlink; X X{ X Ptr_Rolo_List rlist = first_rlink; X if (0 == Begin_Rlist) { X fprintf(stderr,"No further entries in rolodex...\n"); X sleep(2); X return(0); X } X while (rlist != 0) { X set_matched(rlist); X rlist = get_next_link(rlist); X } X display_list_of_entries(first_rlink); X rlist = first_rlink; X while (rlist != 0) { X unset_matched(rlist); X rlist = get_next_link(rlist); X } X X return(0); X} END_OF_FILE if test 9950 -ne `wc -c <'./operatns.c'`; then echo shar: \"'./operatns.c'\" unpacked with wrong size! fi # end of './operatns.c' fi if test -f './rolo.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'./rolo.c'\" else echo shar: Extracting \"'./rolo.c'\" \(18313 characters\) sed "s/^X//" >'./rolo.c' <<'END_OF_FILE' X/* rolo.c */ X#ifdef UNIX X#include <sys/types.h> X#include <sys/stat.h> X#include <pwd.h> X#include <string.h> X#ifdef BSD X#include <sys/file.h> X#else X#include <fcntl.h> X#endif X#endif X X#ifdef VMS X#include <types.h> X#include <file.h> X#include <stat.h> X#include <string.h> X#endif X X#ifdef MSDOS X#include <fcntl.h> X# ifdef MSC X# include <sys ypes.h> X# endif /* MSC */ X#include <sys/stat.h> X#include <errno.h> X#include <string.h> X#endif X X#include <stdio.h> X#include <ctype.h> X/* #include <sgtty.h> */ X#include <signal.h> X X X#ifdef TMC X#include <ctools.h> X#else X#include "ctools.h" X#endif X#include "args.h" X#include "menu.h" X#include "mem.h" X X#include "rolofilz.h" X#include "rolodefs.h" X#include "datadef.h" X X#ifndef BSD X/* BSD Unix gives us these values but AT&T Unix, VMS and MSDOS don't */ X/* Used with 'access(2)' syscall */ X#define R_OK 04 X#define F_OK 00 X#define W_OK 02 X#endif X X#ifdef UNIX X#define DEF_PERM 0600 /* Default permissions: All, for owner only */ X#endif X X#ifdef VMS X#define DEF_PERM 0600 /* Default permissions: All, for owner only */ X#endif X X#ifdef MSDOS X#define DEF_PERM (S_IREAD | S_IWRITE) /* Default permissions: All */ X#endif X X#define MAX_LINES 60 /* Max number of lines/page */ X Xstatic struct stat stat_buf; X Xstatic char rolodir[DIRPATHLEN]; /* directory where rolo data is */ Xstatic char filebuf[DIRPATHLEN]; /* stores result of homedir() */ X Xint changed = 0; Xint name_changed = 0; Xint reorder_file = 0; Xint rololocked = 0; Xint in_search_mode = 0; Xint read_only = 0; X Xchar *rolo_emalloc (size) int size; X X/* error handling memory allocator */ X X{ X char *rval; X char *malloc(); X if (0 == (rval = malloc((unsigned)size))) { X fprintf(stderr,"Fatal error: out of memory\n"); X save_and_exit(-1); X } X return(rval); X} X X Xchar *copystr (s) char *s; X X/* memory allocating string copy routine */ X X X{ X char *copy; X if (s == 0) return(0); X copy = rolo_emalloc(strlen(s) + 1); X strcpy(copy,s); X return(copy); X} X X Xchar *timestring () X X/* returns a string timestamp */ X X{ X char *s; X long timeval; X long time(); X X time(&timeval); X s = ctime(&timeval); X s[strlen(s) - 1] = '\0'; X return(copystr(s)); X} X X Xuser_interrupt () X X/* if the user hits C-C (we assume he does it deliberately) */ X X{ X#ifdef VMS X delete(homedir(ROLOLOCK)); X delete(homedir(ROLOTEMP)); X#else X unlink(homedir(ROLOLOCK)); X unlink(homedir(ROLOTEMP)); X#endif X fprintf(stderr,"\nAborting rolodex, no changes since last save recorded\n"); X exit(-1); X} X X Xuser_eof () X X/* if the user hits C-D */ X X{ X#ifdef VMS X delete(homedir(ROLOLOCK)); X#else X unlink(homedir(ROLOLOCK)); X#endif X fprintf(stderr,"\nUnexpected EOF on terminal. Saving rolodex and exiting\n"); X save_and_exit(-1); X} X X Xroloexit (rval) int rval; X{ X /* In case it hasn't been cleaned up, also clobber ROLOTEMP. */ X clear_the_screen(); X if (rololocked) X#ifdef VMS X delete(homedir(ROLOTEMP)); X delete(homedir(ROLOLOCK)); X exit(rval==0?1:rval); X#else X unlink(homedir(ROLOTEMP)); X unlink(homedir(ROLOLOCK)); X exit(rval); X#endif X} X X Xsave_to_disk () X X/* move the old rolodex to a backup, and write out the new rolodex and */ X/* a copy of the new rolodex (just for safety) */ X X{ X FILE *tempfp,*copyfp; X char *strcpy(); X char d1[DIRPATHLEN], d2[DIRPATHLEN]; X X#ifdef VMS X /* X * Since VMS keeps versions of files around, clobber any that are still X * hanging around. If appropriate access permissions aren't granted, X * well, they'll just have to purge their directory... X */ X delete(homedir(ROLOTEMP)); /* There will be a copy of this from earlier */ X X if(!access(homedir(ROLOCOPY),R_OK)) X if(!access(homedir(ROLOCOPY),W_OK)) /* Implies delete permission */ X delete(homedir(ROLOCOPY)); X#endif X tempfp = fopen(homedir(ROLOTEMP),"w"); X if(tempfp == (FILE *)NULL) X perror(ROLOTEMP); X X copyfp = fopen(homedir(ROLOCOPY),"w"); X if(copyfp == (FILE *)NULL) X perror(ROLOCOPY); X X if (tempfp == (FILE *)NULL || copyfp == (FILE *)NULL) { X fprintf(stderr,"Unable to write rolodex...\n"); X fprintf(stderr,"Any changes made have not been recorded\n"); X roloexit(-1); X } X X /* X * Be sure to set proper permissions on the temp,copy files *before* putting X * data in them... X */ X#ifndef MSDOS X if(chmod(homedir(ROLOTEMP),(int)stat_buf.st_mode)) X fprintf(stderr,"WARNING: Couldn't set permissions on %s\n", X homedir(ROLOTEMP)); X X if(chmod(homedir(ROLOCOPY),(int)stat_buf.st_mode)) X fprintf(stderr,"WARNING: Couldn't set permissions on %s\n", X homedir(ROLOCOPY)); X#endif /* MSDOS */ X X write_rolo(tempfp,copyfp); X X fclose(tempfp); X fclose(copyfp); X X#ifdef UNIX X unlink(strcpy(d1,homedir(ROLOBAK))); X link(strcpy(d1,homedir(ROLODATA)),strcpy(d2,homedir(ROLOBAK))); X unlink(strcpy(d1,homedir(ROLODATA))); X X if(link(strcpy(d1,homedir(ROLOTEMP)),strcpy(d2,homedir(ROLODATA)))) X { X fprintf(stderr,"Link failed. Revised rolodex is in %s\n",ROLOCOPY); X roloexit(-1); X }else X { X unlink(strcpy(d1,homedir(ROLOTEMP))); X unlink(strcpy(d1,homedir(ROLOCOPY))); X } X#endif X X#ifdef VMS X delete(homedir(ROLOBAK)); X X if ((rename(strcpy(d1,homedir(ROLODATA)),strcpy(d2,homedir(ROLOBAK))) != 1) || X (rename(strcpy(d1,homedir(ROLOTEMP)),strcpy(d2,homedir(ROLODATA)))) != 1) { X fprintf(stderr,"Rename failed. Revised rolodex is in %s\n",ROLOCOPY); X roloexit(-1); X }else X delete(homedir(ROLOCOPY)); /* Don't really need this anymore */ X#endif X X#ifdef MSDOS X unlink(homedir(ROLOBAK)); X X if (rename(strcpy(d1,homedir(ROLODATA)),strcpy(d2,homedir(ROLOBAK))) || X rename(strcpy(d1,homedir(ROLOTEMP)),strcpy(d2,homedir(ROLODATA)))) { X fprintf(stderr,"Rename failed. Revised rolodex is in %s\n",ROLOCOPY); X perror(homedir(ROLODATA)); X perror(homedir(ROLOBAK)); X perror(homedir(ROLOTEMP)); X roloexit(-1); X }else X unlink(homedir(ROLOCOPY)); /* Don't really need this anymore */ X#endif X X printf("Rolodex saved\n"); X X sleep(1); X changed = 0; X name_changed = 0; X} X X Xsave_and_exit (rval) int rval; X{ X if (changed) X save_to_disk(); X else X#ifdef VMS X delete(homedir(ROLOTEMP)); X#endif X#ifdef UNIX X unlink(homedir(ROLOTEMP)); X#endif X#ifdef MSDOS X unlink(homedir(ROLOTEMP)); X#endif X X roloexit(rval); X} X X#ifdef UNIX Xextern struct passwd *getpwnam(); X Xchar *home_directory (name) char *name; X{ X struct passwd *pwentry; X if (0 == (pwentry = getpwnam(name))) return(""); X return(pwentry -> pw_dir); X} X#endif X X#ifdef VMS X/* X * This routine should never be called in VMS. X */ Xchar *home_directory(name) char *name; X{ X fprintf(stderr,"INTERNAL ERROR: Called home_directory under VMS.\n"); X exit(0); X} X#endif X X#ifdef MSDOS X/* X * This is rather simplistic. For drives A through C, try to find a directory X * named 'name' under the root. If not found on any of the drives, then X * simply return the root directory of the current drive. X */ Xchar *home_directory (name) char *name; X{ X char *drvspec = "A:\\"; X X static char dirbuff[128]; X int fid; X X for(;*drvspec <= 'C';(*drvspec)++) X { X strcpy(dirbuff,drvspec); X strcat(dirbuff,name); X X if((fid = open(dirbuff,O_RDONLY)) >= 0) X { X close(fid); X return(dirbuff); X }else X if(errno != ENOENT && errno != ENODEV) X return(dirbuff); X } X X return("/"); X} X#endif X Xchar *homedir (filename) char *filename; X X/* e.g., given "rolodex.dat", create "/u/massar/rolodex.dat" */ X/* rolodir generally the user's home directory but could be someone else's */ X/* home directory if the -u option is used. */ X X{ X#ifdef UNIX X nbuffconcat(filebuf,3,rolodir,"/",filename); X#endif X X#ifdef MSDOS X nbuffconcat(filebuf,3,rolodir,"\\",filename); X#endif X X#ifdef VMS X nbuffconcat(filebuf,2,rolodir,filename); X#endif X X return(filebuf); X} X X Xchar *libdir (filename) char *filename; X X/* return a full pathname into the rolodex library directory */ X/* the string must be copied if it is to be saved! */ X X{ X#ifdef UNIX X nbuffconcat(filebuf,3,ROLOLIB,"/",filename); X#endif X X#ifdef MSDOS X /* X * If there's no drive specifier in ROLOLIB, then prepend the current X * drive. X */ X char *curdir; X char *getcwd(); X X curdir = ROLOLIB; X X if(curdir[2] != ':') X { X curdir = getcwd((char *)NULL,128); X curdir[3] = '\0'; X nbuffconcat(filebuf,4,curdir,ROLOLIB,"\\",filename); X (void)free(curdir); X }else X nbuffconcat(filebuf,3,ROLOLIB,"\\",filename); X#endif X X#ifdef VMS X nbuffconcat(filebuf,2,ROLOLIB,filename); X#endif X X X return(filebuf); X} X X Xrolo_only_to_read () X{ X return((option_present(READONLYFLAG) << 1) | X (option_present(SUMMARYFLAG) || n_non_option_args())); X} X X Xlocked_action () X{ X if (option_present(OTHERUSERFLAG)) { X fprintf(stderr,"Someone else is modifying that rolodex, sorry\n"); X exit(-1); X } X else { X cathelpfile(LOCKINFO,"locked rolodex",0); X exit(-1); X } X} X X Xpretty_print() X{ X int elt_lines, index, tmp_line_cnt; X int line_cnt = 0; X char *tmpptr; X char *strchr(); X FILE *lstfp; X Ptr_Rolo_List rptr; X Ptr_Rolo_Entry lentry; X X clear_the_screen(); X X fputs("\nPretty printing the Rolodex...\n",stdout); X fprintf(stdout,"Print the file %-30s\n", homedir(ROLOPRINT)); X X lstfp = fopen(homedir(ROLOPRINT),"w"); X if(lstfp == (FILE *)NULL) { X perror(homedir(ROLOPRINT)); X return; X } X X rptr = Begin_Rlist; X if(rptr == 0) { X fputs("\n\nNo entries to print...\n",stderr); X return; X } X X while (rptr != 0) { X lentry = get_entry(rptr); X X /* Find the number of lines this entry requires to print */ X for(elt_lines = 0, index = 0; index < N_BASIC_FIELDS; index++) { X tmpptr = lentry->basicfields[index]; X elt_lines++; /* Even one for an empty line */ X X while((tmpptr = strchr(tmpptr,';')) != (char *)NULL) { X elt_lines++; X tmpptr++; X } X } X if(lentry->n_others) { X for(index=0; index < lentry->n_others; index++) { X elt_lines++; /* As above, even if the entry is empty... */ X tmpptr = lentry->other_fields[index]; X X while((tmpptr = strchr(tmpptr,';')) != (char *)NULL) { X elt_lines++; X tmpptr++; X } X } X } X X /* X * Check to see if there is enough room on the current page X * to print this entry... Otherwise advance to the top of the X * next page X */ X tmp_line_cnt = line_cnt + elt_lines; X if(tmp_line_cnt > MAX_LINES) { X fputc('\f',lstfp); X line_cnt = 0; X } X X /* X * We can now start the printing of the actual entry X */ X fputs("Name: ",lstfp); X prt_dump(get_basic_rolo_field((int)R_NAME,lentry),lstfp,20); X fputs("Home address: ",lstfp); X prt_dump(get_basic_rolo_field((int)R_HOME_ADDRESS,lentry),lstfp,20); X fputs("Home phone: ",lstfp); X prt_dump(get_basic_rolo_field((int)R_HOME_PHONE,lentry),lstfp,20); X fputs("Company: ",lstfp); X prt_dump(get_basic_rolo_field((int)R_COMPANY,lentry),lstfp,20); X fputs("Work address: ",lstfp); X prt_dump(get_basic_rolo_field((int)R_WORK_ADDRESS,lentry),lstfp,20); X fputs("Work phone: ",lstfp); X prt_dump(get_basic_rolo_field((int)R_WORK_PHONE,lentry),lstfp,20); X fputs("Remarks: ",lstfp); X prt_dump(get_basic_rolo_field((int)R_REMARKS,lentry),lstfp,20); X X /* Now print any user defined fields */ X if(lentry->n_others) { X fputs("*** User defined fields ***\n",lstfp); X line_cnt++; X for(index = 0;index < lentry->n_others; index++) X fprintf(lstfp,"%-30s\n",get_other_field(index,lentry)); X } X X /* Print the date this entry was last updated */ X fputs(" LAST UPDATED: ",lstfp); X prt_dump(get_basic_rolo_field((int)R_UPDATED,lentry),lstfp,20); X X /* Print two(2) blank lines, and increment the line count */ X fputs("\n\n",lstfp); X line_cnt += elt_lines; X line_cnt += 2; /* For the two blank lines between entries */ X rptr = get_next_link(rptr); X } X fclose(lstfp); X} X Xprt_dump(strptr, stream, offset) Xchar *strptr; XFILE *stream; Xint offset; X{ X int i; X X if(*strptr == (char)NULL) X fputs("<<NONE>>\n",stream); X else { X for(; *strptr != '\0'; strptr++) { X if(*strptr == ';') { X fputc('\n',stream); X for(i = 0; i < offset; i++) X fputc(' ',stream); X } X else X fputc(*strptr,stream); X } X fputc('\n',stream); X } X} X Xmain (argc,argv) int argc; char *argv[]; X X{ X int fd,in_use,rolofd; X Bool not_own_rolodex; X char *user = ""; X FILE *tempfp; X X clearinit(); X clear_the_screen(); X X /* parse the options and arguments, if any */ X X switch (get_args(argc,argv,T,T)) { X case ARG_ERROR : X roloexit(-1); X case NO_ARGS : X break; X case ARGS_PRESENT : X if (ALL_LEGAL != legal_options(LEGAL_OPTIONS)) { X fprintf(stderr,"illegal option\nusage: %s\n",USAGE); X roloexit(-1); X } X } X X /* find the directory in which the rolodex file we want to use is */ X X not_own_rolodex = option_present(OTHERUSERFLAG); X if (not_own_rolodex) { X if (NIL == (user = option_arg(OTHERUSERFLAG,1)) || X n_option_args(OTHERUSERFLAG) != 1) { X fprintf(stderr,"Illegal syntax using -u option\nusage: %s\n",USAGE); X roloexit(-1); X } X } X#ifndef MSDOS X else { X if (0 == (user = getenv("HOME"))) { X fprintf(stderr,"Cant find your home directory, no HOME\n"); X roloexit(-1); X } X } X#endif X if (not_own_rolodex) { X#ifndef MSDOS X strcpy(rolodir,user); X#else X strcpy(rolodir,home_directory(user)); X#endif X if (*rolodir == '\0') { X fprintf(stderr,"No user %s is known to the system\n",user); X roloexit(-1); X } X } X else strcpy(rolodir,user); X X /* is the rolodex readable? */ X X if (0 != access(homedir(ROLODATA),R_OK)) { X X /* No. if it exists and we cant read it, that's an error */ X X if (0 == access(homedir(ROLODATA),F_OK)) { X fprintf(stderr,"Cant access rolodex data file to read\n"); X roloexit(-1); X } X X /* if it doesn't exist, should we create one? */ X /* Under Unix, only if it's our own. On other systems, it depends.*/ X X#ifdef UNIX X if (option_present(OTHERUSERFLAG)) { X fprintf(stderr,"No rolodex file belonging to %s found\n",user); X roloexit(-1); X } X#endif X /* try to create it, only if its our own */ X X if (-1 == (fd = creat(homedir(ROLODATA),DEF_PERM))) { X if(option_present(OTHERUSERFLAG)) X fprintf(stderr,"couldn't create rolodex in %s\n",homedir(ROLODATA)); X else X fprintf(stderr,"couldn't create rolodex in your home directory\n"); X X roloexit(-1); X } X X else { X stat_buf.st_mode = DEF_PERM; /* For later mode set */ X close(fd); X fprintf(stderr,"Creating empty rolodex...\n"); X } X X } X X /* see if someone else is using it */ X X in_use = (0 == access(homedir(ROLOLOCK),F_OK)); X X /* are we going to access the rolodex only for reading? */ X X if (!(read_only = rolo_only_to_read())) { X X /* No. Make sure no one else has it locked. */ X X if (in_use) { X locked_action(); X } X X /* create a lock file. Catch interrupts so that we can remove */ X /* the lock file if the user decides to abort */ X X if (!option_present(NOLOCKFLAG)) { X if ((fd = open(homedir(ROLOLOCK),O_EXCL|O_CREAT,00200|00400)) < 0) { X fprintf(stderr,"unable to create lock file...\n"); X#ifdef VMS X exit(0); X#else X exit(1); X#endif X } X rololocked = 1; X close(fd); X#ifdef MSDOS X# ifdef MSC X signal(SIGINT,user_interupt); X# else X ssignal(SIGINT,user_interrupt); /* Very Turbo-ish */ X# endif /* MSC */ X#else X signal(SIGINT,user_interrupt); X#endif X } X X /* open a temporary file for writing changes to make sure we can */ X /* write into the directory */ X X /* when the rolodex is saved, the old rolodex is moved to */ X /* a '~' file (on Unix), the temporary is made to be the new rolodex, */ X /* and a copy of the new rolodex is made */ X X if (NULL == (tempfp = fopen(homedir(ROLOTEMP),"w"))) { X fprintf(stderr,"Can't open temporary file to write to\n"); X roloexit(-1); X } X fclose(tempfp); X X } X X allocate_memory_chunk(CHUNKSIZE); X X if (NULL == (rolofd = open(homedir(ROLODATA),O_RDONLY))) { X fprintf(stderr,"Can't open rolodex data file to read\n"); X roloexit(-1); X } X X /* Get the current rolodex file's permissions */ X if(fstat(rolofd,&stat_buf)) X { X fprintf(stderr,"Can't fstat rolodex data file\n"); X roloexit(-1); X } X X /* read in the rolodex from disk */ X /* It should never be out of order since it is written to disk ordered */ X /* but just in case... */ X X if (!(read_only & 1)) printf("Reading in rolodex from %s\n",homedir(ROLODATA)); X read_rolodex(rolofd); X close(rolofd); X if (!(read_only & 1)) printf("%d entries listed\n",rlength(Begin_Rlist)); X if (reorder_file && !read_only) { X fprintf(stderr,"Reordering rolodex...\n"); X rolo_reorder(); X fprintf(stderr,"Saving reordered rolodex to disk...\n"); X save_to_disk(); X } X X /* the following routines live in 'options.c' */ X X /* -s option. Prints a short listing of people and phone numbers to */ X /* standard output */ X X if (option_present(SUMMARYFLAG)) { X print_short(); X#ifdef VMS X exit(1); X#else X exit(0); X#endif X } X X /* rolo <name1> <name2> ... */ X /* print out info about people whose names contain any of the arguments */ X X if (n_non_option_args() > 0) { X print_people(); X#ifdef VMS X exit(1); X#else X exit(0); X#endif X } X X /* regular rolodex program */ X X interactive_rolo(); X#ifdef VMS X exit(1); X#else X exit(0); X#endif X X} X X#ifdef MSC Xsleep(sec) Xint sec; X{ X register long tloc; X long time(); X X tloc = time((long *)NULL); X X tloc += (long)sec; X X while(time((long *)NULL) <= tloc); X X return(0); X} X#endif END_OF_FILE if test 18313 -ne `wc -c <'./rolo.c'`; then echo shar: \"'./rolo.c'\" unpacked with wrong size! fi # end of './rolo.c' fi if test -f './toolsdir/ctools.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'./toolsdir/ctools.h'\" else echo shar: Extracting \"'./toolsdir/ctools.h'\" \(11422 characters\) sed "s/^X//" >'./toolsdir/ctools.h' <<'END_OF_FILE' X/* -*- Mode: C; Package: (CTOOLS C) -*- */ X X#ifndef Bool X#define Bool int X#endif X X#ifndef T X#define T 1 X#endif X X#ifndef F X#define F 0 X#endif X X#ifdef VMS X#ifndef MAXINT X#define MAXINT 2147483647 X#define MAXINTSTR "2147483647" X#endif X#endif X X#ifdef VMS X#ifndef MAXINT X#define MAXINT 2147483647 X#define MAXINTSTR "2147483647" X#endif X#endif X X#ifndef MAXPATHLEN X#define MAXPATHLEN 80 X#endif X Xextern char *emalloc(); X X /* int space; */ X /* space must be greater than 0 */ X /* Causes executution to halt with a 'Fatal error' message if memory */ X /* cannot be allocated, otherwise returns pointer to malloc-ed space */ X Xextern char *anewstr(); X X /* char *astring; */ X /* emalloc's space and copies astring into that space. Returns pointer */ X /* to new string. */ X X Xextern int copy(); X X /* char *dest, *src; int n; */ X /* copies exactly n bytes. */ X /* return value undefined. Use only as procedure. */ X Xextern int fill(); X X /* char *addr, ch; int n; */ X /* copies ch into n consecutive bytes. */ X /* return value undefined. Use only as procedure. */ X Xextern int to_upper_if_lower(); X X /* char ch; Returns possibly upper-cased value. */ X Xextern int to_lower_if_upper(); X X /* char ch; Returns possibly lower-cased value. */ X Xextern int buffconcat(); X X /* char *buffer, *s1, *s2; */ X /* s1 and s2 must be null terminated. Buffer must be at least */ X /* strlen(s1) + strlen(s2) + 1 characters long. Buffer is null */ X /* terminated upon completion. */ X X /* return value undefined. Use only as procedure. */ X Xextern int nbuffconcat(); X X /* char *buffer; int n; char *s1,*s2,*s3,*s4,*s5,*s6; */ X /* all the strings must be null terminated. Buffer must be big enough */ X /* to hold the null terminated result. 0 < n < 7 .. */ X /* returns -1 if n is out of range, otherwise 0 */ X Xextern int slcompare(); X X /* char *s1; int l1; char *s2; int l2 */ X /* does not stop if it encounters a null character. */ X /* returns 0 if equal, -1 if not equal */ X Xextern int slge_compare(); X X /* char *s1; int l1; char *s2; int l2 */ X /* does not stop if it encounters a null character. */ X /* returns 0 if equal, -1 if s1 < s2, 1 if s1 > s2 */ X Xextern int nocase_compare(); X X /* char *s1; int l1; char *s2; int l2 */ X /* does not stop if it encounters a null character. */ X /* returns 0 if equal, -1 if s1 < s2, 1 if s1 > s2 case independently. */ X Xextern char * strfind(); X X /* char *s1; char *s2; int fast; */ X /* finds s2 as a substring of s1. s1 and s2 are null terminated. */ X /* returns 0 if not found, otherwise pointer into s1 to first matching */ X /* character. */ X X /* WARNING: will access off the end of s1 in the interest of efficiency */ X /* if 'fast' is non-zero. */ X Xextern char * strncfind(); X X /* char *s1; char *s2; int fast; */ X /* finds s2 as a substring of s1 case independently. s1 and s2 are */ X /* null terminated. */ X /* returns 0 if not found, otherwise pointer into s1 to first matching */ X /* character. */ X X /* WARNING: will access off the end of s1 in the interest of efficiency */ X /* if 'fast' is non-zero. */ X Xextern char * strsearch(); X X /* char *s1; int l1; char *s2; int l2 */ X /* finds s2 as a substring of s1. Does not stop if it encounters a null. */ X /* returns pointer into s1, otherwise (char *) 0 if search fails */ X /* case dependent */ X Xextern char * strncsearch(); X X /* char *s1; int l1; char *s2; int l2 */ X /* finds s2 as a substring of s1. */ X /* returns pointer into s1, otherwise (char *) 0 if search fails */ X /* case independent */ X Xextern int remove_excess_blanks(); X X /* char *newstring, *oldstring; */ X /* newstring must be long enough to hold the result, which may be as */ X /* long as oldstring. oldstring must be null terminated. */ X /* an excess blank is any blank before the first non-blank character, */ X /* any blank after the last non-blank character, and any blank immediately */ X /* following a blank. */ X /* returns length of newstring */ X Xextern int yes_or_no_check(); X X /* char *astring; */ X /* returns 1 for yes, 0 for no, -1 for neither. */ X /* astring must be one of "YES", "Y", "NO", "N" in any capitalization. */ X X X/* These routines return T if every char satisfies a certain condition. */ X/* These returns all returns T if given a null string. */ X Xextern Bool all_digits(); Xextern Bool all_whitespace(); Xextern Bool all_uppercase(); Xextern Bool all_lowercase(); Xextern Bool all_alphabetic(); Xextern Bool all_alphanumeric(); Xextern Bool all_ascii(); X X Xextern int str_to_pos_int(); X X /* char *astring; int low,high; */ X /* low must be >= 0. */ X /* returns -1 if *astring is not composed of digits. */ X /* returns -2 if the integer is out of range. */ X /* despite its name, 0 can be returned as a legitimate value. */ X /* treats all digit strings as decimal. */ X X Xextern int sreverse(); X X /* char *buffer; char *astring; */ X /* puts the characters of astring in reverse order into buffer. */ X /* buffer must be at least as long as astring + 1. */ X /* buffer is null terminated when done. */ X /* No return value. Use only as procedure. */ X Xextern char *ip_sreverse(); X X /* char *astring; */ X /* Returns astring with its characters reversed. */ X /* reversal is done in place. */ X X X X#define PATH_MAXPATHLEN 256 X Xchar *temp_path(); X X/* X char *dir; char *filename; X X Returns a pointer to a character string containing the string X <dir>/<filename>. The pointer points to a buffer which will may get X overwritten if any functions in this package are subsequently called. X 0 is returned if the pathname would exceed PATH_MAXPATHLEN-1 chars. X*/ X X Xchar *perm_path(); X X/* X char *dir; char *filename; X X Same as temp_path, except the pathname string is malloc'ed and is thus X permanent unless specifically freed by the user. Further, no limit X on the size of the path is made. X*/ X X Xchar *make_path(); X X/* X char *dir; char *filename; char *extension; Bool perm; X X Creates <dir>/<filename><extension> . The string returned is permanent X or not depending on 'perm'. If perm is not true, 0 will be returned if X the resulting path exceeds PATH_MAXPATHLEN-1 chars. X*/ X X Xchar *make_path_numeric_extension(); X X/* X char *dir; char *filename; int extension; Bool perm; X X Same as make_path except that extension is first converted into a X string using sprintf. X*/ X X Xchar *just_filename(); X X/* X char *path; Bool new; Bool perm; X X Given a path of the form /<x>/<y>/<z> returns <z>. If new is not set X then a pointer into the original input string is returned. If new is X set a copy is returned, either permanent or not depending on perm. X*/ X X X#define ANSWER_NO 0 X#define ANSWER_YES 1 X#define ANSWER_HELP 2 X#define ANSWER_QUIT 3 X#define ANSWER_EOF 4 X X#define AT_EOF -1 X#define TOO_MANY_CHARS -2 X#define IOERROR -3 X#define TOO_MANY_LINES -4 X#define LINE_TOO_LONG -5 X Xextern read_yes_or_no (); X X /* FILE *iport, *oport; char *prompt; char *helpstring; char *quitstring; */ X X /* prints prompt, then reads from iport until is gets 'Y', 'N', 'YES' or */ X /* 'NO' (case independently). If helpstring and/or quitstring are not */ X /* "" or (char *) 0 then if the user types in one of those ANSWER_HELP */ X /* or ANSWER_QUIT are returned, otherwise ANSWER_NO or ANSWER_YES are */ X /* eventually returned. */ X X Xextern int getline (); X X /* FILE *iport; char *buffer; int buflen; */ X X /* reads a line into buffer. Does not put the '\n' into buffer. */ X /* Returns AT_EOF if at end of file when called. If it encounters */ X /* end of file after reading at least one character, the eof is treated */ X /* as if it were a newline. Returns TOO_MANY_CHARS if more than */ X /* buflen - 1 characters are read before encountering a newline. */ X /* In this case exactly buflen - 1 characters are read. */ X /* The last character read is always follwed by a '\0'. */ X /* if successful getline returns the number of characters read exclusive */ X /* of a terminating newline or eof. */ X X Xextern int getlines(); X X /* FILE *fp; int n; char ***ptr_lines; char *linebuf; int maxlinelen; */ X /* See documentation for getfile below */ X /* If called, 'n' must have a value 0. */ X Xextern int getfile(); X X /* char *filename; char ***ptr_lines; char *linebuf; int maxlinelen; */ X X /* read in a file as an array of character strings */ X /* 'maxlinelen+1' is the maximum length a line of the file is allowed */ X /* to be. 'linebuf' must be at least 'maxlinelen+1' characters long. */ X /* Returns the number of lines in the file (and therefore the number */ X /* of entries in *ptr_lines) if successful. Returns IOERROR if it */ X /* could not open the file to read from. Returns TOO_MANY_CHARS if */ X /* it encounters a line longer than 'maxlinelen' characters. */ X X /* Space for each line is malloc'ed as it is read in and the text for */ X /* the jth line is stored in (*ptr_lines)[j] */ X X /* Only works for fairly small files as it recurses its way through the */ X /* file and does a lot of malloc-ing. Use read_file_into_buffer or */ X /* ngetfile for large files. */ X Xextern int ngetlines(); X X /* FILE *fp; int n; char ***ptr_lines; char *linebuf; int maxlinelen; */ X /* Same as getlines, except at most 'n' lines will be read. Returns */ X /* TOO_MANY_LINES if more than 'n' lines are present. */ X Xextern int ngetfile(); X X /* int n; char *filename; char ***ptr_lines; char *linebuf; int maxlinelen; */ X /* See ngetlines above. */ X Xextern int read_file_into_buffer(); X X /* char *filename; X char ***ptr_lines; X int maxlines; X char *buffer; X int buflen; X char *linebuffer; X int linebuflen; X */ X X /* *ptr_lines should be an array of character string pointers maxlines */ X /* big. buffer should be an array of characters buflen long. The routine */ X /* reads lines using getline and stores them into buffer, terminating each */ X /* with a null. A pointer to the nth line read is stored in *ptr_lines[n] */ X /* Returns IOERROR if it cannot open the file for reading, TOO_MANY_LINES */ X /* if more than maxlines were read in, TOO_MANY_CHARS if buffer is */ X /* filled before end of file is reached, and LINE_TOO_LONG is any line is */ X /* longer than linebuflen. Returns number of lines read in if successful. */ X Xextern char *efopen(); X X /* char *filename; char *mode */ X X /* Actually returns a (FILE *), so one must cast the return value to this */ X /* type. It doesn't return a (FILE *) explicitly because then to include */ X /* this file one would have to include <stdio.h> explicitly before it. */ X /* The routine simply calls fopen with the same arguments, but prints a */ X /* reasonable error message and calls exit if the call to fopen fails. */ X X Xextern int record_fseek(); X X /* FILE *fp; long rnum; int fromwhere; int rsize; int hdrsize; */ X X /* Assumes a file is divided into fixed length records with a fixed length */ X /* header (possibly 0 bytes). Performs a fseek which moves to the start */ X /* of a given record. Record numbers begin with 1. */ X X /* Returns what fseek returns. */ X X /* 'rnum' is either relative or absolute, depending on 'fromwhere' which */ X /* corresponds to the 'ptrname' argument of fseek. */ X X XBool check_string(); X X /* char *str; long minlen; long maxlen; */ X X /* Returns T if str is not 0 and has a length between minlen and maxlen */ X /* inclusived, otherwise returns F. */ X X X#ifndef check_int X#define check_int(i,minval,maxval) ((i) >= (minval) && (i) <= (maxval)) X#endif END_OF_FILE if test 11422 -ne `wc -c <'./toolsdir/ctools.h'`; then echo shar: \"'./toolsdir/ctools.h'\" unpacked with wrong size! fi # end of './toolsdir/ctools.h' fi echo shar: End of archive 3 \(of 4\). cp /dev/null ark3isdone MISSING="" for I in 1 2 3 4 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 4 archives. rm -f ark[1-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0 -- For comp.sources.unix stuff, mail to sources@uunet.uu.net.