Add libnsl_hidden_def for xdr_ypupdate_args.
[kopensolaris-gnu/glibc.git] / nis / nis_subr.c
1 /* Copyright (c) 1997, 1999, 2000, 2004, 2005 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.
4
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.
9
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.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA.  */
19
20 #include <errno.h>
21 #include <string.h>
22 #include <rpcsvc/nis.h>
23
24 nis_name
25 nis_leaf_of (const_nis_name name)
26 {
27   static char result[NIS_MAXNAMELEN + 1];
28
29   return nis_leaf_of_r (name, result, NIS_MAXNAMELEN);
30 }
31
32 nis_name
33 nis_leaf_of_r (const_nis_name name, char *buffer, size_t buflen)
34 {
35   size_t i = 0;
36
37   buffer[0] = '\0';
38
39   while (name[i] != '.' && name[i] != '\0')
40     i++;
41
42   if (__builtin_expect (i >= buflen, 0))
43     {
44       __set_errno (ERANGE);
45       return NULL;
46     }
47
48   *((char *) __mempcpy (buffer, name, i)) = '\0';
49
50   return buffer;
51 }
52 libnsl_hidden_def (nis_leaf_of_r)
53
54 nis_name
55 nis_name_of (const_nis_name name)
56 {
57   static char result[NIS_MAXNAMELEN + 1];
58
59   return nis_name_of_r (name, result, NIS_MAXNAMELEN);
60 }
61
62 nis_name
63 nis_name_of_r (const_nis_name name, char *buffer, size_t buflen)
64 {
65   char *local_domain;
66   int diff;
67
68   local_domain = nis_local_directory ();
69
70   diff = strlen (name) - strlen (local_domain);
71   if (diff <= 0)
72     return NULL;
73
74   if (strcmp (&name[diff], local_domain) != 0)
75     return NULL;
76
77   if ((size_t) diff >= buflen)
78     {
79       __set_errno (ERANGE);
80       return NULL;
81     }
82
83   *((char *) __mempcpy (buffer, name, diff - 1)) = '\0';
84
85   if (diff - 1 == 0)
86     return NULL;
87
88   return buffer;
89 }
90 libnsl_hidden_def (nis_name_of_r)
91
92 static int __always_inline
93 count_dots (const_nis_name str)
94 {
95   int count = 0;
96
97   for (size_t i = 0; str[i] != '\0'; ++i)
98     if (str[i] == '.')
99       ++count;
100
101   return count;
102 }
103
104 /* If we run out of memory, we don't give already allocated memory
105    free. The overhead for bringing getnames back in a safe state to
106    free it is to big. */
107 nis_name *
108 nis_getnames (const_nis_name name)
109 {
110   nis_name *getnames = NULL;
111   char local_domain[NIS_MAXNAMELEN + 1];
112   char *path;
113   char *cp;
114   int count;
115   int pos = 0;
116   int have_point;
117   char *saveptr;
118
119   strncpy (local_domain, nis_local_directory (), NIS_MAXNAMELEN);
120   local_domain[NIS_MAXNAMELEN] = '\0';
121
122   count = 1;
123   getnames = malloc ((count + 1) * sizeof (char *));
124   if (__builtin_expect (getnames == NULL, 0))
125       return NULL;
126
127   /* Do we have a fully qualified NIS+ name ? If yes, give it back */
128   if (name[strlen (name) - 1] == '.')
129     {
130       if ((getnames[0] = strdup (name)) == NULL)
131         {
132         free_null:
133           while (pos-- > 0)
134             free (getnames[pos]);
135           free (getnames);
136           return NULL;
137         }
138
139       getnames[1] = NULL;
140
141       return getnames;
142     }
143
144   /* Get the search path, where we have to search "name" */
145   path = getenv ("NIS_PATH");
146   if (path == NULL)
147     path = strdupa ("$");
148   else
149     path = strdupa (path);
150
151   have_point = (strchr (name, '.') != NULL);
152
153   cp = __strtok_r (path, ":", &saveptr);
154   while (cp)
155     {
156       if (strcmp (cp, "$") == 0)
157         {
158           char *cptr = local_domain;
159           char *tmp;
160
161           while ((have_point && *cptr != '\0') || (count_dots (cptr) >= 2))
162             {
163               if (pos >= count)
164                 {
165                   count += 5;
166                   nis_name *newp = realloc (getnames,
167                                             (count + 1) * sizeof (char *));
168                   if (__builtin_expect (newp == NULL, 0))
169                     goto free_null;
170                   getnames = newp;
171                 }
172               tmp = malloc (strlen (cptr) + strlen (local_domain) +
173                             strlen (name) + 2);
174               if (__builtin_expect (tmp == NULL, 0))
175                 goto free_null;
176
177               getnames[pos] = tmp;
178               tmp = stpcpy (tmp, name);
179               *tmp++ = '.';
180               if (cptr[1] != '\0')
181                 stpcpy (tmp, cptr);
182               else
183                 ++cptr;
184
185               ++pos;
186
187               while (*cptr != '.' && *cptr != '\0')
188                 ++cptr;
189               if (cptr[0] != '\0' && cptr[1] != '\0')
190                 /* If we have only ".", don't remove the "." */
191                 ++cptr;
192             }
193         }
194       else
195         {
196           char *tmp;
197           size_t cplen = strlen (cp);
198
199           if (cp[cplen - 1] == '$')
200             {
201               char *p;
202
203               tmp = malloc (cplen + strlen (local_domain) + strlen (name) + 2);
204               if (__builtin_expect (tmp == NULL, 0))
205                 goto free_null;
206
207               p = __stpcpy (tmp, name);
208               *p++ = '.';
209               p = __mempcpy (p, cp, cplen);
210               --p;
211               if (p[-1] != '.')
212                 *p++ = '.';
213               __stpcpy (p, local_domain);
214             }
215           else
216             {
217               char *p;
218
219               tmp = malloc (cplen + strlen (name) + 2);
220               if (__builtin_expect (tmp == NULL, 0))
221                 goto free_null;
222
223               p = __stpcpy (tmp, name);
224               *p++ = '.';
225               memcpy (p, cp, cplen + 1);
226             }
227
228           if (pos >= count)
229             {
230               count += 5;
231               nis_name *newp = realloc (getnames,
232                                         (count + 1) * sizeof (char *));
233               if (__builtin_expect (newp == NULL, 0))
234                 goto free_null;
235               getnames = newp;
236             }
237           getnames[pos] = tmp;
238           ++pos;
239         }
240       cp = __strtok_r (NULL, ":", &saveptr);
241     }
242
243   getnames[pos] = NULL;
244
245   return getnames;
246 }
247 libnsl_hidden_def (nis_getnames)
248
249 void
250 nis_freenames (nis_name *names)
251 {
252   int i = 0;
253
254   while (names[i] != NULL)
255     {
256       free (names[i]);
257       ++i;
258     }
259
260   free (names);
261 }
262 libnsl_hidden_def  (nis_freenames)
263
264 name_pos
265 nis_dir_cmp (const_nis_name n1, const_nis_name n2)
266 {
267   int len1, len2;
268
269   len1 = strlen (n1);
270   len2 = strlen (n2);
271
272   if (len1 == len2)
273     {
274       if (strcmp (n1, n2) == 0)
275         return SAME_NAME;
276       else
277         return NOT_SEQUENTIAL;
278     }
279
280   if (len1 < len2)
281     {
282       if (n2[len2 - len1 - 1] != '.')
283         return NOT_SEQUENTIAL;
284       else if (strcmp (&n2[len2 - len1], n1) == 0)
285         return HIGHER_NAME;
286       else
287         return NOT_SEQUENTIAL;
288     }
289   else
290     {
291       if (n1[len1 - len2 - 1] != '.')
292         return NOT_SEQUENTIAL;
293       else if (strcmp (&n1[len1 - len2], n2) == 0)
294         return LOWER_NAME;
295       else
296         return NOT_SEQUENTIAL;
297
298     }
299 }
300 libnsl_hidden_def (nis_dir_cmp)
301
302 void
303 nis_destroy_object (nis_object *obj)
304 {
305   nis_free_object (obj);
306 }
307 libnsl_hidden_def (nis_destroy_object)