env_attr.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. /*
  2. * (C) Copyright 2012
  3. * Joe Hershberger, National Instruments, joe.hershberger@ni.com
  4. *
  5. * See file CREDITS for list of people who contributed to this
  6. * project.
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License as
  10. * published by the Free Software Foundation; either version 2 of
  11. * the License, or (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  21. * MA 02111-1307 USA
  22. */
  23. #ifdef USE_HOSTCC /* Eliminate "ANSI does not permit..." warnings */
  24. #include <stdint.h>
  25. #include <stdio.h>
  26. #include <linux/linux_string.h>
  27. #else
  28. #include <common.h>
  29. #endif
  30. #include <env_attr.h>
  31. #include <errno.h>
  32. #include <linux/string.h>
  33. #include <malloc.h>
  34. /*
  35. * Iterate through the whole list calling the callback for each found element.
  36. * "attr_list" takes the form:
  37. * attributes = [^,:\s]*
  38. * entry = name[:attributes]
  39. * list = entry[,list]
  40. */
  41. int env_attr_walk(const char *attr_list,
  42. int (*callback)(const char *name, const char *attributes))
  43. {
  44. const char *entry, *entry_end;
  45. char *name, *attributes;
  46. if (!attr_list)
  47. /* list not found */
  48. return 1;
  49. entry = attr_list;
  50. do {
  51. char *entry_cpy = NULL;
  52. entry_end = strchr(entry, ENV_ATTR_LIST_DELIM);
  53. /* check if this is the last entry in the list */
  54. if (entry_end == NULL) {
  55. int entry_len = strlen(entry);
  56. if (entry_len) {
  57. /*
  58. * allocate memory to copy the entry into since
  59. * we will need to inject '\0' chars and squash
  60. * white-space before calling the callback
  61. */
  62. entry_cpy = malloc(entry_len + 1);
  63. if (entry_cpy)
  64. /* copy the rest of the list */
  65. strcpy(entry_cpy, entry);
  66. else
  67. return -ENOMEM;
  68. }
  69. } else {
  70. int entry_len = entry_end - entry;
  71. if (entry_len) {
  72. /*
  73. * allocate memory to copy the entry into since
  74. * we will need to inject '\0' chars and squash
  75. * white-space before calling the callback
  76. */
  77. entry_cpy = malloc(entry_len + 1);
  78. if (entry_cpy) {
  79. /* copy just this entry and null term */
  80. strncpy(entry_cpy, entry, entry_len);
  81. entry_cpy[entry_len] = '\0';
  82. } else
  83. return -ENOMEM;
  84. }
  85. }
  86. /* check if there is anything to process (e.g. not ",,,") */
  87. if (entry_cpy != NULL) {
  88. attributes = strchr(entry_cpy, ENV_ATTR_SEP);
  89. /* check if there is a ':' */
  90. if (attributes != NULL) {
  91. /* replace the ':' with '\0' to term name */
  92. *attributes++ = '\0';
  93. /* remove white-space from attributes */
  94. attributes = strim(attributes);
  95. }
  96. /* remove white-space from name */
  97. name = strim(entry_cpy);
  98. /* only call the callback if there is a name */
  99. if (strlen(name) != 0) {
  100. int retval = 0;
  101. retval = callback(name, attributes);
  102. if (retval) {
  103. free(entry_cpy);
  104. return retval;
  105. }
  106. }
  107. }
  108. free(entry_cpy);
  109. entry = entry_end + 1;
  110. } while (entry_end != NULL);
  111. return 0;
  112. }
  113. /*
  114. * Search for the last matching string in another string with the option to
  115. * start looking at a certain point (i.e. ignore anything beyond that point).
  116. */
  117. static char *reverse_strstr(const char *searched, const char *search_for,
  118. const char *searched_start)
  119. {
  120. char *result = NULL;
  121. if (*search_for == '\0')
  122. return (char *)searched;
  123. for (;;) {
  124. char *match = strstr(searched, search_for);
  125. /*
  126. * Stop looking if no new match is found or looking past the
  127. * searched_start pointer
  128. */
  129. if (match == NULL || (searched_start != NULL &&
  130. match + strlen(search_for) > searched_start))
  131. break;
  132. result = match;
  133. searched = match + 1;
  134. }
  135. return result;
  136. }
  137. /*
  138. * Retrieve the attributes string associated with a single name in the list
  139. * There is no protection on attributes being too small for the value
  140. */
  141. int env_attr_lookup(const char *attr_list, const char *name, char *attributes)
  142. {
  143. const char *entry = NULL;
  144. if (!attributes)
  145. /* bad parameter */
  146. return -1;
  147. if (!attr_list)
  148. /* list not found */
  149. return 1;
  150. entry = reverse_strstr(attr_list, name, NULL);
  151. while (entry != NULL) {
  152. const char *prevch = entry - 1;
  153. const char *nextch = entry + strlen(name);
  154. /* Skip spaces */
  155. while (*prevch == ' ')
  156. prevch--;
  157. while (*nextch == ' ')
  158. nextch++;
  159. /* check for an exact match */
  160. if ((entry == attr_list ||
  161. *prevch == ENV_ATTR_LIST_DELIM) &&
  162. (*nextch == ENV_ATTR_SEP ||
  163. *nextch == ENV_ATTR_LIST_DELIM ||
  164. *nextch == '\0'))
  165. break;
  166. entry = reverse_strstr(attr_list, name, entry);
  167. }
  168. if (entry != NULL) {
  169. int len;
  170. /* skip the name */
  171. entry += strlen(name);
  172. /* skip spaces */
  173. while (*entry == ' ')
  174. entry++;
  175. if (*entry != ENV_ATTR_SEP)
  176. len = 0;
  177. else {
  178. const char *delim;
  179. static const char delims[] = {
  180. ENV_ATTR_LIST_DELIM, ' ', '\0'};
  181. /* skip the attr sep */
  182. entry += 1;
  183. /* skip spaces */
  184. while (*entry == ' ')
  185. entry++;
  186. delim = strpbrk(entry, delims);
  187. if (delim == NULL)
  188. len = strlen(entry);
  189. else
  190. len = delim - entry;
  191. memcpy(attributes, entry, len);
  192. }
  193. attributes[len] = '\0';
  194. /* success */
  195. return 0;
  196. }
  197. /* not found in list */
  198. return 2;
  199. }