]> git.ipfire.org Git - thirdparty/util-linux.git/blame - login-utils/logindefs.c
lslogins: move to login-utils
[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"
439cdf1e 32#include "closestream.h"
3f9c237d 33#include "logindefs.h"
c82d9c97 34#include "nls.h"
c82d9c97 35#include "pathnames.h"
3f9c237d 36#include "xalloc.h"
c82d9c97
KZ
37
38struct item {
39 char *name; /* name of the option. */
40 char *value; /* value of the option. */
41 char *path; /* name of config file for this option. */
42
43 struct item *next; /* pointer to next option. */
44};
45
46static struct item *list = NULL;
47
9c44ac50
LN
48void (*logindefs_load_defaults)(void) = NULL;
49
c82d9c97
KZ
50void free_getlogindefs_data(void)
51{
52 struct item *ptr;
53
54 ptr = list;
55 while (ptr) {
56 struct item *tmp = ptr->next;
57
58 free(ptr->path);
59 free(ptr->name);
60 free(ptr->value);
61 free(ptr);
62 ptr = tmp;
63 }
64
65 list = NULL;
66}
67
68static void store(const char *name, const char *value, const char *path)
69{
70 struct item *new = xmalloc(sizeof(struct item));
71
72 if (!name)
73 abort();
74
75 new->name = xstrdup(name);
76 new->value = value && *value ? xstrdup(value) : NULL;
77 new->path = xstrdup(path);
78 new->next = list;
79 list = new;
80}
81
9c44ac50 82void logindefs_load_file(const char *filename)
c82d9c97
KZ
83{
84 FILE *f;
85 char buf[BUFSIZ];
86
87 f = fopen(filename, "r");
88 if (!f)
89 return;
90
91 while (fgets(buf, sizeof(buf), f)) {
92
93 char *p, *name, *data = NULL;
94
95 if (*buf == '#' || *buf == '\n')
3f9c237d 96 continue; /* only comment or empty line */
c82d9c97
KZ
97
98 p = strchr(buf, '#');
99 if (p)
100 *p = '\0';
101 else {
102 size_t n = strlen(buf);
103 if (n && *(buf + n - 1) == '\n')
104 *(buf + n - 1) = '\0';
105 }
106
107 if (!*buf)
3f9c237d 108 continue; /* empty line */
c82d9c97
KZ
109
110 /* ignore space at begin of the line */
111 name = buf;
3f9c237d 112 while (*name && isspace((unsigned)*name))
c82d9c97
KZ
113 name++;
114
115 /* go to the end of the name */
116 data = name;
3f9c237d 117 while (*data && !(isspace((unsigned)*data) || *data == '='))
c82d9c97
KZ
118 data++;
119 if (data > name && *data)
120 *data++ = '\0';
121
122 if (!*name || data == name)
123 continue;
124
125 /* go to the begin of the value */
3f9c237d
SK
126 while (*data
127 && (isspace((unsigned)*data) || *data == '='
128 || *data == '"'))
129 data++;
c82d9c97
KZ
130
131 /* remove space at the end of the value */
132 p = data + strlen(data);
133 if (p > data)
134 p--;
3f9c237d 135 while (p > data && (isspace((unsigned)*p) || *p == '"'))
c82d9c97
KZ
136 *p-- = '\0';
137
138 store(name, data, filename);
139 }
140
141 fclose(f);
142}
143
4082ab2c 144static void load_defaults(void)
9c44ac50
LN
145{
146 if (logindefs_load_defaults)
147 logindefs_load_defaults();
148 else
149 logindefs_load_file(_PATH_LOGINDEFS);
150}
151
c82d9c97
KZ
152static struct item *search(const char *name)
153{
154 struct item *ptr;
155
156 if (!list)
9c44ac50 157 load_defaults();
c82d9c97
KZ
158
159 ptr = list;
160 while (ptr != NULL) {
161 if (strcasecmp(name, ptr->name) == 0)
162 return ptr;
163 ptr = ptr->next;
164 }
165
166 return NULL;
167}
168
169static const char *search_config(const char *name)
170{
171 struct item *ptr;
172
173 ptr = list;
174 while (ptr != NULL) {
175 if (strcasecmp(name, ptr->name) == 0)
176 return ptr->path;
177 ptr = ptr->next;
178 }
179
180 return NULL;
181}
182
183int getlogindefs_bool(const char *name, int dflt)
184{
3f9c237d 185 struct item *ptr = search(name);
c82d9c97
KZ
186 return ptr && ptr->value ? (strcasecmp(ptr->value, "yes") == 0) : dflt;
187}
188
c9baf5da 189unsigned long getlogindefs_num(const char *name, long dflt)
c82d9c97
KZ
190{
191 struct item *ptr = search(name);
192 char *end = NULL;
c9baf5da 193 unsigned long retval;
c82d9c97
KZ
194
195 if (!ptr || !ptr->value)
196 return dflt;
197
198 errno = 0;
c9baf5da 199 retval = strtoul(ptr->value, &end, 0);
c82d9c97
KZ
200 if (end && *end == '\0' && !errno)
201 return retval;
202
203 syslog(LOG_NOTICE, _("%s: %s contains invalid numerical value: %s"),
3f9c237d 204 search_config(name), name, ptr->value);
c82d9c97
KZ
205 return dflt;
206}
207
208/*
209 * Returns:
210 * @dflt if @name not found
211 * "" (empty string) if found, but value not defined
212 * "string" if found
213 */
214const char *getlogindefs_str(const char *name, const char *dflt)
215{
216 struct item *ptr = search(name);
217
218 if (!ptr)
219 return dflt;
220 if (!ptr->value)
221 return "";
222 return ptr->value;
223}
224
607e6b7c 225/*
a8077509 226 * For compatibility with shadow-utils we have to support additional
607e6b7c
KZ
227 * syntax for environment variables in login.defs(5) file. The standard
228 * syntax is:
229 *
230 * ENV_FOO data
231 *
232 * but shadow-utils supports also
233 *
234 * ENV_FOO FOO=data
235 *
236 * the FOO= prefix has to be remove before we call setenv().
237 */
238int logindefs_setenv(const char *name, const char *conf, const char *dflt)
239{
240 const char *val = getlogindefs_str(conf, dflt);
241 const char *p;
242
243 if (!val)
244 return -1;
245
246 p = strchr(val, '=');
247 if (p) {
248 size_t sz = strlen(name);
249
250 if (strncmp(val, name, sz) == 0 && *(p + 1)) {
251 val = p + 1;
252 if (*val == '"')
253 val++;
254 if (!*val)
255 val = dflt;
256 }
257 }
258
259 return val ? setenv(name, val, 1) : -1;
260}
261
c82d9c97
KZ
262#ifdef TEST_PROGRAM
263int main(int argc, char *argv[])
264{
265 char *name, *type;
439cdf1e 266 atexit(close_stdout);
c82d9c97
KZ
267
268 if (argc <= 1)
269 errx(EXIT_FAILURE, "usage: %s <filename> "
3f9c237d 270 "[<str|num|bool> <valname>]", argv[0]);
c82d9c97 271
9c44ac50 272 logindefs_load_file(argv[1]);
c82d9c97 273
3f9c237d 274 if (argc != 4) { /* list all */
c82d9c97
KZ
275 struct item *ptr;
276
277 for (ptr = list; ptr; ptr = ptr->next)
3f9c237d
SK
278 printf("%s: $%s: '%s'\n", ptr->path, ptr->name,
279 ptr->value);
c82d9c97
KZ
280
281 return EXIT_SUCCESS;
282 }
283
284 type = argv[2];
285 name = argv[3];
286
287 if (strcmp(type, "str") == 0)
288 printf("$%s: '%s'\n", name, getlogindefs_str(name, "DEFAULT"));
289 else if (strcmp(type, "num") == 0)
290 printf("$%s: '%ld'\n", name, getlogindefs_num(name, 0));
291 else if (strcmp(type, "bool") == 0)
3f9c237d
SK
292 printf("$%s: '%s'\n", name,
293 getlogindefs_bool(name, 0) ? "Y" : "N");
c82d9c97
KZ
294
295 return EXIT_SUCCESS;
296}
297#endif