cap_text.c
上传用户:pycemail
上传日期:2007-01-04
资源大小:329k
文件大小:8k
源码类别:

Ftp客户端

开发平台:

Unix_Linux

  1. /*
  2.  * $Id: cap_text.c,v 1.2 1999/09/07 23:14:19 macgyver Exp $
  3.  *
  4.  * Copyright (c) 1997-8 Andrew G Morgan <morgan@linux.kernel.org>
  5.  * Copyright (c) 1997 Andrew Main <zefram@dcs.warwick.ac.uk>
  6.  *
  7.  * See end of file for Log.
  8.  *
  9.  * This file deals with exchanging internal and textual
  10.  * representations of capability sets.
  11.  */
  12. #define LIBCAP_PLEASE_INCLUDE_ARRAY
  13. #include "libcap.h"
  14. #include <ctype.h>
  15. #include <stdio.h>
  16. /* Maximum output text length (16 per cap) */
  17. #define CAP_TEXT_SIZE    (16*__CAP_BITS)
  18. #define LIBCAP_EFF   01
  19. #define LIBCAP_INH   02
  20. #define LIBCAP_PER   04
  21. /*
  22.  * Parse a textual representation of capabilities, returning an internal
  23.  * representation.
  24.  */
  25. #define setbits(A,B) _setbits((__cap_s *)A, (__cap_s *)B)
  26. static void _setbits(__cap_s *a, __cap_s *b)
  27. {
  28.     int n;
  29.     for (n = __CAP_BLKS; n--; )
  30. a->_blk[n] |= b->_blk[n];
  31. }
  32. #define clrbits(A,B) _clrbits((__cap_s *)A, (__cap_s *)B)
  33. static void _clrbits(__cap_s *a, __cap_s *b)
  34. {
  35.     int n;
  36.     for (n = __CAP_BLKS; n--; )
  37. a->_blk[n] &= ~b->_blk[n];
  38. }
  39. static char const *namcmp(char const *str, char const *nam)
  40. {
  41.     while (*nam && tolower((unsigned char)*str) == *nam) {
  42. str++;
  43. nam++;
  44.     }
  45.     if (*nam || isalnum((unsigned char)*str) || *str == '_')
  46. return NULL;
  47.     return str;
  48. }
  49. static int lookupname(char const **strp)
  50. {
  51.     char const *str = *strp;
  52.     if (isdigit(*str)) {
  53. unsigned long n = strtoul(str, (char **)&str, 0);
  54. if (n >= __CAP_BITS)
  55.     return -1;
  56. *strp = str;
  57. return n;
  58.     } else {
  59. char const *s;
  60. int n;
  61. for (n = __CAP_BITS; n--; )
  62.     if (_cap_names[n] && (s = namcmp(str, _cap_names[n]))) {
  63. *strp = s;
  64. return n;
  65.     }
  66. return -1;
  67.     }
  68. }
  69. cap_t cap_from_text(const char *str)
  70. {
  71.     cap_t res;
  72.     __cap_s allones;
  73.     int n;
  74.     if (str == NULL) {
  75. _cap_debug("bad argument");
  76. errno = EINVAL;
  77. return NULL;
  78.     }
  79.     if (!(res = cap_init()))
  80. return NULL;
  81.     for (n = __CAP_BLKS; n--; )
  82. allones._blk[n] = -1;
  83.     _cap_debug("%s", str);
  84.     for (;;) {
  85. char op;
  86. int flags = 0, listed=0;
  87. __cap_s list = {{0}};
  88. /* skip leading spaces */
  89. while (isspace((unsigned char)*str))
  90.     str++;
  91. if (!*str) {
  92.     _cap_debugcap("e = ", &res->set.effective);
  93.     _cap_debugcap("i = ", &res->set.inheritable);
  94.     _cap_debugcap("p = ", &res->set.permitted);
  95.     return res;
  96. }
  97. /* identify caps specified by this clause */
  98. if (isalnum((unsigned char)*str) || *str == '_') {
  99.     for (;;) {
  100. if (namcmp(str, "all")) {
  101.     str += 3;
  102.     list = allones;
  103. } else {
  104.     n = lookupname(&str);
  105.     if (n == -1)
  106. goto bad;
  107.     list.raise_cap(n);
  108. }
  109. if (*str != ',')
  110.     break;
  111. if (!isalnum((unsigned char)*++str) && *str != '_')
  112.     goto bad;
  113.     }
  114.     listed = 1;
  115. } else if (*str == '+' || *str == '-')
  116.     goto bad;                    /* require a list of capabilities */
  117. else
  118.     list = allones;
  119. /* identify first operation on list of capabilities */
  120. op = *str++;
  121. if (op == '=' && (*str == '+' || *str == '-')) {
  122.     if (!listed)
  123. goto bad;
  124.     op = (*str++ == '+' ? 'P':'M'); /* skip '=' and take next op */
  125. } else if (op != '+' && op != '-' && op != '=')
  126.     goto bad;
  127. /* cycle through list of actions */
  128. do {
  129.     _cap_debug("next char = `%c'", *str);
  130.     if (*str && !isspace(*str)) {
  131. switch (*str++) {    /* Effective, Inheritable, Permitted */
  132. case 'e':
  133.     flags |= LIBCAP_EFF;
  134.     break;
  135. case 'i':
  136.     flags |= LIBCAP_INH;
  137.     break;
  138. case 'p':
  139.     flags |= LIBCAP_PER;
  140.     break;
  141. default:
  142.     goto bad;
  143. }
  144.     } else if (op != '=') {
  145. _cap_debug("only '=' can be followed by space");
  146. goto bad;
  147.     }
  148.     _cap_debug("how to read?");
  149.     switch (op) {               /* how do we interpret the caps? */
  150.     case '=':
  151.     case 'P':                                              /* =+ */
  152.     case 'M':                                              /* =- */
  153. clrbits(&res->set.effective,   &list);
  154. clrbits(&res->set.inheritable, &list);
  155. clrbits(&res->set.permitted,   &list);
  156. /* fall through */
  157. if (op == 'M')
  158.     goto minus;
  159.     case '+':
  160. if (flags & LIBCAP_EFF)
  161.     setbits(&res->set.effective,   &list);
  162. if (flags & LIBCAP_INH)
  163.     setbits(&res->set.inheritable, &list);
  164. if (flags & LIBCAP_PER)
  165.     setbits(&res->set.permitted,   &list);
  166. break;
  167.     case '-':
  168.     minus:
  169.         if (flags & LIBCAP_EFF)
  170.     clrbits(&res->set.effective,   &list);
  171. if (flags & LIBCAP_INH)
  172.     clrbits(&res->set.inheritable, &list);
  173. if (flags & LIBCAP_PER)
  174.     clrbits(&res->set.permitted,   &list);
  175. break;
  176.     }
  177.     /* new directive? */
  178.     if (*str == '+' || *str == '-') {
  179. if (!listed) {
  180.     _cap_debug("for + & - must list capabilities");
  181.     goto bad;
  182. }
  183. flags = 0;                       /* reset the flags */
  184. op = *str++;
  185. if (!isalpha(*str))
  186.     goto bad;
  187.     }
  188. } while (*str && !isspace(*str));
  189. _cap_debug("next clause");
  190.     }
  191. bad:
  192.     cap_free(&res);
  193.     errno = EINVAL;
  194.     return NULL;
  195. }
  196. /*
  197.  * Convert an internal representation to a textual one. The textual
  198.  * representation is stored in static memory. It will be overwritten
  199.  * on the next occasion that this function is called.
  200.  */
  201. static int getstateflags(cap_t caps, int capno)
  202. {
  203.     int f = 0;
  204.     if (isset_cap((__cap_s *)(&caps->set.effective),capno))
  205. f |= LIBCAP_EFF;
  206.     if (isset_cap((__cap_s *)(&caps->set.inheritable),capno))
  207. f |= LIBCAP_INH;
  208.     if (isset_cap((__cap_s *)(&caps->set.permitted),capno))
  209. f |= LIBCAP_PER;
  210.     return f;
  211. }
  212. #define CAP_TEXT_BUFFER_ZONE 100
  213. char *cap_to_text(cap_t caps, ssize_t *length_p)
  214. {
  215.     static char buf[CAP_TEXT_SIZE+CAP_TEXT_BUFFER_ZONE];
  216.     char *p;
  217.     int histo[8] = {0};
  218.     int m, n, t;
  219.     /* Check arguments */
  220.     if (!good_cap_t(caps)) {
  221. errno = EINVAL;
  222. return NULL;
  223.     }
  224.     _cap_debugcap("e = ", &caps->set.effective);
  225.     _cap_debugcap("i = ", &caps->set.inheritable);
  226.     _cap_debugcap("p = ", &caps->set.permitted);
  227.     for (n = __CAP_BITS; n--; )
  228. histo[getstateflags(caps, n)]++;
  229.     for (m=t=7; t--; )
  230. if (histo[t] > histo[m])
  231.     m = t;
  232.     /* blank is not a valid capability set */
  233.     p = sprintf(buf, "=%s%s%s",
  234. (m & LIBCAP_EFF) ? "e" : "",
  235. (m & LIBCAP_INH) ? "i" : "",
  236. (m & LIBCAP_PER) ? "p" : "" ) + buf;
  237.     for (t = 8; t--; )
  238. if (t != m && histo[t]) {
  239.     *p++ = ' ';
  240.     for (n = 0; n != __CAP_BITS; n++)
  241. if (getstateflags(caps, n) == t) {
  242.     if (_cap_names[n])
  243. p += sprintf(p, "%s,", _cap_names[n]);
  244.     else
  245. p += sprintf(p, "%d,", n);
  246.     if (p - buf > CAP_TEXT_SIZE) {
  247. errno = ERANGE;
  248. return NULL;
  249.     }
  250. }
  251.     p--;
  252.     n = t & ~m;
  253.     if (n)
  254. p += sprintf(p, "+%s%s%s",
  255.      (n & LIBCAP_EFF) ? "e" : "",
  256.      (n & LIBCAP_INH) ? "i" : "",
  257.      (n & LIBCAP_PER) ? "p" : "");
  258.     n = ~t & m;
  259.     if (n)
  260. p += sprintf(p, "-%s%s%s",
  261.      (n & LIBCAP_EFF) ? "e" : "",
  262.      (n & LIBCAP_INH) ? "i" : "",
  263.      (n & LIBCAP_PER) ? "p" : "");
  264.     if (p - buf > CAP_TEXT_SIZE) {
  265. errno = ERANGE;
  266. return NULL;
  267.     }
  268. }
  269.     _cap_debug("%s", buf);
  270.     if (length_p) {
  271. *length_p = p - buf;
  272.     }
  273.     return (strdup(buf));
  274. }
  275. /*
  276.  * $Log: cap_text.c,v $
  277.  * Revision 1.2  1999/09/07 23:14:19  macgyver
  278.  * Updated capabilities library and model.
  279.  *
  280.  * Revision 1.2  1999/04/17 23:25:09  morgan
  281.  * fixes from peeterj
  282.  *
  283.  * Revision 1.1.1.1  1999/04/17 22:16:31  morgan
  284.  * release 1.0 of libcap
  285.  *
  286.  * Revision 1.4  1998/05/24 22:54:09  morgan
  287.  * updated for 2.1.104
  288.  *
  289.  * Revision 1.3  1997/05/04 05:37:00  morgan
  290.  * case sensitvity to capability flags
  291.  *
  292.  * Revision 1.2  1997/04/28 00:57:11  morgan
  293.  * zefram's replacement file with a number of bug fixes from AGM
  294.  *
  295.  * Revision 1.1  1997/04/21 04:32:52  morgan
  296.  * Initial revision
  297.  *
  298.  */