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) |