home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #20 / NN_1992_20.iso / spool / comp / sources / unix / 266 < prev    next >
Encoding:
Text File  |  1992-09-08  |  75.3 KB  |  2,404 lines

  1. Newsgroups: comp.sources.unix
  2. Path: sparky!uunet!decwrl!deccrl!news.crl.dec.com!pa.dec.com!vixie
  3. From: klin@iat.uni-paderborn.de (Peter Klingebiel)
  4. Subject: v26i067: utree - screen oriented filesystem utility (V3.03b-um), Part04/08
  5. Message-ID: <1992Sep7.214914.26898@PA.dec.com>
  6. Originator: vixie@cognition.pa.dec.com
  7. Sender: unix-sources-moderator@pa.dec.com
  8. Organization: DEC Palo Alto
  9. Date: Mon, 7 Sep 92 21:49:14 GMT
  10. Approved: vixie@pa.dec.com
  11. Lines: 2391
  12.  
  13. Submitted-By: klin@iat.uni-paderborn.de (Peter Klingebiel)
  14. Posting-Number: Volume 26, Issue 67
  15. Archive-Name: utree/part04
  16.  
  17. #! /bin/sh
  18. # This is a shell archive.  Remove anything before this line, then unpack
  19. # it by saving it into a file and typing "sh file".  To overwrite existing
  20. # files, type "sh file -c".  You can also feed this as standard input via
  21. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  22. # will see the following message at the end:
  23. #        "End of archive 4 (of 8)."
  24. # Contents:  src/bind.c src/comm.c src/main.c src/utree.prlist.c
  25. # Wrapped by vixie@cognition.pa.dec.com on Mon Sep  7 14:39:55 1992
  26. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  27. if test -f 'src/bind.c' -a "${1}" != "-c" ; then 
  28.   echo shar: Will not clobber existing file \"'src/bind.c'\"
  29. else
  30. echo shar: Extracting \"'src/bind.c'\" \(17641 characters\)
  31. sed "s/^X//" >'src/bind.c' <<'END_OF_FILE'
  32. X/*
  33. X *      BIND.C
  34. X *      UTREE key binding routines.
  35. X *      3.03-um klin, Sun Feb 23 18:45:19 1992
  36. X *              klin, Fri Mar  6 07:24:23 1992, Minor changes
  37. X *            a klin, Sun Mar 15 19:08:25 1992, Bug fixes in bindings()
  38. X *                                              and insertbinding()
  39. X *
  40. X *      Copyright (c) 1991/92 by Peter Klingebiel & UNIX Magazin Muenchen.
  41. X *      For copying and distribution information see the file COPYRIGHT.
  42. X */
  43. X#ifndef lint
  44. static char sccsid[] = "@(#) utree 3.03a-um (klin) Mar 15 1992 bind.c";
  45. X#endif
  46. X
  47. X#include "defs.h"
  48. X
  49. X/* ---- Local variables and definitions ------------------------------- */
  50. X
  51. X/*
  52. X *      All default keys and some function keys are defined in static
  53. X *      arrays of type struct _ktable. The default keys are hold in the
  54. X *      array defkeys[] and bound at startup to the defined utree keys.
  55. X *      The function keys whose termcap names are stored in the array
  56. X *      are extracted from terminfo/termcap and bound to the default
  57. X *      utree keys if they are defined in the database.
  58. X */
  59. X
  60. LOCAL struct {                 /* Default key bindings                 */
  61. X  char *string;                 /*   Key string                         */
  62. X  ksym symbol;                  /*   Key symbol known by utree          */
  63. X} defkeys[] = {
  64. X  { "\200", K_MARK },           /*   C-@: Set mark                      */
  65. X  { "\001", K_HOME },           /*   C-a: Beginning                     */
  66. X  { "\002", K_BACK },           /*   C-b: Backward                      */
  67. X  { "\003", K_BRK  },           /*   C-c: Break                         */
  68. X  { "\004", K_DOWN },           /*   C-d: Scroll down/delete char       */
  69. X  { "\005", K_END  },           /*   C-e: End                           */
  70. X  { "\006", K_FORW },           /*   C-f: Forward                       */
  71. X  { "\007", K_GOTO },           /*   C-g: Goto mark                     */
  72. X  { "\010", K_DEL  },           /*   C-h: Goto parent/delete char back  */
  73. X  { "\011", K_TAG  },           /*   C-i: Goto tag/transpose chars      */
  74. X  { "\012", K_SEL  },           /*   C-j: Select/accept line            */
  75. X  { "\013", K_KILL },           /*   C-k: Kill line                     */
  76. X  { "\014", K_REFR },           /*   C-l: Refresh screen/line           */
  77. X  { "\015", K_SEL  },           /*   C-m: Select/accept line            */
  78. X  { "\016", K_NEXT },           /*   C-n: Next                          */
  79. X  { "\017", K_INS  },           /*   C-o: Change to/toggle insert mode  */
  80. X  { "\020", K_PREV },           /*   C-p: Previous                      */
  81. X  { "\022", K_HELP },           /*   C-r: Help                          */
  82. X  { "\024", K_TAG  },           /*   C-t: Goto tag/transpose characters */
  83. X  { "\025", K_UP   },           /*   C-u: Scroll up                     */
  84. X  { "\026", K_NPAG },           /*   C-v: Next page/scroll forw line    */
  85. X  { "\027", K_PPAG },           /*   C-w: Prev page/scroll back line    */
  86. X  { "\030", K_CANC },           /*   C-x: Delete input line             */
  87. X  { "\031", K_BRK  },           /*   C-y: Break                         */
  88. X  { "\032", K_EOF  },           /*   C-z: Exit                          */
  89. X  { "\177", K_DEL  },           /*   C-?: Delete                        */
  90. X  { NULL,   K_INV  },           /* End of default key table             */
  91. X};
  92. X
  93. X#define DTSTR(n)        (defkeys[n].string)
  94. X#define DTSYM(n)        (defkeys[n].symbol)
  95. X
  96. LOCAL struct {                 /* Function key table                   */
  97. X  char *string;                 /*   Termcap name                       */
  98. X  ksym symbol;                  /*   Key symbol known by utree          */
  99. X  char *name;                   /*   Key name                           */
  100. X} funkeys[] = {
  101. X  { "ku", K_PREV, "CursorUp-Key"        },
  102. X  { "kd", K_NEXT, "CursorDown-Key"      },
  103. X  { "kl", K_BACK, "CursorBackward-Key"  },
  104. X  { "kr", K_FORW, "CursorForward-Key"   },
  105. X  { "kh", K_HOME, "Home-Key"            },
  106. X#ifdef  XENIX   /* RG 11/22/91 */
  107. X  { "HM", K_HOME, "Begin-Key"           },
  108. X  { "EN", K_END,  "End-Key"             },
  109. X  { "PD", K_NPAG, "NextPage-Key"        },
  110. X  { "PU", K_PPAG, "PrevPage-Key"        },
  111. X#else   /* !XENIX */
  112. X  { "@1", K_HOME, "Begin-Key"           },
  113. X  { "@7", K_END,  "End-Key"             },
  114. X  { "kN", K_NPAG, "NextPage-Key"        },
  115. X  { "kP", K_PPAG, "PrevPage-Key"        },
  116. X#endif  /* XENIX */
  117. X  { "kR", K_UP,   "ScrollUp-Key"        },
  118. X  { "kF", K_DOWN, "ScrollDown-Key"      },
  119. X  { "kI", K_INS,  "Insert-Key"          },
  120. X  { "kD", K_DOWN, "Delete-Key"          },
  121. X  { "kC", K_REFR, "Clear-Key"           },
  122. X  { "%1", K_HELP, "Help-Key"            },
  123. X  { "*6", K_SEL,  "Select-Key"          },
  124. X  { "@4", K_SEL,  "Do/Command-Key"      },
  125. X  { "%2", K_MARK, "Mark-Key"            },
  126. X  { "@8", K_SEL,  "Enter-Key"           },
  127. X  { NULL, K_INV,  NULL   },     /*   End function key table             */
  128. X};
  129. X
  130. X#define FTSTR(n)        (funkeys[n].string)
  131. X#define FTSYM(n)        (funkeys[n].symbol)
  132. X#define FTNAM(n)        (funkeys[n].name)
  133. X
  134. X#define KEYLEN 32               /* Max length of key strings            */
  135. X#define KCOL   12
  136. X#define EOL(c)          (c==' ' || c=='\t' || c=='#' || c=='\n' || c=='\0')
  137. X
  138. LOCAL int klchg = 0;            /* Changes in key bindings list         */
  139. LOCAL char *unknown = "UNKNOWN";
  140. X
  141. X/* ---- External variables and functions ------------------------------ */
  142. X
  143. XEXTRN char *tgetstr();
  144. XEXTRN char *getversion();
  145. XEXTRN char *strclean();
  146. X
  147. X/* ---- Functions and procedures -------------------------------------- */
  148. X
  149. X/*
  150. X *      INTERNAL USED ROUTINES
  151. X */
  152. X
  153. X/* Insert keybinding from string str to symbol sym into binding list */
  154. LOCAL int insertbinding(str, sym, nam, ins, usr)
  155. X  register kchar *str;
  156. X  register ksym sym;
  157. X  register char *nam, *ins;
  158. X  register int usr;
  159. X{
  160. X  register klist *kp, *pp, *p;
  161. X
  162. X  if(str == UNULL)
  163. X    return(0);
  164. X
  165. X  /* Search for string in key binding list */
  166. X  for(kp = kroot; kp; kp = (klist *) KBNXT(kp))
  167. X    if(EQU(str, KBSTR(kp)))
  168. X      break;
  169. X
  170. X  /* Replace an existing key binding */
  171. X  if(kp)  {
  172. X    if(KBSYM(kp) == K_STR && KBINS(kp))
  173. X      ufree(KBINS(kp));
  174. X    if(sym == K_STR && ins)
  175. X      KBINS(kp) = strsav(ins);
  176. X    else
  177. X      KBINS(kp) = NULL;
  178. X    KBSYM(kp) = sym;
  179. X    KBUSR(kp) = usr;
  180. X    return(1);
  181. X  }
  182. X
  183. X  /* Create a new binding */
  184. X  kp = (klist *) ualloc(1, sizeof(klist));
  185. X  KBSTR(kp) = (kchar *) strsav((char *) str);
  186. X  KBINS(kp) = sym == K_STR && ins ? strsav(ins) : NULL;
  187. X  KBNAM(kp) = nam ? strsav(nam) : NULL;
  188. X  KBSYM(kp) = sym;
  189. X  KBUSR(kp) = usr;
  190. X
  191. X  /* Insert the binding into key binding list in reverse lexical order */
  192. X  if(kroot && CMP(str, KBSTR(kroot)) < 0) {
  193. X    for(pp = kroot; KBNXT(pp); pp = (klist *) KBNXT(pp)) {
  194. X      p = (klist *) KBNXT(pp);
  195. X      if(CMP((char *) str, KBSTR(p)) > 0)
  196. X       break;
  197. X    }
  198. X    KBPRV(kp) = (glist *) pp;
  199. X    KBNXT(kp) = KBNXT(pp);
  200. X    if(p = (klist *) KBNXT(pp))
  201. X      KBPRV(p) = (glist *) kp;
  202. X    KBNXT(pp) = (glist *) kp;
  203. X  }
  204. X  else {
  205. X    if(kroot)
  206. X      KBPRV(kroot) = (glist *) kp;
  207. X    KBPRV(kp) = GNULL;
  208. X    KBNXT(kp) = (glist *) kroot;
  209. X    kroot = kp;
  210. X  }
  211. X  return(1);
  212. X
  213. X} /* insertbinding() */
  214. X
  215. X/* Compare key name and return symbol */
  216. LOCAL ksym getkeysymbol(s)
  217. X  register char *s;
  218. X{
  219. X  register int i;
  220. X
  221. X  if(*s == '\"') {              /* Bind key to string to insert */
  222. X    *s++ = '\0';
  223. X    while(*s && *s != '\"')
  224. X      ++s;
  225. X    if(*s == '\"') {
  226. X      *s = '\0';
  227. X      return(K_STR);
  228. X    }
  229. X  }
  230. X  else {                        /* Bind key to utree key */
  231. X    strupper(s);
  232. X    for(i = 0; KNNAM(i); i++)
  233. X      if(EQU(s, KNNAM(i)))
  234. X       return(KNSYM(i));
  235. X  }
  236. X  return(K_INV);
  237. X
  238. X} /* getkeysymbol() */
  239. X
  240. X/* Create a key string from ascii string s */
  241. LOCAL kchar *getkeystring(s)
  242. X  register char *s;
  243. X{
  244. X  static kchar st[KEYLEN+2];
  245. X  register int i, o;
  246. X
  247. X  for(i = 0; !EOL(*s) && i < KEYLEN; i++) {
  248. X    if(*s == '\\') {
  249. X      ++s;
  250. X      if(EOL(*s))
  251. X       return(UNULL);
  252. X      switch(*s) {
  253. X       default:                /* As it is */
  254. X         st[i] = *s;
  255. X         break;
  256. X       case 'e':               /* Escape */
  257. X       case 'E':
  258. X         st[i] = 0x1b;
  259. X         break;
  260. X       case 'n':               /* Newline */
  261. X         st[i] = '\n';
  262. X         break;
  263. X       case 'r':               /* Carriage return */
  264. X         st[i] = '\r';
  265. X         break;
  266. X       case 't':               /* Tab */
  267. X         st[i] = '\t';
  268. X         break;
  269. X       case 's':               /* Space */
  270. X         st[i] = ' ';
  271. X         break;
  272. X       case 'f':               /* Formfeed */
  273. X         st[i] = '\f';
  274. X         break;
  275. X       case 'b':               /* Backspace */
  276. X         st[i] = '\b';
  277. X         break;
  278. X       case '0':               /* Octal given value */
  279. X       case '1':
  280. X       case '2':
  281. X       case '3':
  282. X       case '4':
  283. X       case '5':
  284. X       case '6':
  285. X       case '7':
  286. X         o = 0;
  287. X         do {
  288. X           if(o < 0377) {
  289. X             o <<= 3;
  290. X             o |= *s - '0';
  291. X           }
  292. X           ++s;
  293. X         } while(*s && *s >= '0' && *s <= '7');
  294. X         st[i] = (kchar) o;
  295. X         break;
  296. X      }
  297. X    }
  298. X    else if(*s == '^') {
  299. X      ++s;
  300. X      if(EOL(*s))
  301. X       return(UNULL);
  302. X      if(*s == '?')                     /* DEL */
  303. X       st[i] = 0x7f;
  304. X      else if(*s == '@')                /* NUL */
  305. X       st[i] = 0x80;
  306. X      else if(*s >= 'A' && *s <= '_')   /* SOH .. US */
  307. X       st[i] = *s - '@';
  308. X      else if(*s >= 'a' && *s <= 'z')   /* SOH .. SUB */
  309. X       st[i] = *s - '`';
  310. X      else
  311. X       return(UNULL);
  312. X    }
  313. X    else
  314. X      st[i] = *s;
  315. X    if(*s)
  316. X      ++s;
  317. X  }
  318. X  st[i] = '\0';
  319. X
  320. X  return(i > 0 ? st : UNULL);
  321. X
  322. X} /* getkeystring() */
  323. X
  324. X/* Get and return ascii readable string from key string s */
  325. LOCAL char *keystring(s, buf)
  326. X  register kchar *s;
  327. X  register char *buf;
  328. X
  329. X{
  330. X  if(*s == '\0')
  331. X    return("INVALID");
  332. X  *buf = '\0';
  333. X  while(*s) {
  334. X    switch(*s) {
  335. X      case 0x80:                /* Terminfo: ASCII-NUL */
  336. X       (void) strcat(buf, "^@");
  337. X       break;
  338. X      case 0x1b:                /* ESC */
  339. X       (void) strcat(buf, "\\e");
  340. X       break;
  341. X      case '\b':                /* BS */
  342. X       (void) strcat(buf, "\\b");
  343. X       break;
  344. X      case 0x7f:                /* DEL */
  345. X       (void) strcat(buf, "^?");
  346. X       break;
  347. X      case ' ':                 /* SP */
  348. X       (void) strcat(buf, "\\s");
  349. X       break;
  350. X      case '\n':                /* NL */
  351. X       (void) strcat(buf, "\\n");
  352. X       break;
  353. X      case '\r':                /* CR */
  354. X       (void) strcat(buf, "\\r");
  355. X       break;
  356. X      case '\t':                /* TAB */
  357. X       (void) strcat(buf, "\\t");
  358. X       break;
  359. X      case '\f':                /* FF */
  360. X       (void) strcat(buf, "\\f");
  361. X       break;
  362. X      default:                  /* Others */
  363. X       if(*s < ' ')            /* Control character */
  364. X         (void) sprintf(buf, "%s^%c", buf, *s + '@');
  365. X       else if(*s > 0x80)      /* Most significant bit set */
  366. X         (void) sprintf(buf, "%s\\%03o", buf, *s);
  367. X       else                    /* Printable character */
  368. X         (void) sprintf(buf, "%s%c", buf, *s);
  369. X       break;
  370. X    }
  371. X    ++s;
  372. X  }
  373. X  return(buf);
  374. X
  375. X} /* keystring() */
  376. X
  377. X/* Get and return name of symbol k */
  378. LOCAL char *keysymbol(k)
  379. X  register ksym k;
  380. X{
  381. X  register int i;
  382. X
  383. X  for(i = 0; KNNAM(i); i++)
  384. X    if(KNSYM(i) == k)
  385. X      return(KNNAM(i));
  386. X  return(unknown);
  387. X
  388. X} /* keysymbol() */
  389. X
  390. X/* Get and return meaning of symbol k */
  391. LOCAL char *keymeaning(k)
  392. X  register ksym k;
  393. X{
  394. X  register int i;
  395. X
  396. X  for(i = 0; KNNAM(i); i++)
  397. X    if(KNSYM(i) == k)
  398. X      return(KNCOM(i));
  399. X  return(unknown);
  400. X
  401. X} /* keymeaning() */
  402. X
  403. X/* Show all key bindings */
  404. LOCAL int showbindings()
  405. X{
  406. X  char str[INPLEN];
  407. X  register klist *kp;
  408. X  register char *ks;
  409. X  register int l, c, kl;
  410. X
  411. X  l = firstline;
  412. X  c = RV_OK;
  413. X  clearwindow(firstline, lastline);
  414. X  for(kp = kroot; KBNXT(kp); kp = (klist *) KBNXT(kp))
  415. X    ;
  416. X  for(l = firstline; kp; kp = (klist *) KBPRV(kp)) {
  417. X    ks = keystring(KBSTR(kp), str);
  418. X    kl = strlen(ks);
  419. X    if(KBSYM(kp) == K_STR && KBINS(kp))
  420. X      c = putfxy(kl < KCOL ? KCOL-kl : 0,  l, 0, "%s=\"%s\"", ks, KBINS(kp));
  421. X    else
  422. X      c = putfxy(kl < KCOL ? KCOL-kl : 0,  l, 0, "%s=%s", ks, keysymbol(KBSYM(kp)));
  423. X    if(KBNAM(kp))
  424. X      (void) putfxy(c > columns/2 ? c : columns/2, l, 0, "#%s", KBNAM(kp));
  425. X    else
  426. X      (void) putfxy(c > columns/2 ? c : columns/2, l, 0, "#%s", keymeaning(KBSYM(kp)));
  427. X    if(++l > lastline && KBNXT(kp)) {
  428. X      puthelp("%s (CR:continue  ELSE:quit)", who);
  429. X      c = hitakey("More key bindings ?", echoline, DA_NONE);
  430. X      if( !(c == ' ' || c == '\n'))
  431. X       return(c);
  432. X      clearwindow(firstline, lastline);
  433. X      l = firstline;
  434. X    }
  435. X  }
  436. X  return(c);
  437. X
  438. X} /* showbindings() */
  439. X
  440. X/* Insert a key binding from a startup file line s. Ingore errors */
  441. LOCAL int setbinding(s)
  442. X  register char *s;
  443. X{
  444. X  register char *sp, *cp, *ep;
  445. X  register kchar *str;
  446. X  register ksym sym;
  447. X
  448. X  /* First scan and clean keystring and keyname/string to insert */
  449. X  if((sp = strchr(s, '=')) == NULL)
  450. X    return(0);
  451. X  *sp++ = '\0';
  452. X  s = strclean(s);
  453. X
  454. X  /* Get additional comment and clean binding/comment */
  455. X  if(cp = strchr(sp, '#')) {
  456. X    *cp++ = '\0';
  457. X    cp = strclean(cp);
  458. X  }
  459. X  sp = strclean(sp);
  460. X
  461. X  /* Get key string from s and key symbol from sp */
  462. X  if((str = getkeystring(s)) == UNULL || (sym = getkeysymbol(sp)) == K_INV)
  463. X    return(1);
  464. X  return(insertbinding(str, sym, cp && *cp ? cp : NULL, sym == K_STR ? ++sp : NULL, 1));
  465. X
  466. X} /* setbinding() */
  467. X
  468. X/*
  469. X *      KEY BINDING ROUTINES
  470. X */
  471. X
  472. X/* Initialize key bindings */
  473. GLOBL VOID initbindings(term, cp)
  474. X  register char *term, **cp;
  475. X{
  476. X  char buf[NAMELEN], bind[NAMELEN];
  477. X  register FILE *fp;
  478. X  register kchar *k;
  479. X  register int i;
  480. X
  481. X  /* First: Initialize and link keyname list */
  482. X  KNNXT(0) = KNLST(1);
  483. X  for(i = 1; KNNAM(i+1); i++) {
  484. X    KNNXT(i) = KNLST(i+1);
  485. X    KNPRV(i) = KNLST(i-1);
  486. X  }
  487. X  KNPRV(i) = KNLST(i-1);
  488. X
  489. X  /* Second: Get default keys and insert into list */
  490. X  for(i = 0; DTSTR(i); i++)
  491. X    (void) insertbinding(DTSTR(i), DTSYM(i), NULL, NULL, 0);
  492. X
  493. X  /* Third: Get default function keys from database and insert into list */
  494. X  for(i = 0; FTSTR(i) ; i++)
  495. X    if(k = (kchar *) tgetstr(FTSTR(i), cp))
  496. X      (void) insertbinding(k, FTSYM(i), FTNAM(i), NULL, 0);
  497. X
  498. X#ifdef  UTSTART
  499. X  /* Last: Get global or user defined key bindings and insert into list */
  500. X  (void) sprintf(bind, "%s-%s", UTSTART, term);
  501. X  if(startup(buf, bind) && (fp = fopen(buf, "r"))) {
  502. X    while(fgets(buf, sizeof(buf), fp))
  503. X      if(VALID(buf[0]))
  504. X       (void) setbinding(buf);
  505. X    (void) fclose(fp);
  506. X  }
  507. X#endif  /* UTSTART */
  508. X
  509. X} /* initbindings() */
  510. X
  511. X/* Save user defined key bindings */
  512. GLOBL VOID savebindings(term)
  513. X  register char *term;
  514. X{
  515. X#ifdef  UTSTART
  516. X  char buf[NAMELEN];
  517. X  register klist *kp;
  518. X  register FILE *fp;
  519. X  time_t t;
  520. X
  521. X  if(VARVAL(V_AS) && klchg) {
  522. X    (void) sprintf(buf, ".%s-%s", UTSTART, term);
  523. X    (void) strcpy(buf, pathname(buf, home));
  524. X    if(fp = fopen(buf, "w")) {
  525. X      t = time((time_t *) 0);
  526. X      (void) fprintf(fp, "# %s: ~/.%s-%s, %s", getversion(), UTSTART, term, ctime(&t));
  527. X      for(kp = kroot; kp; kp = (klist *) KBNXT(kp))
  528. X       if(KBUSR(kp)) {
  529. X         (void) fprintf(fp, "%s=", keystring(KBSTR(kp), buf));
  530. X         if(KBSYM(kp) == K_STR && KBINS(kp))
  531. X           (void) fprintf(fp, "\"%s\"", KBINS(kp));
  532. X         else
  533. X           (void) fprintf(fp, "%s", keysymbol(KBSYM(kp)));
  534. X         if(KBNAM(kp))
  535. X           (void) fprintf(fp, "\t#%s\n", KBNAM(kp));
  536. X         else
  537. X           (void) fprintf(fp, "\n");
  538. X       }
  539. X      (void) fclose(fp);
  540. X    }
  541. X  }
  542. X#endif  /* UTSTART */
  543. X
  544. X} /* savebindings() */
  545. X
  546. X/* Show all key bindings */
  547. GLOBL int bindings()
  548. X{
  549. X  char buf[INPLEN], key[KEYLEN], com[INPLEN], k[2];
  550. X  register klist *kp;
  551. X  register char *kb;
  552. X  register int c, f;
  553. X
  554. X  who = "KEY BINDINGS";
  555. X  /* Key bindings loop */
  556. X  f = 1;
  557. X  while(1) {
  558. X    if(f && ((c = showbindings())  < RV_NUL || c == 'q'))
  559. X      break;
  560. X    buf[0] = com[0] = k[1] = '\0';
  561. X    /* Get key sequence terminated with CR */
  562. X    puthelp("%s: Enter key to bind (NO EDIT! CR:quit)", who);
  563. X    (void) putecho("Bind:");
  564. X    cursorset(CF_VISIBLE);
  565. X    k[0] = getchar();
  566. X    if(k[0] == '\n' || k[0] == '\r')
  567. X      break;
  568. X    else if(k[0] == '\0')
  569. X      k[0] = '\200';
  570. X    (void) strcat(buf, keystring(k ,key));
  571. X    puthelp("%s: Enter key to bind (NO EDIT! CR:terminate string)", who);
  572. X    while(1){
  573. X      (void) putecho("Bind: %s", buf);
  574. X      k[0] = getchar();
  575. X      if(k[0] == '\n' || k[0] == '\r')
  576. X       break;
  577. X      else if(k[0] == '\0')
  578. X       k[0] = '\200';
  579. X      (void) strcat(buf, keystring(k ,key));
  580. X    }
  581. X    /* Get utree key to bind to */
  582. X    for(kp = kroot; kp; kp = (klist *) KBNXT(kp))
  583. X      if(EQU(KBSTR(kp), getkeystring(buf)))
  584. X       break;
  585. X    if(kp) {
  586. X      if(KBSYM(kp) == K_STR && KBINS(kp)) {
  587. X       (void) sprintf(key, "\"%s\"", KBINS(kp));
  588. X       kb = key;
  589. X      }
  590. X      else
  591. X       kb = keysymbol(KBSYM(kp));
  592. X    }
  593. X    else
  594. X      kb = NULL;
  595. X    puthelp("%s: Give utree keyname for binding (CR:quit)", who);
  596. X    c = putecho("Bind %s to:", buf);
  597. X    if((c = getline(key, sizeof(key), c, 'k', kb, KNLST(0), 1)) <= RV_NUL)
  598. X      break;
  599. X    /* Get additional comment */
  600. X    (void) sprintf(buf, "%s=%s", buf, key);
  601. X    if(getkeysymbol(key) != K_INV) {
  602. X      puthelp("%s: Give comment for binding", who);
  603. X      c = putecho("Comment for key binding:");
  604. X      if((c = getline(com, sizeof(com), c, 0, NULL, GNULL, 0)) < RV_NUL)
  605. X       break;
  606. X      if(com[0])
  607. X       (void) sprintf(buf, "%s #%s", buf, com);
  608. X      /* Do the binding */
  609. X      if(setbinding(buf)) {
  610. X       f = 1;
  611. X       klchg = 1;
  612. X       continue;
  613. X      }
  614. X    }
  615. X    f = 0;
  616. X    puthelp("%s %s", who, hitkey);
  617. X    if((c = errequest(buf, "Error in setting")) < RV_NUL)
  618. X      break;
  619. X  }
  620. X
  621. X  cursorset(CF_INVISIBLE);
  622. X  treeflag = fileflag = SF_FULL;
  623. X  return(c);
  624. X
  625. X} /* bindings() */
  626. X
  627. END_OF_FILE
  628. if test 17641 -ne `wc -c <'src/bind.c'`; then
  629.     echo shar: \"'src/bind.c'\" unpacked with wrong size!
  630. fi
  631. # end of 'src/bind.c'
  632. fi
  633. if test -f 'src/comm.c' -a "${1}" != "-c" ; then 
  634.   echo shar: Will not clobber existing file \"'src/comm.c'\"
  635. else
  636. echo shar: Extracting \"'src/comm.c'\" \(16221 characters\)
  637. sed "s/^X//" >'src/comm.c' <<'END_OF_FILE'
  638. X/*
  639. X *      COMM.C
  640. X *      UTREE common tree and file commands.
  641. X *      3.01-um klin, Tue Jun  4 14:16:30 1991
  642. X *              klin, Mon Oct  7 15:16:22 1991, File size patterns added
  643. X *              klin, Sat Oct 26 15:07:06 1991, Sorting and zooming filelists changed
  644. X *      3.02-um klin, Fri Nov  1 13:42:28 1991, Minor changes
  645. X *              klin, Sun Nov 24 19:30:43 1991, Cd to current directory before
  646. X *                                              executing some commands
  647. X *      3.03-um klin, Tue Feb 11 19:40:06 1992, Status screen into stat.c
  648. X *                                              getline() changed
  649. X *
  650. X *      Copyright (c) 1991/92 by Peter Klingebiel & UNIX Magazin Muenchen.
  651. X *      For copying and distribution information see the file COPYRIGHT.
  652. X */
  653. X#ifndef lint
  654. static char sccsid[] = "@(#) utree 3.03-um (klin) Feb 11 1992 comm.c";
  655. X#endif  /* !lint */
  656. X
  657. X#include "defs.h"
  658. X
  659. X/* ---- Local variables and definitions ------------------------------- */
  660. X
  661. X#define CCOLUMN -8              /* Column for clock                     */
  662. X
  663. X/* Tokens for file pattern and time pattern matching                    */
  664. X#define TK_ERR  'F'             /* Error                                */
  665. X#define TK_END  'E'             /* End of pattern                       */
  666. X#define TK_WORD 'W'             /* Word or file pattern matching        */
  667. X#define TK_OR   '|'             /* ORing patterns                       */
  668. X#define TK_AND  '&'             /* ANDing pattern                       */
  669. X#define TK_SEQ  '='             /* Filesize equate                      */
  670. X#define TK_SNE  '!'             /* Filesize unequate                    */
  671. X#define TK_SGT  '>'             /* Filesize bigger                      */
  672. X#define TK_SLT  '<'             /* Filesize smaller                     */
  673. X#define TK_MNE  ')'             /* File     modified within (newer)     */
  674. X#define TK_MOL  '('             /* File not modified within (older)     */
  675. X
  676. X/* States from token()                                                  */
  677. X#define ST_NORM 0               /* Normal state                         */
  678. X#define ST_WORD 1               /* In word                              */
  679. X#define ST_QUOT 2               /* In quotes                            */
  680. X#define ST_BRCK 3               /* In brackets                          */
  681. X
  682. LOCAL int patpos;               /* Current position in pattern          */
  683. LOCAL char patbuf[PATLEN];      /* Pattern buffer for internal use      */
  684. X
  685. X/* ---- External variables and functions ------------------------------ */
  686. X
  687. XEXTRN struct tm *localtime();
  688. X
  689. X/* ---- Functions and procedures -------------------------------------- */
  690. X
  691. X/*
  692. X *      COMMON COMMANDS
  693. X */
  694. X
  695. X/* Display current date and time in echo line */
  696. GLOBL int printdate()
  697. X{
  698. X  time_t tloc;
  699. X
  700. X  tloc = time((time_t *) 0);
  701. X  puthelp("DATE: Current date and time %s", hitkey);
  702. X  (void) putecho("%s", ctime(&tloc));
  703. X  return(hitakey(NULL));
  704. X
  705. X} /* printdate() */
  706. X
  707. X/* Display current directory in echo line */
  708. GLOBL int printcwd()
  709. X{
  710. X  puthelp("WHERE: Pathname of current directory %s", hitkey);
  711. X  (void) putecho("%s", CPNAM);
  712. X  return(hitakey(NULL));
  713. X
  714. X} /* printcwd() */
  715. X
  716. X/*
  717. X *      CLOCK ROUTINES
  718. X */
  719. X
  720. X#ifdef  UTCLOCK
  721. X/* Turn on clock in echo line, update every second */
  722. GLOBL VOID clockon()
  723. X{
  724. X  time_t tloc;
  725. X  register struct tm *tm;
  726. X
  727. X  /* Get and display current time in echo line */
  728. X  tloc = time((time_t *) 0);
  729. X  tm   = localtime(&tloc);
  730. X  if(cursorcap & CF_SAVE);
  731. X    cursorset(CF_SAVE);
  732. X  (void) putfxy(CCOLUMN, echoline, 0, "%02d:%02d:%02d",
  733. X               tm->tm_hour, tm->tm_min, tm->tm_sec);
  734. X  if(cursorcap & CF_RESTORE);
  735. X    cursorset(CF_RESTORE);
  736. X  flushout();
  737. X  /* Set alarm for the next second and catch signal SIGALRM */
  738. X  (void) alarm(1);
  739. X  (void) signal(SIGALRM, clockon);
  740. X
  741. X} /* clockon() */
  742. X
  743. X/* Turn off clock in echo line */
  744. GLOBL VOID clockoff()
  745. X{
  746. X  (void) alarm(0);              /* Suppress alarm */
  747. X
  748. X} /* clockoff() */
  749. X#endif  /* UTCLOCK */
  750. X
  751. X/*
  752. X *      FILE AND TIME STAMP PATTERN MATCHING ROUTINES
  753. X */
  754. X
  755. X/* Get and return next token. If a word is found copy it to wp */
  756. LOCAL int token(wp)
  757. X  register char *wp;
  758. X{
  759. X  register int s;
  760. X  register char c, *w;
  761. X
  762. X  s = ST_NORM;
  763. X  w = wp;
  764. X  /* Get token loop */
  765. X  while(1) {
  766. X    c = patbuf[patpos++];
  767. X    switch(s) {
  768. X      case ST_NORM:             /* Normal state */
  769. X       switch(c) {
  770. X         case '\n':
  771. X         case '\r':
  772. X         case '\0':
  773. X           c = TK_END;
  774. X           /*Fall thru*/
  775. X         case TK_END:
  776. X         case TK_AND:
  777. X         case TK_OR:
  778. X         case TK_SEQ:
  779. X         case TK_SNE:
  780. X         case TK_SGT:
  781. X         case TK_SLT:
  782. X         case TK_MNE:
  783. X         case TK_MOL:
  784. X           return(c);
  785. X         case ' ':
  786. X         case '\t':
  787. X           continue;
  788. X         case '"':
  789. X         case '\'':
  790. X           s = ST_QUOT;
  791. X           continue;
  792. X         case '[':
  793. X           s = ST_BRCK;
  794. X           *w++ = c;
  795. X           continue;
  796. X         case '\\':
  797. X           if((c = patbuf[patpos++]) == '\0')
  798. X             return(TK_ERR);
  799. X           /*Fall thru*/
  800. X         default:
  801. X           s = ST_WORD;
  802. X           *w++ = c;
  803. X           continue;
  804. X       }
  805. X      case ST_BRCK:             /* In brackets */
  806. X       switch(c) {
  807. X         case '\n':
  808. X         case '\r':
  809. X         case '\0':
  810. X           return(TK_ERR);
  811. X         case ']':
  812. X           s = ST_WORD;
  813. X           /*Fall thru*/
  814. X         default:
  815. X           *w++ = c;
  816. X           continue;
  817. X       }
  818. X      case ST_QUOT:             /* In quotes */
  819. X       switch(c) {
  820. X         case '"':
  821. X         case '\'':
  822. X           *w = '\0';
  823. X           return(TK_WORD);
  824. X         case '\\':
  825. X           if((c = patbuf[patpos++]) == '\0')
  826. X             return(TK_ERR);
  827. X           /*Fall thru*/
  828. X         default:
  829. X           *w++ = c;
  830. X           continue;
  831. X       }
  832. X      case ST_WORD:             /* In word */
  833. X       switch(c) {
  834. X         case TK_AND:
  835. X         case TK_OR:
  836. X         case TK_SEQ:
  837. X         case TK_SNE:
  838. X         case TK_SGT:
  839. X         case TK_SLT:
  840. X         case TK_MNE:
  841. X         case TK_MOL:
  842. X         case '\n':
  843. X         case ' ':
  844. X         case '\t':
  845. X         case '\0':
  846. X           --patpos;
  847. X           *w = '\0';
  848. X           return(TK_WORD);
  849. X         case '[':
  850. X           s = ST_BRCK;
  851. X           *w++ = c;
  852. X           continue;
  853. X         case '\\':
  854. X           if((c = patbuf[patpos++]) == '\0')
  855. X             return(TK_ERR);
  856. X           /*Fall thru*/
  857. X         default:
  858. X           *w++ = c;
  859. X           continue;
  860. X       }
  861. X    }
  862. X  }
  863. X  /*NOT REACHED*/
  864. X
  865. X} /* token() */
  866. X
  867. X/* Token parsing and file/size/time pattern matching */
  868. LOCAL int imatch(dp, f)
  869. X  register dlist *dp;
  870. X  register int f;
  871. X{
  872. X  static int lt;
  873. X  char w[PATLEN];
  874. X  register time_t ct;
  875. X  register off_t fs;
  876. X  register int t, i;
  877. X
  878. X  /* Inner matching loop */
  879. X  while(1) {
  880. X    switch(t = token(w)) {      /* Get next token */
  881. X      default:                  /* Unknown */
  882. X       t = TK_ERR;
  883. X       /*Fall thru*/
  884. X      case TK_ERR:              /* Return as it is */
  885. X       return(t);
  886. X      case TK_END:              /* End of pattern */
  887. X      case TK_OR:               /* ORing patterns */
  888. X      case TK_AND:              /* ANDing patterns */
  889. X       if(lt != TK_WORD)
  890. X         return(TK_ERR);
  891. X       return(lt = t);
  892. X      case TK_WORD:             /* File pattern matching */
  893. X       lt = t;
  894. X       if(dp)
  895. X         return(match(FFNAM(dp, f), w));
  896. X       return(1);
  897. X      case TK_SEQ:              /* Filesize equate   */
  898. X      case TK_SNE:              /* Filesize unequate */
  899. X      case TK_SGT:              /* Filesize bigger   */
  900. X      case TK_SLT:              /* Filesize smaller  */
  901. X       if((lt = token(w)) != TK_WORD || !isdigit(w[0]))
  902. X         return(TK_ERR);
  903. X       fs = (off_t) 0;
  904. X       for(i = 0; w[i] && isdigit(w[i]); i++)
  905. X         fs = fs * (off_t) 10 + (off_t) (w[i] - '0');
  906. X       switch(w[i]) {
  907. X         default:              /* Error */
  908. X           return(TK_ERR);
  909. X         case 'm':             /* Megabytes */
  910. X           fs *= (off_t) 1024;
  911. X           /*Fall thru*/
  912. X         case 'k':             /* Kilobytes */
  913. X           fs *= (off_t) 1024;
  914. X           /*Fall thru*/
  915. X         case 'b':             /* Bytes (default) */
  916. X         case '\0':
  917. X           break;
  918. X       }
  919. X       if(dp) {
  920. X         switch(t) {
  921. X           case TK_SEQ:
  922. X             return(FSIZE(dp,f ) == fs);
  923. X           case TK_SNE:
  924. X             return(FSIZE(dp, f) != fs);
  925. X           case TK_SGT:
  926. X             return(FSIZE(dp, f)  > fs);
  927. X           case TK_SLT:
  928. X             return(FSIZE(dp,f )  < fs);
  929. X         }
  930. X       }
  931. X       return(1);
  932. X      case TK_MNE:              /* Modified within     days/hours/minutes */
  933. X      case TK_MOL:              /* Not modified within days/hours/minutes */
  934. X       if((lt = token(w)) != TK_WORD || !isdigit(w[0]))
  935. X         return(TK_ERR);
  936. X       ct = (time_t) 0;
  937. X       for(i = 0; w[i] && isdigit(w[i]); i++)
  938. X         ct = ct * (time_t) 10 + (time_t) (w[i] - '0');
  939. X       switch(w[i]) {
  940. X         default:              /* Error */
  941. X           return(TK_ERR);
  942. X         case 'w':             /* Weeks */
  943. X           ct *= (time_t) 7;
  944. X           /*Fall thru*/
  945. X         case 'd':             /* Days */
  946. X           ct *= (time_t) 24;
  947. X           /*Fall thru*/
  948. X         case 'h':             /* Hours (default) */
  949. X         case '\0':
  950. X           ct *= (time_t) 60;
  951. X           /*Fall thru*/
  952. X         case 'm':             /* Minutes */
  953. X           ct *= (time_t) 60;
  954. X           break;
  955. X       }
  956. X       if(ct == (time_t) 0)
  957. X         return(TK_ERR);
  958. X       else if(dp) {
  959. X         ct = time((time_t *) 0) - ct;
  960. X         return(t == TK_MNE ? FMTIM(dp, f) > ct : FMTIM(dp, f) <= ct);
  961. X       }
  962. X       return(1);
  963. X    }
  964. X  }
  965. X  /*NOT REACHED*/
  966. X
  967. X} /* imatch() */
  968. X
  969. X/* Do/combine file/size/time pattern matching */
  970. GLOBL int umatch(dp, f, p)
  971. X  register dlist *dp;
  972. X  register int f;
  973. X  register char *p;
  974. X{
  975. X  register int rv;
  976. X
  977. X  (void) strcpy(patbuf, p);
  978. X  patpos = 0;
  979. X  rv = -1;
  980. X  /* Outer matching loop */
  981. X  while(1) {
  982. X    switch(imatch(dp, f)) {
  983. X      case TK_END:              /* End */
  984. X       return(rv <= 0 ? 0 : 1);
  985. X      case 1:                   /* Match */
  986. X       rv = 1;
  987. X       break;
  988. X      case 0:                   /* No match */
  989. X       rv = 0;
  990. X       break;
  991. X      case TK_OR:               /* ORing */
  992. X       if(rv < 0)
  993. X         return(rv);
  994. X       else
  995. X         rv = (rv || imatch(dp, f) == 1) ? 1 : 0;
  996. X       if(dp && rv)
  997. X         return(rv);
  998. X       break;
  999. X      case TK_AND:              /* ANDing */
  1000. X       if(rv < 0)
  1001. X         return(rv);
  1002. X       else
  1003. X         rv = (rv && imatch(dp, f) == 1) ? 1 : 0;
  1004. X       if(dp && rv == 0)
  1005. X         return(rv);
  1006. X       break;
  1007. X      default:
  1008. X      case TK_ERR:
  1009. X       return(-1);
  1010. X    }
  1011. X  }
  1012. X  /*NOT REACHED*/
  1013. X
  1014. X} /* umatch() */
  1015. X
  1016. X/* Get file/size/time pattern and test it */
  1017. GLOBL int getpattern(p, m)
  1018. X  register char *p, *m;
  1019. X{
  1020. X  register int c;
  1021. X
  1022. X  /* Get/test pattern loop */
  1023. X  while(1) {
  1024. X    c = putecho(m);
  1025. X    c = getline(p, PATLEN, c, 'p', NULL, GNULL, 0);
  1026. X    if(c == RV_OK && umatch(DNULL, 0, p) < 0)
  1027. X      if((c = errequest(p, "Bad file pattern")) >= RV_NUL)
  1028. X       continue;
  1029. X    break;
  1030. X  }
  1031. X  return(c);
  1032. X
  1033. X} /* getpattern() */
  1034. X
  1035. X/*
  1036. X *      COMMON DIRECTORY AND FILE ROUTINES
  1037. X */
  1038. X
  1039. X/* Change current working directory to directory list entry dp */
  1040. GLOBL int changelist(dp, who)
  1041. X  register dlist *dp;
  1042. X{
  1043. X  if(cwlist == dp)                  /* Is already cwd */
  1044. X    return(RV_OK);
  1045. X  else if(DCANC(dp) && chdir(DPNAM(dp)) == 0) {
  1046. X    cwlist = dp;
  1047. X    return(RV_OK);
  1048. X  }
  1049. X  else if(who) {
  1050. X    puthelp("%s: %s %s", who, CFNAM, hitkey);
  1051. X    return(errequest(CFNAM, "Cannot change"));
  1052. X  }
  1053. X  return(RV_NUL);
  1054. X
  1055. X} /* changelist() */
  1056. X
  1057. X/* Check if operation for file fn with mode m is allowed */
  1058. GLOBL int isallowed(fn, m)
  1059. X  register char *fn;
  1060. X  register int m;
  1061. X{
  1062. X#ifdef  S_IFLNK
  1063. X  struct stat st;
  1064. X#endif  /* S_IFLNK */
  1065. X  register char *err;
  1066. X
  1067. X  switch(m) {
  1068. X    default:                    /* Others */
  1069. X      return(1);
  1070. X#ifdef  S_IFLNK
  1071. X    case FF_SLNK:               /* Check symbolic link */
  1072. X      if( !ISDIR(fn, st))
  1073. X       return(1);
  1074. X      /* Fall thru */
  1075. X#endif  /* S_IFLNK */
  1076. X    case FF_DIR:                /* Is directory */
  1077. X      err = "Is a directory";
  1078. X      break;
  1079. X    case FF_ERR:                /* Error in stat */
  1080. X      err = "Cannot stat";
  1081. X      break;
  1082. X  }
  1083. X  setvideo(DA_ERROR);
  1084. X  (void) putecho("!! %s: %s", fn, err);
  1085. X  setvideo(DA_NORMAL);
  1086. X  return(0);
  1087. X
  1088. X} /* isallowed() */
  1089. X
  1090. X/* Set sort flag to f and sort/resort filelist */
  1091. GLOBL int sortlist(dp, f)
  1092. X  register dlist *dp;
  1093. X  register int f;
  1094. X{
  1095. X  register char *n;
  1096. X
  1097. X  if(DSORT(dp) != f) {
  1098. X    DSORT(dp) = f;
  1099. X    if(DNFIL(dp) > 0) {
  1100. X      n = FFNAM(dp, DFCUR(dp));
  1101. X      sortflist(dp);
  1102. X      DFTOP(dp) = DFCUR(dp) = 0;
  1103. X      while(*n != *FFNAM(dp, DFCUR(dp)) || CMP(n, FFNAM(dp, DFCUR(dp))))
  1104. X       (void) gofile(dp, 1);
  1105. X    }
  1106. X  }
  1107. X  return(DNFIL(dp) ? RV_OK : RV_NUL);
  1108. X
  1109. X} /* sortlist() */
  1110. X
  1111. X/* Rebuild file list with new zoom pattern pat */
  1112. GLOBL int zoomlist(dp, pat)
  1113. X  register dlist *dp;
  1114. X  register char *pat;
  1115. X{
  1116. X  register int n;
  1117. X
  1118. X  if(DZOOM(dp)) {               /* Free old pattern */
  1119. X    ufree(DZOOM(dp));
  1120. X    DZOOM(dp) = NULL;
  1121. X  }
  1122. X  if(pat && pat[0])             /* Save new pattern */
  1123. X    DZOOM(dp) = strsav(pat);
  1124. X
  1125. X  n = DNFIL(dp);
  1126. X  if(DFLAG(dp) != FL_NUL) {     /* Rebuild filelist */
  1127. X    (void) newflist(dp);
  1128. X    if(n != DNFIL(dp));
  1129. X      return(1);
  1130. X  }
  1131. X
  1132. X  return(0);
  1133. X
  1134. X} /* zoomlist() */
  1135. X
  1136. X/* Search for pattern in file f from directory dp */
  1137. GLOBL int grepfile(dp, f)
  1138. X  register dlist *dp;
  1139. X  register int f;
  1140. X{
  1141. X  char buf[EXECLEN];
  1142. X  register int rv;
  1143. X
  1144. X  (void) sprintf(buf, "%s %s \"%s\" %s",
  1145. X                GRFILE, GROPTS, gpattern, pathname(FFNAM(dp, f), DPNAM(dp)));
  1146. X  if((rv = callsystem(buf, 0, 0)) == RV_INT)
  1147. X    return(errequest("Grep", "Interrupted"));
  1148. X  return(rv);
  1149. X
  1150. X} /* grepfile() */
  1151. X
  1152. X/* Find file f in directory dp */
  1153. GLOBL int findfile(dp, f)
  1154. X  dlist *dp;
  1155. X  register int f;
  1156. X{
  1157. X
  1158. X  if(f < DNFIL(dp) && umatch(dp, f, fpattern))
  1159. X    return(RV_OK);
  1160. X  return(RV_NUL);
  1161. X
  1162. X} /* findfile() */
  1163. X
  1164. X/* Remove file f from directory dp */
  1165. GLOBL int removefile(dp, f, req)
  1166. X  register dlist *dp;
  1167. X  register int f, req;
  1168. X{
  1169. X  char name[NAMELEN], buf[EXECLEN];
  1170. X  register int c;
  1171. X
  1172. X  /* Check if file can be removed */
  1173. X  if( !isallowed(FFNAM(dp, f), (int) FMODE(dp, f)))
  1174. X    return(hitakey(NULL));
  1175. X
  1176. X  (void) strcpy(name, pathname(FFNAM(dp, f), DPNAM(dp)));
  1177. X  if(req) {
  1178. X    (void) putecho("Remove %s ?", FFNAM(dp, f));
  1179. X    if((c = hitakey(NULL)) != 'y')
  1180. X      return(c);
  1181. X  }
  1182. X  else {
  1183. X    (void) putecho("Removing %s", FFNAM(dp, f));
  1184. X    flushout();
  1185. X  }
  1186. X  (void) sprintf(buf, "%s %s", RMFILE, name);
  1187. X  if(callsystem(buf, 0, 0) != RV_OK)
  1188. X    return(errequest(FFNAM(dp, f), "Cannot remove"));
  1189. X
  1190. X  /* Preserve current file, delete flist and set flags */
  1191. X  if(f < DFCUR(dp))
  1192. X    (void) gofile(dp, -1);
  1193. X  deleteflist(dp, f);
  1194. X  ++buildflag;
  1195. X  DFLAG(dp) = FL_CHG;
  1196. X
  1197. X  return(RV_OK);
  1198. X
  1199. X} /* removefile() */
  1200. X
  1201. X/* Copy file f from directory dp to directory/file to */
  1202. GLOBL int copyfile(dp, f, to, req)
  1203. X  register dlist *dp;
  1204. X  register int f, req;
  1205. X  register char *to;
  1206. X{
  1207. X  char from[NAMELEN], buf[EXECLEN];
  1208. X  register int c;
  1209. X
  1210. X  /* Check if copying is allowed */
  1211. X  if( !isallowed(FFNAM(dp, f), (int) FMODE(dp, f)))
  1212. X    return(hitakey(NULL));
  1213. X
  1214. X  (void) strcpy(from, pathname(FFNAM(dp, f), CPNAM));
  1215. X  if(req) {
  1216. X    (void) putecho("Copy %s ?", FFNAM(dp, f));
  1217. X    if((c = hitakey(NULL)) != 'y')
  1218. X      return(c);
  1219. X  }
  1220. X
  1221. X  (void) putecho("Copying %s to %s", FFNAM(dp, f), to);
  1222. X  (void) sprintf(buf, "%s %s %s", CPFILE, from, to);
  1223. X  if(callsystem(buf, 0, 0) != RV_OK)
  1224. X    return(errequest(FFNAM(dp, f), "Error in copying"));
  1225. X
  1226. X  return(RV_OK);
  1227. X
  1228. X} /* copyfile() */
  1229. X
  1230. X/* Move file f from directory dp to directory/file to */
  1231. GLOBL int movefile(dp, f, to, req)
  1232. X  register dlist *dp;
  1233. X  register int f, req;
  1234. X  register char *to;
  1235. X{
  1236. X  char from[NAMELEN], buf[EXECLEN];
  1237. X  register int c;
  1238. X
  1239. X  /* Check if moving is allowed */
  1240. X  if( !isallowed(FFNAM(dp, f), (int) FMODE(dp, f)))
  1241. X    return(hitakey(NULL));
  1242. X
  1243. X  (void) strcpy(from, pathname(FFNAM(dp, f), CPNAM));
  1244. X  if(req) {
  1245. X    (void) putecho("Move %s to %s ?", FFNAM(dp, f), to);
  1246. X    if((c = hitakey(NULL)) != 'y')
  1247. X      return(c);
  1248. X  }
  1249. X
  1250. X  (void) putecho("Moving %s to %s", FFNAM(dp, f), to);
  1251. X  (void) sprintf(buf, "%s %s %s", MVFILE, from, to);
  1252. X  if(callsystem(buf, 0, 0) != RV_OK)
  1253. X    return(errequest(FFNAM(dp, f), "Error in moving"));
  1254. X
  1255. X  return(RV_OK);
  1256. X
  1257. X} /* movefile() */
  1258. X
  1259. END_OF_FILE
  1260. if test 16221 -ne `wc -c <'src/comm.c'`; then
  1261.     echo shar: \"'src/comm.c'\" unpacked with wrong size!
  1262. fi
  1263. # end of 'src/comm.c'
  1264. fi
  1265. if test -f 'src/main.c' -a "${1}" != "-c" ; then 
  1266.   echo shar: Will not clobber existing file \"'src/main.c'\"
  1267. else
  1268. echo shar: Extracting \"'src/main.c'\" \(21728 characters\)
  1269. sed "s/^X//" >'src/main.c' <<'END_OF_FILE'
  1270. X/*
  1271. X *      MAIN.C
  1272. X *      UTREE main routine.
  1273. X *      3.01-um klin, Sat May  4 15:45:02 1991
  1274. X *              klin, Tue Oct 15 12:26:53 1991, Option -L added
  1275. X *              klin, Sat Oct 26 15:04:54 1991, writedlist() changed
  1276. X *      3.02-um klin, Fri Nov  1 10:46:14 1991, Option -u changed to -n
  1277. X *                                              Option -u added
  1278. X *              klin, Sun Nov 10 19:37:45 1991, buildlist() changed
  1279. X *              klin, Sun Nov 24 19:30:43 1991, Cd to current directory before
  1280. X *                                              executing some commands
  1281. X *      3.03-um klin, Tue Feb 11 22:35:55 1992, Shell command history added
  1282. X *              klin, Sat Feb 15 19:18:30 1992, Video handling and option -v
  1283. X *                                              changed
  1284. X *                                              Partinioning of directory and
  1285. X *                                              file windows changed and
  1286. X *                                              option -p added
  1287. X *              klin, Sun Feb 23 18:45:19 1992, Keybindings, variable AUTOSAVE
  1288. X *                                              and option -o added
  1289. X *
  1290. X *      Copyright (c) 1991/92 by Peter Klingebiel & UNIX Magazin Muenchen.
  1291. X *      For copying and distribution information see the file COPYRIGHT.
  1292. X */
  1293. X#ifndef lint
  1294. static char sccsid[] = "@(#) utree 3.03-um (klin) Feb 23 1992 main.c";
  1295. X#endif  /* !lint */
  1296. X
  1297. X/*
  1298. X *      Usage:  utree   [-LSVabcghnoqrstuw] [-d var=[val]] [-d cmd:[typ]] [-f lst]
  1299. X *                      [-f lst] [-i ind] [-l lev] [-p lin] [-v mod] [-x cmd]
  1300. X *                      [rootdir]
  1301. X *
  1302. X *      Options:        -L              Follow symbolic links
  1303. X *                      -S              Ignore minimal screen size.
  1304. X *                      -V              Display program version.
  1305. X *                      -a              Read in all dirs including hidden.
  1306. X *                      -b              No bell
  1307. X *                      -c              No clock display/update in echoline.
  1308. X *                      -d var=[val]    Define/undefine variable var.
  1309. X *                      -d typ:[cmd]    Define/undefine command for type typ.
  1310. X *                      -f lst          Build tree from list file lst.
  1311. X *                      -g              No graphic characters.
  1312. X *                      -h              Display some help about options.
  1313. X *                      -i ind          Set tree indention to ind (3..9)
  1314. X *                      -l lev          Build tree up to level lev.
  1315. X *                      -n              No scan tree for changes.
  1316. X *                      -o              Omit saving definition/history changes.
  1317. X *                      -p lin          Set file window to lin lines (1..9)
  1318. X *                      -q              Build tree up to level 2 (like -l 2).
  1319. X *                      -r              Recreate tree list (always scan disk).
  1320. X *                      -s              No hardware scrolling.
  1321. X *                      -t              Sort files by modification times.
  1322. X *                      -u              Update directory tree.
  1323. X *                      -v mod          Set video attribute settings (0,1,2)
  1324. X *                      -w              No warning about unreadable dirs.
  1325. X *                      -x cmd          Use string cmd as initial input.
  1326. X *                      The options bcginopsvw may also be set in the environment
  1327. X *                      variable $UTREE.
  1328. X *
  1329. X *      Directory:      /usr/local/bin
  1330. X *
  1331. X *      Environment:    $EDITOR $HOME $PAGER $SHELL $TERM $UTREE $UTLIB
  1332. X *
  1333. X *      Files:          $UTLIB/utree.help       - Utree help pages.
  1334. X *                      $UTLIB/utree            - Global startup file.
  1335. X *                      $UTLIB/utree-$TERM      - Global key bindings for $TERM
  1336. X *                      $HOME/.utree            - User's startupfile.
  1337. X *                      $HOME/.utreelist        - User's tree list file.
  1338. X *                      $HOME/.utreehist        - Shell command history.
  1339. X *                      $HOME/.utree-$TERM      - Users key bindings for $TERM
  1340. X *                      $PATH/utree.prlist      - Tree display program
  1341. X *                      $PATH/utree.backup      - Backup shell script.
  1342. X *                      $PATH/utree.mklist      - Create tree list.
  1343. X *
  1344. X *      Libraries:      -lcurses (SYSV), -ltermcap or -ltermlib (BSD)
  1345. X *
  1346. X *      Bugs:           Changes in filesystem after shell or editor escape
  1347. X *                      are not always detected!
  1348. X *                      Directory tree depth > 32 may confuse utree!
  1349. X *                      Symbolic links to directories may confuse utree!
  1350. X *                      Chown() and chgrp() for normal users on some BSD
  1351. X *                      systems are not allowed!
  1352. X */
  1353. X
  1354. X#define _MAIN_                          /* Declare external variables   */
  1355. X#include "defs.h"                       /* defined in header files      */
  1356. X
  1357. X/* ---- Gobal variables and definitions ------------------------------- */
  1358. X
  1359. X#define USES1   "[-LSVabcghnoqrstuw] [-d var=[val]] [-d cmd:[typ]] [-f lst]"
  1360. X#define USES2   "[-i ind] [-l lev] [-p lin] [-v mod] [-x cmd] [rootdir]"
  1361. X#define UOPTS   "LSVabcd:f:ghi:nl:p:qrstuv:wx:" /* String for getopt()  */
  1362. X
  1363. GLOBL int helpline,   echoline;         /* Help/echo lines              */
  1364. GLOBL int firstline,  lastline;         /* First/last lines             */
  1365. GLOBL int firstdline, lastdline;        /* First/last tree lines        */
  1366. GLOBL int ndlines;                      /* # dir lines on tree screen   */
  1367. GLOBL int firstfline, lastfline;        /* First/last file lines        */
  1368. GLOBL int nflines;                      /* # file lines on tree screen  */
  1369. GLOBL int maxnflines = DEFFIL;          /* Max file lines               */
  1370. GLOBL int fperpage,   fperline;         /* Files per page/line          */
  1371. GLOBL int treeflag,   fileflag;         /* Screen update flags          */
  1372. GLOBL int filecount,  dircount;         /* # of files/directories       */
  1373. GLOBL int indent = -1;                  /* Tree indention: 2..9         */
  1374. GLOBL int videomode = VMODE2;           /* Video mode: all attributes   */
  1375. GLOBL int videoattr = VA_NORMAL;        /* Video attribute              */
  1376. GLOBL int graphattr = GC_OFF;           /* Graphic character set flag   */
  1377. GLOBL int maxindent = 0;                /* User defined tree indention  */
  1378. GLOBL int maxlevel;                     /* Current max tree level       */
  1379. GLOBL int buildflag  = 0;               /* Rebuild directory flag       */
  1380. GLOBL int writeflag  = 0;               /* Rewrite tree list file       */
  1381. GLOBL int sortbytime = 0;               /* Sort file by mod times       */
  1382. GLOBL int hiddendirs = 0;               /* Build up hidden directories  */
  1383. GLOBL int sizechange = 0;               /* Screen size changed          */
  1384. GLOBL int (*statfun)() = lstat;         /* Follow symbolic links        */
  1385. GLOBL dlist *droot   = DNULL;           /* Root of directory list       */
  1386. GLOBL dlist *cdlist  = DNULL;           /* Current directory list       */
  1387. GLOBL dlist *cwlist  = DNULL;           /* Current working directory    */
  1388. GLOBL char fpattern[PATLEN] = { '\0' }; /* Search pattern file search   */
  1389. GLOBL char gpattern[PATLEN] = { '\0' }; /* Search pattern file grep     */
  1390. GLOBL char tpattern[PATLEN] = { '\0' }; /* Tag pattern file tag         */
  1391. GLOBL char rootdir[NAMELEN];            /* Root directory name          */
  1392. GLOBL char utreemenu[MINCOLS];          /* User command tree menu line  */
  1393. GLOBL char ufilemenu[MINCOLS];          /* User command file menu line  */
  1394. GLOBL char *prgname;                    /* Program name/version         */
  1395. GLOBL char *home;                       /* Home directory               */
  1396. X#ifdef  BSD
  1397. GLOBL jmp_buf winchjump;                /* Global goto for SIGWINCH     */
  1398. GLOBL int atread;                       /* Flag if we are in getchar()  */
  1399. X#endif
  1400. X
  1401. GLOBL char *who;                        /* Name of current command      */
  1402. GLOBL char *hitkey = "(Hit a key)";
  1403. X
  1404. X/* ---- External variables and functions ------------------------------ */
  1405. X
  1406. XEXTRN char *optarg;                     /* From getopt()                */
  1407. XEXTRN int optind;                       /*   "     "                    */
  1408. XEXTRN char *initscreen();
  1409. XEXTRN int exitscreen();
  1410. XEXTRN char *calloc();
  1411. XEXTRN char *writedlist();
  1412. X
  1413. X/* ---- Functions and procedures -------------------------------------- */
  1414. X
  1415. X/*
  1416. X *      INTERNAL USED ROUTINES
  1417. X */
  1418. X
  1419. X/* Display usage message and some help about options if flag f is set */
  1420. LOCAL VOID usage(f)
  1421. X  register int f;
  1422. X{
  1423. X  (void) fprintf(stderr, "Usage:\t%s\t%s\n\t\t%s\n", prgname, USES1, USES2);
  1424. X  if(f) {
  1425. X    (void) fprintf(stderr, "\t-L\t\tFollow symbolic links\n");
  1426. X    (void) fprintf(stderr, "\t-S\t\tIgnore minimal screen size\n");
  1427. X    (void) fprintf(stderr, "\t-V\t\tDisplay program version\n");
  1428. X    (void) fprintf(stderr, "\t-a\t\tRead in all (incl hidden) directories\n");
  1429. X    (void) fprintf(stderr, "\t-b\t\tSuppress ringing of the bell\n");
  1430. X    (void) fprintf(stderr, "\t-c\t\tDon't display and update a clock\n");
  1431. X    (void) fprintf(stderr, "\t-d var=[val]\tSet/unset variable\n");
  1432. X    (void) fprintf(stderr, "\t-d typ:[cmd]\tSet/unset filetype command\n");
  1433. X    (void) fprintf(stderr, "\t-f lst\t\tBuild tree from list file lst\n");
  1434. X    (void) fprintf(stderr, "\t-g\t\tDon't use graphic characters\n");
  1435. X    (void) fprintf(stderr, "\t-h\t\tDisplay some help about options\n");
  1436. X    (void) fprintf(stderr, "\t-i ind\t\tSet tree indention to ind (3..9)\n");
  1437. X    (void) fprintf(stderr, "\t-l lev\t\tBuild tree up to level lev\n");
  1438. X    (void) fprintf(stderr, "\t-n\t\tDon't scan tree for changes in tree\n");
  1439. X    (void) fprintf(stderr, "\t-o\t\tOmit saving definition/history changes\n");
  1440. X    (void) fprintf(stderr, "\t-p lin\t\tSet file lines on tree screen to lin (1..9)\n");
  1441. X    (void) fprintf(stderr, "\t-q\t\tBuild tree up to level 2 (like -l 2)\n");
  1442. X    (void) fprintf(stderr, "\t-r\t\tRecreate tree list (always scan disk)\n");
  1443. X    (void) fprintf(stderr, "\t-s\t\tDon't use hardware scrolling\n");
  1444. X    (void) fprintf(stderr, "\t-t\t\tSort files by modification times\n");
  1445. X    (void) fprintf(stderr, "\t-u\t\tUpdate file lists in directory tree\n");
  1446. X    (void) fprintf(stderr, "\t-v mod\t\tSet video attribute mode to mod (0, 1 or 2)\n");
  1447. X    (void) fprintf(stderr, "\t-w\t\tNo warning about unreadable directories\n");
  1448. X    (void) fprintf(stderr, "\t-x cmd\t\tUse string cmd as initial input\n");
  1449. X  }
  1450. X
  1451. X} /* usage() */
  1452. X
  1453. X/* Exit utree on error */
  1454. LOCAL VOID uerror(err)
  1455. X  register char *err;
  1456. X{
  1457. X  (void) cursorxy(0, lines - 1);
  1458. X  clearline();
  1459. X  flushout();
  1460. X  terminalreset(1);
  1461. X  (void) fprintf(stderr, "%s: ", prgname);
  1462. X  perror(err);
  1463. X  exit(1);
  1464. X  /*NOTREACHED*/
  1465. X
  1466. X} /* uerror() */
  1467. X
  1468. X/*
  1469. X *      SETUP VARIABLES
  1470. X */
  1471. X/* Set up terminal dependent variables */
  1472. LOCAL int setupscreen(sig)
  1473. X  register int sig;
  1474. X{
  1475. X#if     defined(SIGWINCH) && defined(TIOCGWINSZ)
  1476. X  struct winsize ws;
  1477. X
  1478. X  /* Signal SIGWINCH catched: get new screen size */
  1479. X  if(sig && ioctl(fileno(stdin), TIOCGWINSZ, (char *) &ws) == 0) {
  1480. X    if(ws.ws_row > 0)
  1481. X      lines = ws.ws_row;
  1482. X    if(ws.ws_col > 0)
  1483. X      columns = ws.ws_col;
  1484. X    sizechange = 1;
  1485. X    if(lines < MINLINS)
  1486. X      bell(1);
  1487. X    if(columns < MINCOLS)
  1488. X      bell(1);
  1489. X    flushout();
  1490. X  }
  1491. X  /* Catch signal SIGWINCH for window changes */
  1492. X  (void) signal(SIGWINCH, setupscreen);
  1493. X#endif  /* SIGWINCH && TIOCGWINSZ */
  1494. X
  1495. X  /* Set up some screen size dependent variables */
  1496. X  echoline   = 0;
  1497. X  helpline   = 1;
  1498. X  firstline  = 2;
  1499. X  lastline   = lines-1;
  1500. X  firstdline = firstline;
  1501. X  lastfline  = lastline;
  1502. X  fperline   = columns/FWINSZ;
  1503. X  fperpage   = (lines-2) * fperline;
  1504. X  if(fperline <= 0)
  1505. X    fperline = 1;
  1506. X  /* Check some variables */
  1507. X  if(fperpage <= 0)
  1508. X    fperpage = 1;
  1509. X  checklines(1);
  1510. X  (void) setvideomode(videomode);
  1511. X
  1512. X#if     defined(BSD) && defined(SIGWINCH) && defined(TIOCGWINSZ)
  1513. X  /* BSD: Because signal SIGWINCH doesn't interrupt the systemcall */
  1514. X  /*      read use the global goto longjmp() to return to getchar  */
  1515. X  if(sig && atread && sizechange)
  1516. X    longjmp(winchjump, 1);
  1517. X#endif  /* BSD && SIGWINCH && TIOCGWINSZ */
  1518. X
  1519. X} /* setupscreen() */
  1520. X
  1521. X/*
  1522. X *      GET STARTUPFILES
  1523. X */
  1524. X
  1525. X/* Build startupfile name from file f and copy it to buffer b */
  1526. GLOBL int startup(b, f)
  1527. X  register char *b, *f;
  1528. X{
  1529. X  register char *e;
  1530. X
  1531. X  /* First: Try user's home directory */
  1532. X  (void) sprintf(b, ".%s", f);
  1533. X  (void) strcpy(b, pathname(b, home));
  1534. X  if(access(b, 04) == 0)
  1535. X    return(1);
  1536. X  /* Second: Try libdir if defined in environment */
  1537. X  if(e = getenv("UTLIB")) {
  1538. X    (void) strcpy(b, pathname(f, e));
  1539. X    if(access(b, 04) == 0)
  1540. X      return(1);
  1541. X  }
  1542. X  /* Third: Try global libdir if defined */
  1543. X#ifdef  UTLIB
  1544. X  (void) strcpy(b, pathname(f, UTLIB));
  1545. X  if(access(b, 04) == 0)
  1546. X    return(1);
  1547. X#endif  /* UTLIB */
  1548. X  return(0);
  1549. X
  1550. X} /* startup() */
  1551. X
  1552. X/*
  1553. X *      MEMORY ALLOCATION
  1554. X */
  1555. X
  1556. X/* Allocate memory. Exit on error */
  1557. GLOBL char *ualloc(n, s)
  1558. X  register unsigned n, s;
  1559. X{
  1560. X  register char *p;
  1561. X
  1562. X  if(p = calloc(n, s))
  1563. X    return(p);
  1564. X  uerror("ualloc");
  1565. X  /*NOTREACHED*/
  1566. X
  1567. X} /* ualloc() */
  1568. X
  1569. X/* Free allocated memory */
  1570. GLOBL VOID ufree(p)
  1571. X  register char *p;
  1572. X{
  1573. X  if(p)
  1574. X    free(p);
  1575. X
  1576. X} /* ufree() */
  1577. X
  1578. X/*
  1579. X *      MAIN ROUTINE
  1580. X */
  1581. X
  1582. GLOBL VOID main(argc, argv)
  1583. X  int argc;
  1584. X  char **argv;
  1585. X{
  1586. X  char list[NAMELEN], name[NAMELEN], cwd[NAMELEN];
  1587. X  struct stat st;
  1588. X  FILE *fp;
  1589. X  char *lst = NULL;
  1590. X  char *cp, *root, *term;
  1591. X  int hard = 0, level = 0, siz = 1, update = 0;
  1592. X  int opt, any, rval, i;
  1593. X
  1594. X  /* Set up programs name and commandline variables */
  1595. X  prgname = basename(argv[0]);
  1596. X
  1597. X  /* Get users home directory */
  1598. X  if((home = getenv("HOME")) == NULL) {
  1599. X    (void) fprintf(stderr, "%s: Can't get your home directory\n", prgname);
  1600. X    exit(1);
  1601. X  }
  1602. X
  1603. X  /* Check if utree is running from a terminal */
  1604. X  if( !isatty(fileno(stdin)) || !isatty(fileno(stdout))) {
  1605. X    (void) fprintf(stderr, "%s: Not attached to a terminal\n", prgname);
  1606. X    exit(1);
  1607. X  }
  1608. X
  1609. X  /* Init utree variables before parsing command line options */
  1610. X  initvariables();
  1611. X
  1612. X  /* Parse and check command line options */
  1613. X  while((opt = getopt(argc, argv, UOPTS)) != EOF)
  1614. X    switch(opt) {
  1615. X      default:                  /* Bad option or missing argument */
  1616. X       usage(0);
  1617. X       exit(1);
  1618. X      case 'L':                 /* Follow symbolic links */
  1619. X       statfun = stat;
  1620. X       break;
  1621. X      case 'S':                 /* Ignore minimal screen size */
  1622. X       siz = 0;
  1623. X       break;
  1624. X      case 'V':                 /* Show utree version */
  1625. X       utreeversion();
  1626. X       exit(0);
  1627. X      case 'a':                 /* Build up all directories */
  1628. X       hiddendirs = 1;
  1629. X       break;
  1630. X      case 'b':                 /* No bell */
  1631. X       (void) setvariable("BL=", VC_SET);
  1632. X       break;
  1633. X      case 'c':                 /* No clock showing and update */
  1634. X       (void) setvariable("CL=", VC_SET);
  1635. X       break;
  1636. X      case 'd':                 /* Define or undefine variables */
  1637. X       if(strchr(optarg, '=')) {
  1638. X         (void) setvariable(optarg, VC_SET);
  1639. X         break;
  1640. X       }
  1641. X       else if(strchr(optarg, ':')) {
  1642. X         (void) setcommand(optarg, VC_SET);
  1643. X         break;
  1644. X       }
  1645. X       (void) fprintf(stderr, "%s: bad assignment -- %s\n",
  1646. X                      prgname, optarg);
  1647. X       usage(0);
  1648. X       exit(1);
  1649. X      case 'f':                 /* Tree list file given */
  1650. X       lst = optarg;
  1651. X       break;
  1652. X      case 'g':                 /* No graphic characters */
  1653. X       (void) setvariable("GC=", VC_SET);
  1654. X       break;
  1655. X      case 'h':                 /* Display some help */
  1656. X       utreeversion();
  1657. X       usage(1);
  1658. X       exit(0);
  1659. X      case 'i':                 /* Tree level indention */
  1660. X       (void) sprintf(list, "TI=%s", optarg);
  1661. X       if(setvariable(list, VC_SET) < 0) {
  1662. X         (void) fprintf(stderr, "%s: bad tree indention (must be 3 .. 9) -- %s\n",
  1663. X                        prgname, optarg);
  1664. X         usage(0);
  1665. X         exit(1);
  1666. X       }
  1667. X       break;
  1668. X      case 'l':                 /* Level to build up the tree */
  1669. X       if((level = atoi(optarg)) <= 0) {
  1670. X         (void) fprintf(stderr, "%s: bad tree level (must be > 0) -- %s\n",
  1671. X                        prgname, optarg);
  1672. X         usage(0);
  1673. X         exit(1);
  1674. X       }
  1675. X       break;
  1676. X      case 'n':                 /* No scan tree for changes */
  1677. X       (void) setvariable("ST=", VC_SET);
  1678. X       break;
  1679. X      case 'o':                 /* Omit saving definition changes */
  1680. X       (void) setvariable("AS=", VC_SET);
  1681. X       break;
  1682. X      case 'p':                 /* Number of file lines on tree screen */
  1683. X       (void) sprintf(list, "FL=%s", optarg);
  1684. X       if(setvariable(list, VC_SET) < 0) {
  1685. X         (void) fprintf(stderr, "%s: bad number of lines (must be 1 .. 9) -- %s\n",
  1686. X                        prgname, optarg);
  1687. X         usage(0);
  1688. X         exit(1);
  1689. X       }
  1690. X       break;
  1691. X      case 'q':                 /* Build tree up to level 2 */
  1692. X       level = 2;
  1693. X       break;
  1694. X      case 'r':                 /* Hard build up the tree */
  1695. X       hard = writeflag = 1;
  1696. X       break;
  1697. X      case 's':                 /* No terminal scrolling */
  1698. X       (void) setvariable("TS=", VC_SET);
  1699. X       break;
  1700. X      case 't':                 /* Sort files by modification times */
  1701. X       (void) setvariable("LS=", VC_SET);
  1702. X       break;
  1703. X      case 'u':                 /* Update filelists in tree */
  1704. X       update = buildflag = 1;
  1705. X       break;
  1706. X      case 'v':                 /* Set video mode */
  1707. X       (void) sprintf(list, "VM=%s", optarg);
  1708. X       if(setvariable(list, VC_SET) < 0) {
  1709. X         (void) fprintf(stderr, "%s: bad mode (use 0, 1 or 2) -- %s\n",
  1710. X                        prgname, optarg);
  1711. X         usage(0);
  1712. X         exit(1);
  1713. X       }
  1714. X       break;
  1715. X      case 'w':                 /* No warning about unreadable directories */
  1716. X       (void) setvariable("WD=", VC_SET);
  1717. X       break;
  1718. X      case 'x':                 /* Fill input buffer */
  1719. X       if(ungetstring(optarg)) {
  1720. X         (void) fprintf(stderr, "%s: bad input string -- %s\n",
  1721. X                        prgname, optarg);
  1722. X         usage(0);
  1723. X         exit(1);
  1724. X       }
  1725. X       break;
  1726. X    }
  1727. X
  1728. X  /* Get current working directory */
  1729. X  (void) getcwd(cwd, NAMELEN-2);
  1730. X
  1731. X  /* Check list file if given and setup rootdirectory */
  1732. X  if(lst) {
  1733. X    if( !(fp = fopen(lst, "r"))) {
  1734. X      (void) fprintf(stderr, "%s: Cannot open list file %s\n", prgname, lst);
  1735. X      exit(1);
  1736. X    }
  1737. X    while(fgets(name, sizeof(name), fp)) {
  1738. X      if(VALID(name[0]) && (name[0] == '/' || name[0] == '.')) {
  1739. X       if(name[i = strlen(name) - 1] == '\n')
  1740. X         name[i] = '\0';
  1741. X       (void) fclose(fp);
  1742. X       goto OUT;
  1743. X      }
  1744. X    }
  1745. X    (void) fclose(fp);
  1746. X    (void) fprintf(stderr, "%s: No root found in list file %s\n", prgname, lst);
  1747. X    exit(1);
  1748. X  }
  1749. OUT:
  1750. X
  1751. X  /* Get root directory from where to build up the directory tree */
  1752. X  switch(argc - optind) {
  1753. X    case 0:                     /* Root from list file */
  1754. X      if(lst) {
  1755. X       (void) strcpy(list, pathname(lst, cwd));
  1756. X       root = pathname(name, cwd);
  1757. X      }
  1758. X      else {                    /* Root is users home directory */
  1759. X       (void) strcpy(list, pathname(UTLIST, home));
  1760. X       root = home;
  1761. X      }
  1762. X      break;
  1763. X    case 1:                     /* Root is given in command line */
  1764. X      root = pathname(argv[optind], cwd);
  1765. X      break;
  1766. X    default:                    /* Too many arguments */
  1767. X      usage(0);
  1768. X      exit(1);
  1769. X  }
  1770. X
  1771. X  /* Test and change to root directory */
  1772. X  if( !ISDIR(root, st)) {
  1773. X    (void) fprintf(stderr, "%s: Root %s is not a directory\n", prgname, root);
  1774. X    exit(1);
  1775. X  }
  1776. X  if(chdir(root)) {
  1777. X    (void) fprintf(stderr, "%s: Can't change to root %s\n", prgname, root);
  1778. X    exit(1);
  1779. X  }
  1780. X  (void) strcpy(rootdir, root);
  1781. X  any = strncmp(root, home, strlen(home));
  1782. X
  1783. X  /* Init screen and check screen size */
  1784. X  term = getenv("TERM");
  1785. X  if(cp = initscreen(term)) {
  1786. X    (void) fprintf(stderr, "%s: %s\n", prgname, cp);
  1787. X    exit(1);
  1788. X  }
  1789. X  else if(siz && (columns < MINCOLS || lines < MINLINS)) {
  1790. X    (void) fprintf(stderr, "%s: Screen too small, %dx%d instead of %dx%d\n",
  1791. X                  prgname, columns, lines, MINCOLS, MINLINS);
  1792. X    exit(1);
  1793. X  }
  1794. X  (void) setupscreen(0);
  1795. X
  1796. X  /* Init history list, help pages, key bindings and graphical character set */
  1797. X  inithistory();
  1798. X  inithelp();
  1799. X  initgraphics(VARSET(V_GC));
  1800. X
  1801. X  /* Catch signals and set terminal to raw mode. ATTENTION:  */
  1802. X  /* SIGKILL cannot be caught. This leaves tty in raw state! */
  1803. X  terminalraw(1);
  1804. X  (void) signal(SIGQUIT, exitscreen);
  1805. X  (void) signal(SIGINT,  exitscreen);
  1806. X  (void) signal(SIGTERM, exitscreen);
  1807. X  enablesignals();
  1808. X
  1809. X  /* Show initial screen */
  1810. X  clearscreen();
  1811. X  (void) putversion(helpline, NULL);
  1812. X  flushout();
  1813. X
  1814. X  /* Build up directory tree and file lists */
  1815. X  if(lst)
  1816. X    rval = buildlist(rootdir, cwd, list);
  1817. X  else if(level) {
  1818. X    update = 0;
  1819. X    rval = buildread(rootdir, 1, level, 0);
  1820. X  }
  1821. X  else if(hard || any) {
  1822. X    update = 0;
  1823. X    rval = buildread(rootdir, 1, HLEVEL, 0);
  1824. X  }
  1825. X  else if((rval = buildlist(rootdir, cwd, list)) != RV_OK) {
  1826. X    update = 0;
  1827. X    writeflag = 1;
  1828. X    rval = buildread(rootdir, 1, HLEVEL, 0);
  1829. X  }
  1830. X
  1831. X  /* Exit on error at building tree */
  1832. X  if(rval != RV_OK)
  1833. X    uerror(rootdir);
  1834. X
  1835. X  /* Disable/ignore signals */
  1836. X  disablesignals();
  1837. X  (void) signal(SIGQUIT, SIG_IGN);
  1838. X  (void) signal(SIGINT,  SIG_IGN);
  1839. X  cursorset(CF_INVISIBLE);
  1840. X  flushout();
  1841. X
  1842. X  /* Call the tree menu */
  1843. X  cwlist = droot;
  1844. X  rval = treemenu(update);
  1845. X
  1846. X  /* Write/rewrite tree and command history lists if needed */
  1847. X  if(EQU(rootdir, home)) {
  1848. X    if(writeflag && !(level || any)) {
  1849. X      (void) strcpy(list, pathname(UTLIST, home));
  1850. X      (void) writedlist(list, droot, "home", 'd');
  1851. X    }
  1852. X  }
  1853. X
  1854. X  /* Save history list, variables, commands and key bindings */
  1855. X  savehistory();
  1856. X  savevariables();
  1857. X  savebindings(term);
  1858. X
  1859. X  /* Clear screen, reset terminal and exit */
  1860. X  clearscreen();
  1861. X  exitscreen(rval == RV_ERR ? 1 : 0);
  1862. X
  1863. X} /* main() */
  1864. X
  1865. END_OF_FILE
  1866. if test 21728 -ne `wc -c <'src/main.c'`; then
  1867.     echo shar: \"'src/main.c'\" unpacked with wrong size!
  1868. fi
  1869. # end of 'src/main.c'
  1870. fi
  1871. if test -f 'src/utree.prlist.c' -a "${1}" != "-c" ; then 
  1872.   echo shar: Will not clobber existing file \"'src/utree.prlist.c'\"
  1873. else
  1874. echo shar: Extracting \"'src/utree.prlist.c'\" \(16227 characters\)
  1875. sed "s/^X//" >'src/utree.prlist.c' <<'END_OF_FILE'
  1876. X/*
  1877. X *      UTREE.PRLIST.C
  1878. X *      Filter for utree 3.02-um tree list files for different devices.
  1879. X *      3.02-um klin, Sun Nov 10 13:13:35 1991
  1880. X *              klin, Sun Nov 24 12:07:16 1991, XENIX graphset handling
  1881. X *      3.03-um klin, Sun Feb 16 15:34:37 1992, Minor changes
  1882. X *            a klin, Sun Mar 15 19:08:25 1992, Minor changes for AIX 3.2
  1883. X *
  1884. X *      Copyright (c) 1991/92 by Peter Klingebiel & UNIX Magazin Muenchen.
  1885. X *      For copying and distribution information see the file COPYRIGHT.
  1886. X */
  1887. static char sccsid[] = "@(#) utree 3.03a-um (klin) Mrz 15 1992 utree.prlist.c";
  1888. X
  1889. X/*
  1890. X *      Usage:  utree.prlist [-Vhr] [-d dev] [-f fnt] [i ind] [-s siz] listfile
  1891. X *      Options:        -V      Display program version.
  1892. X *                      -T dev  or
  1893. X *                      -d dev  Output for device dev.
  1894. X *                              Supported devices are:
  1895. X *                              ascii   ascii meta characters.
  1896. X *                              850     printers with ibm pc850 charset.
  1897. X *                              ps      postscript.
  1898. X *                              term    terminal (default).
  1899. X *                      -f fnt  Font to use (postscript only)
  1900. X *                      -h      Display usage and help.
  1901. X *                      -i ind  Set tree indention to ind.
  1902. X *                      -s siz  Font size (postscript only)
  1903. X *      Remarks:        Formatted utree tree list files can be created
  1904. X *                      with the write-tree command (o) and option list (l)
  1905. X *                      from tree-screen.
  1906. X *      Directory:      /usr/local/bin
  1907. X *      Environment:    $TERM
  1908. X *      Defines:        AIX     for IBM AIX systems
  1909. X *                      BSD     for BSD systems
  1910. X *                      XENIX   for XENIX systems
  1911. X *      Libraries:      -lm -lcurses (SYSV), -ltermcap or -ltermlib (BSD)
  1912. X */
  1913. X
  1914. static char usage[] = "@(#) Usage: utree.prlist [-Vr][-d dev][-f fnt][-i ind][-s siz] listfile";
  1915. static char pvers[] = "UTREE 3.03-um";
  1916. X
  1917. X#include <stdio.h>
  1918. X#include <signal.h>
  1919. X
  1920. X#define MAXLEN  512             /* Buffer length                */
  1921. X#define DEFIND  6               /* Default indention            */
  1922. X#define MININD  3               /* Minimal indention            */
  1923. X#define MAXIND  9               /* Maxinal indention            */
  1924. X#define OPTIONS "T:Vd:f:hi:rs:" /* Optionstring for getopt()    */
  1925. X#define UNULL   ((unsigned char *) 0)
  1926. X
  1927. static char *pname;
  1928. static char *title = "Tree";
  1929. static char root[MAXLEN];
  1930. X
  1931. X/* The generic graphical character set                          */
  1932. static unsigned char *grafset = UNULL;
  1933. X#define H grafset[0]            /* Horizontal bar               */
  1934. X#define V grafset[1]            /* Vertical bar                 */
  1935. X#define U grafset[2]            /* Upper left corner            */
  1936. X#define L grafset[3]            /* Lower left corner            */
  1937. X#define T grafset[4]            /* Left tee                     */
  1938. X#define I grafset[5]            /* Indention                    */
  1939. X#define S grafset[6]            /* Space                        */
  1940. X
  1941. X/* The fix coded character sets for ascii, acsc, ibm and ps     */
  1942. X/*                                    H   V   U   L   T   I   S */
  1943. static unsigned char asciiset[7] = { '-','|','+','+','|',' ',' ' };
  1944. static unsigned char acscset[7]  = { '-','|','+','+','|',' ',' ' };
  1945. static unsigned char ibmset[7]   = { 196,179,218,192,195,' ',' ' };
  1946. static unsigned char psset[7]    = { 'H','V','U','L','T','I','S' };
  1947. X
  1948. static int indent = DEFIND;     /* Indention                    */
  1949. static int rflag  = 1;          /* Print rootdirectory flag     */
  1950. static int isps   = 0;          /* Postscript output            */
  1951. X
  1952. static unsigned char *acsc  = UNULL;    /* Alternate char set   */
  1953. static unsigned char *enacs = UNULL;    /* Enable alt char set  */
  1954. static unsigned char *smacs = UNULL;    /* Alt char set on      */
  1955. static unsigned char *rmacs = UNULL;    /* Alt char set off     */
  1956. X#define ACSCON  if(acsc && smacs) tputs(smacs, 1, putchar)
  1957. X#define ACSCOFF if(acsc && rmacs) tputs(rmacs, 1, putchar)
  1958. X#undef  putchar
  1959. X
  1960. X/* Postscript definitions and variables                         */
  1961. X#define PSFONT  "Courier-Bold"  /* Default postscript font      */
  1962. X#define PSSIZE   10.0           /* Default postscript font size */
  1963. X#define PSMIN    50.0           /* Lower y position             */
  1964. X#define PSMAX   780.0           /* Upper y position             */
  1965. X#define PSIND    85.0           /* Most left x position         */
  1966. X#define PSWID   475.0           /* Page header width            */
  1967. X#define PSEOF   (0x04)          /* C-d: EOF for postscript      */
  1968. static int psp = 0;             /* Page counter                 */
  1969. static double psy;              /* Current y position           */
  1970. static double pps = PSSIZE;     /* Font size                    */
  1971. static double pvs = PSSIZE+2;   /* Vertical space               */
  1972. static char *pft = PSFONT;      /* Font                         */
  1973. X
  1974. extern double atof();
  1975. X#ifdef  BSD
  1976. X#define strrchr rindex
  1977. extern char *rindex();
  1978. X#else   /* !BSD */
  1979. extern char *strrchr();
  1980. X#endif  /* BSD */
  1981. X
  1982. X/*
  1983. X *      Output one character
  1984. X */
  1985. static int putchar(c)
  1986. X  int c;
  1987. X{
  1988. X  putc((unsigned char) c, stdout);
  1989. X  return(c);
  1990. X
  1991. X} /* putchar() */
  1992. X
  1993. X/*
  1994. X *      Catch signals SIGINT, SIGQUIT and SIGTERM
  1995. X */
  1996. static int catchsig(sig)
  1997. X  int sig;
  1998. X{
  1999. X  ACSCOFF;
  2000. X  if(sig == SIGQUIT)
  2001. X    abort();
  2002. X  exit(1);
  2003. X
  2004. X} /* catchsig() */
  2005. X
  2006. X/*
  2007. X *      Init terminal and graphical character set for terminal
  2008. X */
  2009. static void initterm(f)
  2010. X  int f;
  2011. X{
  2012. X  static char termbuf[1024];
  2013. X  char termcap[1024], *term;
  2014. X  char *tp = termbuf;
  2015. X  extern char *getenv();
  2016. X  extern unsigned char *tgetstr();
  2017. X
  2018. X  grafset = asciiset;           /* Default character set */
  2019. X  if(f && !isatty(fileno(stdout)))
  2020. X    return;
  2021. X  else if((term = getenv("TERM")) && tgetent(termcap, term) > 0) {
  2022. X#ifdef  AIX
  2023. X    if(acsc = tgetstr("bx", &tp)) {
  2024. X      grafset = acscset;
  2025. X      if( !(smacs = tgetstr("as", &tp)))
  2026. X     smacs = tgetstr("f1", &tp);     /* AIX 3.2: font1 instead of smacs */
  2027. X      if( !(rmacs = tgetstr("ae", &tp)))
  2028. X     rmacs = tgetstr("f0", &tp);     /* AIX 3.2: font0 instead of rmacs */
  2029. X      U = acsc[0];
  2030. X      L = acsc[5];
  2031. X      H = acsc[1];
  2032. X      T = acsc[9];
  2033. X      V = acsc[3];
  2034. X    }
  2035. X#else   /* !AIX */
  2036. X    if(acsc = tgetstr("ac", &tp)) {
  2037. X      grafset = acscset;
  2038. X      if(enacs = tgetstr("eA", &tp))
  2039. X       tputs(enacs, 1, putchar);
  2040. X      smacs = tgetstr("as", &tp);
  2041. X      rmacs = tgetstr("ae", &tp);
  2042. X      do
  2043. X       switch(*acsc) {
  2044. X         default:              /* Skip */
  2045. X           ++acsc; break;
  2046. X         case 'l':             /* Upper left corner */
  2047. X           U = *++acsc; break;
  2048. X         case 'm':             /* Lower left corner */
  2049. X           L = *++acsc; break;
  2050. X         case 'q':             /* Horizontal bar */
  2051. X           H = *++acsc; break;
  2052. X         case 't':             /* Left tee */
  2053. X           T = *++acsc; break;
  2054. X         case 'x':             /* Vertical bar */
  2055. X           V = *++acsc; break;
  2056. X       }
  2057. X      while(*acsc && *++acsc);
  2058. X    }
  2059. X# ifdef XENIX
  2060. X    else {
  2061. X      unsigned char *gp;
  2062. X
  2063. X      grafset = acscset;
  2064. X      acsc  = acscset;          /* Use as flag */
  2065. X      smacs = tgetstr("GS", &tp);
  2066. X      rmacs = tgetstr("GE", &tp);
  2067. X      if(gp = tgetstr("G2", &tp))
  2068. X       U = *gp;                /* Upper left corner */
  2069. X      if(gp = tgetstr("G3", &tp))
  2070. X       L = *gp;                /* Lower left corner */
  2071. X      if(gp = tgetstr("GH", &tp))
  2072. X       H = *gp;                /* Horizontal bar */
  2073. X      if(gp = tgetstr("GR", &tp))
  2074. X       T = *gp;                /* Left tee */
  2075. X      if(gp = tgetstr("GV", &tp))
  2076. X       V = *gp;                /* Vertical bar */
  2077. X    }
  2078. X# endif /* XENIX */
  2079. X#endif  /* AIX */
  2080. X    signal(SIGINT,  catchsig);
  2081. X    signal(SIGQUIT, catchsig);
  2082. X    signal(SIGTERM, catchsig);
  2083. X  }
  2084. X
  2085. X} /* initterm() */
  2086. X
  2087. X/*
  2088. X *      Select graphical character set for device d
  2089. X */
  2090. static int initgraf(d)
  2091. X  char *d;
  2092. X{
  2093. X  switch(*d) {
  2094. X    default:                    /* Bad device */
  2095. X      return(0);
  2096. X    case 'a':                   /* ASCII meta characters */
  2097. X      grafset = asciiset;
  2098. X      break;
  2099. X    case '8':                   /* IBM PC850 character set */
  2100. X      grafset = ibmset;
  2101. X      break;
  2102. X    case 'p':                   /* Postscript */
  2103. X      grafset = psset;
  2104. X      ++isps;
  2105. X      break;
  2106. X    case 't':
  2107. X      initterm(0);              /* Terminal */
  2108. X      break;
  2109. X  }
  2110. X  return(1);
  2111. X
  2112. X} /* initgraf() */
  2113. X
  2114. X/*
  2115. X *      Write out graphic character c from current character set
  2116. X */
  2117. static void putgraf(c)
  2118. X  int c;
  2119. X{
  2120. X  switch(c) {
  2121. X    case 'I':                   /* Indention */
  2122. X      putchar(I); break;
  2123. X    case 'S':                   /* Space */
  2124. X      putchar(S); break;
  2125. X    default:                    /* Graphical characters */
  2126. X      ACSCON;
  2127. X      switch(c) {
  2128. X       case 'H':               /* Horizontal bar */
  2129. X         putchar(H); break;
  2130. X       case 'L':               /* Lower left corner */
  2131. X         putchar(L); break;
  2132. X       case 'T':               /* Left tee */
  2133. X         putchar(T); break;
  2134. X       case 'U':               /* Upper left corner */
  2135. X         putchar(U); break;
  2136. X       case 'V':               /* Vertical bar */
  2137. X         putchar(V); break;
  2138. X      }
  2139. X      ACSCOFF;
  2140. X      break;
  2141. X  }
  2142. X  if(isps)
  2143. X    putchar(' ');
  2144. X
  2145. X} /* putgraf() */
  2146. X
  2147. X/*
  2148. X *      Write header lines
  2149. X */
  2150. static void putheader()
  2151. X{
  2152. X  if(isps) {
  2153. X    printf("%%!PS-Adobe-2.0\n");
  2154. X    printf("%%%%Creator: %s\n", &sccsid[5]);
  2155. X    printf("%%%%Title: %s: %s\n", title, root);
  2156. X    printf("%%%%DocumentFont: %s\n", pft);
  2157. X    printf("%%%%Pages: (atend)\n");
  2158. X    printf("%% Copyright (c) 1991 by Peter Klingebiel & UNIX Magazin Muenchen\n");
  2159. X    printf("%%%%EndComments\n");
  2160. X    printf("%% Variables for font, fontsize, vertical space and indentions\n");
  2161. X    printf("/ft /%s def\n", pft);
  2162. X    printf("/ps %3.2lf def\n", pps);
  2163. X    printf("/vs %3.2lf def\n", pvs);
  2164. X    printf("/s1 %3.2lf def\n", pvs / 6.0);
  2165. X    printf("/s2 %3.2lf def\n", pvs / 3.0);
  2166. X    printf("/s3 %3.2lf def\n", pvs * 2.0 / 3.0);
  2167. X    printf("%% Procedures for drawing and printing\n");
  2168. X    if(rflag) {
  2169. X      printf("/Z { gsave 0.95 setgray\n");
  2170. X      printf("     0 ps s3 add     rlineto  %3.2lf 0 rlineto\n", PSWID);
  2171. X      printf("     0 ps s3 add neg rlineto -%3.2lf 0 rlineto\n", PSWID);
  2172. X      printf("     fill grestore s2 s2 rmoveto\n");
  2173. X      printf("     gsave show grestore %3.2lf setlinewidth } bind def\n", pps / 20.0);
  2174. X    }
  2175. X    else
  2176. X      printf("/Z { %3.2lf setlinewidth } bind def\n", pps / 20.0);
  2177. X    printf("/F { findfont exch scalefont setfont } bind def\n");
  2178. X    printf("/P { gsave s1 s1 rmoveto show grestore stroke } bind def\n");
  2179. X    printf("/G { moveto } bind def\n");
  2180. X    printf("/U { 0 s2 rlineto s2 0 rlineto 0 s2 neg rmoveto } bind def\n");
  2181. X    printf("/L { 0 vs rmoveto 0 s3 neg rlineto s2 0 rlineto 0 s2 neg rmoveto } bind def\n");
  2182. X    printf("/V { 0 vs rlineto s2 vs neg rmoveto } bind def\n");
  2183. X    printf("/T { 0 vs rlineto 0 s3 neg rmoveto s2 0 rlineto 0 s2 neg rmoveto } bind def\n");
  2184. X    printf("/S { s2 0 rmoveto } bind def\n");
  2185. X    printf("/I { s2 %d mul 0 rmoveto } bind def\n", indent);
  2186. X    printf("/H { 0 s2 rmoveto s2 %d mul 0 rlineto 0 s2 neg rmoveto } bind def\n", indent-1);
  2187. X    printf("%%%%EndProlog\n");
  2188. X    printf("ps ft F\n");
  2189. X  }
  2190. X  else if(rflag)
  2191. X    printf("\n%s  %s: %s\n\n", pvers, title, root);
  2192. X
  2193. X} /* putheader() */
  2194. X
  2195. X/*
  2196. X *      Write trailing lines
  2197. X */
  2198. static void puttrailer()
  2199. X{
  2200. X  if(isps) {
  2201. X    printf("showpage\n");
  2202. X    printf("%%%%Trailer\n");
  2203. X    printf("%%%%Pages: %d\n", psp);
  2204. X    putchar(PSEOF);
  2205. X  }
  2206. X
  2207. X} /* puttrailer() */
  2208. X
  2209. X/*
  2210. X *      Scan one entry line and write out
  2211. X */
  2212. static void putentry(s)
  2213. X  char *s;
  2214. X{
  2215. X  int c, i;
  2216. X
  2217. X  if(isps) {
  2218. X    if(psp == 0 || psy < PSMIN) {
  2219. X      if(psp)
  2220. X       printf("showpage\n");
  2221. X      printf("%%%%Page %d\n", ++psp);
  2222. X      if(rflag) {
  2223. X       printf("%3.2lf %3.2lf G (%s  %s    Page %d) Z\n", PSIND, PSMAX, title, root, psp);
  2224. X       psy = PSMAX - 2.0 * pvs;
  2225. X      }
  2226. X      else {
  2227. X       printf("Z\n");
  2228. X       psy = PSMAX;
  2229. X      }
  2230. X    }
  2231. X    printf("%3.2lf %3.2lf G ", PSIND, psy);
  2232. X    psy -= pvs;
  2233. X  }
  2234. X  else
  2235. X    putgraf(*s++);              /* First column */
  2236. X  while(c = *s++)
  2237. X    switch(c) {
  2238. X      default:                  /* Bad format */
  2239. X       return;
  2240. X      case 'H':                 /* Horizontal bar + file name */
  2241. X       if(isps) {
  2242. X         putgraf(c);
  2243. X         printf("(%s) P\n", s);
  2244. X       }
  2245. X       else {
  2246. X         for(i = 1; i < indent; i++)
  2247. X           putgraf(c);
  2248. X         printf(" %s\n", s);
  2249. X       }
  2250. X       return;
  2251. X      case 'I':                 /* Indention */
  2252. X       if(isps)
  2253. X         putgraf(c);
  2254. X       else
  2255. X         for(i = 0; i < indent; i++)
  2256. X           putgraf(c);
  2257. X       break;
  2258. X      case 'S':                 /* One space */
  2259. X      case 'L':                 /* Lower left corner */
  2260. X      case 'T':                 /* Left tee */
  2261. X      case 'U':                 /* Upper left corner */
  2262. X      case 'V':                 /* Vertical bar */
  2263. X       putgraf(c);
  2264. X       break;
  2265. X    }
  2266. X
  2267. X} /* putentry() */
  2268. X
  2269. X/*
  2270. X *      Main routine
  2271. X */
  2272. main(argc, argv)
  2273. X  int argc;
  2274. X  char **argv;
  2275. X{
  2276. X  char line[MAXLEN], *list;
  2277. X  FILE *fp;
  2278. X  int c;
  2279. X  extern char *optarg;          /* From getopt() */
  2280. X  extern int optind;
  2281. X
  2282. X  /* Get programs name */
  2283. X  if(pname = strrchr(argv[0], '/'))
  2284. X    ++pname;
  2285. X  else
  2286. X    pname = argv[0];
  2287. X
  2288. X  /* Parse and check command line options */
  2289. X  while((c = getopt(argc, argv, OPTIONS)) != EOF) {
  2290. X    switch(c) {
  2291. X      default:                  /* Bad option */
  2292. X       fprintf(stderr, "%s\n", &sccsid[5]);
  2293. X       exit(1);
  2294. X      case 'V':                 /* Version */
  2295. X       fprintf(stderr, "%s\n", &sccsid[5]);
  2296. X       exit(0);
  2297. X      case 'h':                 /* Some help */
  2298. X       fprintf(stderr, "%s\n", &usage[5]);
  2299. X       fprintf(stderr, "\t-T dev\t\tOutput for device dev\n");
  2300. X       fprintf(stderr, "\t-V\t\tDisplay program version\n");
  2301. X       fprintf(stderr, "\t-d dev\t\tOutput for device dev\n");
  2302. X       fprintf(stderr, "\t-f fnt\t\tUse font fnt (ps only, default: Courier-Bold)\n");
  2303. X       fprintf(stderr, "\t-h\t\tDisplay some help\n");
  2304. X       fprintf(stderr, "\t-i ind\t\tSet tree indention to ind (3..9)\n");
  2305. X       fprintf(stderr, "\t-s siz\t\tUse font size siz (ps only, default: 10)\n");
  2306. X       fprintf(stderr, "\t\t\tCurrently supported output devices are:\n");
  2307. X       fprintf(stderr, "\t\t\tascii\tAscii meta graphic characters\n");
  2308. X       fprintf(stderr, "\t\t\t850\tPrinters using IBM PC850 character set\n");
  2309. X       fprintf(stderr, "\t\t\tps\tPostscript\n");
  2310. X       fprintf(stderr, "\t\t\tterm\tTerminal (default)\n");
  2311. X       exit(0);
  2312. X      case 'T':                 /* Device for graphical character set */
  2313. X      case 'd':
  2314. X       if(initgraf(optarg))
  2315. X         break;
  2316. X       fprintf(stderr, "%s: device not supported -- %s\n", pname, optarg);
  2317. X       exit(1);
  2318. X      case 'r':                 /* Suppress pathname of rootdirectory */
  2319. X       rflag = 0;
  2320. X       break;
  2321. X      case 'i':                 /* Indention */
  2322. X       if((indent = atoi(optarg)) < MININD || indent > MAXIND) {
  2323. X         fprintf(stderr, "%s: bad indention -- %d\n", pname, indent);
  2324. X         exit(1);
  2325. X       }
  2326. X       break;
  2327. X     case 'f':                  /* Postscript font */
  2328. X       pft = optarg;
  2329. X       break;
  2330. X     case 's':                  /* Font size */
  2331. X       pps = atof(optarg);
  2332. X       pvs = pps + 2.0;
  2333. X       break;
  2334. X    }
  2335. X  }
  2336. X
  2337. X  /* Get and tree list file name */
  2338. X  if((argc - optind) != 1) {
  2339. X    fprintf(stderr, "%s\n", &usage[5]);
  2340. X    exit(1);
  2341. X  }
  2342. X  else
  2343. X    list = argv[optind];
  2344. X
  2345. X  /* Open directory tree list file */
  2346. X  if( !(fp = fopen(list, "r"))) {
  2347. X    fprintf(stderr, "%s: Cannot open list file %s\n", pname, list);
  2348. X    exit(1);
  2349. X  }
  2350. X
  2351. X  /* Init default graphical character set if needed */
  2352. X  if(grafset == UNULL)
  2353. X    initterm(1);
  2354. X
  2355. X  /* Read, scan and write tree list file line by line */
  2356. X  while(fgets(line, sizeof(line), fp)) {
  2357. X    line[strlen(line)-1] = '\0';
  2358. X    switch(c = line[0]) {
  2359. X      default:                  /* Ignore */
  2360. X       break;
  2361. X      case 'R':                 /* Pathname of rootdirectory */
  2362. X       strncpy(root, &line[1], sizeof(root));
  2363. X       putheader();
  2364. X       break;
  2365. X      case 'H':                 /* Valid tree list entry */
  2366. X      case 'L':
  2367. X      case 'U':
  2368. X      case 'V':
  2369. X       putentry(line);
  2370. X       break;
  2371. X    }
  2372. X  }
  2373. X  fclose(fp);
  2374. X
  2375. X  /* Write trailer and exit */
  2376. X  puttrailer();
  2377. X  exit(0);
  2378. X
  2379. X} /* main() */
  2380. X
  2381. END_OF_FILE
  2382. if test 16227 -ne `wc -c <'src/utree.prlist.c'`; then
  2383.     echo shar: \"'src/utree.prlist.c'\" unpacked with wrong size!
  2384. fi
  2385. # end of 'src/utree.prlist.c'
  2386. fi
  2387. echo shar: End of archive 4 \(of 8\).
  2388. cp /dev/null ark4isdone
  2389. MISSING=""
  2390. for I in 1 2 3 4 5 6 7 8 ; do
  2391.     if test ! -f ark${I}isdone ; then
  2392.     MISSING="${MISSING} ${I}"
  2393.     fi
  2394. done
  2395. if test "${MISSING}" = "" ; then
  2396.     echo You have unpacked all 8 archives.
  2397.     rm -f ark[1-9]isdone
  2398. else
  2399.     echo You still need to unpack the following archives:
  2400.     echo "        " ${MISSING}
  2401. fi
  2402. ##  End of shell archive.
  2403. exit 0
  2404.