Absolute File Name: | /home/opencoverage/opencoverage/guest-scripts/coreutils/src/gnulib/lib/userspec.c |
Source code | Switch to Preprocessed file |
Line | Source | Count | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | /* userspec.c -- Parse a user and group string. | - | ||||||||||||||||||||||||
2 | Copyright (C) 1989-1992, 1997-1998, 2000, 2002-2018 Free Software | - | ||||||||||||||||||||||||
3 | Foundation, Inc. | - | ||||||||||||||||||||||||
4 | - | |||||||||||||||||||||||||
5 | This program is free software: you can redistribute it and/or modify | - | ||||||||||||||||||||||||
6 | it under the terms of the GNU General Public License as published by | - | ||||||||||||||||||||||||
7 | the Free Software Foundation; either version 3 of the License, or | - | ||||||||||||||||||||||||
8 | (at your option) any later version. | - | ||||||||||||||||||||||||
9 | - | |||||||||||||||||||||||||
10 | This program is distributed in the hope that it will be useful, | - | ||||||||||||||||||||||||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | - | ||||||||||||||||||||||||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | - | ||||||||||||||||||||||||
13 | GNU General Public License for more details. | - | ||||||||||||||||||||||||
14 | - | |||||||||||||||||||||||||
15 | You should have received a copy of the GNU General Public License | - | ||||||||||||||||||||||||
16 | along with this program. If not, see <https://www.gnu.org/licenses/>. */ | - | ||||||||||||||||||||||||
17 | - | |||||||||||||||||||||||||
18 | /* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */ | - | ||||||||||||||||||||||||
19 | - | |||||||||||||||||||||||||
20 | #include <config.h> | - | ||||||||||||||||||||||||
21 | - | |||||||||||||||||||||||||
22 | /* Specification. */ | - | ||||||||||||||||||||||||
23 | #include "userspec.h" | - | ||||||||||||||||||||||||
24 | - | |||||||||||||||||||||||||
25 | #include <stdbool.h> | - | ||||||||||||||||||||||||
26 | #include <stdio.h> | - | ||||||||||||||||||||||||
27 | #include <sys/types.h> | - | ||||||||||||||||||||||||
28 | #include <pwd.h> | - | ||||||||||||||||||||||||
29 | #include <grp.h> | - | ||||||||||||||||||||||||
30 | - | |||||||||||||||||||||||||
31 | #if HAVE_SYS_PARAM_H | - | ||||||||||||||||||||||||
32 | # include <sys/param.h> | - | ||||||||||||||||||||||||
33 | #endif | - | ||||||||||||||||||||||||
34 | - | |||||||||||||||||||||||||
35 | #include <limits.h> | - | ||||||||||||||||||||||||
36 | #include <stdlib.h> | - | ||||||||||||||||||||||||
37 | #include <string.h> | - | ||||||||||||||||||||||||
38 | - | |||||||||||||||||||||||||
39 | #include <unistd.h> | - | ||||||||||||||||||||||||
40 | - | |||||||||||||||||||||||||
41 | #include "intprops.h" | - | ||||||||||||||||||||||||
42 | #include "inttostr.h" | - | ||||||||||||||||||||||||
43 | #include "xalloc.h" | - | ||||||||||||||||||||||||
44 | #include "xstrtol.h" | - | ||||||||||||||||||||||||
45 | - | |||||||||||||||||||||||||
46 | #include "gettext.h" | - | ||||||||||||||||||||||||
47 | #define _(msgid) gettext (msgid) | - | ||||||||||||||||||||||||
48 | #define N_(msgid) msgid | - | ||||||||||||||||||||||||
49 | - | |||||||||||||||||||||||||
50 | #ifndef HAVE_ENDGRENT | - | ||||||||||||||||||||||||
51 | # define endgrent() ((void) 0) | - | ||||||||||||||||||||||||
52 | #endif | - | ||||||||||||||||||||||||
53 | - | |||||||||||||||||||||||||
54 | #ifndef HAVE_ENDPWENT | - | ||||||||||||||||||||||||
55 | # define endpwent() ((void) 0) | - | ||||||||||||||||||||||||
56 | #endif | - | ||||||||||||||||||||||||
57 | - | |||||||||||||||||||||||||
58 | #ifndef UID_T_MAX | - | ||||||||||||||||||||||||
59 | # define UID_T_MAX TYPE_MAXIMUM (uid_t) | - | ||||||||||||||||||||||||
60 | #endif | - | ||||||||||||||||||||||||
61 | - | |||||||||||||||||||||||||
62 | #ifndef GID_T_MAX | - | ||||||||||||||||||||||||
63 | # define GID_T_MAX TYPE_MAXIMUM (gid_t) | - | ||||||||||||||||||||||||
64 | #endif | - | ||||||||||||||||||||||||
65 | - | |||||||||||||||||||||||||
66 | /* MAXUID may come from limits.h or sys/params.h. */ | - | ||||||||||||||||||||||||
67 | #ifndef MAXUID | - | ||||||||||||||||||||||||
68 | # define MAXUID UID_T_MAX | - | ||||||||||||||||||||||||
69 | #endif | - | ||||||||||||||||||||||||
70 | #ifndef MAXGID | - | ||||||||||||||||||||||||
71 | # define MAXGID GID_T_MAX | - | ||||||||||||||||||||||||
72 | #endif | - | ||||||||||||||||||||||||
73 | - | |||||||||||||||||||||||||
74 | #ifdef __DJGPP__ | - | ||||||||||||||||||||||||
75 | - | |||||||||||||||||||||||||
76 | /* ISDIGIT differs from isdigit, as follows: | - | ||||||||||||||||||||||||
77 | - Its arg may be any int or unsigned int; it need not be an unsigned char | - | ||||||||||||||||||||||||
78 | or EOF. | - | ||||||||||||||||||||||||
79 | - It's typically faster. | - | ||||||||||||||||||||||||
80 | POSIX says that only '0' through '9' are digits. Prefer ISDIGIT to | - | ||||||||||||||||||||||||
81 | isdigit unless it's important to use the locale's definition | - | ||||||||||||||||||||||||
82 | of "digit" even when the host does not conform to POSIX. */ | - | ||||||||||||||||||||||||
83 | # define ISDIGIT(c) ((unsigned int) (c) - '0' <= 9) | - | ||||||||||||||||||||||||
84 | - | |||||||||||||||||||||||||
85 | /* Return true if STR represents an unsigned decimal integer. */ | - | ||||||||||||||||||||||||
86 | - | |||||||||||||||||||||||||
87 | static bool | - | ||||||||||||||||||||||||
88 | is_number (const char *str) | - | ||||||||||||||||||||||||
89 | { | - | ||||||||||||||||||||||||
90 | do | - | ||||||||||||||||||||||||
91 | { | - | ||||||||||||||||||||||||
92 | if (!ISDIGIT (*str)) | - | ||||||||||||||||||||||||
93 | return false; | - | ||||||||||||||||||||||||
94 | } | - | ||||||||||||||||||||||||
95 | while (*++str); | - | ||||||||||||||||||||||||
96 | - | |||||||||||||||||||||||||
97 | return true; | - | ||||||||||||||||||||||||
98 | } | - | ||||||||||||||||||||||||
99 | #endif | - | ||||||||||||||||||||||||
100 | - | |||||||||||||||||||||||||
101 | static char const * | - | ||||||||||||||||||||||||
102 | parse_with_separator (char const *spec, char const *separator, | - | ||||||||||||||||||||||||
103 | uid_t *uid, gid_t *gid, | - | ||||||||||||||||||||||||
104 | char **username, char **groupname) | - | ||||||||||||||||||||||||
105 | { | - | ||||||||||||||||||||||||
106 | static const char *E_invalid_user = N_("invalid user"); | - | ||||||||||||||||||||||||
107 | static const char *E_invalid_group = N_("invalid group"); | - | ||||||||||||||||||||||||
108 | static const char *E_bad_spec = N_("invalid spec"); | - | ||||||||||||||||||||||||
109 | - | |||||||||||||||||||||||||
110 | const char *error_msg; | - | ||||||||||||||||||||||||
111 | struct passwd *pwd; | - | ||||||||||||||||||||||||
112 | struct group *grp; | - | ||||||||||||||||||||||||
113 | char *u; | - | ||||||||||||||||||||||||
114 | char const *g; | - | ||||||||||||||||||||||||
115 | char *gname = NULL; | - | ||||||||||||||||||||||||
116 | uid_t unum = *uid; | - | ||||||||||||||||||||||||
117 | gid_t gnum = gid ? *gid : -1;
| 44-113 | ||||||||||||||||||||||||
118 | - | |||||||||||||||||||||||||
119 | error_msg = NULL; | - | ||||||||||||||||||||||||
120 | if (username)
| 38-119 | ||||||||||||||||||||||||
121 | *username = NULL; executed 38 times by 1 test: *username = ((void *)0) ; Executed by:
| 38 | ||||||||||||||||||||||||
122 | if (groupname)
| 38-119 | ||||||||||||||||||||||||
123 | *groupname = NULL; executed 38 times by 1 test: *groupname = ((void *)0) ; Executed by:
| 38 | ||||||||||||||||||||||||
124 | - | |||||||||||||||||||||||||
125 | /* Set U and G to nonzero length strings corresponding to user and | - | ||||||||||||||||||||||||
126 | group specifiers or to NULL. If U is not NULL, it is a newly | - | ||||||||||||||||||||||||
127 | allocated string. */ | - | ||||||||||||||||||||||||
128 | - | |||||||||||||||||||||||||
129 | u = NULL; | - | ||||||||||||||||||||||||
130 | if (separator == NULL)
| 29-128 | ||||||||||||||||||||||||
131 | { | - | ||||||||||||||||||||||||
132 | if (*spec)
| 1-127 | ||||||||||||||||||||||||
133 | u = xstrdup (spec); executed 127 times by 2 tests: u = xstrdup (spec); Executed by:
| 127 | ||||||||||||||||||||||||
134 | } executed 128 times by 2 tests: end of block Executed by:
| 128 | ||||||||||||||||||||||||
135 | else | - | ||||||||||||||||||||||||
136 | { | - | ||||||||||||||||||||||||
137 | size_t ulen = separator - spec; | - | ||||||||||||||||||||||||
138 | if (ulen != 0)
| 13-16 | ||||||||||||||||||||||||
139 | { | - | ||||||||||||||||||||||||
140 | u = xmemdup (spec, ulen + 1); | - | ||||||||||||||||||||||||
141 | u[ulen] = '\0'; | - | ||||||||||||||||||||||||
142 | } executed 13 times by 1 test: end of block Executed by:
| 13 | ||||||||||||||||||||||||
143 | } executed 29 times by 1 test: end of block Executed by:
| 29 | ||||||||||||||||||||||||
144 | - | |||||||||||||||||||||||||
145 | g = (separator == NULL || *(separator + 1) == '\0'
| 6-128 | ||||||||||||||||||||||||
146 | ? NULL | - | ||||||||||||||||||||||||
147 | : separator + 1); | - | ||||||||||||||||||||||||
148 | - | |||||||||||||||||||||||||
149 | #ifdef __DJGPP__ | - | ||||||||||||||||||||||||
150 | /* Pretend that we are the user U whose group is G. This makes | - | ||||||||||||||||||||||||
151 | pwd and grp functions "know" about the UID and GID of these. */ | - | ||||||||||||||||||||||||
152 | if (u && !is_number (u)) | - | ||||||||||||||||||||||||
153 | setenv ("USER", u, 1); | - | ||||||||||||||||||||||||
154 | if (g && !is_number (g)) | - | ||||||||||||||||||||||||
155 | setenv ("GROUP", g, 1); | - | ||||||||||||||||||||||||
156 | #endif | - | ||||||||||||||||||||||||
157 | - | |||||||||||||||||||||||||
158 | if (u != NULL)
| 17-140 | ||||||||||||||||||||||||
159 | { | - | ||||||||||||||||||||||||
160 | /* If it starts with "+", skip the look-up. */ | - | ||||||||||||||||||||||||
161 | pwd = (*u == '+' ? NULL : getpwnam (u));
| 3-137 | ||||||||||||||||||||||||
162 | if (pwd == NULL)
| 28-112 | ||||||||||||||||||||||||
163 | { | - | ||||||||||||||||||||||||
164 | bool use_login_group = (separator != NULL && g == NULL);
| 2-21 | ||||||||||||||||||||||||
165 | if (use_login_group)
| 2-26 | ||||||||||||||||||||||||
166 | { | - | ||||||||||||||||||||||||
167 | /* If there is no group, | - | ||||||||||||||||||||||||
168 | then there may not be a trailing ":", either. */ | - | ||||||||||||||||||||||||
169 | error_msg = E_bad_spec; | - | ||||||||||||||||||||||||
170 | } executed 2 times by 1 test: end of block Executed by:
| 2 | ||||||||||||||||||||||||
171 | else | - | ||||||||||||||||||||||||
172 | { | - | ||||||||||||||||||||||||
173 | unsigned long int tmp; | - | ||||||||||||||||||||||||
174 | if (xstrtoul (u, NULL, 10, &tmp, "") == LONGINT_OK
| 12-14 | ||||||||||||||||||||||||
175 | && tmp <= MAXUID && (uid_t) tmp != (uid_t) -1)
| 0-14 | ||||||||||||||||||||||||
176 | unum = tmp; executed 14 times by 2 tests: unum = tmp; Executed by:
| 14 | ||||||||||||||||||||||||
177 | else | - | ||||||||||||||||||||||||
178 | error_msg = E_invalid_user; executed 12 times by 2 tests: error_msg = E_invalid_user; Executed by:
| 12 | ||||||||||||||||||||||||
179 | } | - | ||||||||||||||||||||||||
180 | } | - | ||||||||||||||||||||||||
181 | else | - | ||||||||||||||||||||||||
182 | { | - | ||||||||||||||||||||||||
183 | unum = pwd->pw_uid; | - | ||||||||||||||||||||||||
184 | if (g == NULL && separator != NULL)
| 2-108 | ||||||||||||||||||||||||
185 | { | - | ||||||||||||||||||||||||
186 | /* A separator was given, but a group was not specified, | - | ||||||||||||||||||||||||
187 | so get the login group. */ | - | ||||||||||||||||||||||||
188 | char buf[INT_BUFSIZE_BOUND (uintmax_t)]; | - | ||||||||||||||||||||||||
189 | gnum = pwd->pw_gid; | - | ||||||||||||||||||||||||
190 | grp = getgrgid (gnum); | - | ||||||||||||||||||||||||
191 | gname = xstrdup (grp ? grp->gr_name : umaxtostr (gnum, buf)); | - | ||||||||||||||||||||||||
192 | endgrent (); | - | ||||||||||||||||||||||||
193 | } executed 2 times by 1 test: end of block Executed by:
| 2 | ||||||||||||||||||||||||
194 | } executed 112 times by 2 tests: end of block Executed by:
| 112 | ||||||||||||||||||||||||
195 | endpwent (); | - | ||||||||||||||||||||||||
196 | } executed 140 times by 2 tests: end of block Executed by:
| 140 | ||||||||||||||||||||||||
197 | - | |||||||||||||||||||||||||
198 | if (g != NULL && error_msg == NULL)
| 0-134 | ||||||||||||||||||||||||
199 | { | - | ||||||||||||||||||||||||
200 | /* Explicit group. */ | - | ||||||||||||||||||||||||
201 | /* If it starts with "+", skip the look-up. */ | - | ||||||||||||||||||||||||
202 | grp = (*g == '+' ? NULL : getgrnam (g));
| 0-23 | ||||||||||||||||||||||||
203 | if (grp == NULL)
| 6-17 | ||||||||||||||||||||||||
204 | { | - | ||||||||||||||||||||||||
205 | unsigned long int tmp; | - | ||||||||||||||||||||||||
206 | if (xstrtoul (g, NULL, 10, &tmp, "") == LONGINT_OK
| 0-17 | ||||||||||||||||||||||||
207 | && tmp <= MAXGID && (gid_t) tmp != (gid_t) -1)
| 0-17 | ||||||||||||||||||||||||
208 | gnum = tmp; executed 17 times by 1 test: gnum = tmp; Executed by:
| 17 | ||||||||||||||||||||||||
209 | else | - | ||||||||||||||||||||||||
210 | error_msg = E_invalid_group; never executed: error_msg = E_invalid_group; | 0 | ||||||||||||||||||||||||
211 | } | - | ||||||||||||||||||||||||
212 | else | - | ||||||||||||||||||||||||
213 | gnum = grp->gr_gid; executed 6 times by 1 test: gnum = grp->gr_gid; Executed by:
| 6 | ||||||||||||||||||||||||
214 | endgrent (); /* Save a file descriptor. */ | - | ||||||||||||||||||||||||
215 | gname = xstrdup (g); | - | ||||||||||||||||||||||||
216 | } executed 23 times by 1 test: end of block Executed by:
| 23 | ||||||||||||||||||||||||
217 | - | |||||||||||||||||||||||||
218 | if (error_msg == NULL)
| 14-143 | ||||||||||||||||||||||||
219 | { | - | ||||||||||||||||||||||||
220 | *uid = unum; | - | ||||||||||||||||||||||||
221 | if (gid)
| 32-111 | ||||||||||||||||||||||||
222 | *gid = gnum; executed 32 times by 1 test: *gid = gnum; Executed by:
| 32 | ||||||||||||||||||||||||
223 | if (username)
| 27-116 | ||||||||||||||||||||||||
224 | { | - | ||||||||||||||||||||||||
225 | *username = u; | - | ||||||||||||||||||||||||
226 | u = NULL; | - | ||||||||||||||||||||||||
227 | } executed 27 times by 1 test: end of block Executed by:
| 27 | ||||||||||||||||||||||||
228 | if (groupname)
| 27-116 | ||||||||||||||||||||||||
229 | { | - | ||||||||||||||||||||||||
230 | *groupname = gname; | - | ||||||||||||||||||||||||
231 | gname = NULL; | - | ||||||||||||||||||||||||
232 | } executed 27 times by 1 test: end of block Executed by:
| 27 | ||||||||||||||||||||||||
233 | } executed 143 times by 2 tests: end of block Executed by:
| 143 | ||||||||||||||||||||||||
234 | - | |||||||||||||||||||||||||
235 | free (u); | - | ||||||||||||||||||||||||
236 | free (gname); | - | ||||||||||||||||||||||||
237 | return error_msg ? _(error_msg) : NULL; executed 157 times by 2 tests: return error_msg ? dcgettext (((void *)0), error_msg , 5) : ((void *)0) ; Executed by:
| 157 | ||||||||||||||||||||||||
238 | } | - | ||||||||||||||||||||||||
239 | - | |||||||||||||||||||||||||
240 | /* Extract from SPEC, which has the form "[user][:.][group]", | - | ||||||||||||||||||||||||
241 | a USERNAME, UID U, GROUPNAME, and GID G. | - | ||||||||||||||||||||||||
242 | If the GID parameter is NULL the entire SPEC is treated as a user. | - | ||||||||||||||||||||||||
243 | If the USERNAME and GROUPNAME parameters are NULL they're ignored. | - | ||||||||||||||||||||||||
244 | Either user or group, or both, must be present. | - | ||||||||||||||||||||||||
245 | If the group is omitted but the separator is given, | - | ||||||||||||||||||||||||
246 | use the given user's login group. | - | ||||||||||||||||||||||||
247 | If SPEC contains a ':', then use that as the separator, ignoring | - | ||||||||||||||||||||||||
248 | any '.'s. If there is no ':', but there is a '.', then first look | - | ||||||||||||||||||||||||
249 | up the entire SPEC as a login name. If that look-up fails, then | - | ||||||||||||||||||||||||
250 | try again interpreting the '.' as a separator. | - | ||||||||||||||||||||||||
251 | - | |||||||||||||||||||||||||
252 | USERNAME and GROUPNAME will be in newly malloc'd memory. | - | ||||||||||||||||||||||||
253 | Either one might be NULL instead, indicating that it was not | - | ||||||||||||||||||||||||
254 | given and the corresponding numeric ID was left unchanged. | - | ||||||||||||||||||||||||
255 | - | |||||||||||||||||||||||||
256 | Return NULL if successful, a static error message string if not. */ | - | ||||||||||||||||||||||||
257 | - | |||||||||||||||||||||||||
258 | char const * | - | ||||||||||||||||||||||||
259 | parse_user_spec (char const *spec, uid_t *uid, gid_t *gid, | - | ||||||||||||||||||||||||
260 | char **username, char **groupname) | - | ||||||||||||||||||||||||
261 | { | - | ||||||||||||||||||||||||
262 | char const *colon = gid ? strchr (spec, ':') : NULL;
| 0-113 | ||||||||||||||||||||||||
263 | char const *error_msg = | - | ||||||||||||||||||||||||
264 | parse_with_separator (spec, colon, uid, gid, username, groupname); | - | ||||||||||||||||||||||||
265 | - | |||||||||||||||||||||||||
266 | if (gid && !colon && error_msg)
| 5-113 | ||||||||||||||||||||||||
267 | { | - | ||||||||||||||||||||||||
268 | /* If there's no colon but there is a dot, and if looking up the | - | ||||||||||||||||||||||||
269 | whole spec failed (i.e., the spec is not an owner name that | - | ||||||||||||||||||||||||
270 | includes a dot), then try again, but interpret the dot as a | - | ||||||||||||||||||||||||
271 | separator. This is a compatible extension to POSIX, since | - | ||||||||||||||||||||||||
272 | the POSIX-required behavior is always tried first. */ | - | ||||||||||||||||||||||||
273 | - | |||||||||||||||||||||||||
274 | char const *dot = strchr (spec, '.');
| 0-10 | ||||||||||||||||||||||||
275 | if (dot
| 1-9 | ||||||||||||||||||||||||
276 | && ! parse_with_separator (spec, dot, uid, gid, username, groupname))
| 1-8 | ||||||||||||||||||||||||
277 | error_msg = NULL; executed 8 times by 1 test: error_msg = ((void *)0) ; Executed by:
| 8 | ||||||||||||||||||||||||
278 | } executed 10 times by 1 test: end of block Executed by:
| 10 | ||||||||||||||||||||||||
279 | - | |||||||||||||||||||||||||
280 | return error_msg; executed 148 times by 2 tests: return error_msg; Executed by:
| 148 | ||||||||||||||||||||||||
281 | } | - | ||||||||||||||||||||||||
282 | - | |||||||||||||||||||||||||
283 | #ifdef TEST | - | ||||||||||||||||||||||||
284 | - | |||||||||||||||||||||||||
285 | # define NULL_CHECK(s) ((s) == NULL ? "(null)" : (s)) | - | ||||||||||||||||||||||||
286 | - | |||||||||||||||||||||||||
287 | int | - | ||||||||||||||||||||||||
288 | main (int argc, char **argv) | - | ||||||||||||||||||||||||
289 | { | - | ||||||||||||||||||||||||
290 | int i; | - | ||||||||||||||||||||||||
291 | - | |||||||||||||||||||||||||
292 | for (i = 1; i < argc; i++) | - | ||||||||||||||||||||||||
293 | { | - | ||||||||||||||||||||||||
294 | const char *e; | - | ||||||||||||||||||||||||
295 | char *username, *groupname; | - | ||||||||||||||||||||||||
296 | uid_t uid; | - | ||||||||||||||||||||||||
297 | gid_t gid; | - | ||||||||||||||||||||||||
298 | char *tmp; | - | ||||||||||||||||||||||||
299 | - | |||||||||||||||||||||||||
300 | tmp = strdup (argv[i]); | - | ||||||||||||||||||||||||
301 | e = parse_user_spec (tmp, &uid, &gid, &username, &groupname); | - | ||||||||||||||||||||||||
302 | free (tmp); | - | ||||||||||||||||||||||||
303 | printf ("%s: %lu %lu %s %s %s\n", | - | ||||||||||||||||||||||||
304 | argv[i], | - | ||||||||||||||||||||||||
305 | (unsigned long int) uid, | - | ||||||||||||||||||||||||
306 | (unsigned long int) gid, | - | ||||||||||||||||||||||||
307 | NULL_CHECK (username), | - | ||||||||||||||||||||||||
308 | NULL_CHECK (groupname), | - | ||||||||||||||||||||||||
309 | NULL_CHECK (e)); | - | ||||||||||||||||||||||||
310 | } | - | ||||||||||||||||||||||||
311 | - | |||||||||||||||||||||||||
312 | exit (0); | - | ||||||||||||||||||||||||
313 | } | - | ||||||||||||||||||||||||
314 | - | |||||||||||||||||||||||||
315 | #endif | - | ||||||||||||||||||||||||
316 | - | |||||||||||||||||||||||||
317 | /* | - | ||||||||||||||||||||||||
318 | Local Variables: | - | ||||||||||||||||||||||||
319 | indent-tabs-mode: nil | - | ||||||||||||||||||||||||
320 | End: | - | ||||||||||||||||||||||||
321 | */ | - | ||||||||||||||||||||||||
Source code | Switch to Preprocessed file |