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