]>
sourceware.org Git - glibc.git/blob - nss/nss_files/files-alias.c
99217fa7c5b03e617f703d2b3b2e6713ade7568b
1 /* Mail alias file parser in nss_files module.
2 Copyright (C) 1996 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4 Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public License as
8 published by the Free Software Foundation; either version 2 of the
9 License, or (at your option) any later version.
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
16 You should have received a copy of the GNU Library General Public
17 License along with the GNU C Library; see the file COPYING.LIB. If not,
18 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
24 #include <bits/libc-lock.h>
31 /* Locks the static variables in this file. */
32 __libc_lock_define_initialized (static, lock
)
34 /* Maintenance of the shared stream open on the database file. */
37 static fpos_t position
;
38 static enum { none
, getent
, getby
} last_use
;
41 static enum nss_status
42 internal_setent (void)
44 enum nss_status status
= NSS_STATUS_SUCCESS
;
48 stream
= fopen ("/etc/aliases", "r");
51 status
= NSS_STATUS_UNAVAIL
;
60 /* Thread-safe, exported version of that. */
62 _nss_files_setaliasent (void)
64 enum nss_status status
;
66 __libc_lock_lock (lock
);
68 status
= internal_setent ();
70 if (status
== NSS_STATUS_SUCCESS
&& fgetpos (stream
, &position
) < 0)
74 status
= NSS_STATUS_UNAVAIL
;
79 __libc_lock_unlock (lock
);
85 /* Close the database file. */
87 internal_endent (void)
97 /* Thread-safe, exported version of that. */
99 _nss_files_endaliasent (void)
101 __libc_lock_lock (lock
);
105 __libc_lock_unlock (lock
);
107 return NSS_STATUS_SUCCESS
;
110 /* Parsing the database file into `struct aliasent' data structures. */
111 static enum nss_status
112 get_next_alias (const char *match
, struct aliasent
*result
,
113 char *buffer
, size_t buflen
)
115 enum nss_status status
= NSS_STATUS_NOTFOUND
;
118 result
->alias_members_len
= 0;
122 /* Now we are ready to process the input. We have to read a
123 line and all its continuations and construct the array of
124 string pointers. This pointers and the names itself have to
125 be placed in BUFFER. */
126 char *first_unused
= buffer
;
127 size_t room_left
= buflen
- (buflen
% __alignof__ (char *));
130 /* Read the first line. It must contain the alias name and
131 possibly some alias names. */
132 first_unused
[room_left
- 1] = '\0';
133 line
= fgets (first_unused
, room_left
, stream
);
135 /* Nothing to read. */
137 else if (first_unused
[room_left
- 1] != '\0')
139 /* The line is too long for our buffer. */
141 __set_errno (ERANGE
);
142 status
= NSS_STATUS_TRYAGAIN
;
149 /* If we are in IGNORE mode and the first character in the
150 line is a white space we ignore the line and start
152 if (ignore
&& isspace (*first_unused
))
155 /* Terminate the line for any case. */
156 cp
= strpbrk (first_unused
, "#\n");
160 /* Skip leading blanks. */
161 while (isspace (*line
))
164 result
->alias_name
= first_unused
;
165 while (*line
!= '\0' && *line
!= ':')
166 *first_unused
++ = *line
++;
167 if (*line
== '\0' || result
->alias_name
== first_unused
)
168 /* No valid name. Ignore the line. */
171 *first_unused
++ = '\0';
172 if (room_left
< (size_t) (first_unused
- result
->alias_name
))
174 room_left
-= first_unused
- result
->alias_name
;
177 /* When we search for a specific alias we can avoid all the
178 difficult parts and compare now with the name we are
179 looking for. If it does not match we simply ignore all
180 lines until the next line containing the start of a new
182 ignore
= match
!= NULL
&& strcmp (result
->alias_name
, match
) != 0;
186 while (isspace (*line
))
190 while (*line
!= '\0' && *line
!= ',')
191 *first_unused
++ = *line
++;
193 if (first_unused
!= cp
)
195 /* OK, we can have a regular entry or an include
199 *first_unused
++ = '\0';
201 if (strncmp (cp
, ":include:", 9) != 0)
203 if (room_left
< (first_unused
- cp
) + sizeof (char *))
205 room_left
-= (first_unused
- cp
) + sizeof (char *);
207 ++result
->alias_members_len
;
211 /* Oh well, we have to read the addressed file. */
213 char *old_line
= NULL
;
217 listfile
= fopen (&cp
[9], "r");
218 /* If the file does not exist we simply ignore
221 && (old_line
= strdup (line
)) != NULL
)
223 while (! feof (listfile
))
225 first_unused
[room_left
- 1] = '\0';
226 line
= fgets (first_unused
, room_left
, listfile
);
229 if (first_unused
[room_left
- 1] != '\0')
235 /* Parse the line. */
236 cp
= strpbrk (line
, "#\n");
242 while (isspace (*line
))
246 while (*line
!= '\0' && *line
!= ',')
247 *first_unused
++ = *line
++;
252 if (first_unused
!= cp
)
254 *first_unused
++ = '\0';
255 if (room_left
< ((first_unused
- cp
)
256 + __alignof__ (char *)))
261 room_left
-= ((first_unused
- cp
)
262 + __alignof__ (char *));
263 ++result
->alias_members_len
;
266 while (*line
!= '\0');
270 first_unused
[room_left
- 1] = '\0';
271 strncpy (first_unused
, old_line
, room_left
);
273 if (old_line
!= NULL
)
276 if (first_unused
[room_left
- 1] != '\0')
284 /* Get the next line. But we must be careful. We
285 must not read the whole line at once since it
286 might belong to the current alias. Simply read
287 the first character. If it is a white space we
288 have a continuation line. Otherwise it is the
289 beginning of a new alias and we can push back the
290 just read character. */
294 if (ch
== EOF
|| ch
== '\n' || !isspace (ch
))
298 /* Now prepare the return. Provide string
299 pointers for the currently selected aliases. */
303 /* Adjust the pointer so it is aligned for
305 first_unused
+= __alignof__ (char *) - 1;
306 first_unused
-= ((first_unused
- (char *) 0)
307 % __alignof__ (char *));
308 result
->alias_members
= (char **) first_unused
;
310 /* Compute addresses of alias entry strings. */
311 cp
= result
->alias_name
;
312 for (cnt
= 0; cnt
< result
->alias_members_len
; ++cnt
)
314 cp
= strchr (cp
, '\0') + 1;
315 result
->alias_members
[cnt
] = cp
;
318 status
= (result
->alias_members_len
== 0
319 ? NSS_STATUS_RETURN
: NSS_STATUS_SUCCESS
);
323 /* The just read character is a white space and so
325 first_unused
[room_left
- 1] = '\0';
326 line
= fgets (first_unused
, room_left
, stream
);
327 if (first_unused
[room_left
- 1] != '\0')
329 cp
= strpbrk (line
, "#\n");
336 if (status
!= NSS_STATUS_NOTFOUND
)
337 /* We read something. In any case break here. */
346 _nss_files_getaliasent_r (struct aliasent
*result
, char *buffer
, size_t buflen
)
348 /* Return next entry in host file. */
349 enum nss_status status
= NSS_STATUS_SUCCESS
;
351 __libc_lock_lock (lock
);
353 /* Be prepared that the set*ent function was not called before. */
355 status
= internal_setent ();
357 if (status
== NSS_STATUS_SUCCESS
)
359 /* If the last use was not by the getent function we need the
360 position the stream. */
361 if (last_use
!= getent
)
362 if (fsetpos (stream
, &position
) < 0)
363 status
= NSS_STATUS_UNAVAIL
;
367 if (status
== NSS_STATUS_SUCCESS
)
369 result
->alias_local
= 1;
371 /* Read lines until we get a definite result. */
373 status
= get_next_alias (NULL
, result
, buffer
, buflen
);
374 while (status
== NSS_STATUS_RETURN
);
376 /* If we successfully read an entry remember this position. */
377 if (status
== NSS_STATUS_SUCCESS
)
378 fgetpos (stream
, &position
);
384 __libc_lock_unlock (lock
);
391 _nss_files_getaliasbyname_r (const char *name
, struct aliasent
*result
,
392 char *buffer
, size_t buflen
)
394 /* Return next entry in host file. */
395 enum nss_status status
= NSS_STATUS_SUCCESS
;
399 __set_errno (EINVAL
);
400 return NSS_STATUS_UNAVAIL
;
403 __libc_lock_lock (lock
);
405 /* Open the stream or rest it. */
406 status
= internal_setent ();
409 if (status
== NSS_STATUS_SUCCESS
)
411 result
->alias_local
= 1;
413 /* Read lines until we get a definite result. */
415 status
= get_next_alias (name
, result
, buffer
, buflen
);
416 while (status
== NSS_STATUS_RETURN
);
421 __libc_lock_unlock (lock
);
This page took 0.054146 seconds and 4 git commands to generate.