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