home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / compsrcs / unix / volume20 / pt < prev    next >
Encoding:
Text File  |  1989-10-27  |  16.4 KB  |  747 lines

  1. Path: wuarchive!gem.mps.ohio-state.edu!samsung!xanth!bbn.com!rsalz
  2. From: rsalz@uunet.uu.net (Rich Salz)
  3. Newsgroups: comp.sources.unix
  4. Subject: v20i078:  Display process family tree
  5. Message-ID: <2094@papaya.bbn.com>
  6. Date: 27 Oct 89 17:13:49 GMT
  7. Lines: 737
  8. Approved: rsalz@uunet.UU.NET
  9.  
  10. Submitted-by: Jeff Bauer <bauer@loligo.cc.fsu.edu>
  11. Posting-number: Volume 20, Issue 78
  12. Archive-name: pt
  13.  
  14. Get frustrated poring through "ps" output trying to figure out which child
  15. belongs to what parent?  Well, this might help.  "Pt" makes a valiant
  16. effort to filter "ps" output into a hierarchical process tree.
  17.  
  18. It runs well on System V.3 and makes a good effort on bsd derivatives,
  19. where "ps" columns tend to stretch and run together.  Note the define in
  20. the Makefile for bsd/SysV builds.
  21.  
  22.                     -- Jeff Bauer
  23.  
  24. PS : If anybody hacks at this and has more luck parsing "ps" output or
  25. generates changes to run on different unix flavors, please mail/post me
  26. the diffs.
  27.  
  28. -- Cut here, as usual --
  29. #!/bin/sh
  30. # shar:    Shell Archiver
  31. #    Run the following text with /bin/sh to create:
  32. #    Makefile
  33. #    pt.1
  34. #    pt.c
  35. sed 's/^X//' << 'SHAR_EOF' > Makefile
  36. X#
  37. X# Comment out the next line if you are building for System V
  38. X#
  39. XDEFINES=-DBSD
  40. XCFLAGS=-O
  41. X
  42. Xpt:    pt.c
  43. X    $(CC) $@.c -o $@ $(CFLAGS) $(DEFINES)
  44. SHAR_EOF
  45. sed 's/^X//' << 'SHAR_EOF' > pt.1
  46. X.TH PT 1
  47. X.SH NAME
  48. X\fBpt\fR \- display process family tree
  49. X.SH USAGE
  50. X.B pt [-a] [user]
  51. X.SH DESCRIPTION
  52. XThe 
  53. X.I pt
  54. Xcommand is a convenient alternative to using ps(1) to display a list
  55. Xof user processes.  Instead of showing a list of processes in the order
  56. Xthat they appear in the system process table,
  57. X.I pt
  58. Xdisplays processes in order of their family hierarchy.  The PID of
  59. Xchildren processes are indented to show the relationship between a
  60. Xparent and child process.
  61. X.sp
  62. XWith no parameters specified,
  63. X.I pt
  64. Xwill display only those processes not owned by "root".  If
  65. X.I \-a
  66. Xis specified,
  67. X.I pt
  68. Xwill display all processes.  If
  69. X.I user
  70. Xis specified,
  71. X.I pt
  72. Xwill display only processes owned by the user name specified.
  73. X.sp
  74. XThe column headings are somewhat self-explanatory; for further
  75. Xdetails see ps(1).
  76. X.SH EXAMPLE
  77. X.sp
  78. X$ pt carr
  79. X.br
  80. XPID                  User     Time    Pages  S  Command
  81. X.br
  82. X 8618                carr     0:00        8 (S) -ksh
  83. X.br
  84. X  8724               carr     0:00        8 (S) -ksh
  85. X.br
  86. X   8756              carr    16:13      479 (R) vlad6
  87. X.SH CAVEATS
  88. XWhen a user name is specified on the command line sometimes
  89. X.I pt
  90. Xcannot determine the correct lineage of a process.  Any of these
  91. Xorphan processes will appear under the heading of "Orphans" on
  92. Xthe output.
  93. X.sp
  94. XSince
  95. X.I pt
  96. Xreally is a filter from a forked-off ps(1) sometimes the parsing of
  97. Xthe output from ps(1) fails and the fields get garbled.
  98. X.SH SEE ALSO
  99. X.BR ps(1).
  100. SHAR_EOF
  101. sed 's/^X//' << 'SHAR_EOF' > pt.c
  102. X/*
  103. X    pt.c    - show process family tree
  104. X
  105. X    pt [-a] [user]
  106. X
  107. X    Default compilation is for System V UNIX.
  108. X    To compile for a bsd system try :
  109. X
  110. X    cc pt.c -o pt -O -DBSD
  111. X                            */
  112. X
  113. X#include <stdio.h>
  114. X#include <fcntl.h>
  115. X#include <string.h>
  116. X#ifdef    BSD
  117. X#include <pwd.h>
  118. X#include <ctype.h>
  119. X#endif    BSD
  120. X
  121. X#define    MAXLINE    256
  122. X#define    MYBUFSZ    256
  123. X#define    STDIN    0
  124. X#define    STDOUT    1
  125. X#define    STDERR    2
  126. X
  127. Xchar line[MAXLINE], token[MAXLINE];
  128. Xint firstr, cur_char, cur_row, cur_col;
  129. X
  130. X#define    TRUE    1
  131. X#define    FALSE    0
  132. X#define    UNDEF    2
  133. X
  134. Xstruct psl {
  135. X    char state[8];        /* S */
  136. X    char user[9];        /* UID */
  137. X    unsigned int pid;    /* PID */
  138. X    unsigned int ppid;    /* PPID */
  139. X    unsigned int pages;    /* SZ */
  140. X    char time[12];        /* TIME */
  141. X    char verb[32];        /* COMD */
  142. X};
  143. X
  144. Xstruct plist {
  145. X    struct psl cp;
  146. X    struct plist *s;        /* sibling */
  147. X    struct plist *c;        /* child */
  148. X};
  149. X
  150. Xstruct psl cp;
  151. Xstruct plist *proot;
  152. Xstruct plist *orphans;
  153. Xint orphcnt;
  154. Xint showroot = FALSE;
  155. X#ifdef    BSD
  156. Xstruct passwd *pe;
  157. Xextern int errno;
  158. X#endif    BSD
  159. X
  160. Xextern char *malloc();
  161. Xvoid strcpy2(), cp_plist(), pprint();
  162. Xint pinsert();
  163. Xstruct plist *pfind();
  164. X
  165. Xvoid main(argc, argv)
  166. Xint argc;
  167. Xchar **argv;
  168. X{
  169. X    int gls;
  170. X    int pfds[2];
  171. X    char who[9];
  172. X    int slen, wsp;
  173. X    char tbuf[32], tbuf2[32];
  174. X#ifdef    BSD
  175. X    char d1[32], d2[32], d3[32], d4[32], d5[32], d6[32], d7[32];
  176. X#endif
  177. X    struct plist *child;
  178. X    int fostered;
  179. X    int offset;
  180. X    int adopted;
  181. X    int i, j;
  182. X
  183. X    if (argc == 1) who[0] = '\0';
  184. X
  185. X    while (argc--) {
  186. X      if (argc != 0) {
  187. X        if (strcmp(argv[argc], "-a") == 0)
  188. X          showroot = TRUE;
  189. X        else
  190. X          strcpy2(who, argv[argc], 8);
  191. X      }
  192. X    }
  193. X    if (argc > 3) {
  194. X      fprintf(stderr,"Usage : %s [-a] [user]\n", argv[0]);
  195. X      exit(1);
  196. X    }
  197. X    if (strcmp(who, "root") == 0)
  198. X      showroot = TRUE;
  199. X
  200. X    orphcnt = 0;
  201. X
  202. X    if (pipe(pfds) < 0) {
  203. X        perror("pipe");
  204. X        exit(1);
  205. X    }
  206. X
  207. X    if (fork() == 0) {        /* BEGIN child processing */
  208. X      if (close(STDOUT) < 0) {    /* release fd 1 */
  209. X        perror("close1");
  210. X        exit(1);
  211. X      }
  212. X      if (dup(pfds[1]) < 0) {    /* re-use fd 1 */
  213. X        perror("dup1");
  214. X        exit(1);
  215. X      }
  216. X      if (close(pfds[1]) < 0) {
  217. X        perror("close2");
  218. X        exit(1);
  219. X      }
  220. X      if (close(pfds[0]) < 0) {
  221. X        perror("close3");
  222. X        exit(1);
  223. X      }
  224. X      if (who[0] == '\0')
  225. X#ifdef    BSD
  226. X        execl("/bin/ps","ps","-axlw",0);
  227. X#else
  228. X        execl("/bin/ps","ps","-elf",0);
  229. X#endif    BSD
  230. X      else 
  231. X#ifdef    BSD
  232. X        execl("/bin/ps","ps","-axlw",0);    /* no single-user filter on bsd "ps" */
  233. X#else
  234. X        execl("/bin/ps","ps","-u",who,"-lf",0);
  235. X#endif    BSD
  236. X    }                /* END child processing */
  237. X
  238. X    if (close(STDIN) < 0) {        /* release fd 0 */
  239. X      perror("close4");
  240. X      exit(1);
  241. X    }
  242. X    if (dup(pfds[0]) < 0) {        /* re-use fd 0 */
  243. X      perror("dup2");
  244. X      exit(1);
  245. X    }
  246. X    if (close(pfds[0]) < 0) {
  247. X      perror("close5");
  248. X      exit(1);
  249. X    }
  250. X    if (close(pfds[1]) < 0) {
  251. X      perror("close6");
  252. X      exit(1);
  253. X    }
  254. X
  255. X    firstr = TRUE;
  256. X    cur_row = 0;
  257. X    while ((gls = getline(STDIN, line, MAXLINE)) >= 0) {
  258. X      if (gls == -2) break;
  259. X      cur_char = 0;
  260. X      cur_col = 0;
  261. X      offset = FALSE;
  262. X#ifdef    BSD
  263. X      d7[0] = '\0';
  264. X#endif    BSD
  265. X      while (get_token(line, token, MAXLINE, &wsp) >= 0) {
  266. X        if (cur_row > 0) {        /* skip column headings */
  267. X          switch (cur_col) {
  268. X#ifdef    BSD
  269. X        case 0 :
  270. X          if (((wsp > 0) && (strlen(token) > 5)) ||
  271. X            ((wsp == 0) && (strlen(token) > 10))) {
  272. X            j = 0;
  273. X            for (i = (7 - wsp); i < strlen(token); i++)
  274. X              tbuf[j++] = token[i];
  275. X            tbuf[j+1] = '\0';
  276. X            strcpy(token, tbuf);
  277. X            cur_col += 1;
  278. X            sscanf(token, "%d", &i);
  279. X            if ((pe = getpwuid(i)) != NULL)
  280. X              strcpy2(cp.user, pe->pw_name, 8);
  281. X            else {
  282. X              strcpy2(cp.user, "(bogus)", 8);
  283. X              fprintf(stderr,"1: Checking UID %d : ",i);
  284. X              perror("getpwuid");
  285. X            }
  286. X          }
  287. X          else if ((wsp == 6) && (strlen(token) > 1)) {
  288. X            cur_col += 1;
  289. X            sscanf(token, "%d", &i);
  290. X            if ((pe = getpwuid(i)) != NULL)
  291. X              strcpy2(cp.user, pe->pw_name, 8);
  292. X            else {
  293. X              strcpy2(cp.user, "(bogus)", 8);
  294. X              fprintf(stderr,"2: Checking UID %d : ",i);
  295. X              perror("getpwuid");
  296. X            }
  297. X          }
  298. X          break;      
  299. X        case 1 :
  300. X          sscanf(token, "%d", &i);
  301. X          if ((pe = getpwuid(i)) != NULL)
  302. X            strcpy2(cp.user, pe->pw_name, 8);
  303. X          else {
  304. X            strcpy2(cp.user, "(bogus)", 8);
  305. X            fprintf(stderr,"3: Checking UID %d : ",i);
  306. X            perror("getpwuid");
  307. X          }        
  308. X          break;
  309. X        case 2 :
  310. X          sscanf(token, "%d", &cp.pid);
  311. X          break;
  312. X        case 3 :
  313. X          sscanf(token, "%d", &cp.ppid);
  314. X          break;
  315. X        case 7 :
  316. X          if (strlen(token) > 4)
  317. X            offset = TRUE;
  318. X          break;
  319. X        case 8 :
  320. X          if (offset == TRUE) {
  321. X            strcpy2(d1, token, 32);
  322. X          }
  323. X          break;
  324. X        case 9 :
  325. X          if (offset == TRUE) {
  326. X            strcpy2(d2, token, 32);
  327. X          }
  328. X          else {
  329. X            strcpy2(d1, token, 32);
  330. X          }        
  331. X          break;
  332. X        case 10 :
  333. X          if (offset == TRUE) {
  334. X            strcpy2(d3,token, 32);
  335. X          }
  336. X          else {
  337. X            strcpy2(d2, token, 32);
  338. X          }        
  339. X          break;
  340. X        case 11 :
  341. X          if (offset == TRUE) {
  342. X            strcpy(d4, token, 32);
  343. X          }
  344. X          else {
  345. X            strcpy2(d3, token, 32);
  346. X          }
  347. X          break;
  348. X        case 12 :
  349. X          if (offset == TRUE) {
  350. X            strcpy2(d5, token, 32);
  351. X          }
  352. X          else {
  353. X            strcpy2(d4, token, 32);
  354. X          }
  355. X          break;
  356. X        case 13 :
  357. X          if (offset == TRUE) { 
  358. X            strcpy2(d6, token, 32);
  359. X          }
  360. X          else {
  361. X            strcpy2(d5, token, 32);
  362. X          }
  363. X          break;
  364. X        case 14 :
  365. X          if (offset == TRUE) {
  366. X            strcpy2(d7, token, 32);
  367. X          }
  368. X          else {
  369. X            strcpy2(d6, token, 32);
  370. X          }
  371. X          break;
  372. X#else
  373. X        case 1 :
  374. X          cp.state[0] = token[0];
  375. X          cp.state[1] = '\0';
  376. X          if (strlen(token) > 1) {
  377. X            strcpy2(cp.user, (token+1), 8);
  378. X            cur_col += 1;
  379. X          }
  380. X          if ((cp.state[0] == 'R') || (cp.state[0] == 'O'))
  381. X            offset = TRUE;    /* "WCHAN" is empty */
  382. X          break;
  383. X        case 2 :
  384. X          strcpy2(cp.user, token, 8);
  385. X          break;
  386. X        case 3 :
  387. X          sscanf(token, "%d", &cp.pid);
  388. X          break;
  389. X        case 4 :
  390. X          sscanf(token, "%d", &cp.ppid);
  391. X          break;
  392. X        case 9 :
  393. X          if (cp.state[0] == 'Z') {
  394. X            cp.pages = 0;
  395. X            break;
  396. X          }
  397. X          strcpy(tbuf,token);
  398. X          if ((slen = strlen(token)) > 9 ) {
  399. X            strcpy2(tbuf, token, (slen-9));
  400. X            cur_col += 1;
  401. X          }
  402. X          sscanf(tbuf, "%d", &cp.pages);
  403. X          break;
  404. X        case 12 :
  405. X          if (offset == TRUE) {
  406. X            strcpy2(cp.time, token, 12);
  407. X          }
  408. X          break;
  409. X        case 13 :
  410. X          if (offset == TRUE) {
  411. X            strcpy2(cp.verb, token, 32);
  412. X          }
  413. X          else {
  414. X            strcpy2(cp.time, token, 12);
  415. X          }
  416. X          strcpy2(tbuf2, token, 12);
  417. X          break;
  418. X        case 14 :
  419. X          if (offset == FALSE) {
  420. X            strcpy2(cp.verb, token, 32);
  421. X          }
  422. X          break;
  423. X#endif    BSD
  424. X          }
  425. X          cur_col += 1;
  426. X        }
  427. X      }
  428. X#ifdef    BSD
  429. X    
  430. X      /* Sigh... */
  431. X
  432. X      if (isupper(d2[0]) || (d2[0] == 'p')) {
  433. X        strcpy(cp.state, d2);
  434. X        strcpy(cp.time, d4);
  435. X        strcpy(cp.verb, d5);
  436. X      }
  437. X      else {
  438. X        strcpy(cp.state, d3);
  439. X        strcpy(cp.time, d5);
  440. X        strcpy(cp.verb, d6);
  441. X      }
  442. X
  443. X#endif    BSD
  444. X      if (cur_row > 0) {
  445. X#ifdef    BSD
  446. X        if (who[0] == '\0')
  447. X          pinsert(&cp, TRUE);
  448. X        else
  449. X          if (strcmp(cp.user, who) == 0)
  450. X            pinsert(&cp, TRUE);
  451. X#else
  452. X        pinsert(&cp, TRUE);
  453. X#endif    BSD
  454. X      }
  455. X      cur_row += 1;
  456. X    }
  457. X    wait(0);
  458. X
  459. X    /* Place orphans into their foster homes */
  460. X
  461. X    fostered = 0;
  462. X
  463. X    while (orphcnt != fostered) {
  464. X
  465. X      adopted = FALSE;
  466. X
  467. X      for (child = orphans; child != NULL; child = child->s) {
  468. X        if (strcmp(child->cp.state, "HOME") != 0) {
  469. X          if (pinsert(&child->cp, FALSE) == TRUE) {
  470. X        strcpy(child->cp.state, "HOME");
  471. X            fostered += 1;
  472. X        adopted = TRUE;
  473. X          }
  474. X        }
  475. X      }
  476. X      if (adopted == FALSE) {
  477. X        break;
  478. X      }
  479. X    }
  480. X    printf("PID\t\t\t    User     Time    Pages  S  Command\n");
  481. X    pprint(proot, 0, FALSE);
  482. X    if (orphcnt != fostered) {
  483. X      printf("Orphans :\n");
  484. X      printf("PID (PPID)\t\t    User     Time    Pages  S  Command\n");
  485. X      pprint(orphans, 0, TRUE);
  486. X    }
  487. X}
  488. X
  489. Xint pinsert(cp, adopt)        /* TRUE = info inserted; FALSE = info orphaned */
  490. Xstruct psl *cp;
  491. Xint adopt;            /* TRUE = add orphans to orphan list */
  492. X{
  493. X    struct plist *parent, *sibling;
  494. X    int iflag;
  495. X
  496. X    iflag = TRUE;
  497. X    if (proot == NULL) {    /* call this one root for now */
  498. X      if ((proot = (struct plist *) malloc(sizeof(struct plist))) == NULL) {
  499. X        fprintf(stderr,"malloc failed\n");
  500. X        exit(1);
  501. X      }
  502. X      cp_plist(proot, cp);
  503. X    }
  504. X    else {            /* find parent; traverse sibling list & insert */
  505. X      if ((parent = pfind(proot, cp->ppid)) == NULL) {    /* no parent yet */
  506. X        iflag = FALSE;
  507. X        if (adopt == TRUE) {
  508. X          orphcnt += 1;
  509. X          if (orphans == NULL) {
  510. X            if ((orphans = (struct plist *) malloc(sizeof(struct plist))) == NULL) {
  511. X              fprintf(stderr,"malloc failed\n");
  512. X              exit(1);
  513. X            }
  514. X            cp_plist(orphans, cp);
  515. X          }
  516. X          else {            /* chain orphans together (heartless!) */
  517. X            for (sibling = orphans; sibling->s != NULL; sibling = sibling->s);
  518. X            if ((sibling->s = (struct plist *) malloc(sizeof(struct plist))) == NULL) {
  519. X              fprintf(stderr,"malloc failed\n");
  520. X              exit(1);
  521. X            }
  522. X            cp_plist(sibling->s, cp);
  523. X          }
  524. X        }
  525. X      }
  526. X      else {            /* parent exists */
  527. X        if (parent->c == NULL) {    /* first child */
  528. X          if ((parent->c = (struct plist *) malloc(sizeof(struct plist))) == NULL) {
  529. X            fprintf(stderr,"malloc failed\n");
  530. X            exit(1);
  531. X          }
  532. X          cp_plist(parent->c, cp);
  533. X        }
  534. X        else {            /* siblings exist */
  535. X          sibling = parent->c;
  536. X          while (sibling->s != NULL) sibling = sibling->s;
  537. X          if ((sibling->s = (struct plist *) malloc(sizeof(struct plist))) == NULL) {
  538. X            fprintf(stderr,"malloc failed\n");
  539. X            exit(1);
  540. X          }
  541. X          cp_plist(sibling->s, cp);
  542. X        }
  543. X      }
  544. X    }
  545. X    return(iflag);
  546. X}
  547. X
  548. Xstruct plist *pfind(cp, ppid)
  549. Xstruct plist *cp;
  550. Xint ppid;
  551. X{
  552. X    struct plist *p;
  553. X
  554. X    if (cp == NULL) return(NULL);
  555. X    else if (cp->cp.pid == ppid) return(cp);
  556. X    else {
  557. X      if ((p = pfind(cp->c, ppid)) == NULL)
  558. X        return(pfind(cp->s, ppid));
  559. X      else
  560. X        return(p);
  561. X    }
  562. X}
  563. X
  564. Xvoid pprint(cp, cnt, orphflg)
  565. Xstruct plist *cp;
  566. Xint cnt, orphflg;
  567. X{
  568. X    int i, j;
  569. X    char buf[16];
  570. X
  571. X    if (cp == NULL) return;
  572. X
  573. X    if (strcmp(cp->cp.state, "HOME") != 0) {
  574. X      if (!((showroot == FALSE) && (strcmp(cp->cp.user, "root") == 0))) {
  575. X        if (orphflg == TRUE) {
  576. X#ifdef    BSD
  577. X          sprintf(buf, "%d (%d)",cp->cp.pid, cp->cp.ppid);
  578. X          j = strlen(buf);
  579. X#else
  580. X          j = sprintf(buf, "%d (%d)",cp->cp.pid, cp->cp.ppid);
  581. X#endif    BSD
  582. X        }
  583. X        else {
  584. X#ifdef    BSD
  585. X          sprintf(buf, "%d", cp->cp.pid);
  586. X          j = strlen(buf);
  587. X#else
  588. X          j = sprintf(buf, "%d", cp->cp.pid);
  589. X#endif    BSD
  590. X        }
  591. X        for (i = 0; i < cnt; i++) printf(" ");
  592. X        printf(" %s", buf);
  593. X        for (i = 0; i < (3-(((cnt*1)+j+1)/8)); i++) printf("\t");
  594. X        printf("%8s %8s %8d (%s) %s\n", cp->cp.user, cp->cp.time,
  595. X          cp->cp.pages, cp->cp.state, cp->cp.verb);
  596. X      }
  597. X    }
  598. X
  599. X    pprint(cp->c, cnt+1, orphflg);
  600. X    pprint(cp->s, cnt, orphflg);
  601. X}
  602. X
  603. Xvoid cp_plist(pto, pfrom)
  604. Xstruct plist *pto;
  605. Xstruct psl *pfrom;
  606. X{
  607. X    strcpy(pto->cp.state, pfrom->state);
  608. X    strcpy(pto->cp.user, pfrom->user);
  609. X    pto->cp.pid = pfrom->pid;
  610. X    pto->cp.ppid = pfrom->ppid;
  611. X    pto->cp.pages = pfrom->pages;
  612. X    strcpy(pto->cp.time, pfrom->time);
  613. X    strcpy(pto->cp.verb, pfrom->verb);
  614. X    pto->c = pto->s = NULL;
  615. X}
  616. X
  617. Xint getline(fd,buf,max)
  618. Xint fd;
  619. Xchar *buf;
  620. Xint max;
  621. X
  622. X/*
  623. X    getline(fd, buffer, max)
  624. X
  625. X    Get a line from file *fd* up to *max* bytes into *buffer*.
  626. X    Return 0 if OK, -1 if hit EOF, -2 if first read is NULL,
  627. X    -3 if read failed.
  628. X                                */
  629. X
  630. X{
  631. X    static char mybuf[MYBUFSZ];    /* internal buffer */
  632. X    static int myend = 0;        /* # bytes in mybuf */
  633. X    static int mycnt = 0;        /* # bytes already scanned */
  634. X    static char *curline = NULL;    /* beginning of current line to get */
  635. X    char *p, lastc;
  636. X    int nbytes;
  637. X
  638. X    if (firstr == TRUE) curline = NULL;
  639. X
  640. X    if (curline == NULL) {    /* empty buffer */
  641. X      if ((myend = read(fd, mybuf, MYBUFSZ)) < 0) {
  642. X        perror("read");
  643. X        return(-3);
  644. X      }
  645. X      curline = mybuf;        /* new buffer filled */
  646. X      mycnt = 0;
  647. X    }
  648. X
  649. X    if ((myend == 0) && firstr) {    /* first read hit EOF (empty file) */
  650. X      *buf = '\0';
  651. X      return(-2);
  652. X    }
  653. X
  654. X    if (myend == 0) {        /* later read hit EOF */
  655. X      *buf = '\0';
  656. X      return(-1);
  657. X    }
  658. X
  659. X    firstr = FALSE;
  660. X
  661. X    p = curline;
  662. X    nbytes = 0;
  663. X
  664. X    read_loop:
  665. X
  666. X    while ((*p != '\n') && (mycnt < myend) && (nbytes <= max)) {
  667. X      *buf++ = *p++;
  668. X      mycnt += 1;
  669. X      nbytes += 1;
  670. X    }
  671. X    lastc = *p;
  672. X    p += 1;
  673. X    mycnt += 1;
  674. X
  675. X    if ((mycnt >= myend) && (lastc != '\n')) {
  676. X      if ((myend = read(fd, mybuf, MYBUFSZ)) < 0) {
  677. X        perror("read");
  678. X        return(-3);
  679. X      }
  680. X      p = curline = mybuf;
  681. X      lastc = *p;
  682. X      mycnt = 0;
  683. X    }
  684. X    if ((mycnt != myend) && (lastc != '\n')) goto read_loop;
  685. X
  686. X    *buf += 1;
  687. X    *buf = '\0';
  688. X    curline = p;    /* set for next *getline* call */
  689. X
  690. X    if (mycnt >= myend)
  691. X      curline = NULL;    /* reached end of buffer */
  692. X
  693. X    return(0);
  694. X}
  695. X
  696. Xint get_token(line, token, max, wsp)    /* return 0 = token, -1 = no tokens left on line */
  697. Xchar *line, *token;
  698. Xint *wsp;                /* # of white spaces preceding token */
  699. Xint max;
  700. X{
  701. X    int i, j;
  702. X
  703. X    i = cur_char;
  704. X    j = 0;
  705. X    *wsp = 0;
  706. X
  707. X    if ((i >= (max-1)) || (line[i] == '\0')) {
  708. X      *token = '\0';
  709. X      return(-1);
  710. X    }
  711. X
  712. X    while((line[i] == ' ') || (line[i] == '\t')) {
  713. X      i++;
  714. X      *(wsp)++;
  715. X    }
  716. X
  717. X    while ((line[i] != ' ') && (line[i] != '\t') && (line[i] != '\n')
  718. X        && (line[i] != '\r') && (line[i] != '\0'))
  719. X      token[j++] = line[i++];
  720. X
  721. X    token[j] = '\0';
  722. X
  723. X    if (line[i] != '\0') cur_char = i + 1;
  724. X    else cur_char = i;
  725. X    return(0);
  726. X}
  727. X
  728. Xvoid strcpy2(dst, src, max)
  729. Xchar *dst, *src;
  730. Xint max;
  731. X{
  732. X    int i;
  733. X
  734. X    i = 0;
  735. X    while ((src[i] != ' ') && (i < max) && (src[i] != '\0')) {
  736. X      dst[i] = src[i];
  737. X      i += 1;
  738. X    }
  739. X    dst[i] = '\0';
  740. X}
  741. SHAR_EOF
  742. exit
  743.  
  744. -- 
  745. Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.
  746. Use a domain-based address or give alternate paths, or you may lose out.
  747.