allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc) (12/13/89)
Posting-number: Volume 9, Issue 64 Submitted-by: wht%n4hgf@gatech.edu (Warren Tucker) Archive-name: umdb/part02 ---- Cut Here and unpack ---- #!/bin/sh # this is umdb.02 (part 2 of umdb) # do not concatenate these parts, unpack them in order with /bin/sh # file btree.c continued # touch 2>&1 | fgrep '[-amc]' > /tmp/s3_touch$$ if [ -s /tmp/s3_touch$$ ] then TOUCH=can else TOUCH=cannot fi rm -f /tmp/s3_touch$$ CurArch=2 if test ! -r s3_seq_.tmp then echo "Please unpack part 1 first!" exit 1; fi ( read Scheck if test "$Scheck" != $CurArch then echo "Please unpack part $Scheck next!" exit 1; else exit 0; fi ) < s3_seq_.tmp || exit 1 echo "x - Continuing file btree.c" sed 's/^X//' << 'SHAR_EOF' >> btree.c X bt->lstak.sptr = 0; X bt->rstak.ele[0] = 0; X bt->lstak.ele[0] = 0; X X /* begin at list head */ X s_nod = bt->sblk.root; X X if(_rnode(s_nod,node,bt)) X return(BT_ERR); X while(1) X { X /* search to right */ X if(node->n.rptr != 0) X { X _pushr(bt,s_nod); X s_nod = node->n.rptr; X if(_rnode(s_nod,node,bt)) X return(BT_ERR); X } X else X { X if(node->n.deleted == BT_DELETED) X { X /* skip all deleted nodes */ X while(node->n.deleted == BT_DELETED) X { X if(_btnext(&s_nod,node,bt) == BT_EOF) X { X if(_btprevious(&s_nod,node,bt) <0) X return(BT_ERR); X *node_num = s_nod; X return(0); X } X } X *node_num = s_nod; X return(0); X } X else X { X /* at end of a branch */ X *node_num = s_nod; X return(0); X } X } X } X} X X X/* go to the head of the file */ Xbthead(node_num,key,recno,bt) Xshort *node_num; Xchar **key; Xlong *recno; Xstruct btree *bt; X{ X static struct btnode_m node; X register int retn = _bthead(node_num,&node,bt); X *key = node.key; X *recno = node.n.recno; X return(retn); X} X X/* go to the head of the file */ X_bthead(node_num,node,bt) Xstruct btree *bt; Xshort *node_num; Xregister struct btnode_m *node; X{ X short s_nod; X X bt->rstak.sptr = 0; X bt->lstak.sptr = 0; X bt->rstak.ele[0] = 0; X bt->lstak.ele[0] = 0; X X /* begin at list head */ X s_nod = bt->sblk.root; X X if(_rnode(s_nod,node,bt)) X return(BT_ERR); X while(1) X { X /* search to left */ X if(node->n.lptr != 0) X { X _pushl(bt,s_nod); X s_nod = node->n.lptr; X if(_rnode(s_nod,node,bt)) X return(BT_ERR); X } X else X { X if(node->n.deleted == BT_DELETED) X { X /* skip all deleted nodes */ X while(node->n.deleted == BT_DELETED) X { X if(_btprevious(&s_nod,node,bt) == BT_EOF) X { X if(_btnext(&s_nod,node,bt) <0) X return(BT_ERR); X *node_num = s_nod; X return(0); X } X } X *node_num = s_nod; X return(0); X } X else X { X /* at end of a branch */ X *node_num = s_nod; X return(0); X } X } X } X} X X X X/* find a key */ Xbtfind(key,node_num,reckey,recno,bt) Xchar *key; Xshort *node_num; Xchar **reckey; Xlong *recno; Xstruct btree *bt; X{ X register int direction; X short s_nod; X static struct btnode_m node; X X bt->rstak.sptr = 0; X bt->lstak.sptr = 0; X bt->rstak.ele[0] = 0; X bt->lstak.ele[0] = 0; X X bt->slev = 0; /* tree level at start of search */ X X /* begin at list head */ X s_nod = bt->sblk.root; X X if(_rnode(s_nod,&node,bt)) X return(BT_ERR); X while((direction = strcmp(key,node.key)) != 0 || X node.n.deleted == BT_DELETED) X { X X if(direction > 0) X { X /* search to right */ X if(node.n.rptr != 0) X { X _pushr(bt,s_nod); X s_nod = node.n.rptr; X if(_rnode(s_nod,&node,bt)) X return(BT_ERR); X } X else if(node.n.deleted == BT_DELETED) X { X /* skip all deleted nodes */ X while(node.n.deleted == BT_DELETED) X { X if(_btnext(&s_nod,&node,bt) == BT_EOF) X { X if(_btprevious(&s_nod,&node,bt) <0) X return(BT_ERR); X *recno = node.n.recno; X *reckey = node.key; X *node_num = s_nod; X return(BT_NREC); X } X } X *recno = node.n.recno; X *reckey = node.key; X *node_num = s_nod; X return(BT_NREC); X } X else X { X /* at end of a branch */ X *recno = node.n.recno; X *reckey = node.key; X *node_num = s_nod; X return(BT_NREC); X } X } X else X { X /* search to left */ X if(node.n.lptr != 0) X { X _pushl(bt,s_nod); X s_nod = node.n.lptr; X if(_rnode(s_nod,&node,bt)) X return(BT_ERR); X } X else if(node.n.deleted == BT_DELETED) X { X while(node.n.deleted == BT_DELETED) X { X if(_btnext(&s_nod,&node,bt) == BT_EOF) X { X if(_btprevious(&s_nod,&node,bt) < 0) X return(BT_ERR); X *recno = node.n.recno; X *reckey = node.key; X *node_num = s_nod; X return(BT_NREC); X } X } X *recno = node.n.recno; X *reckey = node.key; X *node_num = s_nod; X return(BT_NREC); X } X else X { X *recno = node.n.recno; X *reckey = node.key; X *node_num = s_nod; X return(BT_NREC); X } X } X } X *recno = node.n.recno; X *reckey = node.key; X *node_num = s_nod; X return(0); X} X X/* find the previous node */ Xbtprevious(node_num,key,recno,bt) Xshort *node_num; Xchar **key; Xlong *recno; Xstruct btree *bt; X{ X static struct btnode_m node; X register int retn; X if(_rnode(*node_num,&node,bt)) X return(BT_ERR); X retn = _btprevious(node_num,&node,bt); X *key = node.key; X *recno = node.n.recno; X return(retn); X} X X/* get the previous node */ X_btprevious(node_num,node,bt) Xshort *node_num; Xregister struct btnode_m *node; Xstruct btree *bt; X{ X short _popr(); X short _popl(); X short s_nod; X X s_nod = *node_num; X X /* if we are called without a node, wind to the end of file */ X if(*node_num == 0) X return(_bttail(node_num,node,bt)); X X do X { X if(node->n.lptr == 0) X { X /* can't move left */ X if(bt->rstak.sptr == 0) X { X /* none in stack */ X if(_rnode(*node_num,node,bt)) X return(BT_ERR); X return(BT_EOF); X /* don't reset node_num */ X } X else X { X /* can't go left & stack full (pop stack) */ X s_nod = _popr(bt); X if(_rnode(s_nod,node,bt)) X return(BT_ERR); X } X } X else X { X /* left then to bottom right - is previous */ X _pushl(bt,s_nod); X s_nod = node->n.lptr; X if(_rnode(s_nod,node,bt)) X return(BT_ERR); X while(node->n.rptr != 0) X { X /* bottom right */ X _pushr(bt,s_nod); X /* of this sub-tree */ X s_nod = node->n.rptr; X if(_rnode(s_nod,node,bt)) X return(BT_ERR); X } X } X } while(node->n.deleted == BT_DELETED); X X *node_num = s_nod; X return(0); X} X X/* print the btree error message */ Xvoid Xbtperror(str) Xchar *str; X{ X extern int errno; X X /* is it ours ?? */ X if(bterrno) X { X ff(se,"(btree) %s: %s\n",str,bterrs[bterrno]); X bterrno = 0; X } X if(errno) X { X fputs("(filesys) ",se); X perror(str); X errno = 0; X } X} X X/* vi: set tabstop=4 shiftwidth=4: */ X/* end of btree.c */ SHAR_EOF echo "File btree.c is complete" chmod 0644 btree.c || echo "restore of btree.c fails" if [ $TOUCH = can ] then touch -m 1210180489 btree.c fi echo "x - extracting diagnose.c (Text)" sed 's/^X//' << 'SHAR_EOF' > diagnose.c && X/*+------------------------------------------------------------------------- X diagnose.c - diagnose problems with btree handler X hacked by ...!gatech!kd4nc!n4hgf!wht X XCopyright (C) 1988, Marcus J. Ranum, William Welch Medical Library X$Author: mjr $ $Log: btree.c,v $ Revision 1.1 88/06/01 21:35:07 mjr XInitial revision The original code was placed in the public domain. XThis is not, since I wish to retain some control over it. No Xrestrictions are placed on modification, or use of this code, as long as Xthe copyrights are not removed. There are some areas that really could Xuse improving (like handling free nodes better) and I hope that if Xsomeone makes improvements they will keep me up to date on them (e-mail Xplease, I am not on usenet). XMarcus J. Ranum, William Welch Medical Library, 1988 Xmjr@jhuigf.BITNET || uunet!mimsy!aplcen!osiris!welchvax!mjr X--------------------------------------------------------------------------*/ X/* nobody ever writes nice test programs. in fact, this one is pretty gross */ X/* basically, this allows exercising all the various functions of the btree */ X/* library */ X X#if defined(pyr) || defined(sun) || defined(BSD4) X#include <sys/file.h> X#endif X X#if defined(M_SYS5) || defined(SYS5) X#include <sys/fcntl.h> X#endif X X#include <stdio.h> X#include "btree.h" X Xextern char *strncpy(); Xextern char *strcpy(); X Xmain(ac,av) Xint ac; Xchar *av[]; X{ X BTREE *h1; X struct btnode_m nn; X char instr[BUFSIZ]; X short node_nbr; X char *keystr; X long recpos; X X printf("sizeof(struct btsuper) = %d(10) %02x\n", X sizeof(struct btsuper),sizeof(struct btsuper)); X printf("sizeof(struct btnode_m) = %d(10) %02x\n", X sizeof(struct btnode_m),sizeof(struct btnode_m)); X printf("offset of node_num: %02x, len=%02x\n", X (int)((char *)&nn.node_num - (char *)&nn),sizeof(nn.node_num)); X printf("offset of n: %02x, len=%02x\n", X (int)((char *)&nn.n - (char *)&nn),sizeof(nn.n)); X printf("offset of key: %02x, len=%02x\n", X (int)(nn.key - (char *)&nn),sizeof(nn.key)); X X if(ac < 2) { X (void)fprintf(stderr,"usage: %s <file>\n",av[0]); X exit(1); X } X X if((h1 = btopen(av[1],O_CREAT|O_RDWR,0600,0)) ==NULL) { X btperror(av[1]); X exit(1); X } X X while(1) { X (void)printf("Find Next Tail Head Prev Insrt Del Quit:"); X if(gets(instr) == NULL) X exit(btclose(h1)); X X switch(*instr) { X X case 'f': X case 'F': X (void)printf("\nKey to Find: "); X (void)gets(instr); X switch(btfind(instr,&node_nbr,&keystr,&recpos,h1)) { X case BT_NREC: X (void)printf("not found: closest = %s (%ld)\n",keystr,recpos); X break; X case -1: X btperror("find"); X break; X case 0: X (void)printf("current=%s (%ld)\n",keystr,recpos); X break; X default: X printf("unknown error code\n"); X break; X } X break; X X case 'h': X case 'H': X switch(bthead(&node_nbr,&keystr,&recpos,h1)) { X case -1: X btperror("bthead() returns -1"); X continue; X break; X default: X (void)printf("current=%s (%ld)\n",keystr,recpos); X } X break; X X case 't': X case 'T': X switch(bttail(&node_nbr,&keystr,&recpos,h1)) { X case -1: X btperror("bttail() returns -1"); X continue; X break; X default: X (void)printf("current=%s (%ld)\n",keystr,recpos); X } X break; X X case 'd': X case 'D': X if(btdelete(node_nbr,h1) < 0) { X btperror("delete failed"); X } else { X (void)printf("...deleted\n"); X } X break; X X case 'n': X case 'N': X switch(btnext(&node_nbr,&keystr,&recpos,h1)) { X case -1: X btperror("btnext() returns -1"); X continue; X break; X X case 0: X (void)printf("current=%s (%ld)\n",keystr,recpos); X break; X X case BT_EOF: X (void)printf("EOF: current=%s (%ld)\n",keystr,recpos); X break; X } X break; X X case 'p': X case 'P': X switch(btprevious(&node_nbr,&keystr,&recpos,h1)) { X case -1: X btperror("btprevious() returns -1"); X continue; X break; X case 0: X (void)printf("current=%s (%ld)\n",keystr,recpos); X break; X case BT_EOF: X (void)printf("SOF: current=%s (%ld)\n",keystr,recpos); X } X break; X X case 'i': X case 'I': X (void)printf("Enter a key: "); X (void)gets(instr); X X /* h1->sblk.free is used here as arbitrary record # */ X /* typical use would be to set this to the recno */ X /* for whatever it is that is being indexed into */ X if(btinsert(instr,(long)h1->sblk.free,h1) < 0) X btperror("insert failed"); X else X (void)printf("...inserted\n"); X break; X X case 'q': X case 'Q': X exit(btclose(h1)); X X default: X (void)printf("huh?\n"); X } X } X} X X/* vi: set tabstop=4 shiftwidth=4: */ X/* end of diagnose.c */ SHAR_EOF chmod 0644 diagnose.c || echo "restore of diagnose.c fails" if [ $TOUCH = can ] then touch -m 1210180489 diagnose.c fi echo "x - extracting umdbdup.c (Text)" sed 's/^X//' << 'SHAR_EOF' > umdbdup.c && X/*+------------------------------------------------------------------------- X umdbdup.c X ...!gatech!kd4nc!n4hgf!wht X--------------------------------------------------------------------------*/ X/*+:EDITS:*/ X/*:12-10-1989-02:28-wht-creation */ X X#include <stdio.h> X#include <fcntl.h> X#include <sys/types.h> X#include "btree.h" X#include "umdb.h" X Xchar *umdb = "/usr/lib/uucp/umdb"; Xchar umdb_name[128]; XFILE *fp_umdb; XBTREE *bt_name; X X/*+------------------------------------------------------------------------- X print_dup_umdb_rec(sitename,umdb_pos) X--------------------------------------------------------------------------*/ Xvoid Xprint_dup_umdb_rec(sitename,umdb_pos) Xchar *sitename; Xlong umdb_pos; X{ Xint ndbarg; Xchar *dbfld[DBFLD_COUNT+1]; Xchar dbrec[512]; X X if(fseek(fp_umdb,umdb_pos,0)) X { X (void)fprintf(stderr,"seek on "); X perror(umdb); X exit(1); X } X if(!fgets(dbrec,sizeof(dbrec),fp_umdb)) X { X (void)fprintf(stderr,"read of "); X perror(umdb); X exit(1); X } X build_dbfld_array(dbrec,dbfld,DBFLD_COUNT+1,&ndbarg); X printf("%s (%s) in %s\n",sitename, X dbfld[DBFLD_SNAME],dbfld[DBFLD_MNAME]); X X} /* end of print_dup_umdb_rec */ X X/*+------------------------------------------------------------------------- X main(argc,argv,envp) X--------------------------------------------------------------------------*/ Xmain(argc,argv,envp) Xint argc; Xchar **argv; Xchar **envp; X{ Xint next_error; Xchar last_sitename[SYSNAME_MAXLEN + 2]; Xchar *sitename; Xlong last_umdb_pos; Xlong umdb_pos; Xunsigned short node_num; X X/* get optional db name */ X if(!strncmp(argv[1],"-n")) X { X if(strlen(argv[1]) > 2) X umdb = argv[1] + 2; X else if(argc < 3) X { X fputs("-n requires map db name\n",stderr); X exit(1); X } X else X umdb = argv[2]; X } X X/* open database main file */ X if(!(fp_umdb = fopen(umdb,"r"))) X { X perror(umdb); X fputs("usage: umdbdup [-n dbname]\n",stderr); X exit(1); X } X X/* build index filename */ X strcpy(umdb_name,umdb); X strcat(umdb_name,".in"); X X/* open index file */ X if(!(bt_name = btopen(umdb_name,O_RDONLY,0644,0))) X { X btperror(umdb_name); X exit(1); X } X X/* read each record, scanning for duplicate names */ X if(bthead(&node_num,&sitename,&umdb_pos,bt_name)) X { X btperror("bthead"); X exit(1); X } X strcpy(last_sitename,sitename); X last_umdb_pos = umdb_pos; X X next_error = 0; X while(!next_error) X { X switch(next_error = btnext(&node_num,&sitename,&umdb_pos,bt_name)) X { X case 0: X if(!strcmp(sitename,last_sitename)) X { X if(last_umdb_pos >= 0) X { X print_dup_umdb_rec(sitename,last_umdb_pos); X last_umdb_pos = -1L; X } X print_dup_umdb_rec(sitename,umdb_pos); X } X else X { X strcpy(last_sitename,sitename); X last_umdb_pos = umdb_pos; X } X break; X X case BT_EOF: X break; X X case BT_ERR: X btperror("btnext"); X exit(1); X } X } X X exit(0); X} /* end of main */ X/* vi: set tabstop=4 shiftwidth=4: */ X/* end of umdbdup.c */ SHAR_EOF chmod 0644 umdbdup.c || echo "restore of umdbdup.c fails" if [ $TOUCH = can ] then touch -m 1210190389 umdbdup.c fi echo "x - extracting umdbpath.c (Text)" sed 's/^X//' << 'SHAR_EOF' > umdbpath.c && X/*+------------------------------------------------------------------------- X umdbpath.c - use "smail -A" to print buf and umdb to print other data X ...gatech!kd4nc!n4hgf!wht X--------------------------------------------------------------------------*/ X/*+:EDITS:*/ X/*:11-13-1989-14:52-wht-creation */ X X#include <stdio.h> X#include <fcntl.h> X#include <sys/types.h> X#include "btree.h" X#include "umdb.h" X X#if defined(M_SYS5) || defined(SYS5) X#define index strchr X#define rindex strrchr X#endif X XFILE *popen(); Xchar *index(); Xchar *basename(); Xchar *index(); Xchar *rindex(); X Xchar *umdb = "/usr/lib/uucp/umdb"; Xchar umdb_name[128]; XFILE *fp_umdb; XBTREE *bt_name; X X/*+------------------------------------------------------------------------- X print_site_info(umdb_pos) X--------------------------------------------------------------------------*/ Xvoid Xprint_site_info(umdb_pos) Xlong umdb_pos; X{ Xregister itmp; Xint ndbarg; Xchar *dbfld[DBFLD_COUNT+1]; Xchar dbrec[512]; Xchar *normalized_loc_to_str(); X X if(fseek(fp_umdb,umdb_pos,0)) X { X (void)fprintf(stderr,"seek on "); X perror(umdb); X exit(1); X } X if(!fgets(dbrec,sizeof(dbrec),fp_umdb)) X { X (void)fprintf(stderr,"read of "); X perror(umdb); X exit(1); X } X build_dbfld_array(dbrec,dbfld,DBFLD_COUNT+1,&ndbarg); X (void)fputs(dbfld[DBFLD_SNAME],stdout); X itmp = 25 - strlen(dbfld[DBFLD_SNAME]); X while(itmp--) X (void)fputc(' ',stdout); X (void)printf(" %s (%s)\n", X normalized_loc_to_str(dbfld[DBFLD_NLOC]), X basename(dbfld[DBFLD_MNAME])); X X} /* end of print_site_info */ X X/*+------------------------------------------------------------------------- X find_best_match(given_sys,&dbpos,bt) X find_best_match(sys[isys],&umdb_pos,bt_name)) X--------------------------------------------------------------------------*/ Xfind_best_match(given_sys,dbpos,bt) Xchar *given_sys; Xlong *dbpos; XBTREE *bt; X{ Xregister itmp; Xregister char *cptr; Xshort node_num; Xchar *site; Xchar site2[SYSNAME_MAXLEN]; Xlong dbpos2; X X switch(btfind(given_sys,&node_num,&site,&*dbpos,bt)) X { X case BT_NREC: X break; X case BT_ERR: X btperror("find_best_match"); X exit(1); X case 0: X return(0); X } X X (void)strcpy(site2,site); X dbpos2 = *dbpos; X if(btnext(&node_num,&site,&*dbpos,bt)) X { X (void)printf("%s not found:",given_sys); X (void)printf(" %s is the closest\n"); X return(BT_NREC); X } X itmp = strlen(given_sys); X if(!strncmp(given_sys,site,itmp) && X (itmp < strlen(site)) && (site[itmp] == '.')) X { X (void)printf("%s not found:",given_sys); X (void)printf(" %s seems to match\n",site); X return(0); X } X else if(!strncmp(given_sys,site2,itmp) && X (itmp < strlen(site2)) && (site2[itmp] == '.')) X { X (void)printf("%s not found:",given_sys); X (void)printf(" %s seems to match\n",site2); X *dbpos = dbpos2; X return(0); X } X else if(cptr = rindex(given_sys,'.')) X { X strncpy(site2,given_sys,cptr - given_sys); X site2[cptr - given_sys] = 0; X return(find_best_match(site2,dbpos,bt)); X } X X (void)printf("%s not found:",given_sys); X (void)printf (" %s and %s are closest\n",site2,site); X return(BT_NREC); X X} /* end of find_best_match */ X X/*+------------------------------------------------------------------------- X main(argc,argv,envp) X--------------------------------------------------------------------------*/ Xmain(argc,argv,envp) Xint argc; Xchar **argv; Xchar **envp; X{ Xregister itmp; Xregister char *cptr; Xint iargv = 1; Xint isys,nsys; Xunsigned short node_num; Xlong umdb_pos; Xchar buf[512]; Xchar path[512]; Xchar *smail_argv[4]; Xchar *sys[MAX_SYSTEMS_PER_PATH+1]; Xchar *site; XFILE *fp; X X/* get optional db name */ X if(!strncmp(argv[1],"-n")) X { X if(strlen(argv[1]) > 2) X { X umdb = argv[1] + 2; X iargv = 2; X } X else if(argc < 3) X { X (void)fputs("-n requires map db name\n",stderr); X exit(1); X } X else X { X umdb = argv[2]; X iargv = 3; X } X } X X/* get buf from smail */ X (void)strcpy(buf,"smail -A "); X (void)strcat(buf,argv[iargv]); X if(!index(argv[iargv],'!') && !index(argv[iargv],'!')) X (void)strcat(buf,"!username"); X X if(!(fp = popen(buf,"r"))) X { X perror("uudbpath: popen to 'smail -A'"); X exit(1); X } X if(!fgets(buf,sizeof(buf),fp)) X { X perror("uudbpath: fgets from 'smail -A' pipe"); X exit(1); X } X pclose(fp); X if(cptr = rindex(buf,'!')) X *cptr = 0; X (void)printf("path: %s\n",buf); X X/* open database main file */ X if(!(fp_umdb = fopen(umdb,"r"))) X { X perror(umdb); X (void)fputs("usage: umdbdup [-n dbname]\n",stderr); X exit(1); X } X X/* build index filename */ X (void)strcpy(umdb_name,umdb); X (void)strcat(umdb_name,".in"); X X/* open index file */ X if(!(bt_name = btopen(umdb_name,O_RDONLY,0644,0))) X { X btperror(umdb_name); X exit(1); X } X X build_arg_array(buf,sys,MAX_SYSTEMS_PER_PATH+1,&nsys,"!\r\n"); X for(isys = 0; isys < nsys; isys++) X { X switch(find_best_match(sys[isys],&umdb_pos,bt_name)) X { X case BT_NREC: X break; X case BT_ERR: X btperror("find"); X break; X case 0: X print_site_info(umdb_pos); X break; X } X } X exit(0); X} /* end of main */ X X/* vi: set tabstop=4 shiftwidth=4: */ X/* end of uupath.c */ SHAR_EOF chmod 0644 umdbpath.c || echo "restore of umdbpath.c fails" if [ $TOUCH = can ] then touch -m 1210182289 umdbpath.c fi echo "x - extracting umdbuild.c (Text)" sed 's/^X//' << 'SHAR_EOF' > umdbuild.c && X/*+------------------------------------------------------------------------- X umdbuild.c X ...!gatech!emory!tridom!wht X XGripes (problems handled): X1. Some #N lines contain duplicate system names X2. Multiple #N lines have the same .domain name X3. A very few entries use '#Name' rather than '#N' X4. Several sites place longitude before latitude X--------------------------------------------------------------------------*/ X/*+:EDITS:*/ X/*:12-09-1989-16:49-wht-creation */ X X#include <stdio.h> X#include <fcntl.h> X#include <sys/types.h> X#include "btree.h" X#include "umdb.h" X Xextern char *normalize_location(); X Xchar *umdb = "/usr/lib/uucp/umdb"; XFILE *fp_umdb; Xchar umdb_name[128]; XBTREE *bt_name; X X#ifdef BUILD_LOC_INDEX Xchar umdb_loc[128]; XBTREE *bt_loc; X#endif X X/*+------------------------------------------------------------------------- X mapfile_to_mapdb(mapname) X--------------------------------------------------------------------------*/ Xvoid Xmapfile_to_mapdb(mapname) Xchar *mapname; X{ Xregister isite,isite2; Xint nsite; Xint found_loc; Xoff_t mappos; Xoff_t dbpos; Xchar mapbuf[512]; /* long map entries? - no stinking problem */ Xchar mapbuf2[512]; /* long map entries? - no stinking problem */ Xchar *site[MAX_SITENAMES_PER_LINE]; Xchar *location; XFILE *fpmap = fopen(mapname,"r"); Xlong start; Xlong time(); Xint name_count = 0; X X if(!fpmap) X { X perror(mapname); X return; X } X X fprintf(stderr,"%s ... ",mapname); X time(&start); X start--; /* show at least 1 second */ X X while(1) X { X /* read map file until #N entry found or EOF */ X do { X mapbuf[0] = 0; X mappos = ftell(fpmap); X } while(fgets(mapbuf,sizeof(mapbuf),fpmap) && X strncmp(mapbuf,"#N",2)); X X /* if EOF, done */ X if(!mapbuf[0]) X break; X X /* must be #N entry - build array of site names*/ X build_sitename_array(mapbuf,site,MAX_SITENAMES_PER_LINE,&nsite); X X /* find #L entry */ X do { X mapbuf2[0] = 0; X } while(fgets(mapbuf2,sizeof(mapbuf2),fpmap) && X (found_loc = strlen(mapbuf2) > 1) /* entry ends with blank line */ X && strncmp(mapbuf2,"#L",2)); X X /* '#Location_of_my_system' will NOT work here; '#L' will :-> */ X if(found_loc) X location = normalize_location(mapbuf2 + 2); X else X location = " 0.0000, 0.00000,?"; X X /* write map db items and name indices, one for each name */ X dbpos = ftell(fp_umdb); X /* site[0] == '#N', '#Name', '#N:-<', etc */ X for(isite = 1; isite < nsite; isite++) X { X if(strlen(site[isite]) > SYSNAME_MAXLEN) X { X fprintf(stderr, X "\n too long a name: %s in %s\n",site[isite],mapname); X continue; X } X/* it was tempting to use this X if(*site[isite] == '.') X continue; X*/ X for(isite2= 0; isite2 < isite; isite2++) X { X if(!strcmp(site[isite],site[isite2])) X goto THIS_NAME_DONE; /* skip dups on _same_ line */ X } X name_count++; X fprintf(fp_umdb,"%s:%s:%s:%ld:\n", X location,site[isite],mapname,mappos); X if(btinsert(site[isite],dbpos,bt_name)) X { X (void)fputs("\n ",stderr); X btperror(umdb_name); X exit(1); X } XTHIS_NAME_DONE: ; X } X X#ifdef BUILD_LOC_INDEX X /* write location index, one for each site */ X if(btinsert(location,dbpos,bt_loc)) X { X btperror(umdb_loc); X exit(1); X } X#endif X XSITE_DONE: ; X } X X (void)fclose(fpmap); X fprintf(stderr,"%d names, %ld seconds\n", X name_count,time((long *)0) - start); X X} /* end of mapfile_to_mapdb */ X X/*+------------------------------------------------------------------------- X main(argc,argv,envp) X--------------------------------------------------------------------------*/ Xmain(argc,argv,envp) Xint argc; Xchar **argv; Xchar **envp; X{ Xint iargv = 1; /* first file argument */ X X/* usage */ X if(argc < 2) X { X (void)fputs( X "usage: umdbuild [-n dbname] mapfile [mapfile ...]\n",stderr); X exit(1); X } X X/* get optional db name */ X if(!strncmp(argv[1],"-n")) X { X if(strlen(argv[1]) > 2) X { X umdb = argv[1] + 2; X iargv = 2; X } X else if(argc < 3) X { X (void)fputs("-n requires map db name\n",stderr); X exit(1); X } X else X { X umdb = argv[2]; X iargv = 3; X } X } X X/* check argv exhaustion */ X if(iargv >= argc) X { X (void)fputs("no map file names!\n",stderr); X exit(1); X } X X/* build index filenames */ X (void)strcpy(umdb_name,umdb); X (void)strcat(umdb_name,".in"); X X#ifdef BUILD_LOC_INDEX X (void)strcpy(umdb_loc,umdb); X (void)strcat(umdb_loc,".il"); X#endif X X/* remove old files */ X (void)unlink(umdb); X (void)unlink(umdb_name); X#ifdef BUILD_LOC_INDEX X (void)unlink(umdb_loc); X#endif X X/* open map database */ X if(!(fp_umdb = fopen(umdb,"w"))) X { X perror(umdb); X exit(1); X } X X/* open index files */ X if(!(bt_name = btopen(umdb_name,O_CREAT|O_RDWR,0644,SYSNAME_MAXLEN + 2))) X { X btperror(umdb_name); X exit(1); X } X#ifdef BUILD_LOC_INDEX X if(!(bt_loc = btopen(umdb_loc,O_CREAT|O_RDWR,0644,LOC_LEN))) X { X btperror(umdb_loc); X exit(1); X } X#endif X X/* make available to others */ X (void)chmod(umdb,0644); X (void)chmod(umdb_name,0644); X#ifdef BUILD_LOC_INDEX X (void)chmod(umdb_loc,0644); X#endif X X/* read [du].* files, copying building header db file and indices to same */ X while(iargv < argc) X mapfile_to_mapdb(argv[iargv++]); X X/* clean up */ X fprintf(stderr,"flushing ... "); X (void)fclose(fp_umdb); X if(btclose(bt_name)) X btperror(umdb_name); X#ifdef BUILD_LOC_INDEX X if(btclose(bt_loc)) X btperror(umdb_loc); X#endif X X fprintf(stderr,"done\n"); X exit(0); X X} /* end of main */ X X X/* vi: set tabstop=4 shiftwidth=4: */ X/* end of umdbuild.c */ SHAR_EOF chmod 0644 umdbuild.c || echo "restore of umdbuild.c fails" if [ $TOUCH = can ] then touch -m 1210203389 umdbuild.c fi echo "x - extracting umdbutil.c (Text)" sed 's/^X//' << 'SHAR_EOF' > umdbutil.c && X/*+------------------------------------------------------------------------- X umdbutil.c X ...!gatech!emory!tridom!wht X Xutilities for map data items X XNOTE: we cover the those who dont read right and put longitude before Xlatitude X--------------------------------------------------------------------------*/ X/*+:EDITS:*/ X/*:12-09-1989-19:19-wht-creation */ X X#include <ctype.h> X#include "umdb.h" X X#if defined(M_SYS5) || defined(SYS5) X#define index strchr X#define rindex strrchr X#endif X Xchar *index(); Xchar *rindex(); X X/*+------------------------------------------------------------------------- X basename(fullname) - strip directory name from filename X Xreturns address of static string X--------------------------------------------------------------------------*/ Xchar * Xbasename(fullname) Xchar *fullname; X{ Xregister char *start; Xstatic char outstr[256]; Xchar *strrchr(); X X start = rindex(fullname,'/'); /* find last slash */ X if(!start) X return(fullname); X start++; X strcpy(outstr,start); X return(outstr); X} /* end of basename */ X X/*+----------------------------------------------------------------------- X arg_token(parsestr,termchars) X XGet next token from string parsestr ((char *)0 on 2nd, 3rd, etc. Xcalls), where tokens are nonempty strings separated by runs of chars Xfrom termchars. Writes nulls into parsestr to end tokens. Xtermchars need not remain constant from call to call. X XTreats multiple occurrences of a termchar as one delimiter (does not Xallow null fields). X------------------------------------------------------------------------*/ Xstatic char *arg_token_static = (char *)0; Xchar *arg_token(parsestr,termchars) Xchar *parsestr; Xchar *termchars; X{ Xregister first = 1; Xregister char *termptr; Xregister char *parseptr; Xchar *token; X X if(parsestr == (char *)0 && arg_token_static == (char *)0) X return((char *)0); X X if(parsestr) X parseptr = parsestr; X else X parseptr = arg_token_static; X X while(*parseptr) X { X if(!strchr(termchars,*parseptr)) X break; X parseptr++; X } X X if(!*parseptr) X { X arg_token_static = (char *)0; X return((char *)0); X } X X token = parseptr; X if(*token == '\'') X { X token++; X parseptr++; X while(*parseptr) X { X if(*parseptr == '\'') X { X arg_token_static = parseptr + 1; X *parseptr = 0; X return(token); X } X parseptr++; X } X arg_token_static = (char *)0; X return(token); X } X while(*parseptr) X { X if(strchr(termchars,*parseptr)) X { X *parseptr = 0; X arg_token_static = parseptr + 1; X while(*arg_token_static) X { X if(!strchr(termchars,*arg_token_static)) X break; X arg_token_static++; X } X return(token); X } X parseptr++; X } X arg_token_static = (char *)0; X return(token); X} /* end of arg_token */ X X/*+------------------------------------------------------------------------- X build_arg_array(argstr,arg,arg_max_quan,&narg,termchars) X--------------------------------------------------------------------------*/ Xvoid Xbuild_arg_array(argstr,arg,arg_max_quan,narg_rtn,termchars) Xchar *argstr; Xchar **arg; Xint arg_max_quan; Xint *narg_rtn; Xchar *termchars; X{ Xregister ilocarg; Xregister narg; X X for(ilocarg = 0; ilocarg < arg_max_quan; ilocarg++) X arg[ilocarg] = (char *)0; X arg[0] = arg_token(argstr,termchars); X X for(narg = 1; narg < arg_max_quan; ++narg) X { X if((arg[narg] = arg_token((char *)0,termchars)) == (char *)0) X break; X } X X *narg_rtn = narg; X X} /* end of build_arg_array */ X X/*+------------------------------------------------------------------------- X build_dbfld_array(dbrec,dbfld,dbfld_max,ndbfld_rtn) X--------------------------------------------------------------------------*/ Xvoid Xbuild_dbfld_array(dbrec,dbfld,dbfld_max,ndbfld_rtn) Xchar *dbrec; Xchar **dbfld; Xint dbfld_max; Xint *ndbfld_rtn; X{ X build_arg_array(dbrec,dbfld,dbfld_max,ndbfld_rtn,":\r\n"); X} /* end of build_sitename_array */ X X/*+------------------------------------------------------------------------- X build_sitename_array(sitenmstr,site,site_max,nsite_rtn) X--------------------------------------------------------------------------*/ Xvoid Xbuild_sitename_array(sitenmstr,site,site_max,nsite_rtn) Xchar *sitenmstr; Xchar **site; Xint site_max; Xint *nsite_rtn; X{ X build_arg_array(sitenmstr,site,site_max,nsite_rtn,", \t\r\n"); X} /* end of build_sitename_array */ X X/*+------------------------------------------------------------------------- X array_to_angle(array,arraylen,&angle) Xlatitude 0 at equator, longitude as degrees west Xreturns ANGLE_? define from umdb.h X--------------------------------------------------------------------------*/ Xint Xarray_to_angle(array,arraylen,angle) Xchar **array; Xint arraylen; Xdouble *angle; X{ Xint iarray; Xdouble atof(); X X *angle = 0.0; X for(iarray = 0; iarray < arraylen; iarray++) X { X if(!isdigit(*array[iarray])) X { X switch(tolower(*array[iarray])) X { X case 'n': X return(ANGLE_LATITUDE); X case 's': X *angle *= -1.0; X return(ANGLE_LATITUDE); X case 'w': X return(ANGLE_LONGITUDE); X case 'e': X *angle = 360.0 - *angle; X return(ANGLE_LONGITUDE); X } X return(ANGLE_BAD); /* bad direction */ X } X switch(iarray) X { X case 0: *angle = atof(array[iarray]); break; X case 1: *angle += atof(array[iarray]) / 60.0; break; X case 2: *angle += atof(array[iarray]) / 3600.0; break; X default: return(ANGLE_BAD); X } X } X X /* NSEW char HAS to be present because SLOBS put long. before lat. */ X return(ANGLE_BAD); X X} /* end of array_to_angle */ X X/*+------------------------------------------------------------------------- X build_normalized_locfld(locfld,latitude,longitude,city) X Xcity == 0, exact long,lat; == 1, CITY; == -1, bad format was detected X--------------------------------------------------------------------------*/ Xvoid Xbuild_normalized_locfld(locfld,latitude,longitude,city) Xchar *locfld; /* must be at least LOC_LEN chars in length */ Xdouble latitude; Xdouble longitude; Xint city; X{ X (void)sprintf(locfld,"%8.4f,%8.4f,%c",latitude,longitude, X (city) ? ((city < 0) ? '?' : 'C') : 'X'); X X} /* end of build_normalized_locfld */ X X/*+------------------------------------------------------------------------- X normalize_location(locstr) X--------------------------------------------------------------------------*/ Xchar * Xnormalize_location(locstr) Xchar *locstr; X{ Xregister ilocarg; X#define LOCARGS 25 /* plenty - avoid overflow today! */ Xchar *locargs[LOCARGS]; Xint nlocargs; Xint city = 0; Xint got_latitude = 0; Xint got_longitude = 0; Xdouble angle; Xdouble longitude = 0.0; Xdouble latitude = 0.0; Xstatic char locfld[LOC_LEN]; X X build_arg_array(locstr,locargs,LOCARGS,&nlocargs," \r\n\t"); X switch(array_to_angle(locargs,nlocargs,&angle)) X { X case ANGLE_LATITUDE: X latitude = angle; X got_latitude = 1; X break; X case ANGLE_LONGITUDE: X longitude = angle; X got_longitude = 1; X break; X case ANGLE_BAD: X city = -1; X break; X } X X for(ilocarg = 0; ilocarg < nlocargs; ilocarg++) X { X if(*locargs[ilocarg] == '/') X { X switch(array_to_angle(locargs + ilocarg + 1, X nlocargs - ilocarg - 1,&angle)) X { X case ANGLE_LATITUDE: X latitude = angle; X if(got_latitude) X city = -1; X got_latitude = 1; X break; X case ANGLE_LONGITUDE: X longitude = angle; X if(got_longitude) X city = -1; X got_longitude = 1; X break; X case ANGLE_BAD: X city = -1; X break; X } X } X else if((!strcmp(locargs[ilocarg],"CITY") || X !strcmp(locargs[ilocarg],"city")) && !city) X city = 1; X } X X if(!got_latitude || !got_longitude) X city = -1; X X build_normalized_locfld(locfld,latitude,longitude,city); X return(locfld); X X} /* end of normalize_location */ X X/*+------------------------------------------------------------------------- X normalized_loc_to_str(nloc) X--------------------------------------------------------------------------*/ Xchar * Xnormalized_loc_to_str(nloc) Xchar *nloc; X{ Xfloat latitude,longitude; Xchar city = '?'; Xchar lat_NS = 'N'; Xchar long_EW = 'W'; Xstatic char presentable[64]; X X sscanf(nloc,"%f,%f,%c",&latitude,&longitude,&city); X if(latitude < 0.0) X { X latitude *= -1; X lat_NS = 'S'; X } X if(longitude > 180.0) X { X longitude = 360.0 - longitude; X long_EW = 'E'; X } X X sprintf(presentable,"%7.4f %c %8.4f %c %s", X latitude,lat_NS, X longitude,long_EW, X ((city == 'X') ? " " : ((city == 'C') ? "city" : "?? "))); X X return(presentable); X X} /* end of normalized_loc_to_str */ X X/* vi: set tabstop=4 shiftwidth=4: */ X/* end of umdbutil.c */ SHAR_EOF chmod 0644 umdbutil.c || echo "restore of umdbutil.c fails" if [ $TOUCH = can ] then touch -m 1210195289 umdbutil.c fi rm -f s3_seq_.tmp echo "You have unpacked the last part" exit 0