1 /* Copyright (C) 1997-2015 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library 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 GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <http://www.gnu.org/licenses/>. */
25 #include <bits/libc-lock.h>
26 #include <rpcsvc/nis.h>
28 #include "nss-nisplus.h"
30 __libc_lock_define_initialized (static, lock
)
32 static nis_result
*result
;
33 static u_long next_entry
;
34 static nis_name tablename_val
;
35 static size_t tablename_len
;
37 #define NISENTRYVAL(idx, col, res) \
38 (NIS_RES_OBJECT (res)[idx].EN_data.en_cols.en_cols_val[col].ec_value.ec_value_val)
40 #define NISENTRYLEN(idx, col, res) \
41 (NIS_RES_OBJECT (res)[idx].EN_data.en_cols.en_cols_val[col].ec_value.ec_value_len)
43 static enum nss_status
44 _nss_create_tablename (int *errnop
)
46 if (tablename_val
== NULL
)
48 const char *local_dir
= nis_local_directory ();
49 size_t local_dir_len
= strlen (local_dir
);
50 static const char prefix
[] = "mail_aliases.org_dir.";
52 char *p
= malloc (sizeof (prefix
) + local_dir_len
);
56 return NSS_STATUS_TRYAGAIN
;
59 memcpy (__stpcpy (p
, prefix
), local_dir
, local_dir_len
+ 1);
61 tablename_len
= sizeof (prefix
) - 1 + local_dir_len
;
63 atomic_write_barrier ();
68 return NSS_STATUS_SUCCESS
;
72 _nss_nisplus_parse_aliasent (nis_result
*result
, unsigned long entry
,
73 struct aliasent
*alias
, char *buffer
,
74 size_t buflen
, int *errnop
)
79 if ((result
->status
!= NIS_SUCCESS
&& result
->status
!= NIS_S_SUCCESS
)
80 || __type_of (&NIS_RES_OBJECT (result
)[entry
]) != NIS_ENTRY_OBJ
81 || strcmp (NIS_RES_OBJECT (result
)[entry
].EN_data
.en_type
,
83 || NIS_RES_OBJECT (result
)[entry
].EN_data
.en_cols
.en_cols_len
< 2)
86 if (NISENTRYLEN (entry
, 1, result
) >= buflen
)
88 /* The line is too long for our buffer. */
94 char *cp
= __stpncpy (buffer
, NISENTRYVAL (entry
, 1, result
),
95 NISENTRYLEN (entry
, 1, result
));
98 char *first_unused
= cp
+ 1;
99 size_t room_left
= buflen
- (first_unused
- buffer
);
101 alias
->alias_local
= 0;
102 alias
->alias_members_len
= 0;
104 if (NISENTRYLEN (entry
, 0, result
) >= room_left
)
107 cp
= __stpncpy (first_unused
, NISENTRYVAL (entry
, 0, result
),
108 NISENTRYLEN (entry
, 0, result
));
110 alias
->alias_name
= first_unused
;
112 /* Terminate the line for any case. */
113 cp
= strpbrk (alias
->alias_name
, "#\n");
117 size_t len
= strlen (alias
->alias_name
) + 1;
121 /* Adjust the pointer so it is aligned for
123 size_t adjust
= ((__alignof__ (char *)
124 - (first_unused
- (char *) 0) % __alignof__ (char *))
125 % __alignof__ (char *));
126 if (room_left
< adjust
)
128 first_unused
+= adjust
;
131 alias
->alias_members
= (char **) first_unused
;
134 while (*line
!= '\0')
136 /* Skip leading blanks. */
137 while (isspace (*line
))
143 if (room_left
< sizeof (char *))
145 room_left
-= sizeof (char *);
146 alias
->alias_members
[alias
->alias_members_len
] = line
;
148 while (*line
!= '\0' && *line
!= ',')
151 if (line
!= alias
->alias_members
[alias
->alias_members_len
])
154 ++alias
->alias_members_len
;
156 else if (*line
== ',')
160 return alias
->alias_members_len
== 0 ? 0 : 1;
163 static enum nss_status
164 internal_setaliasent (void)
166 enum nss_status status
;
171 nis_freeresult (result
);
175 if (_nss_create_tablename (&err
) != NSS_STATUS_SUCCESS
)
176 return NSS_STATUS_UNAVAIL
;
179 result
= nis_list (tablename_val
, FOLLOW_PATH
| FOLLOW_LINKS
, NULL
, NULL
);
182 status
= NSS_STATUS_TRYAGAIN
;
183 __set_errno (ENOMEM
);
187 status
= niserr2nss (result
->status
);
188 if (status
!= NSS_STATUS_SUCCESS
)
190 nis_freeresult (result
);
198 _nss_nisplus_setaliasent (void)
200 enum nss_status status
;
202 __libc_lock_lock (lock
);
204 status
= internal_setaliasent ();
206 __libc_lock_unlock (lock
);
212 _nss_nisplus_endaliasent (void)
214 __libc_lock_lock (lock
);
218 nis_freeresult (result
);
223 __libc_lock_unlock (lock
);
225 return NSS_STATUS_SUCCESS
;
228 static enum nss_status
229 internal_nisplus_getaliasent_r (struct aliasent
*alias
,
230 char *buffer
, size_t buflen
, int *errnop
)
236 enum nss_status status
;
238 status
= internal_setaliasent ();
239 if (result
== NULL
|| status
!= NSS_STATUS_SUCCESS
)
243 /* Get the next entry until we found a correct one. */
246 if (next_entry
>= result
->objects
.objects_len
)
247 return NSS_STATUS_NOTFOUND
;
249 parse_res
= _nss_nisplus_parse_aliasent (result
, next_entry
, alias
,
250 buffer
, buflen
, errnop
);
252 return NSS_STATUS_TRYAGAIN
;
258 return NSS_STATUS_SUCCESS
;
262 _nss_nisplus_getaliasent_r (struct aliasent
*result
, char *buffer
,
263 size_t buflen
, int *errnop
)
267 __libc_lock_lock (lock
);
269 status
= internal_nisplus_getaliasent_r (result
, buffer
, buflen
, errnop
);
271 __libc_lock_unlock (lock
);
277 _nss_nisplus_getaliasbyname_r (const char *name
, struct aliasent
*alias
,
278 char *buffer
, size_t buflen
, int *errnop
)
282 if (tablename_val
== NULL
)
284 __libc_lock_lock (lock
);
286 enum nss_status status
= _nss_create_tablename (errnop
);
288 __libc_lock_unlock (lock
);
290 if (status
!= NSS_STATUS_SUCCESS
)
297 return NSS_STATUS_UNAVAIL
;
300 char buf
[strlen (name
) + 9 + tablename_len
];
303 snprintf (buf
, sizeof (buf
), "[name=%s],%s", name
, tablename_val
);
305 nis_result
*result
= nis_list (buf
, FOLLOW_PATH
| FOLLOW_LINKS
, NULL
, NULL
);
310 return NSS_STATUS_TRYAGAIN
;
313 if (__glibc_unlikely (niserr2nss (result
->status
) != NSS_STATUS_SUCCESS
))
315 enum nss_status status
= niserr2nss (result
->status
);
316 nis_freeresult (result
);
320 parse_res
= _nss_nisplus_parse_aliasent (result
, 0, alias
,
321 buffer
, buflen
, errnop
);
323 /* We do not need the lookup result anymore. */
324 nis_freeresult (result
);
326 if (__glibc_unlikely (parse_res
< 1))
328 __set_errno (olderr
);
331 return NSS_STATUS_TRYAGAIN
;
333 return NSS_STATUS_NOTFOUND
;
336 return NSS_STATUS_SUCCESS
;