(nis_leaf_of_r): Fix buffer problems.
[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;
120
121
122   strncpy (local_domain, nis_local_directory (), NIS_MAXNAMELEN);
123   local_domain[NIS_MAXNAMELEN] = '\0';
124
125   count = 1;
126   if ((getnames = malloc ((count + 1) * sizeof (char *))) == NULL)
127       return NULL;
128
129   /* Do we have a fully qualified NIS+ name ? If yes, give it back */
130   if (name[strlen (name) - 1] == '.')
131     {
132       if ((getnames[0] = strdup (name)) == NULL)
133         {
134           free (getnames);
135           return NULL;
136         }
137       getnames[1] = NULL;
138
139       return getnames;
140     }
141
142   /* Get the search path, where we have to search "name" */
143   path = getenv ("NIS_PATH");
144   if (path == NULL)
145     path = strdupa ("$");
146   else
147     path = strdupa (path);
148
149   pos = 0;
150
151   cp = strtok (path, ":");
152   while (cp)
153     {
154       if (strcmp (cp, "$") == 0)
155         {
156           char *cptr = local_domain;
157           char *tmp;
158
159           while (count_dots (cptr) >= 2)
160             {
161               if (pos >= count)
162                 {
163                   count += 5;
164                   getnames = realloc (getnames, (count + 1) * sizeof (char *));
165                 }
166               tmp = malloc (strlen (cptr) + strlen (local_domain) +
167                             strlen (name) + 2);
168               if (tmp == NULL)
169                 return NULL;
170
171               getnames[pos] = tmp;
172               tmp = stpcpy (tmp, name);
173               *tmp++ = '.';
174               stpcpy (tmp, cptr);
175
176               ++pos;
177
178               while (*cptr != '.')
179                 ++cptr;
180               ++cptr;
181             }
182         }
183       else
184         {
185           char *tmp;
186
187           if (cp[strlen (cp) - 1] == '$')
188             {
189               tmp = malloc (strlen (cp) + strlen (local_domain) +
190                             strlen (name) + 2);
191               if (tmp == NULL)
192                 return NULL;
193
194               tmp = stpcpy (tmp, name);
195               *tmp++ = '.';
196               tmp = stpcpy (tmp, cp);
197               --tmp;
198               if (tmp[-1] != '.')
199                 *tmp++ = '.';
200               stpcpy (tmp, local_domain);
201             }
202           else
203             {
204               tmp = malloc (strlen (cp) + strlen (name) + 2);
205               if (tmp == NULL)
206                 return NULL;
207
208               tmp = stpcpy (tmp, name);
209               *tmp++ = '.';
210               stpcpy (tmp, cp);
211             }
212
213           if (pos > count)
214             {
215               count += 5;
216               getnames = realloc (getnames, (count + 1) * sizeof (char *));
217               if (getnames == NULL)
218                 return NULL;
219             }
220           getnames[pos] = tmp;
221           ++pos;
222         }
223       cp = strtok (NULL, ":");
224     }
225
226   getnames[pos] = NULL;
227
228   return getnames;
229 }
230
231 void
232 nis_freenames (nis_name *names)
233 {
234   int i = 0;
235
236   while (names[i] != NULL)
237     {
238       free (names[i]);
239       ++i;
240     }
241
242   free (names);
243 }
244
245 name_pos
246 nis_dir_cmp (const_nis_name n1, const_nis_name n2)
247 {
248   int len1, len2;
249
250   len1 = strlen (n1);
251   len2 = strlen (n2);
252
253   if (len1 == len2)
254     {
255       if (strcmp (n1, n2) == 0)
256         return SAME_NAME;
257       else
258         return NOT_SEQUENTIAL;
259     }
260
261   if (len1 < len2)
262     {
263       if (n2[len2 - len1 - 1] != '.')
264         return NOT_SEQUENTIAL;
265       else if (strcmp (&n2[len2 - len1], n1) == 0)
266         return HIGHER_NAME;
267       else
268         return NOT_SEQUENTIAL;
269     }
270   else
271     {
272       if (n1[len1 - len2 - 1] != '.')
273         return NOT_SEQUENTIAL;
274       else if (strcmp (&n1[len1 - len2], n2) == 0)
275         return LOWER_NAME;
276       else
277         return NOT_SEQUENTIAL;
278
279     }
280 }
281
282 void
283 nis_destroy_object (nis_object *obj)
284 {
285   nis_free_object (obj);
286 }