avpair.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795
  1. /*
  2. * $Id: avpair.c,v 1.1 2004/11/14 07:26:26 paulus Exp $
  3. *
  4. * Copyright (C) 1995 Lars Fenneberg
  5. *
  6. * Copyright 1992 Livingston Enterprises, Inc.
  7. *
  8. * Copyright 1992,1993, 1994,1995 The Regents of the University of Michigan
  9. * and Merit Network, Inc. All Rights Reserved
  10. *
  11. * See the file COPYRIGHT for the respective terms and conditions.
  12. * If the file is missing contact me at lf@elemental.net
  13. * and I'll send you a copy.
  14. *
  15. */
  16. #include <includes.h>
  17. #include <radiusclient.h>
  18. static void rc_extract_vendor_specific_attributes(int attrlen,
  19. unsigned char *ptr,
  20. VALUE_PAIR **vp);
  21. /*
  22. * Function: rc_avpair_add
  23. *
  24. * Purpose: add an attribute-value pair to the given list.
  25. *
  26. * Returns: pointer to added a/v pair upon success, NULL pointer upon failure.
  27. *
  28. * Remarks: Always appends the new pair to the end of the list.
  29. *
  30. */
  31. VALUE_PAIR *rc_avpair_add (VALUE_PAIR **list, int attrid, void *pval, int len,
  32. int vendorcode)
  33. {
  34. VALUE_PAIR *vp;
  35. vp = rc_avpair_new (attrid, pval, len, vendorcode);
  36. if (vp != (VALUE_PAIR *) NULL)
  37. {
  38. rc_avpair_insert (list, (VALUE_PAIR *) NULL, vp);
  39. }
  40. return vp;
  41. }
  42. /*
  43. * Function: rc_avpair_assign
  44. *
  45. * Purpose: assign the given value to an attribute-value pair.
  46. *
  47. * Returns: 0 on success,
  48. * -1 on failure.
  49. *
  50. */
  51. int rc_avpair_assign (VALUE_PAIR *vp, void *pval, int len)
  52. {
  53. int result = -1;
  54. switch (vp->type)
  55. {
  56. case PW_TYPE_STRING:
  57. if (((len == 0) && (strlen ((char *) pval)) > AUTH_STRING_LEN)
  58. || (len > AUTH_STRING_LEN)) {
  59. error("rc_avpair_assign: bad attribute length");
  60. return result;
  61. }
  62. if (len > 0) {
  63. memcpy(vp->strvalue, (char *)pval, len);
  64. vp->strvalue[len] = '\0';
  65. vp->lvalue = len;
  66. } else {
  67. strncpy (vp->strvalue, (char *) pval, AUTH_STRING_LEN);
  68. vp->lvalue = strlen((char *) pval);
  69. }
  70. result = 0;
  71. break;
  72. case PW_TYPE_DATE:
  73. case PW_TYPE_INTEGER:
  74. case PW_TYPE_IPADDR:
  75. vp->lvalue = * (UINT4 *) pval;
  76. result = 0;
  77. break;
  78. default:
  79. error("rc_avpair_assign: unknown attribute %d", vp->type);
  80. }
  81. return result;
  82. }
  83. /*
  84. * Function: rc_avpair_new
  85. *
  86. * Purpose: make a new attribute-value pair with given parameters.
  87. *
  88. * Returns: pointer to generated a/v pair when successful, NULL when failure.
  89. *
  90. */
  91. VALUE_PAIR *rc_avpair_new (int attrid, void *pval, int len, int vendorcode)
  92. {
  93. VALUE_PAIR *vp = (VALUE_PAIR *) NULL;
  94. DICT_ATTR *pda;
  95. if ((pda = rc_dict_getattr (attrid, vendorcode)) == (DICT_ATTR *) NULL)
  96. {
  97. error("rc_avpair_new: unknown attribute %d", attrid);
  98. }
  99. else
  100. {
  101. if ((vp = (VALUE_PAIR *) malloc (sizeof (VALUE_PAIR)))
  102. != (VALUE_PAIR *) NULL)
  103. {
  104. strncpy (vp->name, pda->name, sizeof (vp->name));
  105. vp->attribute = attrid;
  106. vp->vendorcode = vendorcode;
  107. vp->next = (VALUE_PAIR *) NULL;
  108. vp->type = pda->type;
  109. if (rc_avpair_assign (vp, pval, len) == 0)
  110. {
  111. return vp;
  112. }
  113. free (vp);
  114. vp = (VALUE_PAIR *) NULL;
  115. }
  116. else
  117. novm("rc_avpair_new");
  118. }
  119. return vp;
  120. }
  121. /*
  122. *
  123. * Function: rc_avpair_gen
  124. *
  125. * Purpose: takes attribute/value pairs from buffer and builds a
  126. * value_pair list using allocated memory.
  127. *
  128. * Returns: value_pair list or NULL on failure
  129. */
  130. VALUE_PAIR *rc_avpair_gen (AUTH_HDR *auth)
  131. {
  132. int length;
  133. int x_len;
  134. int attribute;
  135. int attrlen;
  136. UINT4 lvalue;
  137. unsigned char *x_ptr;
  138. unsigned char *ptr;
  139. DICT_ATTR *attr;
  140. VALUE_PAIR *vp;
  141. VALUE_PAIR *pair;
  142. unsigned char hex[3]; /* For hex string conversion. */
  143. char buffer[512];
  144. /*
  145. * Extract attribute-value pairs
  146. */
  147. ptr = auth->data;
  148. length = ntohs ((unsigned short) auth->length) - AUTH_HDR_LEN;
  149. vp = (VALUE_PAIR *) NULL;
  150. while (length > 0)
  151. {
  152. attribute = *ptr++;
  153. attrlen = *ptr++;
  154. attrlen -= 2;
  155. if (attrlen < 0)
  156. {
  157. error("rc_avpair_gen: received attribute with invalid length");
  158. break;
  159. }
  160. /* Handle vendor-specific specially */
  161. if (attribute == PW_VENDOR_SPECIFIC) {
  162. rc_extract_vendor_specific_attributes(attrlen, ptr, &vp);
  163. ptr += attrlen;
  164. length -= (attrlen + 2);
  165. continue;
  166. }
  167. if ((attr = rc_dict_getattr (attribute, VENDOR_NONE)) == (DICT_ATTR *) NULL)
  168. {
  169. *buffer= '\0'; /* Initial length. */
  170. for (x_ptr = ptr, x_len = attrlen ;
  171. x_len > 0 ;
  172. x_len--, x_ptr++)
  173. {
  174. sprintf (hex, "%2.2X", *x_ptr);
  175. strcat (buffer, hex);
  176. }
  177. warn("rc_avpair_gen: received unknown attribute %d of length %d: 0x%s",
  178. attribute, attrlen, buffer);
  179. }
  180. else
  181. {
  182. if ((pair =
  183. (VALUE_PAIR *) malloc (sizeof (VALUE_PAIR))) ==
  184. (VALUE_PAIR *) NULL)
  185. {
  186. novm("rc_avpair_gen");
  187. rc_avpair_free(vp);
  188. return NULL;
  189. }
  190. strcpy (pair->name, attr->name);
  191. pair->attribute = attr->value;
  192. pair->vendorcode = VENDOR_NONE;
  193. pair->type = attr->type;
  194. pair->next = (VALUE_PAIR *) NULL;
  195. switch (attr->type)
  196. {
  197. case PW_TYPE_STRING:
  198. memcpy (pair->strvalue, (char *) ptr, (size_t) attrlen);
  199. pair->strvalue[attrlen] = '\0';
  200. pair->lvalue = attrlen;
  201. rc_avpair_insert (&vp, (VALUE_PAIR *) NULL, pair);
  202. break;
  203. case PW_TYPE_INTEGER:
  204. case PW_TYPE_IPADDR:
  205. memcpy ((char *) &lvalue, (char *) ptr,
  206. sizeof (UINT4));
  207. pair->lvalue = ntohl (lvalue);
  208. rc_avpair_insert (&vp, (VALUE_PAIR *) NULL, pair);
  209. break;
  210. default:
  211. warn("rc_avpair_gen: %s has unknown type", attr->name);
  212. free (pair);
  213. break;
  214. }
  215. }
  216. ptr += attrlen;
  217. length -= attrlen + 2;
  218. }
  219. return (vp);
  220. }
  221. /*
  222. * Function: rc_extract_vendor_specific_attributes
  223. *
  224. * Purpose: Extracts vendor-specific attributes, assuming they are in
  225. * the "SHOULD" format recommended by RCF 2138.
  226. *
  227. * Returns: found value_pair
  228. *
  229. */
  230. static void rc_extract_vendor_specific_attributes(int attrlen,
  231. unsigned char *ptr,
  232. VALUE_PAIR **vp)
  233. {
  234. int vendor_id;
  235. int vtype;
  236. int vlen;
  237. UINT4 lvalue;
  238. DICT_ATTR *attr;
  239. VALUE_PAIR *pair;
  240. /* ptr is sitting at vendor-ID */
  241. if (attrlen < 8) {
  242. /* Nothing to see here... */
  243. return;
  244. }
  245. /* High-order octet of Vendor-Id must be zero (RFC2138) */
  246. if (*ptr) {
  247. return;
  248. }
  249. /* Extract vendor_id */
  250. vendor_id = (int) (
  251. ((unsigned int) ptr[1]) * 256 * 256 +
  252. ((unsigned int) ptr[2]) * 256 +
  253. ((unsigned int) ptr[3]));
  254. /* Bump ptr up to contents */
  255. ptr += 4;
  256. /* Set attrlen to length of data */
  257. attrlen -= 4;
  258. for (; attrlen; attrlen -= vlen+2, ptr += vlen) {
  259. vtype = *ptr++;
  260. vlen = *ptr++;
  261. vlen -= 2;
  262. if (vlen < 0 || vlen > attrlen - 2) {
  263. /* Do not log an error. We are supposed to be able to cope with
  264. arbitrary vendor-specific gunk */
  265. return;
  266. }
  267. /* Looks plausible... */
  268. if ((attr = rc_dict_getattr(vtype, vendor_id)) == NULL) {
  269. continue;
  270. }
  271. /* TODO: Check that length matches data size!!!!! */
  272. pair = (VALUE_PAIR *) malloc(sizeof(VALUE_PAIR));
  273. if (!pair) {
  274. novm("rc_avpair_gen");
  275. return;
  276. }
  277. strcpy(pair->name, attr->name);
  278. pair->attribute = attr->value;
  279. pair->vendorcode = vendor_id;
  280. pair->type = attr->type;
  281. pair->next = NULL;
  282. switch (attr->type) {
  283. case PW_TYPE_STRING:
  284. memcpy (pair->strvalue, (char *) ptr, (size_t) vlen);
  285. pair->strvalue[vlen] = '\0';
  286. pair->lvalue = vlen;
  287. rc_avpair_insert (vp, (VALUE_PAIR *) NULL, pair);
  288. break;
  289. case PW_TYPE_INTEGER:
  290. case PW_TYPE_IPADDR:
  291. memcpy ((char *) &lvalue, (char *) ptr,
  292. sizeof (UINT4));
  293. pair->lvalue = ntohl (lvalue);
  294. rc_avpair_insert (vp, (VALUE_PAIR *) NULL, pair);
  295. break;
  296. default:
  297. warn("rc_avpair_gen: %s has unknown type", attr->name);
  298. free (pair);
  299. break;
  300. }
  301. }
  302. }
  303. /*
  304. * Function: rc_avpair_get
  305. *
  306. * Purpose: Find the first attribute value-pair (which matches the given
  307. * attribute) from the specified value-pair list.
  308. *
  309. * Returns: found value_pair
  310. *
  311. */
  312. VALUE_PAIR *rc_avpair_get (VALUE_PAIR *vp, UINT4 attr)
  313. {
  314. for (; vp != (VALUE_PAIR *) NULL && vp->attribute != attr; vp = vp->next)
  315. {
  316. continue;
  317. }
  318. return (vp);
  319. }
  320. /*
  321. * Function: rc_avpair_copy
  322. *
  323. * Purpose: Return a copy of the existing list "p" ala strdup().
  324. *
  325. */
  326. VALUE_PAIR *rc_avpair_copy(VALUE_PAIR *p)
  327. {
  328. VALUE_PAIR *vp, *fp = NULL, *lp = NULL;
  329. while (p) {
  330. vp = malloc(sizeof(VALUE_PAIR));
  331. if (!vp) {
  332. novm("rc_avpair_copy");
  333. return NULL; /* leaks a little but so what */
  334. }
  335. *vp = *p;
  336. if (!fp)
  337. fp = vp;
  338. if (lp)
  339. lp->next = vp;
  340. lp = vp;
  341. p = p->next;
  342. }
  343. return fp;
  344. }
  345. /*
  346. * Function: rc_avpair_insert
  347. *
  348. * Purpose: Given the address of an existing list "a" and a pointer
  349. * to an entry "p" in that list, add the list "b" to
  350. * the "a" list after the "p" entry. If "p" is NULL, add
  351. * the list "b" to the end of "a".
  352. *
  353. */
  354. void rc_avpair_insert (VALUE_PAIR **a, VALUE_PAIR *p, VALUE_PAIR *b)
  355. {
  356. VALUE_PAIR *this_node = NULL;
  357. VALUE_PAIR *vp;
  358. if (*a == (VALUE_PAIR *) NULL)
  359. {
  360. *a = b;
  361. return;
  362. }
  363. if (!b)
  364. return;
  365. vp = *a;
  366. if ( p == (VALUE_PAIR *) NULL) /* run to end of "a" list */
  367. {
  368. while (vp != (VALUE_PAIR *) NULL)
  369. {
  370. this_node = vp;
  371. vp = vp->next;
  372. }
  373. }
  374. else /* look for the "p" entry in the "a" list (or run to end) */
  375. {
  376. this_node = *a;
  377. while (this_node != (VALUE_PAIR *) NULL)
  378. {
  379. if (this_node == p)
  380. {
  381. break;
  382. }
  383. this_node = this_node->next;
  384. }
  385. }
  386. /* add "b" at this_node */
  387. vp = this_node->next;
  388. this_node->next = b;
  389. /* run to end of "b" and connect the rest of "a" */
  390. while (b->next)
  391. b = b->next;
  392. b->next = vp;
  393. return;
  394. }
  395. /*
  396. * Function: rc_avpair_free
  397. *
  398. * Purpose: frees all value_pairs in the list
  399. *
  400. */
  401. void rc_avpair_free (VALUE_PAIR *pair)
  402. {
  403. VALUE_PAIR *next;
  404. while (pair != (VALUE_PAIR *) NULL)
  405. {
  406. next = pair->next;
  407. free (pair);
  408. pair = next;
  409. }
  410. }
  411. /*
  412. * Function: rc_fieldcpy
  413. *
  414. * Purpose: Copy a data field from the buffer. Advance the buffer
  415. * past the data field.
  416. *
  417. */
  418. static void rc_fieldcpy (char *string, char **uptr)
  419. {
  420. char *ptr;
  421. ptr = *uptr;
  422. if (*ptr == '"')
  423. {
  424. ptr++;
  425. while (*ptr != '"' && *ptr != '\0' && *ptr != '\n')
  426. {
  427. *string++ = *ptr++;
  428. }
  429. *string = '\0';
  430. if (*ptr == '"')
  431. {
  432. ptr++;
  433. }
  434. *uptr = ptr;
  435. return;
  436. }
  437. while (*ptr != ' ' && *ptr != '\t' && *ptr != '\0' && *ptr != '\n' &&
  438. *ptr != '=' && *ptr != ',')
  439. {
  440. *string++ = *ptr++;
  441. }
  442. *string = '\0';
  443. *uptr = ptr;
  444. return;
  445. }
  446. /*
  447. * Function: rc_avpair_parse
  448. *
  449. * Purpose: parses the buffer to extract the attribute-value pairs.
  450. *
  451. * Returns: 0 = successful parse of attribute-value pair,
  452. * -1 = syntax (or other) error detected.
  453. *
  454. */
  455. #define PARSE_MODE_NAME 0
  456. #define PARSE_MODE_EQUAL 1
  457. #define PARSE_MODE_VALUE 2
  458. #define PARSE_MODE_INVALID 3
  459. int rc_avpair_parse (char *buffer, VALUE_PAIR **first_pair)
  460. {
  461. int mode;
  462. char attrstr[AUTH_ID_LEN];
  463. char valstr[AUTH_ID_LEN];
  464. DICT_ATTR *attr = NULL;
  465. DICT_VALUE *dval;
  466. VALUE_PAIR *pair;
  467. VALUE_PAIR *link;
  468. struct tm *tm;
  469. time_t timeval;
  470. mode = PARSE_MODE_NAME;
  471. while (*buffer != '\n' && *buffer != '\0')
  472. {
  473. if (*buffer == ' ' || *buffer == '\t')
  474. {
  475. buffer++;
  476. continue;
  477. }
  478. switch (mode)
  479. {
  480. case PARSE_MODE_NAME: /* Attribute Name */
  481. rc_fieldcpy (attrstr, &buffer);
  482. if ((attr =
  483. rc_dict_findattr (attrstr)) == (DICT_ATTR *) NULL)
  484. {
  485. error("rc_avpair_parse: unknown attribute");
  486. if (*first_pair) {
  487. rc_avpair_free(*first_pair);
  488. *first_pair = (VALUE_PAIR *) NULL;
  489. }
  490. return (-1);
  491. }
  492. mode = PARSE_MODE_EQUAL;
  493. break;
  494. case PARSE_MODE_EQUAL: /* Equal sign */
  495. if (*buffer == '=')
  496. {
  497. mode = PARSE_MODE_VALUE;
  498. buffer++;
  499. }
  500. else
  501. {
  502. error("rc_avpair_parse: missing or misplaced equal sign");
  503. if (*first_pair) {
  504. rc_avpair_free(*first_pair);
  505. *first_pair = (VALUE_PAIR *) NULL;
  506. }
  507. return (-1);
  508. }
  509. break;
  510. case PARSE_MODE_VALUE: /* Value */
  511. rc_fieldcpy (valstr, &buffer);
  512. if ((pair =
  513. (VALUE_PAIR *) malloc (sizeof (VALUE_PAIR)))
  514. == (VALUE_PAIR *) NULL)
  515. {
  516. novm("rc_avpair_parse");
  517. if (*first_pair) {
  518. rc_avpair_free(*first_pair);
  519. *first_pair = (VALUE_PAIR *) NULL;
  520. }
  521. return (-1);
  522. }
  523. strcpy (pair->name, attr->name);
  524. pair->attribute = attr->value;
  525. pair->type = attr->type;
  526. pair->vendorcode = attr->vendorcode;
  527. switch (pair->type)
  528. {
  529. case PW_TYPE_STRING:
  530. strcpy (pair->strvalue, valstr);
  531. pair->lvalue = strlen(valstr);
  532. break;
  533. case PW_TYPE_INTEGER:
  534. if (isdigit (*valstr))
  535. {
  536. pair->lvalue = atoi (valstr);
  537. }
  538. else
  539. {
  540. if ((dval = rc_dict_findval (valstr))
  541. == (DICT_VALUE *) NULL)
  542. {
  543. error("rc_avpair_parse: unknown attribute value: %s", valstr);
  544. if (*first_pair) {
  545. rc_avpair_free(*first_pair);
  546. *first_pair = (VALUE_PAIR *) NULL;
  547. }
  548. free (pair);
  549. return (-1);
  550. }
  551. else
  552. {
  553. pair->lvalue = dval->value;
  554. }
  555. }
  556. break;
  557. case PW_TYPE_IPADDR:
  558. pair->lvalue = rc_get_ipaddr(valstr);
  559. break;
  560. case PW_TYPE_DATE:
  561. timeval = time (0);
  562. tm = localtime (&timeval);
  563. tm->tm_hour = 0;
  564. tm->tm_min = 0;
  565. tm->tm_sec = 0;
  566. rc_str2tm (valstr, tm);
  567. #ifdef TIMELOCAL
  568. pair->lvalue = (UINT4) timelocal (tm);
  569. #else /* TIMELOCAL */
  570. pair->lvalue = (UINT4) mktime (tm);
  571. #endif /* TIMELOCAL */
  572. break;
  573. default:
  574. error("rc_avpair_parse: unknown attribute type %d", pair->type);
  575. if (*first_pair) {
  576. rc_avpair_free(*first_pair);
  577. *first_pair = (VALUE_PAIR *) NULL;
  578. }
  579. free (pair);
  580. return (-1);
  581. }
  582. pair->next = (VALUE_PAIR *) NULL;
  583. if (*first_pair == (VALUE_PAIR *) NULL)
  584. {
  585. *first_pair = pair;
  586. }
  587. else
  588. {
  589. link = *first_pair;
  590. while (link->next != (VALUE_PAIR *) NULL)
  591. {
  592. link = link->next;
  593. }
  594. link->next = pair;
  595. }
  596. mode = PARSE_MODE_NAME;
  597. break;
  598. default:
  599. mode = PARSE_MODE_NAME;
  600. break;
  601. }
  602. }
  603. return (0);
  604. }
  605. /*
  606. * Function: rc_avpair_tostr
  607. *
  608. * Purpose: Translate an av_pair into two strings
  609. *
  610. * Returns: 0 on success, -1 on failure
  611. *
  612. */
  613. int rc_avpair_tostr (VALUE_PAIR *pair, char *name, int ln, char *value, int lv)
  614. {
  615. DICT_VALUE *dval;
  616. char buffer[32];
  617. struct in_addr inad;
  618. unsigned char *ptr;
  619. *name = *value = '\0';
  620. if (!pair || pair->name[0] == '\0') {
  621. error("rc_avpair_tostr: pair is NULL or empty");
  622. return (-1);
  623. }
  624. strncpy(name, pair->name, (size_t) ln);
  625. switch (pair->type)
  626. {
  627. case PW_TYPE_STRING:
  628. lv--;
  629. ptr = (unsigned char *) pair->strvalue;
  630. while (*ptr != '\0')
  631. {
  632. if (!(isprint (*ptr)))
  633. {
  634. sprintf (buffer, "\\%03o", *ptr);
  635. strncat(value, buffer, (size_t) lv);
  636. lv -= 4;
  637. if (lv < 0) break;
  638. }
  639. else
  640. {
  641. strncat(value, ptr, 1);
  642. lv--;
  643. if (lv < 0) break;
  644. }
  645. ptr++;
  646. }
  647. break;
  648. case PW_TYPE_INTEGER:
  649. dval = rc_dict_getval (pair->lvalue, pair->name);
  650. if (dval != (DICT_VALUE *) NULL)
  651. {
  652. strncpy(value, dval->name, (size_t) lv-1);
  653. }
  654. else
  655. {
  656. sprintf (buffer, "%ld", pair->lvalue);
  657. strncpy(value, buffer, (size_t) lv);
  658. }
  659. break;
  660. case PW_TYPE_IPADDR:
  661. inad.s_addr = htonl(pair->lvalue);
  662. strncpy (value, inet_ntoa (inad), (size_t) lv-1);
  663. break;
  664. case PW_TYPE_DATE:
  665. strftime (buffer, sizeof (buffer), "%m/%d/%y %H:%M:%S",
  666. gmtime ((time_t *) & pair->lvalue));
  667. strncpy(value, buffer, lv-1);
  668. break;
  669. default:
  670. error("rc_avpair_tostr: unknown attribute type %d", pair->type);
  671. return (-1);
  672. break;
  673. }
  674. return 0;
  675. }
  676. /*
  677. * Function: rc_avpair_readin
  678. *
  679. * Purpose: get a sequence of attribute value pairs from the file input
  680. * and make them into a list of value_pairs
  681. *
  682. */
  683. VALUE_PAIR *rc_avpair_readin(FILE *input)
  684. {
  685. VALUE_PAIR *vp = NULL;
  686. char buffer[1024], *q;
  687. while (fgets(buffer, sizeof(buffer), input) != NULL)
  688. {
  689. q = buffer;
  690. while(*q && isspace(*q)) q++;
  691. if ((*q == '\n') || (*q == '#') || (*q == '\0'))
  692. continue;
  693. if (rc_avpair_parse(q, &vp) < 0) {
  694. error("rc_avpair_readin: malformed attribute: %s", buffer);
  695. rc_avpair_free(vp);
  696. return NULL;
  697. }
  698. }
  699. return vp;
  700. }