Expand PMF_FN_* macros.
[netbsd-mini2440.git] / external / bsd / pkg_install / dist / lib / var.c
blobc2c57f322e06aa51a293ef0accab97b6196e7817
1 /* $NetBSD: var.c,v 1.8 2009/08/02 17:56:45 joerg Exp $ */
3 /*-
4 * Copyright (c) 2005, 2008 The NetBSD Foundation, Inc.
5 * All rights reserved.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Dieter Baron, Thomas Klausner, Johnny Lam, and Joerg Sonnenberger.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of The NetBSD Foundation nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
23 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
25 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
26 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
35 #if HAVE_CONFIG_H
36 #include "config.h"
37 #endif
38 #include <nbcompat.h>
39 #if HAVE_SYS_CDEFS_H
40 #include <sys/cdefs.h>
41 #endif
42 __RCSID("$NetBSD: var.c,v 1.8 2009/08/02 17:56:45 joerg Exp $");
44 #if HAVE_SYS_STAT_H
45 #include <sys/stat.h>
46 #endif
47 #if HAVE_ERR_H
48 #include <err.h>
49 #endif
50 #if HAVE_ERRNO_H
51 #include <errno.h>
52 #endif
53 #if HAVE_STDIO_H
54 #include <stdio.h>
55 #endif
57 #include "lib.h"
59 static const char *var_cmp(const char *, size_t, const char *, size_t);
60 static void var_print(FILE *, const char *, const char *);
63 * Copy the specified varibales from the file fname to stdout.
65 int
66 var_copy_list(const char *buf, const char **variables)
68 const char *eol, *next;
69 size_t len;
70 int i;
72 for (; *buf; buf = next) {
73 if ((eol = strchr(buf, '\n')) != NULL) {
74 next = eol + 1;
75 len = eol - buf;
76 } else {
77 next = eol;
78 len = strlen(buf);
81 for (i=0; variables[i]; i++) {
82 if (var_cmp(buf, len, variables[i],
83 strlen(variables[i])) != NULL) {
84 printf("%.*s\n", (int)len, buf);
85 break;
89 return 0;
93 * Print the value of variable from the file fname to stdout.
95 char *
96 var_get(const char *fname, const char *variable)
98 FILE *fp;
99 char *line;
100 size_t len;
101 size_t varlen;
102 char *value;
103 size_t valuelen;
104 size_t thislen;
105 const char *p;
107 varlen = strlen(variable);
108 if (varlen == 0)
109 return NULL;
111 fp = fopen(fname, "r");
112 if (!fp) {
113 if (errno != ENOENT)
114 warn("var_get: can't open '%s' for reading", fname);
115 return NULL;
118 value = NULL;
119 valuelen = 0;
121 while ((line = fgetln(fp, &len)) != (char *) NULL) {
122 if (line[len - 1] == '\n')
123 --len;
124 if ((p=var_cmp(line, len, variable, varlen)) == NULL)
125 continue;
127 thislen = line+len - p;
128 if (value) {
129 value = xrealloc(value, valuelen+thislen+2);
130 value[valuelen++] = '\n';
132 else {
133 value = xmalloc(thislen+1);
135 sprintf(value+valuelen, "%.*s", (int)thislen, p);
136 valuelen += thislen;
138 (void) fclose(fp);
139 return value;
143 * Print the value of variable from the memory buffer to stdout.
145 char *
146 var_get_memory(const char *buf, const char *variable)
148 const char *eol, *next, *data;
149 size_t len, varlen, thislen, valuelen;
150 char *value;
152 varlen = strlen(variable);
153 if (varlen == 0)
154 return NULL;
156 value = NULL;
157 valuelen = 0;
159 for (; *buf; buf = next) {
160 if ((eol = strchr(buf, '\n')) != NULL) {
161 next = eol + 1;
162 len = eol - buf;
163 } else {
164 next = eol;
165 len = strlen(buf);
167 if ((data = var_cmp(buf, len, variable, varlen)) == NULL)
168 continue;
170 thislen = buf + len - data;
171 if (value) {
172 value = xrealloc(value, valuelen+thislen+2);
173 value[valuelen++] = '\n';
175 else {
176 value = xmalloc(thislen+1);
178 sprintf(value + valuelen, "%.*s", (int)thislen, data);
179 valuelen += thislen;
181 return value;
185 * Add given variable with given value to file, overwriting any
186 * previous occurrence.
189 var_set(const char *fname, const char *variable, const char *value)
191 FILE *fp;
192 FILE *fout;
193 char *tmpname;
194 int fd;
195 char *line;
196 size_t len;
197 size_t varlen;
198 Boolean done;
199 struct stat st;
201 varlen = strlen(variable);
202 if (varlen == 0)
203 return 0;
205 fp = fopen(fname, "r");
206 if (fp == NULL) {
207 if (errno != ENOENT) {
208 warn("var_set: can't open '%s' for reading", fname);
209 return -1;
211 if (value == NULL)
212 return 0; /* Nothing to do */
215 tmpname = xasprintf("%s.XXXXXX", fname);
216 if ((fd = mkstemp(tmpname)) < 0) {
217 free(tmpname);
218 if (fp != NULL)
219 fclose(fp);
220 warn("var_set: can't open temp file for '%s' for writing",
221 fname);
222 return -1;
224 if (chmod(tmpname, 0644) < 0) {
225 close(fd);
226 if (fp != NULL)
227 fclose(fp);
228 free(tmpname);
229 warn("var_set: can't set permissions for temp file for '%s'",
230 fname);
231 return -1;
233 if ((fout=fdopen(fd, "w")) == NULL) {
234 close(fd);
235 remove(tmpname);
236 free(tmpname);
237 if (fp != NULL)
238 fclose(fp);
239 warn("var_set: can't open temp file for '%s' for writing",
240 fname);
241 return -1;
244 done = FALSE;
246 if (fp) {
247 while ((line = fgetln(fp, &len)) != (char *) NULL) {
248 if (var_cmp(line, len, variable, varlen) == NULL)
249 fprintf(fout, "%.*s", (int)len, line);
250 else {
251 if (!done && value) {
252 var_print(fout, variable, value);
253 done = TRUE;
257 (void) fclose(fp);
260 if (!done && value)
261 var_print(fout, variable, value);
263 if (fclose(fout) < 0) {
264 free(tmpname);
265 warn("var_set: write error for '%s'", fname);
266 return -1;
269 if (stat(tmpname, &st) < 0) {
270 free(tmpname);
271 warn("var_set: cannot stat tempfile for '%s'", fname);
272 return -1;
275 if (st.st_size == 0) {
276 if (remove(tmpname) < 0) {
277 free(tmpname);
278 warn("var_set: cannot remove tempfile for '%s'",
279 fname);
280 return -1;
282 free(tmpname);
283 if (remove(fname) < 0) {
284 warn("var_set: cannot remove '%s'", fname);
285 return -1;
287 return 0;
290 if (rename(tmpname, fname) < 0) {
291 free(tmpname);
292 warn("var_set: cannot move tempfile to '%s'", fname);
293 return -1;
295 free(tmpname);
296 return 0;
300 * Check if line contains variable var, return pointer to its value or NULL.
302 static const char *
303 var_cmp(const char *line, size_t linelen, const char *var, size_t varlen)
306 * We expect lines to look like one of the following
307 * forms:
308 * VAR=value
309 * VAR= value
310 * We print out the value of VAR, or nothing if it
311 * doesn't exist.
313 if (linelen < varlen+1)
314 return NULL;
315 if (strncmp(var, line, varlen) != 0)
316 return NULL;
318 line += varlen;
319 if (*line != '=')
320 return NULL;
322 ++line;
323 linelen -= varlen+1;
324 if (linelen > 0 && *line == ' ')
325 ++line;
326 return line;
330 * Print given variable with value to file f.
332 static void
333 var_print(FILE *f, const char *variable, const char *value)
335 const char *p;
337 while ((p=strchr(value, '\n')) != NULL) {
338 if (p != value)
339 fprintf(f, "%s=%.*s\n", variable, (int)(p-value), value);
340 value = p+1;
343 if (*value)
344 fprintf(f, "%s=%s\n", variable, value);