home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume16 / cap / part01 next >
Encoding:
Internet Message Format  |  1991-01-12  |  14.0 KB

  1. From: sjg@zen.void.oz.au (Simon J. Gerraty)
  2. Newsgroups: comp.sources.misc
  3. Subject: v16i069:  generic capability database routines., Part01/01
  4. Message-ID: <1991Jan12.051632.8982@sparky.IMD.Sterling.COM>
  5. Date: 12 Jan 91 05:16:32 GMT
  6. Approved: kent@sparky.imd.sterling.com
  7. X-Checksum-Snefru: 264244e6 52db193b bb402b5a 7712b3f5
  8.  
  9. Submitted-by: sjg@zen.void.oz.au (Simon J. Gerraty)
  10. Posting-number: Volume 16, Issue 69
  11. Archive-name: cap/part01
  12.  
  13. facility analagous to termcap(3X) but in a slightly more general
  14. manner.   These routines can be used to extract entries from
  15. files that follow the termcap(5),printcap(5) format.
  16.  
  17. cap_getent() will search up to MAX_DBASE files for an entry and
  18. follows ":tc=like:" pointers.  The header section of cap.c
  19. includes the documentation.
  20.  
  21. --------------------(cut)--------------------
  22. echo x - cap.c
  23. sed 's/^X//' >cap.c <<'*-*-END-of-cap.c-*-*'
  24. X/* NAME:
  25. X *      cap.c - generic capability database facility.
  26. X *
  27. X * SYNOPSIS:
  28. X *      int cap_getent(char *buf, char *name);
  29. X *      int cap_ngetent(char *buf, char *name, int nbytes);
  30. X *      char *cap_getstr(char *id, char **area);
  31. X *      int cap_getnum(char *id);
  32. X *      int cap_getflag(char *id);
  33. X *
  34. X * DESCRIPTION:
  35. X *      The cap module provides functions similar to termcap(3X).
  36. X *      It is more general however.  An application can 
  37. X *      initialize *_cap_database[0-MAX_DBASE] to a list of 
  38. X *      database files to search for cap entries.
  39. X *
  40. X *      Each file refered to by _cap_database[n] is expected to 
  41. X *      follow the layout of /etc/termcap.  If _cap_database[0] 
  42. X *      is not initialized the package "should" behave like the 
  43. X *      equivalent termcap facilities.
  44. X *      
  45. X *      An application must call cap_getent or cap_ngetent 
  46. X *      before calling any of the other functions.  cap_getent 
  47. X *      simply calls cap_ngetent with an assumed size of the 
  48. X *      buffer provided by the application.  The buffer passed 
  49. X *      to cap_ngetent must remain valid for all subsequent 
  50. X *      calls to this module.
  51. X *      
  52. X *      cap_ngetent will "follow" a ":tc=like:" at the end of an 
  53. X *      an entry using recursive calls to cap_ngetent.  If the 
  54. X *      "like" entry is not found in any of the files refered to 
  55. X *      by *_cap_database[] it is left as ":tc=like:".
  56. X *
  57. X *
  58. X * RETURN VALUE:
  59. X *      cap_getent 1==success, 0==entry not found, -1==error.
  60. X *      cap_ngetent nbytes copied==success, 0==entry not found, -1==error.
  61. X *      cap_getstr str==success, NULL==failure.
  62. X *      cap_getnum num=success, -1==failure.
  63. X *      cap_getflag  1==success, 0==not found
  64. X *
  65. X * FILES:
  66. X *      /etc/termcap     default database
  67. X *
  68. X * SEE ALSO:
  69. X *      termcap(3X), termcap(5), printcap(5).
  70. X *
  71. X * BUGS:
  72. X *      cap_get{str,num,flag} do not tolerate any spaces between 
  73. X *      the : and the name.  That is ":tc=like:" is ok, but 
  74. X *      ": tc=like:" is not, nor is ":tc =like:".  Whether this 
  75. X *      is a bug or a feature is a bit subjective :-)
  76. X *      
  77. X *      cap_getstr does not interperate the content of the 
  78. X *      string capability found in any way.  (unlike tgetstr(3)).
  79. X *      
  80. X * AMENDED:
  81. X *      91/01/08  16:58:12  (sjg)
  82. X *
  83. X * RELEASED:
  84. X *      91/01/08  16:58:15  v1.8
  85. X *
  86. X * SCCSID:
  87. X *      @(#)cap.c  1.8  91/01/08  16:58:12  (sjg)
  88. X *
  89. X *      Copyright (c) 1989 Simon J. Gerraty.
  90. X *
  91. X *      This is free software.  It comes with NO WARRANTY.
  92. X *      Permission to use, modify and distribute this source code 
  93. X *      is granted subject to the following conditions.
  94. X *      1/ that that the above copyright notice and this notice 
  95. X *      are preserved in all copies and that due credit be given 
  96. X *      to the author.  
  97. X *      2/ that any changes to this code are clearly commented 
  98. X *      as such so that the author does get blamed for bugs 
  99. X *      other than his own.
  100. X *      
  101. X *      Please send copies of changes and bug-fixes to:
  102. X *      sjg@zen.void.oz.au
  103. X *                                                                
  104. X */
  105. X#ifndef lint
  106. Xstatic char  sccs_id[] = "@(#)cap.c     1.8  91/01/08  16:58:12  (sjg)";
  107. X#endif
  108. X
  109. X/* include files */
  110. X#include <stdio.h>
  111. X#ifdef __STDC__
  112. X# include <stdlib.h>
  113. X#endif
  114. X#ifdef USG
  115. X# include <string.h>
  116. X#else
  117. X# include <strings.h>
  118. X# define strchr index
  119. X# define strrchr rindex
  120. X#endif /* USG */
  121. X
  122. X#define EXTERN
  123. X#include "cap.h"
  124. X#undef EXTERN
  125. X
  126. X/* some useful #defines */
  127. X#define ENTRY
  128. X#define LOCAL static
  129. X#define TRUE  1
  130. X#define FALSE 0
  131. X
  132. X#if defined(__STDC__) || defined(PROTO)
  133. X# define _P_(p) p
  134. X#else
  135. X# define _P_(p) ()
  136. X#endif
  137. X
  138. X/* manifest constants */
  139. X
  140. X/* macros */
  141. X
  142. X/* globals */
  143. Xstatic char    capname[CAP_NAMESZ + 1];
  144. X
  145. X
  146. X/* external variable declarations */
  147. X
  148. X/* function prototypes */
  149. Xextern char *getenv    _P_((char *));
  150. Xextern char *strstr    _P_((const char *s1, const char *s2));
  151. X  
  152. X
  153. X
  154. X/* functions */
  155. X
  156. X
  157. X/* NAME:
  158. X *      cap_getent - look for capability description
  159. X *
  160. X * SYNOPSIS:
  161. X *      int cap_getent(char *buf, char *name);
  162. X *
  163. X * DESCRIPTION:
  164. X *      Look for cap entry "name" in either /etc/termcap, the 
  165. X *      environment or the files listed in *_cap_database[].
  166. X *      If an entry is found it is copied to "buf".
  167. X *      ":tc=like:" entries cause a recursive call to cap_ngetent.
  168. X *      
  169. X * RETURN VALUE:
  170. X *      1==success, 0==entry not found, -1==failure
  171. X */
  172. X
  173. XENTRY int
  174. Xcap_getent(buf, name)
  175. X  char     *buf;
  176. X  char    *name;
  177. X{
  178. X  register int    i;
  179. X  
  180. X  return (((i = cap_ngetent(buf, name, (CAP_BUFSZ - 1))) > 0)
  181. X      ? 1 : i);
  182. X}
  183. X
  184. X
  185. X/* NAME:
  186. X *      cap_ngetent - look for capability description
  187. X *
  188. X * SYNOPSIS:
  189. X *      int cap_ngetent(char *buf, char *name, int nbytes);
  190. X *
  191. X * DESCRIPTION:
  192. X *      Look for cap entry "name" in either /etc/termcap, the 
  193. X *      environment or the files listed in *_cap_database[].
  194. X *      If an entry is found it is copied to "buf" up to a 
  195. X *      maximum of "nbytes".
  196. X *      ":tc=like:" entries cause a recursive call to cap_ngetent.
  197. X *      
  198. X * RETURN VALUE:
  199. X *      nbytes copied==success, 0==entry not found, -1==failure
  200. X */
  201. X
  202. XENTRY int
  203. Xcap_ngetent(buf, name, nbytes)
  204. X  char     *buf;
  205. X  char    *name;
  206. X  int    nbytes;
  207. X{
  208. X  static    callcnt = 0;        /* check if we're recursing */
  209. X  register char    *rcp;
  210. X  register int    len;
  211. X  FILE        *fp;
  212. X  char        *cp;
  213. X  char        tc_name[CAP_NAMESZ + 1];
  214. X  int        finished = FALSE;
  215. X  int        found = FALSE;
  216. X  int        max = nbytes;
  217. X  int        i = 0;
  218. X  
  219. X  if (max <= 0)
  220. X    return -1;
  221. X  if (callcnt == 0)
  222. X  {
  223. X    if (_cap_database[0] == NULL)
  224. X    {
  225. X      if ((rcp = getenv("TERMCAP")) != NULL)
  226. X      {
  227. X    if (*rcp == '/')
  228. X      _cap_database[0] = rcp;
  229. X    else
  230. X      if (strncmp(getenv("TERM"), name, strlen(name)))
  231. X        _cap_database[0] = "/etc/termcap";
  232. X    _cap_database[1] = NULL;
  233. X      }
  234. X      else
  235. X    return -1;        /* nothing to work with */
  236. X    }
  237. X    _cap_buf = buf;            /* needed by other functions */
  238. X    if (_cap_database[0] == NULL)
  239. X    {
  240. X      /*
  241. X       * we have a cap entry in the environment
  242. X       */
  243. X      (void) strncpy(buf, rcp, nbytes);
  244. X      buf[nbytes] = '\0';
  245. X      return (strlen(buf));
  246. X    }
  247. X  }
  248. X  /*
  249. X   * we have to look up "name" in the database file(s).
  250. X   */
  251. X  for (i = 0; max > 0 && found == FALSE &&
  252. X       i < MAX_DBASE && _cap_database[i]; i++)
  253. X  {
  254. X    if ((fp = fopen(_cap_database[i], "r")) == NULL)
  255. X      continue ;            /* try next one */
  256. X    cp = buf;
  257. X    rcp = buf;
  258. X    finished = FALSE;
  259. X    
  260. X    while (!(finished))
  261. X    {
  262. X      if (max <= 0 || (fgets(cp, max, fp) == NULL))
  263. X    finished = TRUE;
  264. X      else
  265. X      {
  266. X    len = strlen(cp);
  267. X    rcp = cp;
  268. X    while (*rcp == ' ' || *rcp == '\t')
  269. X      rcp++;
  270. X    if (*rcp && *rcp != '\n' && *rcp != '#')
  271. X    {
  272. X      /* not a comment or blank */
  273. X      if (!found)
  274. X        if (*rcp != ':')    /* start of an entry */
  275. X        {
  276. X          register char *rcp2;
  277. X
  278. X          /*
  279. X           * be sure that the names match
  280. X           * not part of another tc=
  281. X           */
  282. X          if (rcp2 = strchr(rcp, ':'))
  283. X        *rcp2 = '\0';
  284. X          found = (strstr(rcp, name) != NULL);
  285. X          if (found && rcp2)
  286. X          {
  287. X        *rcp2 = ':';
  288. X        if (callcnt)
  289. X          /*
  290. X           * We are a recursive call,
  291. X           * we don't want the name part or the ':'.
  292. X           */
  293. X          rcp = ++rcp2;
  294. X          }
  295. X        }
  296. X      if (found)
  297. X      {
  298. X        if (rcp != cp)
  299. X          rcp = strcpy(cp, rcp);
  300. X        len = strlen(rcp);
  301. X        if (rcp[len - 2] == '\\') /* more to get */
  302. X        {
  303. X          len -= 2;        /* lose the \ and \n */
  304. X          rcp[len] = '\0';
  305. X          cp = &rcp[len];
  306. X        }
  307. X        else
  308. X          finished = TRUE;
  309. X        max -= len;
  310. X      }
  311. X    }
  312. X      }
  313. X    }
  314. X    (void) fclose(fp);
  315. X  }
  316. X  if (found)
  317. X  {
  318. X    /*
  319. X     * allow for tc=termtype
  320. X     * as the last entry.
  321. X     */
  322. X    cp = tc_name;
  323. X    if ((name = cap_getstr("tc", &cp)) != NULL)
  324. X    {
  325. X      if ((rcp = strstr(buf, ":tc=")) != NULL)
  326. X      {
  327. X    callcnt++;
  328. X    if ((len = cap_ngetent(++rcp, name, max)) <= 0)
  329. X      (void) sprintf(rcp, "tc=%s\n", tc_name);
  330. X    else
  331. X      max -= len;
  332. X    callcnt--;
  333. X      }
  334. X    }
  335. X  }
  336. X  buf[nbytes] = '\0';
  337. X  if (max < 0)
  338. X    max = 0;
  339. X  return (found ? nbytes - max : 0);
  340. X}
  341. X
  342. X
  343. X/* NAME:
  344. X *      cap_getstr - get a string capability
  345. X *
  346. X * SYNOPSIS:
  347. X *      cap_getstr()
  348. X *
  349. X * DESCRIPTION:
  350. X *      Look for an item ":id=str:" in the buffer pointed to by 
  351. X *      _cap_buf.  If found copy "str" into the buffer at "area" 
  352. X *      and advance "area".  If all ok return a pointer to "str" 
  353. X *      within the user's buffer (ie. the previous value of 
  354. X *      "*area". 
  355. X *      
  356. X *      Unlike tgetstr(3), this function does not interperate 
  357. X *      the contents of "str" in anyway.
  358. X *
  359. X * RETURN VALUE:
  360. X *      str==success, -1==failure
  361. X */
  362. X
  363. XENTRY char *
  364. Xcap_getstr(id, area)
  365. X  char    *id;
  366. X  char    **area;
  367. X{
  368. X  register char    *rcp;
  369. X  register int    len;
  370. X  
  371. X  (void) sprintf(capname, ":%s=", id);
  372. X  if ((rcp = strstr(_cap_buf, capname)) != NULL)
  373. X  {
  374. X    rcp += strlen(capname);
  375. X    len = strcspn(rcp, ":\n");
  376. X    rcp = strncpy((*area), rcp, len);
  377. X    (*area)[len] = '\0';
  378. X    *area += ++len;
  379. X    return rcp;
  380. X  }
  381. X  return NULL;
  382. X}
  383. X
  384. X
  385. X/* NAME:
  386. X *      cap_getnum - get a numeric capability
  387. X *
  388. X * SYNOPSIS:
  389. X *      cap_getnum()
  390. X *
  391. X * DESCRIPTION:
  392. X *      This function looks for an item ":id#num:" in the buffer 
  393. X *      pointer to by _cap_buf.  If found it returns "num" 
  394. X *      otherwise -1.
  395. X *
  396. X * RETURN VALUE:
  397. X *      num==success, -1==failure
  398. X */
  399. X
  400. XENTRY int
  401. Xcap_getnum(id)
  402. X  char    *id;
  403. X{
  404. X  register char    *rcp;
  405. X  
  406. X  (void) sprintf(capname, ":%s#", id);
  407. X  if ((rcp = strstr(_cap_buf, capname)) != NULL)
  408. X  {
  409. X    rcp += strlen(capname);
  410. X    return (atoi(rcp));
  411. X  }
  412. X  return -1;
  413. X}
  414. X
  415. X
  416. X/* NAME:
  417. X *      cap_getflag - check for presence of capability
  418. X *
  419. X * SYNOPSIS:
  420. X *      cap_getflag()
  421. X *
  422. X * DESCRIPTION:
  423. X *      This function simply looks for any item that matches the 
  424. X *      RE ":id[:=#]" in the buffer pointed to by _cap_buf.  
  425. X *      That is, it will return TRUE as soon as it finds a 
  426. X *      boolean, numeric or string capability with the right 
  427. X *      name "id".
  428. X *
  429. X * RETURN VALUE:
  430. X *      1==found, 0==not found
  431. X */
  432. X
  433. XENTRY int
  434. Xcap_getflag(id)
  435. X  char    *id;
  436. X{
  437. X  register char    *rcp;
  438. X  
  439. X  (void) sprintf(capname, ":%s", id);
  440. X  if ((rcp = strstr(_cap_buf, capname)) != NULL)
  441. X  {
  442. X    rcp += strlen(capname);
  443. X    return (strcspn(rcp, "=#:\n") == 0);
  444. X  }
  445. X  return 0;
  446. X}
  447. X
  448. X/* This lot (for GNU-Emacs) goes at the end of the file. */
  449. X/* 
  450. X * Local Variables:
  451. X * version-control:t
  452. X * comment-column:40
  453. X * End:
  454. X */
  455. *-*-END-of-cap.c-*-*
  456. echo x - cap.h
  457. sed 's/^X//' >cap.h <<'*-*-END-of-cap.h-*-*'
  458. X/* NAME:
  459. X *      cap.h - definitions for cap module
  460. X *
  461. X * SYNOPSIS:
  462. X *      int cap_getent(char *buf, char *name);
  463. X *      int cap_ngetent(char *buf, char *name, int nbytes);
  464. X *      int cap_getnum(char *id);
  465. X *      int cap_getflag(char *id);
  466. X *      char *cap_getstr(char *id, char **area);
  467. X *
  468. X * DESCRIPTION:
  469. X *      The cap module provides functions similar to termcap(3X).
  470. X *      Refer to the documentation in cap.c for full description.
  471. X *
  472. X * SEE ALSO:
  473. X *      cap.c
  474. X *
  475. X * AMENDED:
  476. X *      91/01/04  13:20:04  (sjg)
  477. X *
  478. X * RELEASED:
  479. X *      91/01/04  13:20:06  v1.4
  480. X *
  481. X * SCCSID:
  482. X *      @(#)cap.h  1.4  91/01/04  13:20:04  (sjg)
  483. X *
  484. X *      Copyright (c) 1989 Simon J. Gerraty.
  485. X *
  486. X *      This is free software.  It comes with NO WARRANTY.
  487. X *      Permission to use, modify and distribute this source code 
  488. X *      is granted subject to the following conditions.
  489. X *      1/ that that the above copyright notice and this notice 
  490. X *      are preserved in all copies and that due credit be given 
  491. X *      to the author.  
  492. X *      2/ that any changes to this code are clearly commented 
  493. X *      as such so that the author does get blamed for bugs 
  494. X *      other than his own.
  495. X *      
  496. X *      Please send copies of changes and bug-fixes to:
  497. X *      sjg@zen.void.oz.au
  498. X */
  499. X
  500. X/* some useful #defines */
  501. X#ifndef EXTERN
  502. X# define EXTERN extern
  503. X# define EXTERN_DEFINED
  504. X#endif
  505. X
  506. X#define ENTRY
  507. X#define LOCAL static
  508. X#define TRUE  1
  509. X#define FALSE 0
  510. X
  511. X#if defined(__STDC__) || defined(PROTO)
  512. X# define _P_(p) p
  513. X#else
  514. X# define _P_(p) ()
  515. X#endif
  516. X
  517. X/* manifest constants */
  518. X#define MAX_DBASE 10
  519. X#define CAP_BUFSZ 1024
  520. X#define CAP_NAMESZ 50
  521. X
  522. X/* struct / union */
  523. X
  524. X/* macros */
  525. X
  526. X/* external variable declarations */
  527. XEXTERN char    *_cap_database[MAX_DBASE];
  528. XEXTERN char    *_cap_buf;
  529. X
  530. X/* function prototypes */
  531. X
  532. XENTRY int     cap_getent    _P_((char *buf, char *name));
  533. XENTRY int     cap_ngetent    _P_((char *buf, char *name, int nbytes));
  534. XENTRY int     cap_getnum    _P_((char *id));
  535. XENTRY int     cap_getflag    _P_((char *id));
  536. XENTRY char     *cap_getstr    _P_((char *id, char **area));
  537. X
  538. X
  539. X
  540. X/* This lot goes at the END */
  541. X/* be sure not to interfere with anyone else's idea about EXTERN */
  542. X#ifdef EXTERN_DEFINED
  543. X# undef EXTERN_DEFINED
  544. X# undef EXTERN
  545. X#endif
  546. X/*
  547. X * Local Variables:
  548. X * version-control:t
  549. X * comment-column:40
  550. X * End:
  551. X */
  552. *-*-END-of-cap.h-*-*
  553. exit
  554.  
  555. exit 0 # Just in case...
  556. -- 
  557. Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
  558. Sterling Software, IMD           UUCP:     uunet!sparky!kent
  559. Phone:    (402) 291-8300         FAX:      (402) 291-4362
  560. Please send comp.sources.misc-related mail to kent@uunet.uu.net.
  561.