Annotation of embedaddon/pimd/libite/lfile.c, revision 1.1.1.1
1.1 misho 1: /* Parse UNIX /etc configuration files like /etc/protocols and /etc/services
2: *
3: * Copyright (c) 2015 Joachim Nilsson <troglobit@gmail.com>
4: *
5: * Permission to use, copy, modify, and/or distribute this software for any
6: * purpose with or without fee is hereby granted, provided that the above
7: * copyright notice and this permission notice appear in all copies.
8: *
9: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16: */
17:
18: #include <errno.h>
19: #include <stdio.h> /* FILE */
20: #include <stdlib.h> /* atoi() */
21: #include <string.h> /* strlen(), strncmp(), strtok_r() */
22: #include <sys/param.h> /* MAX() */
23:
24: typedef struct lfile {
25: FILE *fp;
26: char buf[256];
27: char *sep, *save;
28: } lfile_t;
29:
30: /**
31: * lfopen - Open file and return parsing context
32: * @file: File to parse
33: * @sep: Separator(s) to use in lftok()
34: *
35: * Returns:
36: * Pointer to a &lftile_t parser context, or %NULL on error.
37: */
38: lfile_t *lfopen(char *file, char *sep)
39: {
40: lfile_t *lf;
41:
42: if (!file || !sep) {
43: errno = EINVAL;
44: return NULL;
45: }
46:
47: /* Use calloc for clearing buf on behalf of lftok() */
48: lf = calloc(sizeof(*lf), sizeof(char));
49: if (lf) {
50: lf->fp = fopen(file, "r");
51: lf->sep = sep;
52: lf->save = lf->buf;
53:
54: if (!lf->fp) {
55: free(lf);
56: return NULL;
57: }
58: }
59:
60: return lf;
61: }
62:
63: /**
64: * lfclose - Close a parser context
65: * @lf: Pointer to &lfile_t context from lfopen()
66: */
67: void lfclose(lfile_t *lf)
68: {
69: if (!lf)
70: return;
71:
72: if (lf->fp)
73: fclose(lf->fp);
74: free(lf);
75: }
76:
77: /**
78: * lftok - Get next token in file
79: * @lf: Pointer to &lfile_t context from lfopen()
80: *
81: * Returns:
82: * Next token, read from file previously opened with lfopen(),
83: * or %NULL if EOF.
84: */
85: char *lftok(lfile_t *lf)
86: {
87: char *token;
88:
89: if (!lf || !lf->fp || !lf->sep) {
90: errno = EINVAL;
91: return NULL;
92: }
93:
94: token = strtok_r(NULL, lf->sep, &lf->save);
95: if (!token) {
96: while (fgets(lf->buf, sizeof(lf->buf), lf->fp)) {
97: if (lf->buf[0] == '#')
98: continue;
99:
100: token = strtok_r(lf->buf, lf->sep, &lf->save);
101: if (!token)
102: continue;
103:
104: return token;
105: }
106:
107: errno = ENOENT;
108: return NULL;
109: }
110:
111: return token;
112: }
113:
114: /**
115: * lfgetkey - Find key in file
116: * @lf: Pointer to &lfile_t context from lfopen()
117: * @key: Key to look for
118: *
119: * Locate @key from the current position in the file parser context
120: * returned from lfopen(). Please note, the search for @key does not
121: * start from the beginning of the file, it searches from the current
122: * position. To restart search from the beginning use rewind() on the
123: * lf->fp.
124: *
125: * Returns:
126: * The value to @key, or %NULL if not found.
127: */
128: char *lfgetkey(lfile_t *lf, char *key)
129: {
130: char *token;
131:
132: while ((token = lftok(lf))) {
133: if (token[0] == '#')
134: continue;
135:
136: if (!strncmp(token, key, MAX(strlen(token), strlen(key))))
137: return lftok(lf);
138: }
139:
140: return NULL;
141: }
142:
143: /**
144: * lfgetint - Same as lfgetkey() but returns an integer
145: * @lf: Pointer to &lfile_t context from lfopen()
146: * @key: Key to look for
147: *
148: * This function is the same as lfgetkey() but returns the positive
149: * integer value for the matching @key, if found.
150: *
151: * Returns:
152: * The positive integer value for @key, or -1 if not found.
153: */
154: int lfgetint(lfile_t *lf, char *key)
155: {
156: char *token = lfgetkey(lf, key);
157:
158: if (token)
159: return atoi(token);
160:
161: return -1;
162: }
163:
164: /**
165: * fgetint - Find the integer value for key in a file
166: * @file: File to search for @key
167: * @sep: Separator for tokens in @file
168: * @key: Key to look for in @file
169: *
170: * This is a convenience wrapper for lfopen(), lfgetint(), and
171: * lfclose().
172: *
173: * Returns:
174: * The positive integer value for @key, or -1 if not found.
175: */
176: int fgetint(char *file, char *sep, char *key)
177: {
178: int val = -1;
179: lfile_t *lf;
180:
181: lf = lfopen(file, sep);
182: if (lf) {
183: val = lfgetint(lf, key);
184: lfclose(lf);
185: }
186:
187: return val;
188: }
189:
190: #ifdef UNITTEST
191: int main(void)
192: {
193: int val;
194: lfile_t lf;
195:
196: val = fgetint("/etc/protocols", " \n\t", "udp");
197: if (val == -1) {
198: perror("Failed locating 'udp' protocol");
199: return 1;
200: }
201: printf("udp has proto %d\n", val);
202:
203: val = fgetint("/etc/services", " /\n\t", "ftp");
204: if (val == -1) {
205: perror("Failed locating 'ftp' service");
206: return 1;
207: }
208: printf("ftp is inet port %d\n", val);
209:
210: val = fgetint("/etc/group", "x:\n", "utmp");
211: if (val == -1) {
212: perror("Failed locating group 'utmp'");
213: return 1;
214: }
215: printf("utmp is gid %d\n", val);
216:
217: val = fgetint("/etc/passwd", "x:\n", "nobody");
218: if (val == -1) {
219: perror("Failed locating user 'nobody'");
220: return 1;
221: }
222: printf("nobody is uid %d\n", val);
223:
224: return 0;
225: }
226: #endif
227:
228: /**
229: * Local Variables:
230: * compile-command: "make V=1 -f lfile.mk"
231: * version-control: t
232: * indent-tabs-mode: t
233: * c-file-style: "linux"
234: * End:
235: */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>