home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / unix / volume26 / utree / part04 < prev    next >
Encoding:
Text File  |  1992-09-06  |  75.1 KB  |  2,398 lines

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