]> git.ipfire.org Git - thirdparty/util-linux.git/blame - login-utils/logindefs.c
misc-utils: verify writing to streams was successful
[thirdparty/util-linux.git] / login-utils / logindefs.c
CommitLineData
c82d9c97
KZ
1/*
2 * Copyright (C) 2003, 2004, 2005 Thorsten Kukuk
3 * Author: Thorsten Kukuk <kukuk@suse.de>
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain any existing copyright
10 * notice, and this entire permission notice in its entirety,
11 * including the disclaimer of warranties.
12 *
13 * 2. Redistributions in binary form must reproduce all prior and current
14 * copyright notices, this list of conditions, and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
17 *
18 * 3. The name of any author may not be used to endorse or promote
19 * products derived from this software without their specific prior
20 * written permission.
21 */
3f9c237d 22#include <assert.h>
c82d9c97 23#include <ctype.h>
3f9c237d
SK
24#include <errno.h>
25#include <limits.h>
c82d9c97
KZ
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
c82d9c97
KZ
29#include <sys/syslog.h>
30
31#include "c.h"
3f9c237d 32#include "logindefs.h"
c82d9c97 33#include "nls.h"
c82d9c97 34#include "pathnames.h"
3f9c237d 35#include "xalloc.h"
c82d9c97
KZ
36
37struct item {
38 char *name; /* name of the option. */
39 char *value; /* value of the option. */
40 char *path; /* name of config file for this option. */
41
42 struct item *next; /* pointer to next option. */
43};
44
45static struct item *list = NULL;
46
47void free_getlogindefs_data(void)
48{
49 struct item *ptr;
50
51 ptr = list;
52 while (ptr) {
53 struct item *tmp = ptr->next;
54
55 free(ptr->path);
56 free(ptr->name);
57 free(ptr->value);
58 free(ptr);
59 ptr = tmp;
60 }
61
62 list = NULL;
63}
64
65static void store(const char *name, const char *value, const char *path)
66{
67 struct item *new = xmalloc(sizeof(struct item));
68
69 if (!name)
70 abort();
71
72 new->name = xstrdup(name);
73 new->value = value && *value ? xstrdup(value) : NULL;
74 new->path = xstrdup(path);
75 new->next = list;
76 list = new;
77}
78
c82d9c97
KZ
79static void load_defaults(const char *filename)
80{
81 FILE *f;
82 char buf[BUFSIZ];
83
84 f = fopen(filename, "r");
85 if (!f)
86 return;
87
88 while (fgets(buf, sizeof(buf), f)) {
89
90 char *p, *name, *data = NULL;
91
92 if (*buf == '#' || *buf == '\n')
3f9c237d 93 continue; /* only comment or empty line */
c82d9c97
KZ
94
95 p = strchr(buf, '#');
96 if (p)
97 *p = '\0';
98 else {
99 size_t n = strlen(buf);
100 if (n && *(buf + n - 1) == '\n')
101 *(buf + n - 1) = '\0';
102 }
103
104 if (!*buf)
3f9c237d 105 continue; /* empty line */
c82d9c97
KZ
106
107 /* ignore space at begin of the line */
108 name = buf;
3f9c237d 109 while (*name && isspace((unsigned)*name))
c82d9c97
KZ
110 name++;
111
112 /* go to the end of the name */
113 data = name;
3f9c237d 114 while (*data && !(isspace((unsigned)*data) || *data == '='))
c82d9c97
KZ
115 data++;
116 if (data > name && *data)
117 *data++ = '\0';
118
119 if (!*name || data == name)
120 continue;
121
122 /* go to the begin of the value */
3f9c237d
SK
123 while (*data
124 && (isspace((unsigned)*data) || *data == '='
125 || *data == '"'))
126 data++;
c82d9c97
KZ
127
128 /* remove space at the end of the value */
129 p = data + strlen(data);
130 if (p > data)
131 p--;
3f9c237d 132 while (p > data && (isspace((unsigned)*p) || *p == '"'))
c82d9c97
KZ
133 *p-- = '\0';
134
135 store(name, data, filename);
136 }
137
138 fclose(f);
139}
140
141static struct item *search(const char *name)
142{
143 struct item *ptr;
144
145 if (!list)
146 load_defaults(_PATH_LOGINDEFS);
147
148 ptr = list;
149 while (ptr != NULL) {
150 if (strcasecmp(name, ptr->name) == 0)
151 return ptr;
152 ptr = ptr->next;
153 }
154
155 return NULL;
156}
157
158static const char *search_config(const char *name)
159{
160 struct item *ptr;
161
162 ptr = list;
163 while (ptr != NULL) {
164 if (strcasecmp(name, ptr->name) == 0)
165 return ptr->path;
166 ptr = ptr->next;
167 }
168
169 return NULL;
170}
171
172int getlogindefs_bool(const char *name, int dflt)
173{
3f9c237d 174 struct item *ptr = search(name);
c82d9c97
KZ
175 return ptr && ptr->value ? (strcasecmp(ptr->value, "yes") == 0) : dflt;
176}
177
178long getlogindefs_num(const char *name, long dflt)
179{
180 struct item *ptr = search(name);
181 char *end = NULL;
182 long retval;
183
184 if (!ptr || !ptr->value)
185 return dflt;
186
187 errno = 0;
188 retval = strtol(ptr->value, &end, 0);
189 if (end && *end == '\0' && !errno)
190 return retval;
191
192 syslog(LOG_NOTICE, _("%s: %s contains invalid numerical value: %s"),
3f9c237d 193 search_config(name), name, ptr->value);
c82d9c97
KZ
194 return dflt;
195}
196
197/*
198 * Returns:
199 * @dflt if @name not found
200 * "" (empty string) if found, but value not defined
201 * "string" if found
202 */
203const char *getlogindefs_str(const char *name, const char *dflt)
204{
205 struct item *ptr = search(name);
206
207 if (!ptr)
208 return dflt;
209 if (!ptr->value)
210 return "";
211 return ptr->value;
212}
213
607e6b7c 214/*
a8077509 215 * For compatibility with shadow-utils we have to support additional
607e6b7c
KZ
216 * syntax for environment variables in login.defs(5) file. The standard
217 * syntax is:
218 *
219 * ENV_FOO data
220 *
221 * but shadow-utils supports also
222 *
223 * ENV_FOO FOO=data
224 *
225 * the FOO= prefix has to be remove before we call setenv().
226 */
227int logindefs_setenv(const char *name, const char *conf, const char *dflt)
228{
229 const char *val = getlogindefs_str(conf, dflt);
230 const char *p;
231
232 if (!val)
233 return -1;
234
235 p = strchr(val, '=');
236 if (p) {
237 size_t sz = strlen(name);
238
239 if (strncmp(val, name, sz) == 0 && *(p + 1)) {
240 val = p + 1;
241 if (*val == '"')
242 val++;
243 if (!*val)
244 val = dflt;
245 }
246 }
247
248 return val ? setenv(name, val, 1) : -1;
249}
250
c82d9c97
KZ
251#ifdef TEST_PROGRAM
252int main(int argc, char *argv[])
253{
254 char *name, *type;
255
256 if (argc <= 1)
257 errx(EXIT_FAILURE, "usage: %s <filename> "
3f9c237d 258 "[<str|num|bool> <valname>]", argv[0]);
c82d9c97
KZ
259
260 load_defaults(argv[1]);
261
3f9c237d 262 if (argc != 4) { /* list all */
c82d9c97
KZ
263 struct item *ptr;
264
265 for (ptr = list; ptr; ptr = ptr->next)
3f9c237d
SK
266 printf("%s: $%s: '%s'\n", ptr->path, ptr->name,
267 ptr->value);
c82d9c97
KZ
268
269 return EXIT_SUCCESS;
270 }
271
272 type = argv[2];
273 name = argv[3];
274
275 if (strcmp(type, "str") == 0)
276 printf("$%s: '%s'\n", name, getlogindefs_str(name, "DEFAULT"));
277 else if (strcmp(type, "num") == 0)
278 printf("$%s: '%ld'\n", name, getlogindefs_num(name, 0));
279 else if (strcmp(type, "bool") == 0)
3f9c237d
SK
280 printf("$%s: '%s'\n", name,
281 getlogindefs_bool(name, 0) ? "Y" : "N");
c82d9c97
KZ
282
283 return EXIT_SUCCESS;
284}
285#endif