home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume9 / umdb / part02 < prev    next >
Text File  |  1989-12-12  |  36KB  |  1,576 lines

  1. Newsgroups: comp.sources.misc
  2. subject: v09i064: umdb - UUCP Map Database - part 02/02
  3. from: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  4. Reply-To: wht%n4hgf@gatech.edu (Warren Tucker)
  5.  
  6. Posting-number: Volume 9, Issue 64
  7. Submitted-by: wht%n4hgf@gatech.edu (Warren Tucker)
  8. Archive-name: umdb/part02
  9.  
  10. ---- Cut Here and unpack ----
  11. #!/bin/sh
  12. # this is umdb.02 (part 2 of umdb)
  13. # do not concatenate these parts, unpack them in order with /bin/sh
  14. # file btree.c continued
  15. #
  16. touch 2>&1 | fgrep '[-amc]' > /tmp/s3_touch$$
  17. if [ -s /tmp/s3_touch$$ ]
  18. then
  19.     TOUCH=can
  20. else
  21.     TOUCH=cannot
  22. fi
  23. rm -f /tmp/s3_touch$$
  24. CurArch=2
  25. if test ! -r s3_seq_.tmp
  26. then echo "Please unpack part 1 first!"
  27.      exit 1; fi
  28. ( read Scheck
  29.   if test "$Scheck" != $CurArch
  30.   then echo "Please unpack part $Scheck next!"
  31.        exit 1;
  32.   else exit 0; fi
  33. ) < s3_seq_.tmp || exit 1
  34. echo "x - Continuing file btree.c"
  35. sed 's/^X//' << 'SHAR_EOF' >> btree.c
  36. X    bt->lstak.sptr = 0;
  37. X    bt->rstak.ele[0] = 0;
  38. X    bt->lstak.ele[0] = 0;
  39. X
  40. X    /* begin at list head */
  41. X    s_nod = bt->sblk.root;
  42. X
  43. X    if(_rnode(s_nod,node,bt))
  44. X        return(BT_ERR);
  45. X    while(1)
  46. X    {
  47. X        /* search to right */
  48. X        if(node->n.rptr != 0)
  49. X        {
  50. X            _pushr(bt,s_nod);
  51. X            s_nod = node->n.rptr;
  52. X            if(_rnode(s_nod,node,bt))
  53. X                return(BT_ERR);
  54. X        }
  55. X        else 
  56. X        {
  57. X            if(node->n.deleted == BT_DELETED)
  58. X            {
  59. X                /* skip all deleted nodes */
  60. X                while(node->n.deleted == BT_DELETED)
  61. X                {
  62. X                    if(_btnext(&s_nod,node,bt) == BT_EOF)
  63. X                    {
  64. X                        if(_btprevious(&s_nod,node,bt) <0)
  65. X                            return(BT_ERR);
  66. X                        *node_num = s_nod;
  67. X                        return(0);
  68. X                    }
  69. X                }
  70. X                *node_num = s_nod;
  71. X                return(0);
  72. X            }
  73. X            else 
  74. X            {
  75. X                /* at end of a branch */
  76. X                *node_num = s_nod;
  77. X                return(0);
  78. X            }
  79. X        }
  80. X    }
  81. X}
  82. X
  83. X
  84. X/* go to the head of the file */
  85. Xbthead(node_num,key,recno,bt)
  86. Xshort *node_num;
  87. Xchar **key;
  88. Xlong *recno;
  89. Xstruct btree *bt;
  90. X{
  91. X    static struct btnode_m node;
  92. X    register int retn = _bthead(node_num,&node,bt);
  93. X    *key = node.key;
  94. X    *recno = node.n.recno;
  95. X    return(retn);
  96. X}
  97. X
  98. X/* go to the head of the file */
  99. X_bthead(node_num,node,bt)
  100. Xstruct btree *bt;
  101. Xshort *node_num;
  102. Xregister struct btnode_m *node;
  103. X{
  104. X    short s_nod;
  105. X
  106. X    bt->rstak.sptr = 0;
  107. X    bt->lstak.sptr = 0;
  108. X    bt->rstak.ele[0] = 0;
  109. X    bt->lstak.ele[0] = 0;
  110. X
  111. X    /* begin at list head */
  112. X    s_nod = bt->sblk.root;
  113. X
  114. X    if(_rnode(s_nod,node,bt))
  115. X        return(BT_ERR);
  116. X    while(1)
  117. X    {
  118. X        /* search to left */
  119. X        if(node->n.lptr != 0)
  120. X        {
  121. X            _pushl(bt,s_nod);
  122. X            s_nod = node->n.lptr;
  123. X            if(_rnode(s_nod,node,bt))
  124. X                return(BT_ERR);
  125. X        }
  126. X        else 
  127. X        {
  128. X            if(node->n.deleted == BT_DELETED)
  129. X            {
  130. X                /* skip all deleted nodes */
  131. X                while(node->n.deleted == BT_DELETED)
  132. X                {
  133. X                    if(_btprevious(&s_nod,node,bt) == BT_EOF)
  134. X                    {
  135. X                        if(_btnext(&s_nod,node,bt) <0)
  136. X                            return(BT_ERR);
  137. X                        *node_num = s_nod;
  138. X                        return(0);
  139. X                    }
  140. X                }
  141. X                *node_num = s_nod;
  142. X                return(0);
  143. X            }
  144. X            else 
  145. X            {
  146. X                /* at end of a branch */
  147. X                *node_num = s_nod;
  148. X                return(0);
  149. X            }
  150. X        }
  151. X    }
  152. X}
  153. X
  154. X
  155. X
  156. X/* find a key */
  157. Xbtfind(key,node_num,reckey,recno,bt)
  158. Xchar *key;
  159. Xshort *node_num;
  160. Xchar **reckey;
  161. Xlong *recno;
  162. Xstruct btree *bt;
  163. X{
  164. X    register int direction;
  165. X    short s_nod;
  166. X    static struct btnode_m node;
  167. X
  168. X    bt->rstak.sptr = 0;
  169. X    bt->lstak.sptr = 0;
  170. X    bt->rstak.ele[0] = 0;
  171. X    bt->lstak.ele[0] = 0;
  172. X
  173. X    bt->slev = 0;        /* tree level at start of search */
  174. X
  175. X    /* begin at list head */
  176. X    s_nod = bt->sblk.root;
  177. X
  178. X    if(_rnode(s_nod,&node,bt))
  179. X        return(BT_ERR);
  180. X    while((direction = strcmp(key,node.key)) != 0 ||
  181. X        node.n.deleted == BT_DELETED)
  182. X    {
  183. X
  184. X        if(direction > 0)
  185. X        {
  186. X            /* search to right */
  187. X            if(node.n.rptr != 0)
  188. X            {
  189. X                _pushr(bt,s_nod);
  190. X                s_nod = node.n.rptr;
  191. X                if(_rnode(s_nod,&node,bt))
  192. X                    return(BT_ERR);
  193. X            }
  194. X            else if(node.n.deleted == BT_DELETED)
  195. X            {
  196. X                /* skip all deleted nodes */
  197. X                while(node.n.deleted == BT_DELETED)
  198. X                {
  199. X                    if(_btnext(&s_nod,&node,bt) == BT_EOF)
  200. X                    {
  201. X                        if(_btprevious(&s_nod,&node,bt) <0)
  202. X                            return(BT_ERR);
  203. X                        *recno = node.n.recno;
  204. X                        *reckey = node.key;
  205. X                        *node_num = s_nod;
  206. X                        return(BT_NREC);
  207. X                    }
  208. X                }
  209. X                *recno = node.n.recno;
  210. X                *reckey = node.key;
  211. X                *node_num = s_nod;
  212. X                return(BT_NREC);
  213. X            }
  214. X            else 
  215. X            {
  216. X                /* at end of a branch */
  217. X                *recno = node.n.recno;
  218. X                *reckey = node.key;
  219. X                *node_num = s_nod;
  220. X                return(BT_NREC);
  221. X            }
  222. X        }
  223. X        else 
  224. X        {
  225. X            /* search to left */
  226. X            if(node.n.lptr != 0)
  227. X            {
  228. X                _pushl(bt,s_nod);
  229. X                s_nod = node.n.lptr;
  230. X                if(_rnode(s_nod,&node,bt))
  231. X                    return(BT_ERR);
  232. X            }
  233. X            else if(node.n.deleted == BT_DELETED)
  234. X            {
  235. X                while(node.n.deleted == BT_DELETED)
  236. X                {
  237. X                    if(_btnext(&s_nod,&node,bt) == BT_EOF)
  238. X                    {
  239. X                        if(_btprevious(&s_nod,&node,bt) < 0)
  240. X                            return(BT_ERR);
  241. X                        *recno = node.n.recno;
  242. X                        *reckey = node.key;
  243. X                        *node_num = s_nod;
  244. X                        return(BT_NREC);
  245. X                    }
  246. X                }
  247. X                *recno = node.n.recno;
  248. X                *reckey = node.key;
  249. X                *node_num = s_nod;
  250. X                return(BT_NREC);
  251. X            }
  252. X            else 
  253. X            {
  254. X                *recno = node.n.recno;
  255. X                *reckey = node.key;
  256. X                *node_num = s_nod;
  257. X                return(BT_NREC);
  258. X            }
  259. X        }
  260. X    }
  261. X    *recno = node.n.recno;
  262. X    *reckey = node.key;
  263. X    *node_num = s_nod;
  264. X    return(0);
  265. X}
  266. X
  267. X/* find the previous node */
  268. Xbtprevious(node_num,key,recno,bt)
  269. Xshort *node_num;
  270. Xchar **key;
  271. Xlong *recno;
  272. Xstruct btree *bt;
  273. X{
  274. X    static struct btnode_m node;
  275. X    register int retn;
  276. X    if(_rnode(*node_num,&node,bt))
  277. X        return(BT_ERR);
  278. X    retn = _btprevious(node_num,&node,bt);
  279. X    *key = node.key;
  280. X    *recno = node.n.recno;
  281. X    return(retn);
  282. X}
  283. X
  284. X/* get the previous node */
  285. X_btprevious(node_num,node,bt)
  286. Xshort *node_num;
  287. Xregister struct btnode_m *node;
  288. Xstruct btree *bt;
  289. X{
  290. X    short _popr();
  291. X    short _popl();
  292. X    short s_nod;
  293. X
  294. X    s_nod = *node_num;
  295. X
  296. X    /* if we are called without a node, wind to the end of file */
  297. X    if(*node_num == 0)
  298. X        return(_bttail(node_num,node,bt));
  299. X
  300. X    do 
  301. X    {
  302. X        if(node->n.lptr == 0)
  303. X        {
  304. X            /* can't move left */
  305. X            if(bt->rstak.sptr == 0)
  306. X            {
  307. X                /* none in stack */
  308. X                if(_rnode(*node_num,node,bt))
  309. X                    return(BT_ERR);
  310. X                return(BT_EOF);
  311. X                /* don't reset node_num */
  312. X            }
  313. X            else 
  314. X            {
  315. X                /* can't go left & stack full (pop stack) */
  316. X                s_nod = _popr(bt);
  317. X                if(_rnode(s_nod,node,bt))
  318. X                    return(BT_ERR);
  319. X            }
  320. X        }
  321. X        else 
  322. X        {
  323. X            /* left then to bottom right - is previous */
  324. X            _pushl(bt,s_nod);
  325. X            s_nod = node->n.lptr;
  326. X            if(_rnode(s_nod,node,bt))
  327. X                return(BT_ERR);
  328. X            while(node->n.rptr != 0)
  329. X            {
  330. X                /* bottom right */
  331. X                _pushr(bt,s_nod);
  332. X                /* of this sub-tree */
  333. X                s_nod = node->n.rptr;
  334. X                if(_rnode(s_nod,node,bt))
  335. X                    return(BT_ERR);
  336. X            }
  337. X        }
  338. X    } while(node->n.deleted == BT_DELETED);
  339. X
  340. X    *node_num = s_nod;
  341. X    return(0);
  342. X}
  343. X
  344. X/* print the btree error message */
  345. Xvoid
  346. Xbtperror(str)
  347. Xchar *str;
  348. X{
  349. X    extern    int errno;
  350. X
  351. X    /* is it ours ?? */
  352. X    if(bterrno)
  353. X    {
  354. X        ff(se,"(btree) %s: %s\n",str,bterrs[bterrno]);
  355. X        bterrno = 0;
  356. X    }
  357. X    if(errno)
  358. X    {
  359. X        fputs("(filesys) ",se);
  360. X        perror(str);
  361. X        errno = 0;
  362. X    }
  363. X}
  364. X
  365. X/* vi: set tabstop=4 shiftwidth=4: */
  366. X/* end of btree.c */
  367. SHAR_EOF
  368. echo "File btree.c is complete"
  369. chmod 0644 btree.c || echo "restore of btree.c fails"
  370. if [ $TOUCH = can ]
  371. then
  372.     touch -m 1210180489 btree.c
  373. fi
  374. echo "x - extracting diagnose.c (Text)"
  375. sed 's/^X//' << 'SHAR_EOF' > diagnose.c &&
  376. X/*+-------------------------------------------------------------------------
  377. X    diagnose.c - diagnose problems with btree handler
  378. X    hacked by ...!gatech!kd4nc!n4hgf!wht
  379. X
  380. XCopyright (C) 1988, Marcus J.  Ranum, William Welch Medical Library
  381. X$Author: mjr $ $Log: btree.c,v $ Revision 1.1 88/06/01 21:35:07 mjr
  382. XInitial revision The original code was placed in the public domain.
  383. XThis is not, since I wish to retain some control over it.  No
  384. Xrestrictions are placed on modification, or use of this code, as long as
  385. Xthe copyrights are not removed.  There are some areas that really could
  386. Xuse improving (like handling free nodes better) and I hope that if
  387. Xsomeone makes improvements they will keep me up to date on them (e-mail
  388. Xplease, I am not on usenet).
  389. XMarcus J. Ranum, William Welch Medical Library, 1988
  390. Xmjr@jhuigf.BITNET || uunet!mimsy!aplcen!osiris!welchvax!mjr
  391. X--------------------------------------------------------------------------*/
  392. X/* nobody ever writes nice test programs. in fact, this one is pretty gross */
  393. X/* basically, this allows exercising all the various functions of the btree */
  394. X/* library */
  395. X
  396. X#if defined(pyr) || defined(sun) || defined(BSD4)
  397. X#include <sys/file.h>
  398. X#endif
  399. X
  400. X#if defined(M_SYS5) || defined(SYS5)
  401. X#include <sys/fcntl.h>
  402. X#endif
  403. X
  404. X#include <stdio.h>
  405. X#include "btree.h"
  406. X
  407. Xextern    char *strncpy();
  408. Xextern    char *strcpy();
  409. X
  410. Xmain(ac,av)
  411. Xint ac;
  412. Xchar *av[];
  413. X{
  414. X    BTREE    *h1;
  415. X    struct btnode_m nn;    
  416. X    char instr[BUFSIZ];
  417. X    short node_nbr;
  418. X    char *keystr;
  419. X    long recpos;
  420. X
  421. X    printf("sizeof(struct btsuper) = %d(10) %02x\n",
  422. X        sizeof(struct btsuper),sizeof(struct btsuper));
  423. X    printf("sizeof(struct btnode_m) = %d(10) %02x\n",
  424. X        sizeof(struct btnode_m),sizeof(struct btnode_m));
  425. X    printf("offset of node_num: %02x, len=%02x\n",
  426. X        (int)((char *)&nn.node_num - (char *)&nn),sizeof(nn.node_num));
  427. X    printf("offset of n: %02x, len=%02x\n",
  428. X        (int)((char *)&nn.n - (char *)&nn),sizeof(nn.n));
  429. X    printf("offset of key: %02x, len=%02x\n",
  430. X        (int)(nn.key - (char *)&nn),sizeof(nn.key));
  431. X
  432. X    if(ac < 2) {
  433. X        (void)fprintf(stderr,"usage: %s <file>\n",av[0]);
  434. X        exit(1);
  435. X    }
  436. X
  437. X    if((h1 = btopen(av[1],O_CREAT|O_RDWR,0600,0)) ==NULL) {
  438. X        btperror(av[1]);
  439. X        exit(1);
  440. X    }
  441. X
  442. X    while(1) {
  443. X        (void)printf("Find  Next  Tail  Head  Prev  Insrt  Del  Quit:");
  444. X        if(gets(instr) == NULL)
  445. X            exit(btclose(h1));
  446. X
  447. X        switch(*instr) {
  448. X
  449. X        case 'f':
  450. X        case 'F':
  451. X            (void)printf("\nKey to Find: ");
  452. X            (void)gets(instr);
  453. X            switch(btfind(instr,&node_nbr,&keystr,&recpos,h1)) {
  454. X            case BT_NREC:
  455. X                (void)printf("not found: closest = %s (%ld)\n",keystr,recpos);
  456. X                break;
  457. X            case -1:
  458. X                btperror("find");
  459. X                break;
  460. X            case 0:
  461. X                (void)printf("current=%s (%ld)\n",keystr,recpos);
  462. X                break;
  463. X            default:
  464. X                printf("unknown error code\n");
  465. X                break;
  466. X            }
  467. X            break;
  468. X
  469. X        case 'h':
  470. X        case 'H':
  471. X            switch(bthead(&node_nbr,&keystr,&recpos,h1)) {
  472. X            case -1:
  473. X                btperror("bthead() returns -1");
  474. X                continue;
  475. X                break;
  476. X            default:
  477. X                (void)printf("current=%s (%ld)\n",keystr,recpos);
  478. X            }
  479. X            break;
  480. X
  481. X        case 't':
  482. X        case 'T':
  483. X            switch(bttail(&node_nbr,&keystr,&recpos,h1)) {
  484. X            case -1:
  485. X                btperror("bttail() returns -1");
  486. X                continue;
  487. X                break;
  488. X            default:
  489. X                (void)printf("current=%s (%ld)\n",keystr,recpos);
  490. X            }
  491. X            break;
  492. X
  493. X        case 'd':
  494. X        case 'D':
  495. X            if(btdelete(node_nbr,h1) < 0) {
  496. X                btperror("delete failed");
  497. X            } else {
  498. X                (void)printf("...deleted\n");
  499. X            }
  500. X            break;
  501. X
  502. X        case 'n':
  503. X        case 'N':
  504. X            switch(btnext(&node_nbr,&keystr,&recpos,h1)) {
  505. X            case -1:
  506. X                btperror("btnext() returns -1");
  507. X                continue;
  508. X                break;
  509. X
  510. X            case 0:
  511. X                (void)printf("current=%s (%ld)\n",keystr,recpos);
  512. X                break;
  513. X
  514. X            case BT_EOF:
  515. X                (void)printf("EOF: current=%s (%ld)\n",keystr,recpos);
  516. X                break;
  517. X            }
  518. X            break;
  519. X
  520. X        case 'p':
  521. X        case 'P':
  522. X            switch(btprevious(&node_nbr,&keystr,&recpos,h1)) {
  523. X            case -1:
  524. X                btperror("btprevious() returns -1");
  525. X                continue;
  526. X                break;
  527. X            case 0:
  528. X                (void)printf("current=%s (%ld)\n",keystr,recpos);
  529. X                break;
  530. X            case BT_EOF:
  531. X                (void)printf("SOF: current=%s (%ld)\n",keystr,recpos);
  532. X            }
  533. X            break;
  534. X
  535. X        case 'i':
  536. X        case 'I':
  537. X            (void)printf("Enter a key: ");
  538. X            (void)gets(instr);
  539. X
  540. X            /* h1->sblk.free is used here as arbitrary record # */
  541. X            /* typical use would be to set this to the recno */
  542. X            /* for whatever it is that is being indexed into */
  543. X            if(btinsert(instr,(long)h1->sblk.free,h1) < 0)
  544. X                btperror("insert failed");
  545. X            else
  546. X                (void)printf("...inserted\n");
  547. X            break;
  548. X
  549. X        case 'q':
  550. X        case 'Q':
  551. X            exit(btclose(h1));
  552. X
  553. X        default:
  554. X            (void)printf("huh?\n");
  555. X        }
  556. X    }
  557. X}
  558. X
  559. X/* vi: set tabstop=4 shiftwidth=4: */
  560. X/* end of diagnose.c */
  561. SHAR_EOF
  562. chmod 0644 diagnose.c || echo "restore of diagnose.c fails"
  563. if [ $TOUCH = can ]
  564. then
  565.     touch -m 1210180489 diagnose.c
  566. fi
  567. echo "x - extracting umdbdup.c (Text)"
  568. sed 's/^X//' << 'SHAR_EOF' > umdbdup.c &&
  569. X/*+-------------------------------------------------------------------------
  570. X    umdbdup.c
  571. X    ...!gatech!kd4nc!n4hgf!wht
  572. X--------------------------------------------------------------------------*/
  573. X/*+:EDITS:*/
  574. X/*:12-10-1989-02:28-wht-creation */
  575. X
  576. X#include <stdio.h>
  577. X#include <fcntl.h>
  578. X#include <sys/types.h>
  579. X#include "btree.h"
  580. X#include "umdb.h"
  581. X
  582. Xchar *umdb = "/usr/lib/uucp/umdb";
  583. Xchar umdb_name[128];
  584. XFILE *fp_umdb;
  585. XBTREE *bt_name;
  586. X
  587. X/*+-------------------------------------------------------------------------
  588. X    print_dup_umdb_rec(sitename,umdb_pos)
  589. X--------------------------------------------------------------------------*/
  590. Xvoid
  591. Xprint_dup_umdb_rec(sitename,umdb_pos)
  592. Xchar *sitename;
  593. Xlong umdb_pos;
  594. X{
  595. Xint ndbarg;
  596. Xchar *dbfld[DBFLD_COUNT+1];
  597. Xchar dbrec[512];
  598. X
  599. X    if(fseek(fp_umdb,umdb_pos,0))
  600. X    {
  601. X        (void)fprintf(stderr,"seek on ");
  602. X        perror(umdb);
  603. X        exit(1);
  604. X    }
  605. X    if(!fgets(dbrec,sizeof(dbrec),fp_umdb))
  606. X    {
  607. X        (void)fprintf(stderr,"read of ");
  608. X        perror(umdb);
  609. X        exit(1);
  610. X    }
  611. X    build_dbfld_array(dbrec,dbfld,DBFLD_COUNT+1,&ndbarg);
  612. X    printf("%s (%s) in %s\n",sitename,
  613. X        dbfld[DBFLD_SNAME],dbfld[DBFLD_MNAME]);
  614. X
  615. X}    /* end of print_dup_umdb_rec */
  616. X
  617. X/*+-------------------------------------------------------------------------
  618. X    main(argc,argv,envp)
  619. X--------------------------------------------------------------------------*/
  620. Xmain(argc,argv,envp)
  621. Xint argc;
  622. Xchar **argv;
  623. Xchar **envp;
  624. X{
  625. Xint next_error;
  626. Xchar last_sitename[SYSNAME_MAXLEN + 2];
  627. Xchar *sitename;
  628. Xlong last_umdb_pos;
  629. Xlong umdb_pos;
  630. Xunsigned short node_num;
  631. X
  632. X/* get optional db name */
  633. X    if(!strncmp(argv[1],"-n"))
  634. X    {
  635. X        if(strlen(argv[1]) > 2)
  636. X            umdb = argv[1] + 2;
  637. X        else if(argc < 3)
  638. X        {
  639. X            fputs("-n requires map db name\n",stderr);
  640. X            exit(1);
  641. X        }
  642. X        else
  643. X            umdb = argv[2];
  644. X    }
  645. X
  646. X/* open database main file */
  647. X    if(!(fp_umdb = fopen(umdb,"r")))
  648. X    {
  649. X        perror(umdb);
  650. X        fputs("usage: umdbdup [-n dbname]\n",stderr);
  651. X        exit(1);
  652. X    }
  653. X
  654. X/* build index filename */
  655. X    strcpy(umdb_name,umdb);
  656. X    strcat(umdb_name,".in");
  657. X
  658. X/* open index file */
  659. X    if(!(bt_name = btopen(umdb_name,O_RDONLY,0644,0)))
  660. X    {
  661. X        btperror(umdb_name);
  662. X        exit(1);
  663. X    }
  664. X
  665. X/* read each record, scanning for duplicate names */
  666. X    if(bthead(&node_num,&sitename,&umdb_pos,bt_name))
  667. X    {
  668. X        btperror("bthead");
  669. X        exit(1);
  670. X    }
  671. X    strcpy(last_sitename,sitename);
  672. X    last_umdb_pos = umdb_pos;
  673. X
  674. X    next_error = 0;
  675. X    while(!next_error)
  676. X    {
  677. X        switch(next_error = btnext(&node_num,&sitename,&umdb_pos,bt_name))
  678. X        {
  679. X            case 0:
  680. X                if(!strcmp(sitename,last_sitename))
  681. X                {
  682. X                    if(last_umdb_pos >= 0)
  683. X                    {
  684. X                        print_dup_umdb_rec(sitename,last_umdb_pos);
  685. X                        last_umdb_pos = -1L;
  686. X                    }
  687. X                    print_dup_umdb_rec(sitename,umdb_pos);
  688. X                }
  689. X                else
  690. X                {
  691. X                    strcpy(last_sitename,sitename);
  692. X                    last_umdb_pos = umdb_pos;
  693. X                }
  694. X                break;
  695. X
  696. X            case BT_EOF:
  697. X                break;
  698. X
  699. X            case BT_ERR:
  700. X                btperror("btnext");
  701. X                exit(1);
  702. X        }
  703. X    }
  704. X
  705. X    exit(0);
  706. X}    /* end of main */
  707. X/* vi: set tabstop=4 shiftwidth=4: */
  708. X/* end of umdbdup.c */
  709. SHAR_EOF
  710. chmod 0644 umdbdup.c || echo "restore of umdbdup.c fails"
  711. if [ $TOUCH = can ]
  712. then
  713.     touch -m 1210190389 umdbdup.c
  714. fi
  715. echo "x - extracting umdbpath.c (Text)"
  716. sed 's/^X//' << 'SHAR_EOF' > umdbpath.c &&
  717. X/*+-------------------------------------------------------------------------
  718. X    umdbpath.c - use "smail -A" to print buf and umdb to print other data
  719. X    ...gatech!kd4nc!n4hgf!wht
  720. X--------------------------------------------------------------------------*/
  721. X/*+:EDITS:*/
  722. X/*:11-13-1989-14:52-wht-creation */
  723. X
  724. X#include <stdio.h>
  725. X#include <fcntl.h>
  726. X#include <sys/types.h>
  727. X#include "btree.h"
  728. X#include "umdb.h"
  729. X
  730. X#if defined(M_SYS5) || defined(SYS5)
  731. X#define index strchr
  732. X#define rindex strrchr
  733. X#endif
  734. X
  735. XFILE *popen();
  736. Xchar *index();
  737. Xchar *basename();
  738. Xchar *index();
  739. Xchar *rindex();
  740. X
  741. Xchar *umdb = "/usr/lib/uucp/umdb";
  742. Xchar umdb_name[128];
  743. XFILE *fp_umdb;
  744. XBTREE *bt_name;
  745. X
  746. X/*+-------------------------------------------------------------------------
  747. X    print_site_info(umdb_pos)
  748. X--------------------------------------------------------------------------*/
  749. Xvoid
  750. Xprint_site_info(umdb_pos)
  751. Xlong umdb_pos;
  752. X{
  753. Xregister itmp;
  754. Xint ndbarg;
  755. Xchar *dbfld[DBFLD_COUNT+1];
  756. Xchar dbrec[512];
  757. Xchar *normalized_loc_to_str();
  758. X
  759. X    if(fseek(fp_umdb,umdb_pos,0))
  760. X    {
  761. X        (void)fprintf(stderr,"seek on ");
  762. X        perror(umdb);
  763. X        exit(1);
  764. X    }
  765. X    if(!fgets(dbrec,sizeof(dbrec),fp_umdb))
  766. X    {
  767. X        (void)fprintf(stderr,"read of ");
  768. X        perror(umdb);
  769. X        exit(1);
  770. X    }
  771. X    build_dbfld_array(dbrec,dbfld,DBFLD_COUNT+1,&ndbarg);
  772. X    (void)fputs(dbfld[DBFLD_SNAME],stdout);
  773. X    itmp = 25 - strlen(dbfld[DBFLD_SNAME]);
  774. X    while(itmp--)
  775. X        (void)fputc(' ',stdout);
  776. X    (void)printf(" %s (%s)\n",
  777. X        normalized_loc_to_str(dbfld[DBFLD_NLOC]),
  778. X        basename(dbfld[DBFLD_MNAME]));
  779. X
  780. X}    /* end of print_site_info */
  781. X
  782. X/*+-------------------------------------------------------------------------
  783. X    find_best_match(given_sys,&dbpos,bt)
  784. X    find_best_match(sys[isys],&umdb_pos,bt_name))
  785. X--------------------------------------------------------------------------*/
  786. Xfind_best_match(given_sys,dbpos,bt)
  787. Xchar *given_sys;
  788. Xlong *dbpos;
  789. XBTREE *bt;
  790. X{
  791. Xregister itmp;
  792. Xregister  char *cptr;
  793. Xshort node_num;
  794. Xchar *site;
  795. Xchar site2[SYSNAME_MAXLEN];
  796. Xlong dbpos2;
  797. X
  798. X    switch(btfind(given_sys,&node_num,&site,&*dbpos,bt))
  799. X    {
  800. X        case BT_NREC:
  801. X            break;
  802. X        case BT_ERR:
  803. X            btperror("find_best_match");
  804. X            exit(1);
  805. X        case 0:
  806. X            return(0);
  807. X    }
  808. X
  809. X    (void)strcpy(site2,site);
  810. X    dbpos2 = *dbpos;
  811. X    if(btnext(&node_num,&site,&*dbpos,bt))
  812. X    {
  813. X        (void)printf("%s not found:",given_sys);
  814. X        (void)printf(" %s is the closest\n");
  815. X        return(BT_NREC);
  816. X    }
  817. X    itmp = strlen(given_sys);
  818. X    if(!strncmp(given_sys,site,itmp) &&
  819. X        (itmp < strlen(site)) && (site[itmp] == '.'))
  820. X    {
  821. X        (void)printf("%s not found:",given_sys);
  822. X        (void)printf(" %s seems to match\n",site);
  823. X        return(0);
  824. X    }
  825. X    else if(!strncmp(given_sys,site2,itmp) &&
  826. X        (itmp < strlen(site2)) && (site2[itmp] == '.'))
  827. X    {
  828. X        (void)printf("%s not found:",given_sys);
  829. X        (void)printf(" %s seems to match\n",site2);
  830. X        *dbpos = dbpos2;
  831. X        return(0);
  832. X    }
  833. X    else if(cptr = rindex(given_sys,'.'))
  834. X    {
  835. X        strncpy(site2,given_sys,cptr - given_sys);
  836. X        site2[cptr - given_sys] = 0;
  837. X        return(find_best_match(site2,dbpos,bt));
  838. X    }
  839. X
  840. X    (void)printf("%s not found:",given_sys);
  841. X    (void)printf (" %s and %s are closest\n",site2,site);
  842. X    return(BT_NREC);
  843. X
  844. X}    /* end of find_best_match */
  845. X
  846. X/*+-------------------------------------------------------------------------
  847. X    main(argc,argv,envp)
  848. X--------------------------------------------------------------------------*/
  849. Xmain(argc,argv,envp)
  850. Xint argc;
  851. Xchar **argv;
  852. Xchar **envp;
  853. X{
  854. Xregister itmp;
  855. Xregister char *cptr;
  856. Xint iargv = 1;
  857. Xint isys,nsys;
  858. Xunsigned short node_num;
  859. Xlong umdb_pos;
  860. Xchar buf[512];
  861. Xchar path[512];
  862. Xchar *smail_argv[4];
  863. Xchar *sys[MAX_SYSTEMS_PER_PATH+1];
  864. Xchar *site;
  865. XFILE *fp;
  866. X
  867. X/* get optional db name */
  868. X    if(!strncmp(argv[1],"-n"))
  869. X    {
  870. X        if(strlen(argv[1]) > 2)
  871. X        {
  872. X            umdb = argv[1] + 2;
  873. X            iargv = 2;
  874. X        }
  875. X        else if(argc < 3)
  876. X        {
  877. X            (void)fputs("-n requires map db name\n",stderr);
  878. X            exit(1);
  879. X        }
  880. X        else
  881. X        {
  882. X            umdb = argv[2];
  883. X            iargv = 3;
  884. X        }
  885. X    }
  886. X
  887. X/* get buf from smail */
  888. X    (void)strcpy(buf,"smail -A ");
  889. X    (void)strcat(buf,argv[iargv]);
  890. X    if(!index(argv[iargv],'!') && !index(argv[iargv],'!'))
  891. X        (void)strcat(buf,"!username");
  892. X
  893. X    if(!(fp = popen(buf,"r")))
  894. X    {
  895. X        perror("uudbpath: popen to 'smail -A'");
  896. X        exit(1);
  897. X    }
  898. X    if(!fgets(buf,sizeof(buf),fp))
  899. X    {
  900. X        perror("uudbpath: fgets from 'smail -A' pipe");
  901. X        exit(1);
  902. X    }
  903. X    pclose(fp);
  904. X    if(cptr = rindex(buf,'!'))
  905. X        *cptr = 0;
  906. X    (void)printf("path: %s\n",buf);
  907. X
  908. X/* open database main file */
  909. X    if(!(fp_umdb = fopen(umdb,"r")))
  910. X    {
  911. X        perror(umdb);
  912. X        (void)fputs("usage: umdbdup [-n dbname]\n",stderr);
  913. X        exit(1);
  914. X    }
  915. X
  916. X/* build index filename */
  917. X    (void)strcpy(umdb_name,umdb);
  918. X    (void)strcat(umdb_name,".in");
  919. X
  920. X/* open index file */
  921. X    if(!(bt_name = btopen(umdb_name,O_RDONLY,0644,0)))
  922. X    {
  923. X        btperror(umdb_name);
  924. X        exit(1);
  925. X    }
  926. X
  927. X    build_arg_array(buf,sys,MAX_SYSTEMS_PER_PATH+1,&nsys,"!\r\n");
  928. X    for(isys = 0; isys < nsys; isys++)
  929. X    {
  930. X        switch(find_best_match(sys[isys],&umdb_pos,bt_name))
  931. X        {
  932. X            case BT_NREC:
  933. X                break;
  934. X            case BT_ERR:
  935. X                btperror("find");
  936. X                break;
  937. X            case 0:
  938. X                print_site_info(umdb_pos);
  939. X                break;
  940. X        }
  941. X    }
  942. X    exit(0);
  943. X}    /* end of main */
  944. X
  945. X/* vi: set tabstop=4 shiftwidth=4: */
  946. X/* end of uupath.c */
  947. SHAR_EOF
  948. chmod 0644 umdbpath.c || echo "restore of umdbpath.c fails"
  949. if [ $TOUCH = can ]
  950. then
  951.     touch -m 1210182289 umdbpath.c
  952. fi
  953. echo "x - extracting umdbuild.c (Text)"
  954. sed 's/^X//' << 'SHAR_EOF' > umdbuild.c &&
  955. X/*+-------------------------------------------------------------------------
  956. X    umdbuild.c
  957. X    ...!gatech!emory!tridom!wht
  958. X
  959. XGripes (problems handled):
  960. X1.  Some #N lines contain duplicate system names
  961. X2.  Multiple #N lines have the same .domain name
  962. X3.  A very few entries use '#Name' rather than '#N'
  963. X4.  Several sites place longitude before latitude
  964. X--------------------------------------------------------------------------*/
  965. X/*+:EDITS:*/
  966. X/*:12-09-1989-16:49-wht-creation */
  967. X
  968. X#include <stdio.h>
  969. X#include <fcntl.h>
  970. X#include <sys/types.h>
  971. X#include "btree.h"
  972. X#include "umdb.h"
  973. X
  974. Xextern char *normalize_location();
  975. X
  976. Xchar *umdb = "/usr/lib/uucp/umdb";
  977. XFILE *fp_umdb;
  978. Xchar umdb_name[128];
  979. XBTREE *bt_name;
  980. X
  981. X#ifdef BUILD_LOC_INDEX
  982. Xchar umdb_loc[128];
  983. XBTREE *bt_loc;
  984. X#endif
  985. X
  986. X/*+-------------------------------------------------------------------------
  987. X    mapfile_to_mapdb(mapname)
  988. X--------------------------------------------------------------------------*/
  989. Xvoid
  990. Xmapfile_to_mapdb(mapname)
  991. Xchar *mapname;
  992. X{
  993. Xregister isite,isite2;
  994. Xint nsite;
  995. Xint found_loc;
  996. Xoff_t mappos;
  997. Xoff_t dbpos;
  998. Xchar mapbuf[512];    /* long map entries? - no stinking problem */
  999. Xchar mapbuf2[512];    /* long map entries? - no stinking problem */
  1000. Xchar *site[MAX_SITENAMES_PER_LINE];
  1001. Xchar *location;
  1002. XFILE *fpmap = fopen(mapname,"r");
  1003. Xlong start;
  1004. Xlong time();
  1005. Xint name_count = 0;
  1006. X
  1007. X    if(!fpmap)
  1008. X    {
  1009. X        perror(mapname);
  1010. X        return;
  1011. X    }
  1012. X
  1013. X    fprintf(stderr,"%s ... ",mapname);
  1014. X    time(&start);
  1015. X    start--;    /* show at least 1 second */
  1016. X
  1017. X    while(1)
  1018. X    {
  1019. X        /* read map file until #N entry found or EOF */
  1020. X        do {
  1021. X            mapbuf[0] = 0;
  1022. X            mappos = ftell(fpmap);
  1023. X        } while(fgets(mapbuf,sizeof(mapbuf),fpmap) &&
  1024. X            strncmp(mapbuf,"#N",2));
  1025. X
  1026. X        /* if EOF, done */
  1027. X        if(!mapbuf[0])
  1028. X            break;
  1029. X
  1030. X        /* must be #N entry - build array of site names*/
  1031. X        build_sitename_array(mapbuf,site,MAX_SITENAMES_PER_LINE,&nsite);
  1032. X
  1033. X        /* find #L entry */
  1034. X        do {
  1035. X            mapbuf2[0] = 0;
  1036. X        } while(fgets(mapbuf2,sizeof(mapbuf2),fpmap) &&
  1037. X            (found_loc = strlen(mapbuf2) > 1) /* entry ends with blank line */
  1038. X            && strncmp(mapbuf2,"#L",2));
  1039. X
  1040. X        /* '#Location_of_my_system' will NOT work here; '#L' will :-> */
  1041. X        if(found_loc)
  1042. X            location = normalize_location(mapbuf2 + 2);
  1043. X        else
  1044. X            location = " 0.0000,  0.00000,?";
  1045. X
  1046. X        /* write map db items and name indices, one for each name */
  1047. X        dbpos = ftell(fp_umdb);
  1048. X        /* site[0] == '#N', '#Name', '#N:-<', etc */
  1049. X        for(isite = 1; isite < nsite; isite++)
  1050. X        {
  1051. X            if(strlen(site[isite]) > SYSNAME_MAXLEN)
  1052. X            {
  1053. X                fprintf(stderr,
  1054. X                    "\n  too long a name: %s in  %s\n",site[isite],mapname);
  1055. X                continue;
  1056. X            }
  1057. X/* it was tempting to use this
  1058. X            if(*site[isite] == '.')
  1059. X                continue;
  1060. X*/
  1061. X            for(isite2= 0; isite2 < isite; isite2++)
  1062. X            {
  1063. X                if(!strcmp(site[isite],site[isite2]))
  1064. X                    goto THIS_NAME_DONE;    /* skip dups on _same_ line */
  1065. X            }
  1066. X            name_count++;
  1067. X            fprintf(fp_umdb,"%s:%s:%s:%ld:\n",
  1068. X                location,site[isite],mapname,mappos);
  1069. X            if(btinsert(site[isite],dbpos,bt_name))
  1070. X            {
  1071. X                (void)fputs("\n  ",stderr);
  1072. X                btperror(umdb_name);
  1073. X                exit(1);
  1074. X            }
  1075. XTHIS_NAME_DONE: ;
  1076. X        }
  1077. X
  1078. X#ifdef BUILD_LOC_INDEX
  1079. X        /* write location index, one for each site */
  1080. X        if(btinsert(location,dbpos,bt_loc))
  1081. X        {
  1082. X            btperror(umdb_loc);
  1083. X            exit(1);
  1084. X        }
  1085. X#endif
  1086. X
  1087. XSITE_DONE: ;
  1088. X    }
  1089. X
  1090. X    (void)fclose(fpmap);
  1091. X    fprintf(stderr,"%d names, %ld seconds\n",
  1092. X        name_count,time((long *)0) - start);
  1093. X
  1094. X}    /* end of mapfile_to_mapdb */
  1095. X
  1096. X/*+-------------------------------------------------------------------------
  1097. X    main(argc,argv,envp)
  1098. X--------------------------------------------------------------------------*/
  1099. Xmain(argc,argv,envp)
  1100. Xint argc;
  1101. Xchar **argv;
  1102. Xchar **envp;
  1103. X{
  1104. Xint iargv = 1;    /* first file argument */
  1105. X
  1106. X/* usage */
  1107. X    if(argc < 2)
  1108. X    {
  1109. X        (void)fputs(
  1110. X            "usage: umdbuild [-n dbname] mapfile [mapfile ...]\n",stderr);
  1111. X        exit(1);
  1112. X    }
  1113. X
  1114. X/* get optional db name */
  1115. X    if(!strncmp(argv[1],"-n"))
  1116. X    {
  1117. X        if(strlen(argv[1]) > 2)
  1118. X        {
  1119. X            umdb = argv[1] + 2;
  1120. X            iargv = 2;
  1121. X        }
  1122. X        else if(argc < 3)
  1123. X        {
  1124. X            (void)fputs("-n requires map db name\n",stderr);
  1125. X            exit(1);
  1126. X        }
  1127. X        else
  1128. X        {
  1129. X            umdb = argv[2];
  1130. X            iargv = 3;
  1131. X        }
  1132. X    }
  1133. X
  1134. X/* check argv exhaustion */
  1135. X    if(iargv >= argc)
  1136. X    {
  1137. X        (void)fputs("no map file names!\n",stderr);
  1138. X        exit(1);
  1139. X    }
  1140. X
  1141. X/* build index filenames */
  1142. X    (void)strcpy(umdb_name,umdb);
  1143. X    (void)strcat(umdb_name,".in");
  1144. X
  1145. X#ifdef BUILD_LOC_INDEX
  1146. X    (void)strcpy(umdb_loc,umdb);
  1147. X    (void)strcat(umdb_loc,".il");
  1148. X#endif
  1149. X
  1150. X/* remove old files */
  1151. X    (void)unlink(umdb);
  1152. X    (void)unlink(umdb_name);
  1153. X#ifdef BUILD_LOC_INDEX
  1154. X    (void)unlink(umdb_loc);
  1155. X#endif
  1156. X
  1157. X/* open map database */
  1158. X    if(!(fp_umdb = fopen(umdb,"w")))
  1159. X    {
  1160. X        perror(umdb);
  1161. X        exit(1);
  1162. X    }
  1163. X
  1164. X/* open index files */
  1165. X    if(!(bt_name = btopen(umdb_name,O_CREAT|O_RDWR,0644,SYSNAME_MAXLEN + 2)))
  1166. X    {
  1167. X        btperror(umdb_name);
  1168. X        exit(1);
  1169. X    }
  1170. X#ifdef BUILD_LOC_INDEX
  1171. X    if(!(bt_loc = btopen(umdb_loc,O_CREAT|O_RDWR,0644,LOC_LEN)))
  1172. X    {
  1173. X        btperror(umdb_loc);
  1174. X        exit(1);
  1175. X    }
  1176. X#endif
  1177. X
  1178. X/* make available to others */
  1179. X    (void)chmod(umdb,0644);
  1180. X    (void)chmod(umdb_name,0644);
  1181. X#ifdef BUILD_LOC_INDEX
  1182. X    (void)chmod(umdb_loc,0644);
  1183. X#endif
  1184. X
  1185. X/* read [du].* files, copying building header db file and indices to same */
  1186. X    while(iargv < argc)
  1187. X        mapfile_to_mapdb(argv[iargv++]);
  1188. X
  1189. X/* clean up */
  1190. X    fprintf(stderr,"flushing ... ");
  1191. X    (void)fclose(fp_umdb);
  1192. X    if(btclose(bt_name))
  1193. X        btperror(umdb_name);
  1194. X#ifdef BUILD_LOC_INDEX
  1195. X    if(btclose(bt_loc))
  1196. X        btperror(umdb_loc);
  1197. X#endif
  1198. X
  1199. X    fprintf(stderr,"done\n");
  1200. X    exit(0);
  1201. X
  1202. X}    /* end of main */
  1203. X
  1204. X
  1205. X/* vi: set tabstop=4 shiftwidth=4: */
  1206. X/* end of umdbuild.c */
  1207. SHAR_EOF
  1208. chmod 0644 umdbuild.c || echo "restore of umdbuild.c fails"
  1209. if [ $TOUCH = can ]
  1210. then
  1211.     touch -m 1210203389 umdbuild.c
  1212. fi
  1213. echo "x - extracting umdbutil.c (Text)"
  1214. sed 's/^X//' << 'SHAR_EOF' > umdbutil.c &&
  1215. X/*+-------------------------------------------------------------------------
  1216. X    umdbutil.c
  1217. X    ...!gatech!emory!tridom!wht
  1218. X
  1219. Xutilities for map data items
  1220. X
  1221. XNOTE: we cover the those who dont read right and put longitude before
  1222. Xlatitude
  1223. X--------------------------------------------------------------------------*/
  1224. X/*+:EDITS:*/
  1225. X/*:12-09-1989-19:19-wht-creation */
  1226. X
  1227. X#include <ctype.h>
  1228. X#include "umdb.h"
  1229. X
  1230. X#if defined(M_SYS5) || defined(SYS5)
  1231. X#define index strchr
  1232. X#define rindex strrchr
  1233. X#endif
  1234. X
  1235. Xchar *index();
  1236. Xchar *rindex();
  1237. X
  1238. X/*+-------------------------------------------------------------------------
  1239. X    basename(fullname) - strip directory name from filename
  1240. X
  1241. Xreturns address of static string
  1242. X--------------------------------------------------------------------------*/
  1243. Xchar *
  1244. Xbasename(fullname)
  1245. Xchar *fullname;
  1246. X{
  1247. Xregister char *start;
  1248. Xstatic char outstr[256];
  1249. Xchar *strrchr();
  1250. X
  1251. X    start = rindex(fullname,'/'); /* find last slash */
  1252. X    if(!start)
  1253. X        return(fullname);
  1254. X    start++;
  1255. X    strcpy(outstr,start);
  1256. X    return(outstr);
  1257. X}    /* end of basename */
  1258. X
  1259. X/*+-----------------------------------------------------------------------
  1260. X    arg_token(parsestr,termchars)
  1261. X
  1262. XGet next token from string parsestr ((char *)0 on 2nd, 3rd, etc.
  1263. Xcalls), where tokens are nonempty strings separated by runs of chars
  1264. Xfrom termchars.  Writes nulls into parsestr to end tokens.
  1265. Xtermchars need not remain constant from call to call.
  1266. X
  1267. XTreats multiple occurrences of a termchar as one delimiter (does not
  1268. Xallow null fields).
  1269. X------------------------------------------------------------------------*/
  1270. Xstatic char *arg_token_static = (char *)0;
  1271. Xchar *arg_token(parsestr,termchars)
  1272. Xchar *parsestr;
  1273. Xchar *termchars;
  1274. X{
  1275. Xregister first = 1;
  1276. Xregister char *termptr;
  1277. Xregister char *parseptr;
  1278. Xchar *token;
  1279. X
  1280. X    if(parsestr == (char *)0 && arg_token_static == (char *)0)
  1281. X        return((char *)0);
  1282. X
  1283. X    if(parsestr)
  1284. X        parseptr = parsestr;
  1285. X    else
  1286. X       parseptr = arg_token_static;
  1287. X
  1288. X    while(*parseptr)
  1289. X    {
  1290. X        if(!strchr(termchars,*parseptr))
  1291. X            break;
  1292. X        parseptr++;
  1293. X    }
  1294. X
  1295. X    if(!*parseptr)
  1296. X    {
  1297. X        arg_token_static = (char *)0;
  1298. X        return((char *)0);
  1299. X    }
  1300. X
  1301. X    token = parseptr;
  1302. X    if(*token == '\'')
  1303. X    {
  1304. X        token++;
  1305. X        parseptr++;
  1306. X        while(*parseptr)
  1307. X        {
  1308. X            if(*parseptr == '\'')
  1309. X            {
  1310. X                arg_token_static = parseptr + 1;
  1311. X                *parseptr = 0;
  1312. X                return(token);
  1313. X            }
  1314. X            parseptr++;
  1315. X        }
  1316. X        arg_token_static = (char *)0;
  1317. X        return(token);
  1318. X    }
  1319. X    while(*parseptr)
  1320. X    {
  1321. X        if(strchr(termchars,*parseptr))
  1322. X        {
  1323. X            *parseptr = 0;
  1324. X            arg_token_static = parseptr + 1;
  1325. X            while(*arg_token_static)
  1326. X            {
  1327. X                if(!strchr(termchars,*arg_token_static))
  1328. X                    break;
  1329. X                arg_token_static++;
  1330. X            }
  1331. X            return(token);
  1332. X        }
  1333. X        parseptr++;
  1334. X    }
  1335. X    arg_token_static = (char *)0;
  1336. X    return(token);
  1337. X}    /* end of arg_token */
  1338. X
  1339. X/*+-------------------------------------------------------------------------
  1340. X    build_arg_array(argstr,arg,arg_max_quan,&narg,termchars)
  1341. X--------------------------------------------------------------------------*/
  1342. Xvoid
  1343. Xbuild_arg_array(argstr,arg,arg_max_quan,narg_rtn,termchars)
  1344. Xchar *argstr;
  1345. Xchar **arg;
  1346. Xint arg_max_quan;
  1347. Xint *narg_rtn;
  1348. Xchar *termchars;
  1349. X{
  1350. Xregister ilocarg;
  1351. Xregister narg;
  1352. X
  1353. X    for(ilocarg = 0; ilocarg < arg_max_quan; ilocarg++)
  1354. X        arg[ilocarg] = (char *)0;
  1355. X    arg[0] = arg_token(argstr,termchars);
  1356. X
  1357. X    for(narg = 1; narg < arg_max_quan; ++narg)
  1358. X    {
  1359. X        if((arg[narg] = arg_token((char *)0,termchars)) == (char *)0) 
  1360. X            break;
  1361. X    }
  1362. X
  1363. X    *narg_rtn = narg;
  1364. X
  1365. X}    /* end of build_arg_array */
  1366. X
  1367. X/*+-------------------------------------------------------------------------
  1368. X    build_dbfld_array(dbrec,dbfld,dbfld_max,ndbfld_rtn)
  1369. X--------------------------------------------------------------------------*/
  1370. Xvoid
  1371. Xbuild_dbfld_array(dbrec,dbfld,dbfld_max,ndbfld_rtn)
  1372. Xchar *dbrec;
  1373. Xchar **dbfld;
  1374. Xint dbfld_max;
  1375. Xint *ndbfld_rtn;
  1376. X{
  1377. X    build_arg_array(dbrec,dbfld,dbfld_max,ndbfld_rtn,":\r\n");
  1378. X}    /* end of build_sitename_array */
  1379. X
  1380. X/*+-------------------------------------------------------------------------
  1381. X    build_sitename_array(sitenmstr,site,site_max,nsite_rtn)
  1382. X--------------------------------------------------------------------------*/
  1383. Xvoid
  1384. Xbuild_sitename_array(sitenmstr,site,site_max,nsite_rtn)
  1385. Xchar *sitenmstr;
  1386. Xchar **site;
  1387. Xint site_max;
  1388. Xint *nsite_rtn;
  1389. X{
  1390. X    build_arg_array(sitenmstr,site,site_max,nsite_rtn,", \t\r\n");
  1391. X}    /* end of build_sitename_array */
  1392. X
  1393. X/*+-------------------------------------------------------------------------
  1394. X    array_to_angle(array,arraylen,&angle)
  1395. Xlatitude 0 at equator, longitude as degrees west
  1396. Xreturns ANGLE_? define from umdb.h
  1397. X--------------------------------------------------------------------------*/
  1398. Xint
  1399. Xarray_to_angle(array,arraylen,angle)
  1400. Xchar **array;
  1401. Xint arraylen;
  1402. Xdouble *angle;
  1403. X{
  1404. Xint iarray;
  1405. Xdouble atof();
  1406. X
  1407. X    *angle = 0.0;
  1408. X    for(iarray = 0; iarray < arraylen; iarray++)
  1409. X    {
  1410. X        if(!isdigit(*array[iarray]))
  1411. X        {
  1412. X            switch(tolower(*array[iarray]))
  1413. X            {
  1414. X                case 'n':
  1415. X                    return(ANGLE_LATITUDE);
  1416. X                case 's':
  1417. X                    *angle *= -1.0;
  1418. X                    return(ANGLE_LATITUDE);
  1419. X                case 'w':
  1420. X                    return(ANGLE_LONGITUDE);
  1421. X                case 'e':
  1422. X                    *angle = 360.0 - *angle;
  1423. X                    return(ANGLE_LONGITUDE);
  1424. X            }
  1425. X            return(ANGLE_BAD);    /* bad direction */
  1426. X        }
  1427. X        switch(iarray)
  1428. X        {
  1429. X            case 0: *angle = atof(array[iarray]); break;
  1430. X            case 1: *angle += atof(array[iarray]) / 60.0; break;
  1431. X            case 2: *angle += atof(array[iarray]) / 3600.0; break;
  1432. X            default: return(ANGLE_BAD);
  1433. X        }
  1434. X    }
  1435. X
  1436. X    /* NSEW char HAS to be present because SLOBS put long. before lat. */
  1437. X    return(ANGLE_BAD);
  1438. X            
  1439. X}    /* end of array_to_angle */
  1440. X
  1441. X/*+-------------------------------------------------------------------------
  1442. X    build_normalized_locfld(locfld,latitude,longitude,city)
  1443. X
  1444. Xcity == 0, exact long,lat; == 1, CITY; == -1, bad format was detected
  1445. X--------------------------------------------------------------------------*/
  1446. Xvoid
  1447. Xbuild_normalized_locfld(locfld,latitude,longitude,city)
  1448. Xchar *locfld;    /* must be at least LOC_LEN chars in length */
  1449. Xdouble latitude;
  1450. Xdouble longitude;
  1451. Xint city;
  1452. X{
  1453. X    (void)sprintf(locfld,"%8.4f,%8.4f,%c",latitude,longitude,
  1454. X        (city) ?  ((city < 0) ? '?' : 'C') : 'X');
  1455. X
  1456. X}    /* end of build_normalized_locfld */
  1457. X
  1458. X/*+-------------------------------------------------------------------------
  1459. X    normalize_location(locstr)
  1460. X--------------------------------------------------------------------------*/
  1461. Xchar *
  1462. Xnormalize_location(locstr)
  1463. Xchar *locstr;
  1464. X{
  1465. Xregister ilocarg;
  1466. X#define LOCARGS 25    /* plenty - avoid overflow today! */
  1467. Xchar *locargs[LOCARGS];
  1468. Xint nlocargs;
  1469. Xint city = 0;
  1470. Xint got_latitude = 0;
  1471. Xint got_longitude = 0;
  1472. Xdouble angle;
  1473. Xdouble longitude = 0.0;
  1474. Xdouble latitude = 0.0;
  1475. Xstatic char locfld[LOC_LEN];
  1476. X
  1477. X    build_arg_array(locstr,locargs,LOCARGS,&nlocargs," \r\n\t");
  1478. X    switch(array_to_angle(locargs,nlocargs,&angle))
  1479. X    {
  1480. X        case ANGLE_LATITUDE:
  1481. X            latitude = angle;
  1482. X            got_latitude = 1;
  1483. X            break;
  1484. X        case ANGLE_LONGITUDE:
  1485. X            longitude = angle;
  1486. X            got_longitude = 1;
  1487. X            break;
  1488. X        case ANGLE_BAD:
  1489. X            city = -1;
  1490. X            break;
  1491. X    }
  1492. X
  1493. X    for(ilocarg =  0; ilocarg < nlocargs; ilocarg++)
  1494. X    {
  1495. X        if(*locargs[ilocarg] == '/')
  1496. X        {
  1497. X            switch(array_to_angle(locargs + ilocarg + 1,
  1498. X                                    nlocargs - ilocarg - 1,&angle))
  1499. X            {
  1500. X                case ANGLE_LATITUDE:
  1501. X                    latitude = angle;
  1502. X                    if(got_latitude)
  1503. X                        city = -1;
  1504. X                    got_latitude = 1;
  1505. X                    break;
  1506. X                case ANGLE_LONGITUDE:
  1507. X                    longitude = angle;
  1508. X                    if(got_longitude)
  1509. X                        city = -1;
  1510. X                    got_longitude = 1;
  1511. X                    break;
  1512. X                case ANGLE_BAD:
  1513. X                    city = -1;
  1514. X                    break;
  1515. X            }
  1516. X        }
  1517. X        else if((!strcmp(locargs[ilocarg],"CITY") ||
  1518. X                !strcmp(locargs[ilocarg],"city")) && !city)
  1519. X            city = 1;
  1520. X    }
  1521. X
  1522. X    if(!got_latitude || !got_longitude)
  1523. X        city = -1;
  1524. X
  1525. X    build_normalized_locfld(locfld,latitude,longitude,city);
  1526. X    return(locfld);
  1527. X
  1528. X}    /* end of normalize_location */
  1529. X
  1530. X/*+-------------------------------------------------------------------------
  1531. X    normalized_loc_to_str(nloc)
  1532. X--------------------------------------------------------------------------*/
  1533. Xchar *
  1534. Xnormalized_loc_to_str(nloc)
  1535. Xchar *nloc;
  1536. X{
  1537. Xfloat latitude,longitude;
  1538. Xchar city = '?';
  1539. Xchar lat_NS = 'N';
  1540. Xchar long_EW = 'W';
  1541. Xstatic char presentable[64];
  1542. X
  1543. X    sscanf(nloc,"%f,%f,%c",&latitude,&longitude,&city);
  1544. X    if(latitude < 0.0)
  1545. X    {
  1546. X        latitude *= -1;
  1547. X        lat_NS = 'S';
  1548. X    }
  1549. X    if(longitude > 180.0)
  1550. X    {
  1551. X        longitude = 360.0 - longitude;
  1552. X        long_EW = 'E';
  1553. X    }
  1554. X
  1555. X    sprintf(presentable,"%7.4f %c %8.4f %c %s",
  1556. X        latitude,lat_NS,
  1557. X        longitude,long_EW,
  1558. X        ((city == 'X') ? "    " : ((city == 'C') ? "city" : "??  ")));
  1559. X
  1560. X    return(presentable);
  1561. X
  1562. X}    /* end of normalized_loc_to_str */
  1563. X
  1564. X/* vi: set tabstop=4 shiftwidth=4: */
  1565. X/* end of umdbutil.c */
  1566. SHAR_EOF
  1567. chmod 0644 umdbutil.c || echo "restore of umdbutil.c fails"
  1568. if [ $TOUCH = can ]
  1569. then
  1570.     touch -m 1210195289 umdbutil.c
  1571. fi
  1572. rm -f s3_seq_.tmp
  1573. echo "You have unpacked the last part"
  1574. exit 0
  1575.  
  1576.