v13i051: Screen-oriented rolodex program, Part03/04
Rich Salz
rsalz at bbn.com
Thu Feb 18 13:44:53 AEST 1988
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 at uunet.uu.net.
More information about the Comp.sources.unix
mailing list