Rev 3346 | Rev 3376 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 3346 | Rev 3366 | ||
|---|---|---|---|
| Line 50... | Line 50... | ||
| 50 | 50 | ||
| 51 | #include "config.h" |
51 | #include "config.h" |
| 52 | #include "errors.h" |
52 | #include "errors.h" |
| 53 | #include "util.h" |
53 | #include "util.h" |
| 54 | 54 | ||
| - | 55 | extern volatile int cli_errno; |
|
| - | 56 | ||
| 55 | /* some platforms do not have strdup, implement it here. |
57 | /* some platforms do not have strdup, implement it here. |
| 56 | * Returns a pointer to an allocated string or NULL on failure */ |
58 | * Returns a pointer to an allocated string or NULL on failure */ |
| 57 | char * cli_strdup(const char *s1) |
59 | char * cli_strdup(const char *s1) |
| 58 | { |
60 | { |
| 59 | size_t len = strlen(s1) + 1; |
61 | size_t len = strlen(s1) + 1; |
| 60 | void *ret = malloc(len); |
62 | void *ret = malloc(len); |
| 61 | 63 | ||
| 62 | if (ret == NULL) |
64 | if (ret == NULL) { |
| - | 65 | cli_errno = CL_ENOMEM; |
|
| 63 | return (char *) NULL; |
66 | return (char *) NULL; |
| - | 67 | } |
|
| 64 | 68 | ||
| - | 69 | cli_errno = CL_EOK; |
|
| 65 | return (char *) memcpy(ret, s1, len); |
70 | return (char *) memcpy(ret, s1, len); |
| 66 | } |
71 | } |
| 67 | 72 | ||
| 68 | /* |
73 | /* |
| 69 | * Take a previously allocated string (s1), re-size it to accept s2 and copy |
74 | * Take a previously allocated string (s1), re-size it to accept s2 and copy |
| Line 77... | Line 82... | ||
| 77 | if (! len) |
82 | if (! len) |
| 78 | return -1; |
83 | return -1; |
| 79 | 84 | ||
| 80 | *s1 = realloc(*s1, len); |
85 | *s1 = realloc(*s1, len); |
| 81 | 86 | ||
| 82 | if (*s1 == NULL) |
87 | if (*s1 == NULL) { |
| - | 88 | cli_errno = CL_ENOMEM; |
|
| 83 | return -1; |
89 | return -1; |
| - | 90 | } |
|
| 84 | 91 | ||
| 85 | memset(*s1, 0, sizeof(*s1)); |
92 | memset(*s1, 0, sizeof(*s1)); |
| 86 | memcpy(*s1, s2, len); |
93 | memcpy(*s1, s2, len); |
| - | 94 | cli_errno = CL_EOK; |
|
| 87 | return (int) len; |
95 | return (int) len; |
| 88 | } |
96 | } |
| 89 | 97 | ||
| 90 | /* An asprintf() for concantenating paths. Allocates the system PATH_MAX value, |
98 | /* An asprintf() for formatting paths, similar to asprintf() but ensures |
| - | 99 | * the returned allocated string is <= PATH_MAX. On failure, an attempt |
|
| - | 100 | * is made to return the original string (if not null) unmodified. |
|
| - | 101 | * |
|
| 91 | * expands the formatted string and re-sizes the block s1 points to accordingly. |
102 | * Returns: Length of the new string on success, 0 if the string was handed |
| - | 103 | * back unmodified, -1 on failure. On failure, cli_errno is set. |
|
| 92 | * |
104 | * |
| 93 | * Returns the length of the new s1 on success, -1 on failure. On failure, an |
105 | * We do not use POSIX_PATH_MAX, as it is typically much smaller than the |
| 94 | * attempt is made to return s1 unmodified for sanity, in this case 0 is returned. |
- | |
| 95 | * to indicate that s1 was not modified. |
106 | * PATH_MAX defined by the kernel. |
| 96 | * |
107 | * |
| - | 108 | * Use this like: |
|
| 97 | * FIXME: ugly hack to get around asprintf(), if you use this, CHECK ITS VALUE! */ |
109 | * if (1 > cli_psprintf(&char, "%s/%s", foo, bar)) { |
| - | 110 | * cli_error(cli_errno, "Failed to format path"); |
|
| - | 111 | * stop_what_your_doing_as_your_out_of_memory(); |
|
| - | 112 | * } |
|
| - | 113 | */ |
|
| - | 114 | ||
| 98 | int cli_psprintf(char **s1, const char *fmt, ...) |
115 | int cli_psprintf(char **s1, const char *fmt, ...) |
| 99 | { |
116 | { |
| 100 | va_list ap; |
117 | va_list ap; |
| 101 | size_t needed, base = PATH_MAX + 1; |
118 | size_t needed, base = PATH_MAX + 1; |
| - | 119 | int skipped = 0; |
|
| - | 120 | char *orig = NULL; |
|
| 102 | char *tmp = (char *) malloc(base); |
121 | char *tmp = (char *) malloc(base); |
| 103 | 122 | ||
| - | 123 | /* Don't even touch s1, not enough memory */ |
|
| 104 | if (NULL == tmp) |
124 | if (NULL == tmp) { |
| - | 125 | cli_errno = CL_ENOMEM; |
|
| 105 | return -1; |
126 | return -1; |
| - | 127 | } |
|
| 106 | 128 | ||
| - | 129 | /* If re-allocating s1, save a copy in case we fail */ |
|
| 107 | char *orig = *s1; |
130 | if (NULL != *s1) |
| - | 131 | orig = cli_strdup(*s1); |
|
| 108 | 132 | ||
| - | 133 | /* Print the string to tmp so we can determine the size that |
|
| - | 134 | * we actually need */ |
|
| 109 | memset(tmp, 0, sizeof(tmp)); |
135 | memset(tmp, 0, sizeof(tmp)); |
| 110 | va_start(ap, fmt); |
136 | va_start(ap, fmt); |
| - | 137 | /* vsnprintf will return the # of bytes not written */ |
|
| 111 | vsnprintf(tmp, base, fmt, ap); |
138 | skipped = vsnprintf(tmp, base, fmt, ap); |
| 112 | va_end(ap); |
139 | va_end(ap); |
| - | 140 | ||
| - | 141 | /* realloc/alloc s1 to be just the size that we need */ |
|
| 113 | needed = strlen(tmp) + 1; |
142 | needed = strlen(tmp) + 1; |
| 114 | *s1 = realloc(*s1, needed); |
143 | *s1 = realloc(*s1, needed); |
| - | 144 | ||
| 115 | if (NULL == *s1) { |
145 | if (NULL == *s1) { |
| - | 146 | /* No string lived here previously, or we failed to |
|
| - | 147 | * make a copy of it, either way there's nothing we |
|
| - | 148 | * can do. */ |
|
| - | 149 | if (NULL == *orig) { |
|
| - | 150 | cli_errno = CL_ENOMEM; |
|
| - | 151 | return -1; |
|
| - | 152 | } |
|
| - | 153 | /* We can't even allocate enough size to restore the |
|
| - | 154 | * saved copy, just give up */ |
|
| 116 | *s1 = realloc(*s1, strlen(orig) + 1); |
155 | *s1 = realloc(*s1, strlen(orig) + 1); |
| 117 | if (NULL == *s1) { |
156 | if (NULL == *s1) { |
| 118 | free(tmp); |
157 | free(tmp); |
| - | 158 | free(orig); |
|
| - | 159 | cli_errno = CL_ENOMEM; |
|
| 119 | return -1; |
160 | return -1; |
| 120 | } |
161 | } |
| - | 162 | /* Give the string back as we found it */ |
|
| 121 | memset(*s1, 0, sizeof(*s1)); |
163 | memset(*s1, 0, sizeof(*s1)); |
| 122 | memcpy(*s1, orig, strlen(orig) + 1); |
164 | memcpy(*s1, orig, strlen(orig) + 1); |
| 123 | free(tmp); |
165 | free(tmp); |
| - | 166 | free(orig); |
|
| - | 167 | cli_errno = CL_ENOMEM; |
|
| 124 | return 0; |
168 | return 0; |
| 125 | } |
169 | } |
| - | 170 | ||
| - | 171 | /* Ok, great, we have enough room */ |
|
| 126 | memset(*s1, 0, sizeof(*s1)); |
172 | memset(*s1, 0, sizeof(*s1)); |
| 127 | memcpy(*s1, tmp, needed); |
173 | memcpy(*s1, tmp, needed); |
| 128 | free(tmp); |
174 | free(tmp); |
| 129 | 175 | ||
| - | 176 | /* Free tmp only if s1 was reallocated instead of allocated */ |
|
| - | 177 | if (NULL != orig) |
|
| - | 178 | free(orig); |
|
| - | 179 | ||
| - | 180 | if (skipped) { |
|
| - | 181 | /* s1 was bigger than PATH_MAX when expanded, however part |
|
| - | 182 | * of the string was printed. Tell the caller not to use it */ |
|
| - | 183 | cli_errno = CL_ETOOBIG; |
|
| - | 184 | return -1; |
|
| - | 185 | } |
|
| - | 186 | ||
| - | 187 | /* Success! */ |
|
| - | 188 | cli_errno = CL_EOK; |
|
| 130 | return (int) needed; |
189 | return (int) needed; |
| 131 | } |
190 | } |
| 132 | 191 | ||
| 133 | /* Ported from FBSD strtok.c 8.1 (Berkeley) 6/4/93 */ |
192 | /* Ported from FBSD strtok.c 8.1 (Berkeley) 6/4/93 */ |
| 134 | char * cli_strtok_r(char *s, const char *delim, char **last) |
193 | char * cli_strtok_r(char *s, const char *delim, char **last) |
| 135 | { |
194 | { |
| 136 | char *spanp, *tok; |
195 | char *spanp, *tok; |
| 137 | int c, sc; |
196 | int c, sc; |
| 138 | 197 | ||
| 139 | if (s == NULL && (s = *last) == NULL) |
198 | if (s == NULL && (s = *last) == NULL) { |
| - | 199 | cli_errno = CL_EFAIL; |
|
| 140 | return (NULL); |
200 | return (NULL); |
| - | 201 | } |
|
| 141 | 202 | ||
| 142 | cont: |
203 | cont: |
| 143 | c = *s++; |
204 | c = *s++; |
| 144 | for (spanp = (char *)delim; (sc = *spanp++) != 0;) { |
205 | for (spanp = (char *)delim; (sc = *spanp++) != 0;) { |
| 145 | if (c == sc) |
206 | if (c == sc) |