xref: /illumos-gate/usr/src/cmd/ldap/ns_ldap/ldapaddent.c (revision 60405de4d8688d96dd05157c28db3ade5c9bc234)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 /*
29  * ldapaddent.c
30  *
31  * Utility to add /etc files into LDAP.
32  * Can also be used to dump entries from a ldap container in /etc format.
33  */
34 
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <libintl.h>
38 #include <strings.h>
39 #include <sys/param.h>
40 #include <ctype.h>
41 #include <sys/types.h>
42 #include <sys/socket.h>
43 #include <netinet/in.h>
44 #include <arpa/inet.h>
45 #include <locale.h>
46 #include <syslog.h>
47 
48 #undef opaque
49 
50 #include <nss_dbdefs.h>
51 #include <netdb.h>
52 #include <rpc/rpcent.h>
53 #include <grp.h>
54 #include <pwd.h>
55 #include <shadow.h>
56 #include <sys/systeminfo.h>
57 #include "ns_internal.h"
58 #include "ldapaddent.h"
59 
60 #define	OP_ADD	0
61 #define	OP_DUMP	3
62 
63 static struct ttypelist_t {
64 	char *ttype;		/* type tag */
65 	int (*genent)(char *, int(*)());
66 				/* routine to turn line into ldap entries */
67 	void (*dump)(ns_ldap_result_t *);
68 				/* routine to print ldap containers */
69 	int (*filedbmline)();	/* routine to turn file line into dbm line */
70 	char *objclass;		/* Objectclass for the servicetype */
71 } *tt;
72 
73 char	parse_err_msg [PARSE_ERR_MSG_LEN];
74 int	continue_onerror = 0;  /* do not exit on error */
75 
76 static int get_basedn(char *service, char **basedn);
77 static int check_ipaddr(char *addr, char **newaddr);
78 
79 extern	int	optind;
80 extern	char	*optarg;
81 
82 extern	char	*__nis_quote_key(const char *, char *, int);
83 /* from ns_internal.h */
84 extern	int __s_api_prepend_automountmapname_to_dn(
85 	const char *, char **, ns_ldap_error_t **);
86 
87 static char	*inputbasedn = NULL;
88 static char	*databasetype = NULL;
89 static int	exit_val = 0;
90 static unsigned	nent_add = 0;
91 static FILE	*etcf = 0;
92 static ns_cred_t	authority;
93 unsigned	flags = 0;
94 
95 static void
96 perr(ns_ldap_error_t *e)
97 {
98 	if (e)
99 		(void) fprintf(stderr, gettext("%d: %s\n"),
100 				e->status, e->message);
101 }
102 
103 
104 static int
105 ascii_to_int(char *str)
106 {
107 	int i;
108 	char *c = str;
109 
110 	if (c == NULL || *c == '\0')
111 		return (-1);
112 
113 	while (c != '\0' && *c == ' ')
114 		c++;
115 	if (*c == '\0')
116 		return (-1);
117 
118 	for (i = 0; i < strlen(c); i++)
119 		if (!isdigit(c[i]))
120 			return (-1);
121 
122 	return (atoi(c));
123 }
124 
125 /*
126  * Internet network address interpretation routine.
127  * The library routines call this routine to interpret
128  * network numbers.
129  */
130 static in_addr_t
131 encode_network(const char *cp)
132 {
133 	in_addr_t val;
134 	int base;
135 	ptrdiff_t n;
136 	char c;
137 	in_addr_t parts[4], *pp = parts;
138 	int i;
139 
140 again:
141 	val = 0; base = 10;
142 	if (*cp == '0') {
143 		if (*++cp == 'x' || *cp == 'X')
144 			base = 16, cp++;
145 		else
146 			base = 8;
147 	}
148 	while ((c = *cp) != NULL) {
149 		if (isdigit(c)) {
150 			if ((c - '0') >= base)
151 			    break;
152 			val = (val * base) + (c - '0');
153 			cp++;
154 			continue;
155 		}
156 		if (base == 16 && isxdigit(c)) {
157 			val = (val << 4) + (c + 10 - (islower(c) ? 'a' : 'A'));
158 			cp++;
159 			continue;
160 		}
161 		break;
162 	}
163 	if (*cp == '.') {
164 		if (pp >= parts + 4)
165 			return ((in_addr_t)-1);
166 		*pp++ = val, cp++;
167 		goto again;
168 	}
169 	if (*cp && !isspace(*cp))
170 		return ((in_addr_t)-1);
171 	*pp++ = val;
172 	n = pp - parts;
173 	if (n > 4)
174 		return ((in_addr_t)-1);
175 	for (val = 0, i = 0; i < n; i++) {
176 		val <<= 8;
177 		val |= parts[i] & 0xff;
178 	}
179 	for (/* no init */; i < 4; i++)
180 		val <<= 8;
181 	return (val);
182 }
183 
184 static void
185 replace_tab2space(char *str)
186 {
187 	int i = 0;
188 
189 	while ((str) && (str[i])) {
190 		if (str[i] == '\t')
191 			str[i] = ' ';
192 		i++;
193 	}
194 }
195 
196 static int
197 blankline(char *line)
198 {
199 	char *p;
200 
201 	for (p = line; *p; p++)
202 		if (*p != ' ' && *p != '\t')
203 			return (0);
204 	return (1);
205 }
206 
207 /*
208  * check whether the token <tok> is a triplet,
209  * i. e. <tok> := (<hostname>,<username>,<domainname>)
210  * where <hostname>, <username>, <domainname> are IA5String
211  * <tok> supposes to contain NO spaces and start with '('
212  */
213 static int
214 is_triplet(char *tok)
215 {
216 	char *s;
217 	return (strchr(++tok, '(') == NULL &&		/* no more '(' */
218 		(s = strchr(tok, ')')) != NULL &&	/* find ')' */
219 		!*++s &&				/* ')' ends token */
220 		(tok = strchr(tok, ',')) != NULL &&	/* host up to ',' */
221 		(tok = strchr(++tok, ',')) != NULL &&	/* user up to ',' */
222 		strchr(++tok, ',') == NULL);		/* no more ',' */
223 }
224 
225 static void
226 line_buf_expand(struct line_buf *line)
227 {
228 	line->alloc += BUFSIZ;
229 	line->str = (char *)realloc(line->str, line->alloc);
230 
231 	if (line->str == NULL) {
232 		(void) fprintf(stderr,
233 		    gettext("line_buf_expand: out of memory\n"));
234 		exit(1);
235 	}
236 }
237 
238 static void
239 line_buf_init(struct line_buf *line)
240 {
241 	(void) memset((char *)line, 0, sizeof (*line));
242 	line_buf_expand(line);
243 }
244 
245 static int
246 __s_add_attr(ns_ldap_entry_t *e, char *attrname, char *value)
247 {
248 	ns_ldap_attr_t	*a;
249 	char		*v;
250 
251 	a = (ns_ldap_attr_t *)calloc(1, sizeof (ns_ldap_attr_t));
252 	if (a == NULL)
253 		return (NS_LDAP_MEMORY);
254 	a->attrname = strdup(attrname);
255 	if (a->attrname == NULL) {
256 		free(a);
257 		return (NS_LDAP_MEMORY);
258 	}
259 	a->attrvalue = (char **)calloc(1, sizeof (char **));
260 	if (a->attrvalue == NULL) {
261 		free(a->attrname);
262 		free(a);
263 		return (NS_LDAP_MEMORY);
264 	}
265 	a->value_count = 1;
266 	a->attrvalue[0] = NULL;
267 	v = strdup(value);
268 	if (v == NULL) {
269 		free(a->attrname);
270 		free(a->attrvalue);
271 		free(a);
272 		return (NS_LDAP_MEMORY);
273 	}
274 	a->attrvalue[0] = v;
275 	e->attr_pair[e->attr_count] = a;
276 	e->attr_count++;
277 	return (NS_LDAP_SUCCESS);
278 }
279 
280 static int
281 __s_add_attrlist(ns_ldap_entry_t *e, char *attrname, char **argv)
282 {
283 	ns_ldap_attr_t	*a;
284 	char		*v;
285 	char		**av;
286 	int		i, j;
287 
288 	a = (ns_ldap_attr_t *)calloc(1, sizeof (ns_ldap_attr_t));
289 	if (a == NULL)
290 		return (NS_LDAP_MEMORY);
291 	a->attrname = strdup(attrname);
292 	if (a->attrname == NULL) {
293 		free(a);
294 		return (NS_LDAP_MEMORY);
295 	}
296 
297 	for (i = 0, av = argv; *av != NULL; av++, i++)
298 		;
299 
300 	a->attrvalue = (char **)calloc(i, sizeof (char **));
301 
302 	if (a->attrvalue == NULL) {
303 		free(a->attrname);
304 		free(a);
305 		return (NS_LDAP_MEMORY);
306 	}
307 	a->value_count = i;
308 	for (j = 0; j < i; j++) {
309 		v = strdup(argv[j]);
310 		if (v == NULL) {
311 			free(a->attrname);
312 			free(a->attrvalue);
313 			free(a);
314 			return (NS_LDAP_MEMORY);
315 		}
316 		a->attrvalue[j] = v;
317 	}
318 	e->attr_pair[e->attr_count] = a;
319 	e->attr_count++;
320 	return (NS_LDAP_SUCCESS);
321 }
322 
323 static ns_ldap_entry_t *
324 __s_mk_entry(char **objclass, int max_attr)
325 {
326 	ns_ldap_entry_t *e;
327 	e = (ns_ldap_entry_t *)calloc(1, sizeof (ns_ldap_entry_t));
328 	if (e == NULL)
329 		return (NULL);
330 	e->attr_pair = (ns_ldap_attr_t **)calloc(max_attr+1,
331 						sizeof (ns_ldap_attr_t *));
332 	if (e->attr_pair == NULL) {
333 		free(e);
334 		return (NULL);
335 	}
336 	e->attr_count = 0;
337 	if (__s_add_attrlist(e, "objectClass", objclass) != NS_LDAP_SUCCESS) {
338 		free(e->attr_pair);
339 		free(e);
340 		return (NULL);
341 	}
342 	return (e);
343 }
344 
345 static void
346 ldap_freeEntry(ns_ldap_entry_t *ep)
347 {
348 	int		j, k = 0;
349 
350 	if (ep == NULL)
351 		return;
352 
353 	if (ep->attr_pair == NULL) {
354 		free(ep);
355 		return;
356 	}
357 	for (j = 0; j < ep->attr_count; j++) {
358 		if (ep->attr_pair[j] == NULL)
359 			continue;
360 		if (ep->attr_pair[j]->attrname)
361 			free(ep->attr_pair[j]->attrname);
362 		if (ep->attr_pair[j]->attrvalue) {
363 			for (k = 0; (k < ep->attr_pair[j]->value_count) &&
364 				    (ep->attr_pair[j]->attrvalue[k]); k++) {
365 				free(ep->attr_pair[j]->attrvalue[k]);
366 			}
367 			free(ep->attr_pair[j]->attrvalue);
368 		}
369 		free(ep->attr_pair[j]);
370 	}
371 	free(ep->attr_pair);
372 	free(ep);
373 }
374 
375 static int
376 addentry(void *entry, int mod)
377 {
378 	int		 result = 0;
379 	ns_ldap_error_t	 *eres = NULL;
380 	int		rc = 1;
381 
382 
383 	/*  adds entry into the LDAP tree */
384 	if (mod)
385 		result = __ns_ldap_addTypedEntry(databasetype, inputbasedn,
386 		    entry, 0, &authority, NS_LDAP_FOLLOWREF, &eres);
387 	else
388 		result = __ns_ldap_addTypedEntry(databasetype, inputbasedn,
389 		    entry, 1, &authority, NS_LDAP_FOLLOWREF, &eres);
390 	/*
391 	 *  Return	0 on success
392 	 *		LDAP_ALREADY_EXISTS if entry exists already
393 	 *		1 for all other non-fatal errors.
394 	 *  Exit on fatal errors.
395 	 */
396 	switch (result) {
397 	case NS_LDAP_SUCCESS:
398 		nent_add++;
399 		rc = 0;
400 		break;
401 
402 	case NS_LDAP_OP_FAILED:
403 		(void) fprintf(stderr, gettext("operation failed.\n"));
404 		rc = 1;
405 		break;
406 
407 	case NS_LDAP_INVALID_PARAM:
408 		(void) fprintf(stderr,
409 		    gettext("invalid parameter(s) passed.\n"));
410 		rc = 1;
411 		break;
412 
413 	case NS_LDAP_NOTFOUND:
414 		(void) fprintf(stderr, gettext("entry not found.\n"));
415 		rc = 1;
416 		break;
417 
418 	case NS_LDAP_MEMORY:
419 		(void) fprintf(stderr,
420 		    gettext("internal memory allocation error.\n"));
421 		exit(1);
422 		break;
423 
424 	case NS_LDAP_CONFIG:
425 		(void) fprintf(stderr,
426 		    gettext("LDAP Configuration problem.\n"));
427 		perr(eres);
428 		exit(1);
429 		break;
430 
431 	case NS_LDAP_PARTIAL:
432 		(void) fprintf(stderr,
433 		    gettext("partial result returned\n"));
434 		perr(eres);
435 		rc = 1;
436 		break;
437 
438 	case NS_LDAP_INTERNAL:
439 		if (eres->status == LDAP_ALREADY_EXISTS ||
440 			eres->status == LDAP_NO_SUCH_OBJECT)
441 			rc = eres->status;
442 		else {
443 			rc = 1;
444 			perr(eres);
445 		}
446 		break;
447 	}
448 
449 	if (eres)
450 		(void) __ns_ldap_freeError(&eres);
451 	return (rc);
452 }
453 
454 
455 /*
456  * usage(char *msg)
457  * Display usage message to STDERR.
458  */
459 static void
460 usage(char *msg) {
461 
462 	if (msg)
463 		(void) fprintf(stderr, gettext("%s\n"), msg);
464 
465 	(void) fprintf(stderr, gettext(
466 	    "usage: ldapaddent [ -cpv ] [ -a authenticationMethod ]\n"
467 	    "[ -b baseDN ] -D bindDN -w bind_password [ -f file ] database\n\n"
468 	    "usage: ldapaddent -d [ -cpv ] [ -a authenticationMethod ]\n"
469 	    "[ -b baseDN ] [ -D bindDN ] [ -w bind_password ] database\n"));
470 	exit(1);
471 }
472 
473 /*
474  * Determine if the given string is an IP address (IPv4 or IPv6).
475  * If so, it's converted to the preferred form (rfc2373) and
476  * *newaddr will point to the new address.
477  *
478  * Returns	-2		: inet_ntop error
479  *		-1		: not an IP address
480  *		0		: unsupported IP address (future use)
481  *		AF_INET		: IPv4
482  *		AF_INET6	: IPv6
483  */
484 static int
485 check_ipaddr(char *addr, char **newaddr) {
486 	ipaddr_t	addr_ipv4 = 0;
487 	in6_addr_t	addr_ipv6;
488 
489 	/* IPv6 */
490 	if (inet_pton(AF_INET6, addr, &addr_ipv6) == 1) {
491 		if (newaddr == NULL)
492 			return (AF_INET6);
493 
494 		/* Convert IPv4-mapped IPv6 address to IPv4 */
495 		if (IN6_IS_ADDR_V4MAPPED(&addr_ipv6) ||
496 					IN6_IS_ADDR_V4COMPAT(&addr_ipv6)) {
497 			IN6_V4MAPPED_TO_IPADDR(&addr_ipv6, addr_ipv4);
498 			if ((*newaddr = calloc(1, INET_ADDRSTRLEN)) == NULL) {
499 				(void) fprintf(stderr,
500 				    gettext("out of memory\n"));
501 				exit(1);
502 			}
503 			if (inet_ntop(AF_INET, &addr_ipv4, *newaddr,
504 			    INET_ADDRSTRLEN))
505 				return (AF_INET6);
506 			free(*newaddr);
507 			return (-2);
508 		}
509 
510 		/* Processing general IPv6 addresses */
511 		if ((*newaddr = calloc(1, INET6_ADDRSTRLEN)) == NULL) {
512 			(void) fprintf(stderr, gettext("out of memory\n"));
513 			exit(1);
514 		}
515 		if (inet_ntop(AF_INET6, &addr_ipv6, *newaddr, INET6_ADDRSTRLEN))
516 			return (AF_INET6);
517 		free(*newaddr);
518 		return (-2);
519 	}
520 
521 	/* Processing IPv4 addresses of the type d.d.d.d. */
522 	if (inet_pton(AF_INET, addr, &addr_ipv4) == 1) {
523 		if (newaddr == NULL)
524 			return (AF_INET);
525 		if ((*newaddr = calloc(1, INET_ADDRSTRLEN)) == NULL) {
526 			(void) fprintf(stderr, gettext("out of memory\n"));
527 			exit(1);
528 		}
529 		if (inet_ntop(AF_INET, &addr_ipv4, *newaddr, INET_ADDRSTRLEN))
530 			return (AF_INET);
531 		free(*newaddr);
532 		return (-2);
533 	}
534 
535 	/* Processing IPv4 addresses d.d.d , d.d and d */
536 	if (inet_addr(addr) != (in_addr_t)-1) {
537 		if (newaddr == NULL)
538 			return (AF_INET);
539 		if ((*newaddr = strdup(addr)) == NULL) {
540 			(void) fprintf(stderr, gettext("out of memory\n"));
541 			exit(1);
542 		}
543 		return (AF_INET);
544 	}
545 
546 	return (-1);
547 }
548 
549 static int
550 genent_hosts(char *line, int (*cback)())
551 {
552 	char buf[BUFSIZ+1];
553 	char *t, *comment;
554 	entry_col ecol[4];
555 	char *cname, *pref_addr;
556 	int ctr = 0, retval = 1;
557 	int rc = GENENT_OK, af;
558 
559 	struct hostent  data;
560 	char *alias;
561 
562 	/*
563 	 * don't clobber our argument
564 	 */
565 	if (strlen(line) >= sizeof (buf)) {
566 		(void) strcpy(parse_err_msg, "line too long");
567 		return (GENENT_PARSEERR);
568 	}
569 	(void) strcpy(buf, line);
570 
571 	/*
572 	 * clear column data
573 	 */
574 	(void) memset((char *)ecol, 0, sizeof (ecol));
575 
576 	/*
577 	 * comment (col 3)
578 	 * All leading spaces will be deleted from the comment
579 	 */
580 	ecol[3].ec_value.ec_value_val = "";
581 	ecol[3].ec_value.ec_value_len = 0;
582 	comment = t = strchr(buf, '#');
583 	if (comment) {
584 		do {
585 			++comment;
586 		} while (*comment != '\0' && isspace(*comment));
587 		if (*comment != '\0') {
588 			*--comment = '#';
589 			ecol[3].ec_value.ec_value_val = strdup(comment);
590 			ecol[3].ec_value.ec_value_len = strlen(comment)+1;
591 		}
592 
593 		*t = '\0';
594 	}
595 
596 	/*
597 	 * addr(col 2)
598 	 */
599 	if ((t = strtok(buf, " \t")) == 0) {
600 		(void) strcpy(parse_err_msg, "no host");
601 		return (GENENT_PARSEERR);
602 	}
603 
604 	af = check_ipaddr(t, &pref_addr);
605 	if (af == -2) {
606 		(void) strcpy(parse_err_msg, "Internal error");
607 	} else if (af == -1) {
608 		(void) snprintf(parse_err_msg, sizeof (parse_err_msg),
609 		    "Invalid IP address: %s", t);
610 	} else if (flags & F_VERBOSE) {
611 		if ((strncasecmp(t, pref_addr, strlen(t))) != 0) {
612 			(void) fprintf(stdout,
613 			    gettext("IP address %s converted to %s\n"),
614 			    t, pref_addr);
615 		}
616 	}
617 
618 	if (af < 0) {
619 		(void) fprintf(stderr, gettext("%s\n"), parse_err_msg);
620 		if (continue_onerror == 0)
621 			return (GENENT_CBERR);
622 		else
623 			return (rc);
624 	}
625 
626 	ecol[2].ec_value.ec_value_val = pref_addr;
627 	ecol[2].ec_value.ec_value_len = strlen(pref_addr)+1;
628 
629 	/*
630 	 * cname (col 0)
631 	 */
632 	if ((t = strtok(NULL, " \t")) == 0) {
633 		(void) strcpy(parse_err_msg, "no cname");
634 		return (GENENT_PARSEERR);
635 	}
636 	ecol[0].ec_value.ec_value_val = t;
637 	ecol[0].ec_value.ec_value_len = strlen(t)+1;
638 	cname = t;
639 
640 
641 	/* build entry */
642 	if ((data.h_addr_list = (char **)calloc(2, sizeof (char **))) == NULL) {
643 		(void) fprintf(stderr, gettext("out of memory\n"));
644 		exit(1);
645 	}
646 	data.h_addr_list[0] = strdup(ecol[2].ec_value.ec_value_val);
647 	data.h_addr_list[1] = NULL;
648 
649 	free(pref_addr);
650 	data.h_name = strdup(ecol[0].ec_value.ec_value_val);
651 
652 	/*
653 	 * name (col 1)
654 	 */
655 
656 	data.h_aliases = NULL;
657 
658 	do {
659 		/*
660 		 * don't clobber comment in canonical entry
661 		 */
662 
663 		/* This call to AddEntry may move out of the loop */
664 		/* This is because we have to call the function just once */
665 		if (t != cname && strcasecmp(t, cname) == 0)
666 			continue;
667 		if (strcasecmp(t, ecol[0].ec_value.ec_value_val) == 0)
668 			continue;
669 
670 		ecol[1].ec_value.ec_value_val = t;
671 		ecol[1].ec_value.ec_value_len = strlen(t)+1;
672 
673 		ctr++;
674 		alias = strdup(ecol[1].ec_value.ec_value_val);
675 		if ((data.h_aliases = (char **)realloc(data.h_aliases,
676 			ctr * sizeof (char **))) == NULL) {
677 			(void) fprintf(stderr, gettext("out of memory\n"));
678 			exit(1);
679 		}
680 		data.h_aliases[ctr-1] = alias;
681 	} while (t = strtok(NULL, " \t"));
682 
683 	/*
684 	 * End the list of all the aliases by NULL
685 	 * If there is some comment, it will be stored as the last entry
686 	 * in the list of the host aliases
687 	 */
688 	if ((data.h_aliases = (char **)realloc(data.h_aliases,
689 		(ecol[3].ec_value.ec_value_len != 0 ?
690 			ctr + 2 : ctr + 1) * sizeof (char **))) == NULL) {
691 		(void) fprintf(stderr, gettext("out of memory\n"));
692 		exit(1);
693 	}
694 
695 	if (ecol[3].ec_value.ec_value_len != 0) {
696 		data.h_aliases[ctr++] = ecol[3].ec_value.ec_value_val;
697 	}
698 	data.h_aliases[ctr] = NULL;
699 
700 	if (flags & F_VERBOSE)
701 		(void) fprintf(stdout,
702 		    gettext("Adding entry : cn=%s+ipHostNumber=%s\n"),
703 		    data.h_name, data.h_addr_list[0]);
704 
705 	retval = (*cback)(&data, 0);
706 
707 	if (ecol[3].ec_value.ec_value_len != 0) {
708 		free(ecol[3].ec_value.ec_value_val);
709 	}
710 
711 	if (retval == LDAP_ALREADY_EXISTS) {
712 		if (continue_onerror)
713 			(void) fprintf(stderr,
714 				gettext("Entry: cn=%s+ipHostNumber=%s "
715 					"already Exists -skipping it\n"),
716 					data.h_name, data.h_addr_list[0]);
717 		else {
718 			rc = GENENT_CBERR;
719 			(void) fprintf(stderr,
720 				gettext("Entry: cn=%s+ipHostNumber=%s"
721 					" already Exists\n"),
722 					data.h_name, data.h_addr_list[0]);
723 		}
724 	} else if (retval)
725 		rc = GENENT_CBERR;
726 
727 	free(data.h_name);
728 	free(data.h_aliases);
729 	free(data.h_addr_list);
730 
731 	return (rc);
732 }
733 
734 
735 
736 static void
737 dump_hosts(ns_ldap_result_t *res)
738 {
739 	ns_ldap_attr_t	*attrptr = NULL,
740 			*cn = NULL,
741 			*iphostnumber = NULL,
742 			*desc = NULL;
743 	int		 i, j;
744 	char		*name; /* host name */
745 
746 	if (res == NULL || res->entry == NULL)
747 		return;
748 	for (i = 0; i < res->entry->attr_count; i++) {
749 		attrptr = res->entry->attr_pair[i];
750 		if (strcasecmp(attrptr->attrname, "cn") == 0)
751 			cn = attrptr;
752 		else if (strcasecmp(attrptr->attrname, "iphostnumber") == 0)
753 			iphostnumber = attrptr;
754 		else if (strcasecmp(attrptr->attrname, "description") == 0) {
755 			desc = attrptr;
756 		}
757 	}
758 	/* sanity check */
759 	if (cn == NULL || cn->attrvalue == NULL || cn->attrvalue[0] == NULL ||
760 	    iphostnumber == NULL || iphostnumber->attrvalue == NULL ||
761 	    iphostnumber->attrvalue[0] == NULL)
762 		return;
763 
764 	if ((name = __s_api_get_canonical_name(res->entry, cn, 1)) == NULL)
765 		return;
766 
767 	/* ip host/ipnode number */
768 	if (strlen(iphostnumber->attrvalue[0]) <= INET_ADDRSTRLEN)
769 		/* IPV4 or IPV6 but <= NET_ADDRSTRLEN */
770 		(void) fprintf(stdout, "%-18s", iphostnumber->attrvalue[0]);
771 	else
772 		/* IPV6 */
773 		(void) fprintf(stdout, "%-48s", iphostnumber->attrvalue[0]);
774 
775 	/* host/ipnode name */
776 	(void) fprintf(stdout, "%s ", name);
777 
778 	/* aliases */
779 	for (j = 0; j < cn->value_count; j++) {
780 		if (cn->attrvalue[j]) {
781 			if (strcasecmp(name, cn->attrvalue[j]) == 0)
782 				/* skip host name */
783 				continue;
784 			(void) fprintf(stdout, "%s ", cn->attrvalue[j]);
785 		}
786 	}
787 
788 	/* description */
789 	if (desc != NULL && desc->attrvalue != NULL &&
790 	    desc->attrvalue[0] != NULL) {
791 		(void) fprintf(stdout, "#%s", desc->attrvalue[0]);
792 	}
793 
794 	/* end of line */
795 	(void) fprintf(stdout, "\n");
796 }
797 
798 /*
799  * /etc/rpc
800  */
801 
802 static int
803 genent_rpc(char *line, int (*cback)())
804 {
805 	char buf[BUFSIZ+1];
806 	char *t;
807 	entry_col ecol[4];
808 	char *cname;
809 
810 	struct rpcent	data;
811 	char *alias;
812 	int ctr = 0;
813 	int retval = 1;
814 	int rc = GENENT_OK;
815 
816 	/*
817 	 * don't clobber our argument
818 	 */
819 	if (strlen(line) >= sizeof (buf)) {
820 		(void) strcpy(parse_err_msg, "line too long");
821 		return (GENENT_PARSEERR);
822 	}
823 	(void) strcpy(buf, line);
824 
825 	/*
826 	 * clear column data
827 	 */
828 	(void) memset((char *)ecol, 0, sizeof (ecol));
829 
830 	/*
831 	 * comment (col 3)
832 	 */
833 	t = strchr(buf, '#');
834 	if (t) {
835 		*t++ = 0;
836 		ecol[3].ec_value.ec_value_val = t;
837 		ecol[3].ec_value.ec_value_len = strlen(t)+1;
838 	} else {
839 		ecol[3].ec_value.ec_value_val = 0;
840 		ecol[3].ec_value.ec_value_len = 0;
841 	}
842 
843 	/*
844 	 * cname(col 0)
845 	 */
846 	if ((t = strtok(buf, " \t")) == 0) {
847 		(void) strcpy(parse_err_msg, "no number");
848 		return (GENENT_PARSEERR);
849 	}
850 	ecol[0].ec_value.ec_value_val = t;
851 	ecol[0].ec_value.ec_value_len = strlen(t)+1;
852 	cname = t;
853 
854 	/*
855 	 * number (col 2)
856 	 */
857 	if ((t = strtok(NULL, " \t")) == 0) {
858 		(void) strcpy(parse_err_msg, "no number");
859 		return (GENENT_PARSEERR);
860 	}
861 	ecol[2].ec_value.ec_value_val = t;
862 	ecol[2].ec_value.ec_value_len = strlen(t)+1;
863 
864 
865 	/*
866 	 * build entry
867 	 */
868 
869 	data.r_name = strdup(ecol[0].ec_value.ec_value_val);
870 	if (ecol[2].ec_value.ec_value_val != NULL &&
871 		ecol[2].ec_value.ec_value_val[0] != '\0') {
872 
873 		data.r_number = ascii_to_int(ecol[2].ec_value.ec_value_val);
874 		if (data.r_number == -1) {
875 			(void) snprintf(parse_err_msg, sizeof (parse_err_msg),
876 			    "invalid program number: %s",
877 			    ecol[2].ec_value.ec_value_val);
878 		return (GENENT_PARSEERR);
879 		}
880 	} else
881 		data.r_number = -1;
882 
883 	/*
884 	 * name (col 1)
885 	 */
886 	t = cname;
887 	data.r_aliases = NULL;
888 	do {
889 
890 		/*
891 		 * don't clobber comment in canonical entry
892 		 */
893 		if (t != cname && strcasecmp(t, cname) == 0)
894 			continue;
895 		if (strcasecmp(t, ecol[0].ec_value.ec_value_val) == 0)
896 			continue;
897 
898 		ecol[1].ec_value.ec_value_val = t;
899 		ecol[1].ec_value.ec_value_len = strlen(t)+1;
900 
901 		ctr++;
902 		alias = strdup(ecol[1].ec_value.ec_value_val);
903 		if ((data.r_aliases = (char **)realloc(data.r_aliases,
904 			ctr * sizeof (char **))) == NULL) {
905 			(void) fprintf(stderr, gettext("out of memory\n"));
906 			exit(1);
907 		}
908 		data.r_aliases[ctr-1] = alias;
909 
910 
911 		/*
912 		 * only put comment in canonical entry
913 		 */
914 		ecol[3].ec_value.ec_value_val = 0;
915 		ecol[3].ec_value.ec_value_len = 0;
916 
917 	} while (t = strtok(NULL, " \t"));
918 
919 	/* End the list of all the aliases by NULL */
920 	if ((data.r_aliases = (char **)realloc(data.r_aliases,
921 		(ctr + 1) * sizeof (char **))) == NULL) {
922 		(void) fprintf(stderr, gettext("out of memory\n"));
923 		exit(1);
924 	}
925 	data.r_aliases[ctr] = NULL;
926 
927 	if (flags & F_VERBOSE)
928 		(void) fprintf(stdout,
929 		    gettext("Adding entry : %s\n"), data.r_name);
930 
931 	retval = (*cback)(&data, 0);
932 
933 	if (retval == LDAP_ALREADY_EXISTS) {
934 		if (continue_onerror)
935 			(void) fprintf(stderr,
936 			gettext("Entry: %s - already Exists, skipping it.\n"),
937 			data.r_name);
938 		else {
939 			rc = GENENT_CBERR;
940 			(void) fprintf(stderr,
941 				gettext("Entry: %s - already Exists\n"),
942 				data.r_name);
943 		}
944 	} else if (retval)
945 		rc = GENENT_CBERR;
946 
947 	free(data.r_name);
948 	free(data.r_aliases);
949 
950 	return (rc);
951 }
952 
953 
954 
955 static void
956 dump_rpc(ns_ldap_result_t *res)
957 {
958 	ns_ldap_attr_t	*attrptr = NULL, *cn = NULL, *rpcnumber = NULL;
959 	int		 i, j;
960 	char		*name; /* rpc name */
961 
962 	if (res == NULL || res->entry == NULL)
963 		return;
964 	for (i = 0; i < res->entry->attr_count; i++) {
965 		attrptr = res->entry->attr_pair[i];
966 		if (strcasecmp(attrptr->attrname, "cn") == 0)
967 			cn = attrptr;
968 		else if (strcasecmp(attrptr->attrname, "oncRpcNumber") == 0)
969 			rpcnumber = attrptr;
970 	}
971 	/* sanity check */
972 	if (cn == NULL || cn->attrvalue == NULL || cn->attrvalue[0] == NULL ||
973 	    rpcnumber == NULL || rpcnumber->attrvalue == NULL ||
974 	    rpcnumber->attrvalue[0] == NULL)
975 		return;
976 
977 	if ((name = __s_api_get_canonical_name(res->entry, cn, 1)) == NULL)
978 		return;
979 
980 	/* rpc name */
981 	if (strlen(name) < 8)
982 		(void) fprintf(stdout, "%s\t\t", name);
983 	else
984 		(void) fprintf(stdout, "%s\t", name);
985 
986 	/* rpc number */
987 	(void) fprintf(stdout, "%-8s", rpcnumber->attrvalue[0]);
988 
989 
990 	/* aliases */
991 	for (j = 0; j < cn->value_count; j++) {
992 		if (cn->attrvalue[j]) {
993 			if (strcasecmp(name, cn->attrvalue[j]) == 0)
994 				/* skip rpc name */
995 				continue;
996 			(void) fprintf(stdout, "%s ", cn->attrvalue[j]);
997 		}
998 	}
999 
1000 	/* end of line */
1001 	(void) fprintf(stdout, "\n");
1002 
1003 }
1004 
1005 /*
1006  * /etc/protocols
1007  *
1008  */
1009 
1010 static int
1011 genent_protocols(char *line, int (*cback)())
1012 {
1013 	char buf[BUFSIZ+1];
1014 	char *t;
1015 	entry_col ecol[4];
1016 	char *cname;
1017 
1018 	struct protoent	data;
1019 	char *alias;
1020 	int ctr = 0;
1021 	int retval = 1;
1022 	int rc = GENENT_OK;
1023 
1024 	/*
1025 	 * don't clobber our argument
1026 	 */
1027 	if (strlen(line) >= sizeof (buf)) {
1028 		(void) strcpy(parse_err_msg, "line too long");
1029 		return (GENENT_PARSEERR);
1030 	}
1031 	(void) strcpy(buf, line);
1032 
1033 	/*
1034 	 * clear column data
1035 	 */
1036 	(void) memset((char *)ecol, 0, sizeof (ecol));
1037 
1038 	/*
1039 	 * comment (col 3)
1040 	 */
1041 	t = strchr(buf, '#');
1042 	if (t) {
1043 		*t++ = 0;
1044 		ecol[3].ec_value.ec_value_val = t;
1045 		ecol[3].ec_value.ec_value_len = strlen(t)+1;
1046 	} else {
1047 		ecol[3].ec_value.ec_value_val = 0;
1048 		ecol[3].ec_value.ec_value_len = 0;
1049 	}
1050 
1051 	/*
1052 	 * cname(col 0)
1053 	 */
1054 	if ((t = strtok(buf, " \t")) == 0) {
1055 		(void) strcpy(parse_err_msg, "no number");
1056 		return (GENENT_PARSEERR);
1057 	}
1058 	ecol[0].ec_value.ec_value_val = t;
1059 	ecol[0].ec_value.ec_value_len = strlen(t)+1;
1060 	cname = t;
1061 
1062 	/*
1063 	 * number (col 2)
1064 	 */
1065 	if ((t = strtok(NULL, " \t")) == 0) {
1066 		(void) strcpy(parse_err_msg, "no number");
1067 		return (GENENT_PARSEERR);
1068 	}
1069 	ecol[2].ec_value.ec_value_val = t;
1070 	ecol[2].ec_value.ec_value_len = strlen(t)+1;
1071 
1072 
1073 	/*
1074 	 * build entry
1075 	 */
1076 	data.p_name = strdup(ecol[0].ec_value.ec_value_val);
1077 
1078 	if (ecol[2].ec_value.ec_value_val != NULL &&
1079 		ecol[2].ec_value.ec_value_val[0] != '\0') {
1080 
1081 		data.p_proto = ascii_to_int(ecol[2].ec_value.ec_value_val);
1082 		if (data.p_proto == -1) {
1083 			(void) snprintf(parse_err_msg, sizeof (parse_err_msg),
1084 			    "invalid protocol number: %s",
1085 			    ecol[2].ec_value.ec_value_val);
1086 		return (GENENT_PARSEERR);
1087 		}
1088 	} else
1089 		data.p_proto = -1;
1090 
1091 	/*
1092 	 * name (col 1)
1093 	 */
1094 	t = cname;
1095 	ctr = 0;
1096 	data.p_aliases = NULL;
1097 
1098 	do {
1099 		/*
1100 		 * don't clobber comment in canonical entry
1101 		 */
1102 		if (t != cname && strcasecmp(t, cname) == 0)
1103 			continue;
1104 		if (strcasecmp(t, ecol[0].ec_value.ec_value_val) == 0)
1105 			continue;
1106 
1107 		ecol[1].ec_value.ec_value_val = t;
1108 		ecol[1].ec_value.ec_value_len = strlen(t)+1;
1109 
1110 		ctr++;
1111 		alias = strdup(ecol[1].ec_value.ec_value_val);
1112 		if ((data.p_aliases = (char **)realloc(data.p_aliases,
1113 			ctr * sizeof (char **))) == NULL) {
1114 			(void) fprintf(stderr, gettext("out of memory\n"));
1115 			exit(1);
1116 		}
1117 		data.p_aliases[ctr-1] = alias;
1118 
1119 		/*
1120 		 * only put comment in canonical entry
1121 		 */
1122 		ecol[3].ec_value.ec_value_val = 0;
1123 		ecol[3].ec_value.ec_value_len = 0;
1124 
1125 	} while (t = strtok(NULL, " \t"));
1126 
1127 	/* End the list of all the aliases by NULL */
1128 	if ((data.p_aliases = (char **)realloc(data.p_aliases,
1129 		(ctr + 1) * sizeof (char **))) == NULL) {
1130 		(void) fprintf(stderr, gettext("out of memory\n"));
1131 		exit(1);
1132 	}
1133 	data.p_aliases[ctr] = NULL;
1134 
1135 	if (flags & F_VERBOSE)
1136 		(void) fprintf(stdout,
1137 		    gettext("Adding entry : %s\n"), data.p_name);
1138 
1139 	retval = (*cback)(&data, 0);
1140 
1141 	if (retval == LDAP_ALREADY_EXISTS) {
1142 		if (continue_onerror)
1143 			(void) fprintf(stderr,
1144 			gettext("Entry: %s - already Exists, skipping it.\n"),
1145 			data.p_name);
1146 		else {
1147 			rc = GENENT_CBERR;
1148 			(void) fprintf(stderr,
1149 				gettext("Entry: %s - already Exists\n"),
1150 				data.p_name);
1151 		}
1152 	} else if (retval)
1153 		rc = GENENT_CBERR;
1154 
1155 	free(data.p_name);
1156 	free(data.p_aliases);
1157 
1158 	return (rc);
1159 }
1160 
1161 
1162 static void
1163 dump_protocols(ns_ldap_result_t *res)
1164 {
1165 	ns_ldap_attr_t	*attrptr = NULL, *cn = NULL, *protocolnumber = NULL;
1166 	int		 i, j;
1167 	char		*name, *cp;
1168 
1169 	if (res == NULL || res->entry == NULL)
1170 		return;
1171 	for (i = 0; i < res->entry->attr_count; i++) {
1172 		attrptr = res->entry->attr_pair[i];
1173 		if (strcasecmp(attrptr->attrname, "cn") == 0)
1174 			cn = attrptr;
1175 		else if (strcasecmp(attrptr->attrname, "ipProtocolNumber")
1176 									== 0)
1177 			protocolnumber = attrptr;
1178 	}
1179 	/* sanity check */
1180 	if (cn == NULL || cn->attrvalue == NULL || cn->attrvalue[0] == NULL ||
1181 	    protocolnumber == NULL || protocolnumber->attrvalue == NULL ||
1182 	    protocolnumber->attrvalue[0] == NULL)
1183 		return;
1184 
1185 	if ((name = __s_api_get_canonical_name(res->entry, cn, 1)) == NULL)
1186 		return;
1187 
1188 	/* protocol name */
1189 	if (strlen(name) < 8)
1190 		(void) fprintf(stdout, "%s\t\t", name);
1191 	else
1192 		(void) fprintf(stdout, "%s\t", name);
1193 
1194 	/* protocol number */
1195 	(void) fprintf(stdout, "%-16s", protocolnumber->attrvalue[0]);
1196 
1197 	/* aliases */
1198 	for (j = 0; j < cn->value_count; j++) {
1199 		if (cn->attrvalue[j]) {
1200 			if (strcasecmp(name, cn->attrvalue[j]) == 0) {
1201 				if (cn->value_count > 1)
1202 					/* Do not replicate */
1203 					continue;
1204 				/*
1205 				 * Replicate name in uppercase as an aliase
1206 				 */
1207 				for (cp = cn->attrvalue[j]; *cp; cp++)
1208 					*cp = toupper(*cp);
1209 			}
1210 			(void) fprintf(stdout, "%s ", cn->attrvalue[j]);
1211 		}
1212 	}
1213 
1214 	/* end of line */
1215 	(void) fprintf(stdout, "\n");
1216 
1217 }
1218 
1219 
1220 
1221 
1222 
1223 /*
1224  * /etc/networks
1225  *
1226  */
1227 
1228 static int
1229 genent_networks(char *line, int (*cback)())
1230 {
1231 	char buf[BUFSIZ+1];
1232 	char *t;
1233 	entry_col ecol[4];
1234 	char *cname;
1235 
1236 	struct netent	data;
1237 	char *alias;
1238 	int ctr = 0;
1239 	int retval = 1;
1240 	int enet;
1241 	int rc = GENENT_OK;
1242 
1243 	/*
1244 	 * don't clobber our argument
1245 	 */
1246 	if (strlen(line) >= sizeof (buf)) {
1247 		(void) strcpy(parse_err_msg, "line too long");
1248 		return (GENENT_PARSEERR);
1249 	}
1250 	(void) strcpy(buf, line);
1251 
1252 	/*
1253 	 * clear column data
1254 	 */
1255 	(void) memset((char *)ecol, 0, sizeof (ecol));
1256 
1257 	/*
1258 	 * comment (col 3)
1259 	 */
1260 	t = strchr(buf, '#');
1261 	if (t) {
1262 		*t++ = 0;
1263 		ecol[3].ec_value.ec_value_val = t;
1264 		ecol[3].ec_value.ec_value_len = strlen(t)+1;
1265 	} else {
1266 		ecol[3].ec_value.ec_value_val = 0;
1267 		ecol[3].ec_value.ec_value_len = 0;
1268 	}
1269 
1270 	/*
1271 	 * cname(col 0)
1272 	 */
1273 	if ((t = strtok(buf, " \t")) == 0) {
1274 		(void) strcpy(parse_err_msg, "no number");
1275 		return (GENENT_PARSEERR);
1276 	}
1277 	ecol[0].ec_value.ec_value_val = t;
1278 	ecol[0].ec_value.ec_value_len = strlen(t)+1;
1279 	cname = t;
1280 
1281 	/*
1282 	 * number (col 2)
1283 	 */
1284 	if ((t = strtok(NULL, " \t")) == 0) {
1285 		(void) strcpy(parse_err_msg, "no number");
1286 		return (GENENT_PARSEERR);
1287 	}
1288 	ecol[2].ec_value.ec_value_val = t;
1289 	ecol[2].ec_value.ec_value_len = strlen(t)+1;
1290 
1291 
1292 	/*
1293 	 * build entry
1294 	 */
1295 
1296 	data.n_name = strdup(ecol[0].ec_value.ec_value_val);
1297 	/*
1298 	 * data.n_net is an unsigned field,
1299 	 * assign -1 to it, make no sense.
1300 	 * Use enet here to avoid lint warning.
1301 	 */
1302 	enet = encode_network(ecol[2].ec_value.ec_value_val);
1303 
1304 	if (enet == -1 && continue_onerror == 0) {
1305 		(void) fprintf(stderr, gettext("Invalid network number\n"));
1306 		if (continue_onerror == 0)
1307 			return (GENENT_CBERR);
1308 	} else
1309 		data.n_net = enet;
1310 
1311 	/*
1312 	 * name (col 1)
1313 	 */
1314 	t = cname;
1315 	data.n_aliases = NULL;
1316 
1317 	do {
1318 		/*
1319 		 * don't clobber comment in canonical entry
1320 		 */
1321 		if (t != cname && strcasecmp(t, cname) == 0)
1322 			continue;
1323 		if (strcasecmp(t, ecol[0].ec_value.ec_value_val) == 0)
1324 			continue;
1325 
1326 		ecol[1].ec_value.ec_value_val = t;
1327 		ecol[1].ec_value.ec_value_len = strlen(t)+1;
1328 
1329 		ctr++;
1330 		alias = strdup(ecol[1].ec_value.ec_value_val);
1331 		if ((data.n_aliases = (char **)realloc(data.n_aliases,
1332 			ctr * sizeof (char **))) == NULL) {
1333 			(void) fprintf(stderr, gettext("out of memory\n"));
1334 			exit(1);
1335 		}
1336 		data.n_aliases[ctr-1] = alias;
1337 
1338 		/*
1339 		 * only put comment in canonical entry
1340 		 */
1341 		ecol[3].ec_value.ec_value_val = 0;
1342 		ecol[3].ec_value.ec_value_len = 0;
1343 
1344 	} while (t = strtok(NULL, " \t"));
1345 
1346 	/* End the list of all the aliases by NULL */
1347 	if ((data.n_aliases = (char **)realloc(data.n_aliases,
1348 		(ctr + 1) * sizeof (char **))) == NULL) {
1349 		(void) fprintf(stderr, gettext("out of memory\n"));
1350 		exit(1);
1351 	}
1352 	data.n_aliases[ctr] = NULL;
1353 
1354 	if (flags & F_VERBOSE)
1355 		(void) fprintf(stdout,
1356 		    gettext("Adding entry : %s\n"), data.n_name);
1357 
1358 	retval = (*cback)(&data, 0);
1359 
1360 	if (retval == LDAP_ALREADY_EXISTS) {
1361 		if (continue_onerror)
1362 			(void) fprintf(stderr,
1363 			gettext("Entry: %s - already Exists, skipping it.\n"),
1364 			data.n_name);
1365 		else {
1366 			rc = GENENT_CBERR;
1367 			(void) fprintf(stderr,
1368 				gettext("Entry: %s - already Exists\n"),
1369 				data.n_name);
1370 		}
1371 	} else if (retval)
1372 		rc = GENENT_CBERR;
1373 
1374 	free(data.n_name);
1375 	free(data.n_aliases);
1376 
1377 	return (rc);
1378 }
1379 
1380 
1381 static void
1382 dump_networks(ns_ldap_result_t *res)
1383 {
1384 	ns_ldap_attr_t	*attrptr = NULL, *cn = NULL, *networknumber = NULL;
1385 	int		 i, j;
1386 	char		*name;
1387 
1388 	if (res == NULL || res->entry == NULL)
1389 		return;
1390 	for (i = 0; i < res->entry->attr_count; i++) {
1391 		attrptr = res->entry->attr_pair[i];
1392 		if (strcasecmp(attrptr->attrname, "cn") == 0)
1393 			cn = attrptr;
1394 		else if (strcasecmp(attrptr->attrname, "ipNetworkNumber")
1395 									== 0)
1396 			networknumber = attrptr;
1397 	}
1398 	/* sanity check */
1399 	if (cn == NULL || cn->attrvalue == NULL || cn->attrvalue[0] == NULL ||
1400 	    networknumber == NULL || networknumber->attrvalue == NULL ||
1401 	    networknumber->attrvalue[0] == NULL)
1402 		return;
1403 
1404 	/*
1405 	 * cn can be a MUST attribute(RFC 2307) or MAY attribute(2307bis).
1406 	 * If the canonical name can not be found (2307bis), use the 1st
1407 	 * value as the official name.
1408 	 */
1409 
1410 	/* network name */
1411 	if ((name = __s_api_get_canonical_name(res->entry, cn, 1)) == NULL)
1412 		name = cn->attrvalue[0];
1413 
1414 	if (strlen(name) < 8)
1415 		(void) fprintf(stdout, "%s\t\t", name);
1416 	else
1417 		(void) fprintf(stdout, "%s\t", name);
1418 
1419 	/* network number */
1420 	(void) fprintf(stdout, "%-16s", networknumber->attrvalue[0]);
1421 
1422 	/* aliases */
1423 	for (j = 0; j < cn->value_count; j++) {
1424 		if (cn->attrvalue[j]) {
1425 			if (strcasecmp(name, cn->attrvalue[j]) == 0)
1426 				/* skip name */
1427 				continue;
1428 			(void) fprintf(stdout, "%s ", cn->attrvalue[j]);
1429 		}
1430 	}
1431 
1432 	/* end of line */
1433 	(void) fprintf(stdout, "\n");
1434 
1435 }
1436 
1437 
1438 
1439 
1440 /*
1441  * /etc/services
1442  *
1443  */
1444 
1445 static int
1446 genent_services(char *line, int (*cback)())
1447 {
1448 	char buf[BUFSIZ+1];
1449 	char *t, *p;
1450 	entry_col ecol[5];
1451 	char *cname;
1452 
1453 	struct servent	data;
1454 	char *alias;
1455 	int ctr = 0;
1456 	int retval = 1;
1457 	int rc = GENENT_OK;
1458 
1459 	/*
1460 	 * don't clobber our argument
1461 	 */
1462 	if (strlen(line) >= sizeof (buf)) {
1463 		(void) strcpy(parse_err_msg, "line too long");
1464 		return (GENENT_PARSEERR);
1465 	}
1466 	(void) strcpy(buf, line);
1467 
1468 	/*
1469 	 * clear column data
1470 	 */
1471 	(void) memset((char *)ecol, 0, sizeof (ecol));
1472 
1473 	/*
1474 	 * comment (col 4)
1475 	 */
1476 	t = strchr(buf, '#');
1477 	if (t) {
1478 		*t++ = 0;
1479 		ecol[4].ec_value.ec_value_val = t;
1480 		ecol[4].ec_value.ec_value_len = strlen(t)+1;
1481 	} else {
1482 		ecol[4].ec_value.ec_value_val = 0;
1483 		ecol[4].ec_value.ec_value_len = 0;
1484 	}
1485 
1486 	/*
1487 	 * cname(col 0)
1488 	 */
1489 	if ((t = strtok(buf, " \t")) == 0) {
1490 		(void) strcpy(parse_err_msg, "no port");
1491 		return (GENENT_PARSEERR);
1492 	}
1493 	ecol[0].ec_value.ec_value_val = t;
1494 	ecol[0].ec_value.ec_value_len = strlen(t)+1;
1495 	cname = t;
1496 
1497 	/*
1498 	 * port (col 3)
1499 	 */
1500 	if ((t = strtok(NULL, " \t")) == 0) {
1501 		(void) strcpy(parse_err_msg, "no protocol");
1502 		return (GENENT_PARSEERR);
1503 	}
1504 	if ((p = strchr(t, '/')) == 0) {
1505 		(void) strcpy(parse_err_msg, "bad port/proto");
1506 		return (GENENT_PARSEERR);
1507 	}
1508 	*(p++) = 0;
1509 	ecol[3].ec_value.ec_value_val = t;
1510 	ecol[3].ec_value.ec_value_len = strlen(t)+1;
1511 
1512 	/*
1513 	 * proto (col 2)
1514 	 */
1515 	ecol[2].ec_value.ec_value_val = p;
1516 	ecol[2].ec_value.ec_value_len = strlen(p)+1;
1517 
1518 
1519 	/*
1520 	 * build entry
1521 	 */
1522 
1523 	data.s_name = strdup(ecol[0].ec_value.ec_value_val);
1524 	data.s_proto = strdup(ecol[2].ec_value.ec_value_val);
1525 
1526 	if (ecol[3].ec_value.ec_value_val != NULL &&
1527 		ecol[3].ec_value.ec_value_val[0] != '\0') {
1528 
1529 		data.s_port = ascii_to_int(ecol[3].ec_value.ec_value_val);
1530 		if (data.s_port == -1) {
1531 			(void) snprintf(parse_err_msg, sizeof (parse_err_msg),
1532 			    "invalid port number: %s",
1533 			    ecol[3].ec_value.ec_value_val);
1534 		return (GENENT_PARSEERR);
1535 		}
1536 	} else
1537 		data.s_port = -1;
1538 
1539 	/*
1540 	 * name (col 1)
1541 	 */
1542 	t = cname;
1543 	data.s_aliases = NULL;
1544 
1545 	do {
1546 		/*
1547 		 * don't clobber comment in canonical entry
1548 		 */
1549 		if (t != cname && strcasecmp(t, cname) == 0)
1550 			continue;
1551 		if (strcasecmp(t, ecol[0].ec_value.ec_value_val) == 0)
1552 			continue;
1553 
1554 		ecol[1].ec_value.ec_value_val = t;
1555 		ecol[1].ec_value.ec_value_len = strlen(t)+1;
1556 
1557 		ctr++;
1558 		alias = strdup(ecol[1].ec_value.ec_value_val);
1559 		if ((data.s_aliases = (char **)realloc(data.s_aliases,
1560 			ctr * sizeof (char **))) == NULL) {
1561 			(void) fprintf(stderr, gettext("out of memory\n"));
1562 			exit(1);
1563 		}
1564 		data.s_aliases[ctr-1] = alias;
1565 
1566 		/*
1567 		 * only put comment in canonical entry
1568 		 */
1569 		ecol[4].ec_value.ec_value_val = 0;
1570 		ecol[4].ec_value.ec_value_len = 0;
1571 
1572 	} while (t = strtok(NULL, " \t"));
1573 
1574 	/* End the list of all the aliases by NULL */
1575 	if ((data.s_aliases = (char **)realloc(data.s_aliases,
1576 		(ctr + 1) * sizeof (char **))) == NULL) {
1577 		(void) fprintf(stderr, gettext("out of memory\n"));
1578 		exit(1);
1579 	}
1580 	data.s_aliases[ctr] = NULL;
1581 
1582 	if (flags & F_VERBOSE)
1583 		(void) fprintf(stdout,
1584 		    gettext("Adding entry : %s\n"), line);
1585 
1586 	retval = (*cback)(&data, 0);
1587 
1588 	if (retval == LDAP_ALREADY_EXISTS) {
1589 		if (continue_onerror)
1590 			(void) fprintf(stderr, gettext(
1591 					"Entry: cn=%s+ipServiceProtocol=%s"
1592 					" already Exists, skipping it.\n"),
1593 					data.s_name, data.s_proto);
1594 		else {
1595 			rc = GENENT_CBERR;
1596 			(void) fprintf(stderr,
1597 				gettext("Entry: cn=%s+ipServiceProtocol=%s"
1598 					" - already Exists\n"),
1599 					data.s_name, data.s_proto);
1600 		}
1601 	} else if (retval)
1602 		rc = GENENT_CBERR;
1603 
1604 	free(data.s_name);
1605 	free(data.s_proto);
1606 	free(data.s_aliases);
1607 
1608 	return (rc);
1609 }
1610 
1611 
1612 
1613 static void
1614 dump_services(ns_ldap_result_t *res)
1615 {
1616 	ns_ldap_attr_t	*attrptr = NULL, *cn = NULL, *port = NULL;
1617 	ns_ldap_attr_t	*protocol = NULL;
1618 	int		i, j, len;
1619 	char		*name; /* service name */
1620 
1621 	/*
1622 	 * cn can have multiple values.(service name and its aliases)
1623 	 * In order to support RFC 2307, section 5.5, ipserviceprotocol  can
1624 	 * have multiple values too.
1625 	 * The output format should look like
1626 	 *
1627 	 * test		2345/udp mytest
1628 	 * test		2345/tcp mytest
1629 	 */
1630 	if (res == NULL || res->entry == NULL)
1631 		return;
1632 	for (i = 0; i < res->entry->attr_count; i++) {
1633 		attrptr = res->entry->attr_pair[i];
1634 		if (strcasecmp(attrptr->attrname, "cn") == 0)
1635 			cn = attrptr;
1636 		else if (strcasecmp(attrptr->attrname, "ipServicePort") == 0)
1637 			port = attrptr;
1638 		else if (strcasecmp(attrptr->attrname,
1639 					"ipServiceProtocol") == 0)
1640 			protocol = attrptr;
1641 	}
1642 	/* sanity check */
1643 	if (cn == NULL || cn->attrvalue == NULL || cn->attrvalue[0] == NULL ||
1644 	    port == NULL || port->attrvalue == NULL ||
1645 	    port->attrvalue[0] == NULL || protocol == NULL ||
1646 	    protocol->attrvalue == NULL || protocol->attrvalue[0] == NULL)
1647 		return;
1648 
1649 	if ((name = __s_api_get_canonical_name(res->entry, cn, 1)) == NULL)
1650 		return;
1651 	for (i = 0; i < protocol->value_count; i++) {
1652 		if (protocol->attrvalue[i] == NULL)
1653 			return;
1654 		/* service name */
1655 		(void) fprintf(stdout, "%-16s", name);
1656 
1657 		/* port & protocol */
1658 		(void) fprintf(stdout, "%s/%s%n", port->attrvalue[0],
1659 				protocol->attrvalue[i], &len);
1660 
1661 		if (len < 8)
1662 			(void) fprintf(stdout, "\t\t");
1663 		else
1664 			(void) fprintf(stdout, "\t");
1665 
1666 		/* aliases */
1667 		for (j = 0; j < cn->value_count; j++) {
1668 			if (cn->attrvalue[j]) {
1669 				if (strcasecmp(name, cn->attrvalue[j]) == 0)
1670 					/* skip service name */
1671 					continue;
1672 				(void) fprintf(stdout, "%s ", cn->attrvalue[j]);
1673 			}
1674 		}
1675 
1676 		/* end of line */
1677 		(void) fprintf(stdout, "\n");
1678 	}
1679 }
1680 
1681 
1682 /*
1683  * /etc/group
1684  */
1685 
1686 static int
1687 genent_group(char *line, int (*cback)())
1688 {
1689 	char buf[BIGBUF+1];
1690 	char *s, *t;
1691 	entry_col ecol[5];
1692 
1693 	struct group	data;
1694 	int ctr = 0;
1695 	int retval = 1;
1696 	int rc = GENENT_OK;
1697 
1698 	/*
1699 	 * don't clobber our argument
1700 	 */
1701 	if (strlen(line) >= sizeof (buf)) {
1702 		(void) strcpy(parse_err_msg, "line too long");
1703 		return (GENENT_PARSEERR);
1704 	}
1705 	(void) strcpy(buf, line);
1706 	t = buf;
1707 
1708 	/* ignore empty entries */
1709 	if (*t == '\0')
1710 		return (GENENT_OK);
1711 
1712 	/*
1713 	 * clear column data
1714 	 */
1715 	(void) memset((char *)ecol, 0, sizeof (ecol));
1716 
1717 	/*
1718 	 * name (col 0)
1719 	 */
1720 	if ((s = strchr(t, ':')) == 0) {
1721 		(void) strcpy(parse_err_msg, "no passwd");
1722 		return (GENENT_PARSEERR);
1723 	}
1724 	*s++ = 0;
1725 	ecol[0].ec_value.ec_value_val = t;
1726 	ecol[0].ec_value.ec_value_len = strlen(t)+1;
1727 	t = s;
1728 
1729 	/*
1730 	 * passwd (col 1)
1731 	 */
1732 	if ((s = strchr(t, ':')) == 0) {
1733 		(void) strcpy(parse_err_msg, "no gid");
1734 		return (GENENT_PARSEERR);
1735 	}
1736 	*s++ = 0;
1737 	ecol[1].ec_value.ec_value_val = t;
1738 	ecol[1].ec_value.ec_value_len = strlen(t)+1;
1739 	t = s;
1740 
1741 
1742 	/*
1743 	 * gid (col 2)
1744 	 */
1745 	if ((s = strchr(t, ':')) == 0 || s == t) {
1746 		(void) strcpy(parse_err_msg, "no members");
1747 		return (GENENT_PARSEERR);
1748 	}
1749 	*s++ = 0;
1750 	ecol[2].ec_value.ec_value_val = t;
1751 	ecol[2].ec_value.ec_value_len = strlen(t)+1;
1752 	t = s;
1753 
1754 	/*
1755 	 * members (col 3)
1756 	 */
1757 	ecol[3].ec_value.ec_value_val = t;
1758 	ecol[3].ec_value.ec_value_len = strlen(t)+1;
1759 
1760 
1761 	/*
1762 	 * build entry
1763 	 */
1764 	data.gr_name = strdup(ecol[0].ec_value.ec_value_val);
1765 	data.gr_passwd = strdup(ecol[1].ec_value.ec_value_val);
1766 	if (ecol[2].ec_value.ec_value_val != NULL &&
1767 		ecol[2].ec_value.ec_value_val[0] != '\0') {
1768 
1769 		data.gr_gid = ascii_to_int(ecol[2].ec_value.ec_value_val);
1770 		if (data.gr_gid == -1) {
1771 			(void) snprintf(parse_err_msg, sizeof (parse_err_msg),
1772 			    "invalid group id: %s",
1773 			    ecol[2].ec_value.ec_value_val);
1774 		return (GENENT_PARSEERR);
1775 		}
1776 	} else
1777 		data.gr_gid = -1;
1778 
1779 	data.gr_mem = NULL;
1780 
1781 	/* Compute maximum amount of members */
1782 	s = t;
1783 	while (s = strchr(s, ',')) {
1784 		s++;
1785 		ctr++;
1786 	}
1787 
1788 	/* Allocate memory for all members */
1789 	data.gr_mem = calloc(ctr + 2, sizeof (char **));
1790 	if (data.gr_mem == NULL) {
1791 		(void) fprintf(stderr, gettext("out of memory\n"));
1792 		exit(1);
1793 	}
1794 
1795 	ctr = 0;
1796 	while (s = strchr(t, ',')) {
1797 
1798 		*s++ = 0;
1799 		ecol[3].ec_value.ec_value_val = t;
1800 		t = s;
1801 		/* Send to server only non empty member names */
1802 		if (strlen(ecol[3].ec_value.ec_value_val) != 0)
1803 			data.gr_mem[ctr++] = ecol[3].ec_value.ec_value_val;
1804 	}
1805 
1806 	/* Send to server only non empty member names */
1807 	if (strlen(t) != 0)
1808 		data.gr_mem[ctr++] = t;
1809 
1810 	/* Array of members completed, finished by NULL, see calloc() */
1811 
1812 	if (flags & F_VERBOSE)
1813 		(void) fprintf(stdout,
1814 		    gettext("Adding entry : %s\n"), data.gr_name);
1815 
1816 	retval = (*cback)(&data, 0);
1817 
1818 	if (retval == LDAP_ALREADY_EXISTS) {
1819 		if (continue_onerror)
1820 			(void) fprintf(stderr,
1821 			gettext("Entry: %s - already Exists, skipping it.\n"),
1822 			data.gr_name);
1823 		else {
1824 			rc = GENENT_CBERR;
1825 			(void) fprintf(stderr,
1826 				gettext("Entry: %s - already Exists\n"),
1827 				data.gr_name);
1828 		}
1829 	} else if (retval)
1830 		rc = GENENT_CBERR;
1831 
1832 	free(data.gr_name);
1833 	free(data.gr_passwd);
1834 	free(data.gr_mem);
1835 
1836 	return (rc);
1837 }
1838 
1839 static void
1840 dump_group(ns_ldap_result_t *res)
1841 {
1842 	char    **value = NULL;
1843 	char	pnam[256];
1844 	int	attr_count = 0;
1845 
1846 	value = __ns_ldap_getAttr(res->entry, "cn");
1847 	if (value && value[0])
1848 		(void) fprintf(stdout, "%s:", value[0]);
1849 	value = __ns_ldap_getAttr(res->entry, "userPassword");
1850 	if (value == NULL || value[0] == NULL)
1851 		(void) fprintf(stdout, "*:");
1852 	else {
1853 		(void) strcpy(pnam, value[0]);
1854 		if (strncasecmp(value[0], "{crypt}", 7) == 0)
1855 			(void) fprintf(stdout, "%s:", (pnam+7));
1856 		else
1857 			(void) fprintf(stdout, "*:");
1858 	}
1859 	value = __ns_ldap_getAttr(res->entry, "gidNumber");
1860 	if (value && value[0])
1861 		(void) fprintf(stdout, "%s:", value[0]);
1862 
1863 	value = __ns_ldap_getAttr(res->entry, "memberUid");
1864 	if (value != NULL && value[0] != NULL) {
1865 		while (value[attr_count] != NULL) {
1866 			if (value[attr_count+1] == NULL)
1867 				(void) fprintf(stdout, "%s", value[attr_count]);
1868 			else
1869 				(void) fprintf(stdout, "%s,",
1870 					value[attr_count]);
1871 			attr_count++;
1872 		}
1873 		(void) fprintf(stdout, "\n");
1874 	}
1875 	else
1876 		(void) fprintf(stdout, "\n");
1877 }
1878 
1879 
1880 
1881 
1882 
1883 /*
1884  * /etc/ethers
1885  */
1886 
1887 static int
1888 genent_ethers(char *line, int (*cback)())
1889 {
1890 	char buf[BUFSIZ+1];
1891 	char *t;
1892 	entry_col ecol[3];
1893 	int retval = 1;
1894 	struct _ns_ethers	data;
1895 	int rc = GENENT_OK;
1896 
1897 	/*
1898 	 * don't clobber our argument
1899 	 */
1900 	if (strlen(line) >= sizeof (buf)) {
1901 		(void) strcpy(parse_err_msg, "line too long");
1902 		return (GENENT_PARSEERR);
1903 	}
1904 	(void) strcpy(buf, line);
1905 
1906 	/*
1907 	 * clear column data
1908 	 */
1909 	(void) memset((char *)ecol, 0, sizeof (ecol));
1910 
1911 	/*
1912 	 * comment (col 2)
1913 	 */
1914 	t = strchr(buf, '#');
1915 	if (t) {
1916 		*t++ = 0;
1917 		ecol[2].ec_value.ec_value_val = t;
1918 		ecol[2].ec_value.ec_value_len = strlen(t)+1;
1919 	} else {
1920 		ecol[2].ec_value.ec_value_val = 0;
1921 		ecol[2].ec_value.ec_value_len = 0;
1922 	}
1923 
1924 	/*
1925 	 * addr(col 0)
1926 	 */
1927 	if ((t = strtok(buf, " \t")) == 0) {
1928 		(void) strcpy(parse_err_msg, "no name");
1929 		return (GENENT_PARSEERR);
1930 	}
1931 	ecol[0].ec_value.ec_value_val = t;
1932 	ecol[0].ec_value.ec_value_len = strlen(t)+1;
1933 
1934 	/*
1935 	 * name(col 1)
1936 	 */
1937 	if ((t = strtok(NULL, " \t")) == 0) {
1938 		(void) strcpy(parse_err_msg, "no white space allowed in name");
1939 		return (GENENT_PARSEERR);
1940 	}
1941 	ecol[1].ec_value.ec_value_val = t;
1942 	ecol[1].ec_value.ec_value_len = strlen(t)+1;
1943 
1944 
1945 	/*
1946 	 * build entry
1947 	 */
1948 
1949 	data.ether = strdup(ecol[0].ec_value.ec_value_val);
1950 	data.name  = strdup(ecol[1].ec_value.ec_value_val);
1951 
1952 
1953 	if (flags & F_VERBOSE)
1954 		(void) fprintf(stdout,
1955 		    gettext("Adding entry : %s\n"), data.name);
1956 
1957 	retval = (*cback)(&data, 0);
1958 
1959 	if (retval == LDAP_ALREADY_EXISTS) {
1960 		if (continue_onerror)
1961 			(void) fprintf(stderr,
1962 			gettext("Entry: %s - already Exists, skipping it.\n"),
1963 			data.name);
1964 		else {
1965 			rc = GENENT_CBERR;
1966 			(void) fprintf(stderr,
1967 				gettext("Entry: %s - already Exists\n"),
1968 				data.name);
1969 		}
1970 	} else if (retval)
1971 		rc = GENENT_CBERR;
1972 
1973 	free(data.ether);
1974 	free(data.name);
1975 
1976 	return (rc);
1977 }
1978 
1979 
1980 static void
1981 dump_ethers(ns_ldap_result_t *res)
1982 {
1983 	char	**value = NULL;
1984 
1985 	value = __ns_ldap_getAttr(res->entry, "macAddress");
1986 	if (value && value[0])
1987 		(void) fprintf(stdout, "%s", value[0]);
1988 	else
1989 		return;
1990 	value = __ns_ldap_getAttr(res->entry, "cn");
1991 	if (value && value[0])
1992 		(void) fprintf(stdout, "	%s\n", value[0]);
1993 }
1994 
1995 static int
1996 genent_aliases(char *line, int (*cback)())
1997 {
1998 	char buf[BUFSIZ+1];
1999 	char *t, *aliases;
2000 	char *cname;
2001 	int ctr = 0;
2002 	int retval = 1;
2003 	int i;
2004 
2005 	struct _ns_alias data;
2006 	char *alias;
2007 	int rc = GENENT_OK;
2008 
2009 	/*
2010 	 * don't clobber our argument
2011 	 */
2012 	if (strlen(line) >= sizeof (buf)) {
2013 		(void) strcpy(parse_err_msg, "line too long");
2014 		return (GENENT_PARSEERR);
2015 	}
2016 
2017 	(void) strcpy(buf, line);
2018 
2019 	if ((t = strchr(buf, ':')) == 0) {
2020 		(void) strcpy(parse_err_msg, "no alias name");
2021 		return (GENENT_PARSEERR);
2022 	}
2023 
2024 	t[0] = '\0';
2025 	if (++t == '\0') {
2026 		(void) strcpy(parse_err_msg, "no alias value");
2027 		return (GENENT_PARSEERR);
2028 	}
2029 
2030 	cname = buf;
2031 	aliases = t;
2032 
2033 	/* build entry */
2034 	data.alias = strdup(cname);
2035 	if (!data.alias) {
2036 		(void) fprintf(stderr, gettext("out of memory\n"));
2037 		exit(1);
2038 	}
2039 
2040 	data.member = NULL;
2041 	t = strtok(aliases, ",");
2042 	do {
2043 		ctr++;
2044 		while (t[0] == ' ')
2045 			t++;
2046 		alias = strdup(t);
2047 		if ((alias == NULL) ||
2048 			((data.member = (char **)realloc(data.member,
2049 			(ctr + 1) * sizeof (char **))) == NULL)) {
2050 			(void) fprintf(stderr, gettext("out of memory\n"));
2051 			exit(1);
2052 		}
2053 		data.member[ctr-1] = alias;
2054 
2055 	} while (t = strtok(NULL, ","));
2056 
2057 	data.member[ctr] = NULL;
2058 
2059 	if (flags & F_VERBOSE)
2060 		(void) fprintf(stdout,
2061 		    gettext("Adding entry : %s\n"), data.alias);
2062 
2063 	retval = (*cback)(&data, 0);
2064 
2065 	if (retval == LDAP_ALREADY_EXISTS) {
2066 		if (continue_onerror)
2067 			(void) fprintf(stderr,
2068 			gettext("Entry: %s - already Exists, skipping it.\n"),
2069 			data.alias);
2070 		else {
2071 			rc = GENENT_CBERR;
2072 			(void) fprintf(stderr,
2073 				gettext("Entry: %s - already Exists\n"),
2074 				data.alias);
2075 		}
2076 	} else if (retval)
2077 		rc = GENENT_CBERR;
2078 
2079 	free(data.alias);
2080 	i = 0;
2081 	while (data.member[i])
2082 		free(data.member[i++]);
2083 	free(data.member);
2084 
2085 	return (rc);
2086 }
2087 
2088 
2089 static void
2090 dump_aliases(ns_ldap_result_t *res)
2091 {
2092 
2093 	char	**value = NULL;
2094 	int 		attr_count = 0;
2095 
2096 	value = __ns_ldap_getAttr(res->entry, "mail");
2097 	if (value && value[0])
2098 		(void) fprintf(stdout, "%s:", value[0]);
2099 	value = __ns_ldap_getAttr(res->entry, "mgrpRFC822MailMember");
2100 	if (value != NULL)
2101 		while (value[attr_count] != NULL) {
2102 			(void) fprintf(stdout, "%s,", value[attr_count]);
2103 			attr_count++;
2104 		}
2105 	(void) fprintf(stdout, "\n");
2106 
2107 }
2108 
2109 /*
2110  * /etc/publickey
2111  */
2112 
2113 static int
2114 genent_publickey(char *line, int (*cback)())
2115 {
2116 	char buf[BUFSIZ+1], tmpbuf[BUFSIZ+1], cname[BUFSIZ+1];
2117 	char *t, *p, *tmppubkey, *tmpprivkey;
2118 	entry_col ecol[3];
2119 	int buflen, uid, retval = 1;
2120 	struct passwd *pwd;
2121 	char auth_type[BUFSIZ+1];
2122 	keylen_t keylen;
2123 	algtype_t algtype;
2124 	struct _ns_pubkey data;
2125 	struct hostent *hp;
2126 	struct in_addr in;
2127 
2128 	/*
2129 	 * don't clobber our argument
2130 	 */
2131 	if (strlen(line) >= sizeof (buf)) {
2132 		(void) strcpy(parse_err_msg, "line too long");
2133 		return (GENENT_PARSEERR);
2134 	}
2135 	(void) strcpy(buf, line);
2136 
2137 	/*
2138 	 * clear column data
2139 	 */
2140 	(void) memset((char *)ecol, 0, sizeof (ecol));
2141 
2142 	if ((t = strtok(buf, " \t")) == 0) {
2143 		(void) strcpy(parse_err_msg, "no cname");
2144 		return (GENENT_PARSEERR);
2145 	}
2146 
2147 	/*
2148 	 * Special case:  /etc/publickey usually has an entry
2149 	 * for principal "nobody".  We skip it.
2150 	 */
2151 	if (strcmp(t, "nobody") == 0)
2152 		return (GENENT_OK);
2153 
2154 	/*
2155 	 * cname (col 0)
2156 	 */
2157 	if (strncmp(t, "unix.", 5)) {
2158 		(void) strcpy(parse_err_msg, "bad cname");
2159 		return (GENENT_PARSEERR);
2160 	}
2161 	(void) strcpy(tmpbuf, &(t[5]));
2162 	if ((p = strchr(tmpbuf, '@')) == 0) {
2163 		(void) strcpy(parse_err_msg, "bad cname");
2164 		return (GENENT_PARSEERR);
2165 	}
2166 	*(p++) = 0;
2167 	if (isdigit(*tmpbuf)) {
2168 
2169 		uid = atoi(tmpbuf);
2170 		/*
2171 		 * don't generate entries for uids without passwd entries
2172 		 */
2173 		if ((pwd = getpwuid(uid)) == 0) {
2174 			(void) fprintf(stderr,
2175 			gettext("can't map uid %d to username, skipping\n"),
2176 				uid);
2177 			return (GENENT_OK);
2178 		}
2179 		(void) strcpy(cname, pwd->pw_name);
2180 		data.hostcred = NS_HOSTCRED_FALSE;
2181 	} else {
2182 		if ((hp = gethostbyname(tmpbuf)) == 0) {
2183 			(void) fprintf(stderr,
2184 		gettext("can't map hostname %s to hostaddress, skipping\n"),
2185 			tmpbuf);
2186 			return (GENENT_OK);
2187 		}
2188 		(void) memcpy((char *)&in.s_addr, hp->h_addr_list[0],
2189 		    sizeof (in));
2190 		data.hostcred = NS_HOSTCRED_TRUE;
2191 		(void) snprintf(cname, sizeof (cname),
2192 		    "%s+ipHostNumber=%s", tmpbuf, inet_ntoa(in));
2193 	}
2194 
2195 	ecol[0].ec_value.ec_value_val = cname;
2196 	ecol[0].ec_value.ec_value_len = strlen(cname)+1;
2197 
2198 	/*
2199 	 * public_data (col 1)
2200 	 */
2201 	if ((t = strtok(NULL, " \t")) == 0) {
2202 		(void) strcpy(parse_err_msg, "no private_data");
2203 		return (GENENT_PARSEERR);
2204 	}
2205 	if ((p = strchr(t, ':')) == 0) {
2206 		(void) strcpy(parse_err_msg, "bad public_data");
2207 		return (GENENT_PARSEERR);
2208 	}
2209 	*(p++) = 0;
2210 	ecol[1].ec_value.ec_value_val = t;
2211 	ecol[1].ec_value.ec_value_len = strlen(t)+1;
2212 	keylen = (strlen(t) / 2) * 8;
2213 
2214 	/*
2215 	 * private_data (col 2) and algtype extraction
2216 	 */
2217 	if (*p == ':')
2218 		p++;
2219 	t = p;
2220 	if (!(t = strchr(t, ':'))) {
2221 		(void) fprintf(stderr,
2222 		gettext("WARNING: No algorithm type data found "
2223 			"in publickey file, assuming 0\n"));
2224 		algtype = 0;
2225 	} else {
2226 		*t = '\0';
2227 		t++;
2228 		algtype = atoi(t);
2229 	}
2230 	ecol[2].ec_value.ec_value_val = p;
2231 	ecol[2].ec_value.ec_value_len = strlen(p)+1;
2232 
2233 	/*
2234 	 * auth_type (col 1)
2235 	 */
2236 	if (!(__nis_keyalg2authtype(keylen, algtype, auth_type,
2237 						MECH_MAXATNAME))) {
2238 		(void) fprintf(stderr,
2239 		gettext("Could not convert algorithm type to "
2240 			"corresponding auth type string\n"));
2241 		return (GENENT_ERR);
2242 	}
2243 
2244 	/*
2245 	 * build entry
2246 	 */
2247 	data.name = strdup(ecol[0].ec_value.ec_value_val);
2248 	if (data.name == NULL) {
2249 		(void) fprintf(stderr, gettext("out of memory\n"));
2250 		exit(1);
2251 	}
2252 
2253 	buflen = sizeof (auth_type) + strlen(ecol[1].ec_value.ec_value_val) + 3;
2254 	if ((tmppubkey = (char *)malloc(buflen)) == NULL) {
2255 		(void) fprintf(stderr, gettext("out of memory\n"));
2256 		exit(1);
2257 	}
2258 	(void) snprintf(tmppubkey, buflen, "{%s}%s", auth_type,
2259 	    ecol[1].ec_value.ec_value_val);
2260 	data.pubkey = tmppubkey;
2261 
2262 	buflen = sizeof (auth_type) + strlen(ecol[2].ec_value.ec_value_val) + 3;
2263 	if ((tmpprivkey = (char *)malloc(buflen)) == NULL) {
2264 		(void) fprintf(stderr, gettext("out of memory\n"));
2265 		exit(1);
2266 	}
2267 
2268 	(void) snprintf(tmpprivkey, buflen, "{%s}%s", auth_type,
2269 	    ecol[2].ec_value.ec_value_val);
2270 	data.privkey = tmpprivkey;
2271 
2272 	retval = (*cback)(&data, 1);
2273 	if (retval != NS_LDAP_SUCCESS) {
2274 		if (retval == LDAP_NO_SUCH_OBJECT) {
2275 			if (data.hostcred == NS_HOSTCRED_TRUE)
2276 				(void) fprintf(stdout,
2277 				gettext("Cannot add publickey entry (%s), "
2278 					"add host entry first\n"),
2279 					tmpbuf);
2280 			else
2281 				(void) fprintf(stdout,
2282 				gettext("Cannot add publickey entry (%s), "
2283 					"add passwd entry first\n"),
2284 					data.name);
2285 		}
2286 		if (continue_onerror == 0)
2287 			return (GENENT_CBERR);
2288 	}
2289 
2290 	free(data.name);
2291 	free(data.pubkey);
2292 	free(data.privkey);
2293 	return (GENENT_OK);
2294 
2295 }
2296 
2297 static void
2298 dump_publickey(ns_ldap_result_t *res, char *container)
2299 {
2300 	char	**value = NULL;
2301 	char	buf[BUFSIZ];
2302 	char	domainname[BUFSIZ];
2303 	char	*pubptr, *prvptr;
2304 
2305 	if (res == NULL)
2306 		return;
2307 
2308 	if (sysinfo(SI_SRPC_DOMAIN, domainname, BUFSIZ) < 0) {
2309 		(void) fprintf(stderr,
2310 			gettext("could not obtain domainname\n"));
2311 		exit(1);
2312 	}
2313 
2314 	/*
2315 	 * Retrieve all the attributes, but don't print
2316 	 * until we have all the required ones.
2317 	 */
2318 
2319 	if (strcmp(container, "passwd") == 0)
2320 		value = __ns_ldap_getAttr(res->entry, "uidNumber");
2321 	else
2322 		value = __ns_ldap_getAttr(res->entry, "cn");
2323 
2324 	if (value && value[0])
2325 		(void) snprintf(buf, sizeof (buf), "unix.%s@%s",
2326 		    value[0], domainname);
2327 	else
2328 		return;
2329 
2330 	value = __ns_ldap_getAttr(res->entry, "nisPublickey");
2331 	if (value != NULL && value[0] != NULL) {
2332 		if ((pubptr = strchr(value[0], '}')) == NULL)
2333 			return;
2334 	}
2335 
2336 	value = __ns_ldap_getAttr(res->entry, "nisSecretkey");
2337 	if (value != NULL && value[0] != NULL)
2338 		if ((prvptr = strchr(value[0], '}')) == NULL)
2339 			return;
2340 
2341 	/* print the attributes, algorithm type is always 0 */
2342 	(void) fprintf(stdout, "%s	%s:%s:0\n", buf, ++pubptr, ++prvptr);
2343 }
2344 
2345 
2346 
2347 /*
2348  * /etc/netmasks
2349  */
2350 
2351 static int
2352 genent_netmasks(char *line, int (*cback)())
2353 {
2354 	char buf[BUFSIZ+1];
2355 	char *t;
2356 	entry_col ecol[3];
2357 	int retval;
2358 
2359 	struct _ns_netmasks data;
2360 
2361 
2362 	/*
2363 	 * don't clobber our argument
2364 	 */
2365 	if (strlen(line) >= sizeof (buf)) {
2366 		(void) strcpy(parse_err_msg, "line too long");
2367 		return (GENENT_PARSEERR);
2368 	}
2369 	(void) strcpy(buf, line);
2370 
2371 	/*
2372 	 * clear column data
2373 	 */
2374 	(void) memset((char *)ecol, 0, sizeof (ecol));
2375 
2376 	/*
2377 	 * comment (col 2)
2378 	 */
2379 	t = strchr(buf, '#');
2380 	if (t) {
2381 		*t++ = 0;
2382 		ecol[2].ec_value.ec_value_val = t;
2383 		ecol[2].ec_value.ec_value_len = strlen(t)+1;
2384 	} else {
2385 		ecol[2].ec_value.ec_value_val = 0;
2386 		ecol[2].ec_value.ec_value_len = 0;
2387 	}
2388 
2389 	/*
2390 	 * addr(col 0)
2391 	 */
2392 	if ((t = strtok(buf, " \t")) == 0) {
2393 		(void) strcpy(parse_err_msg, "no mask");
2394 		return (GENENT_PARSEERR);
2395 	}
2396 	ecol[0].ec_value.ec_value_val = t;
2397 	ecol[0].ec_value.ec_value_len = strlen(t)+1;
2398 
2399 	/*
2400 	 * mask (col 1)
2401 	 */
2402 	if ((t = strtok(NULL, " \t")) == 0) {
2403 		(void) strcpy(parse_err_msg, "no mask");
2404 		return (GENENT_PARSEERR);
2405 	}
2406 	ecol[1].ec_value.ec_value_val = t;
2407 	ecol[1].ec_value.ec_value_len = strlen(t)+1;
2408 
2409 	/* build entry */
2410 	data.netnumber = ecol[0].ec_value.ec_value_val;
2411 	data.netmask = ecol[1].ec_value.ec_value_val;
2412 
2413 	if (flags & F_VERBOSE)
2414 		(void) fprintf(stdout,
2415 		    gettext("Adding entry : %s\n"), data.netnumber);
2416 
2417 	retval = (*cback)(&data, 1);
2418 	if (retval != NS_LDAP_SUCCESS) {
2419 		if (retval == LDAP_NO_SUCH_OBJECT)
2420 			(void) fprintf(stdout,
2421 			gettext("Cannot add netmask entry (%s), "
2422 				"add network entry first\n"), data.netnumber);
2423 		if (continue_onerror == 0)
2424 			return (GENENT_CBERR);
2425 	}
2426 
2427 	return (GENENT_OK);
2428 }
2429 
2430 static void
2431 dump_netmasks(ns_ldap_result_t *res)
2432 {
2433 	char	**value = NULL;
2434 
2435 	value = __ns_ldap_getAttr(res->entry, "ipNetworkNumber");
2436 	if (value && value[0])
2437 		(void) fprintf(stdout, "%s", value[0]);
2438 	value = __ns_ldap_getAttr(res->entry, "ipNetmaskNumber");
2439 	if (value && value[0])
2440 		(void) fprintf(stdout, "	%s\n", value[0]);
2441 }
2442 
2443 
2444 /*
2445  * /etc/netgroup
2446  * column data format is:
2447  *    col 0: netgroup name (or cname)
2448  *    col 1: netgroup member, if this is a triplet
2449  *    col 2: netgroup member, if not a triplet
2450  *    col 3: comment
2451  */
2452 
2453 static int
2454 genent_netgroup(char *line, int (*cback)())
2455 {
2456 	char buf[BIGBUF+1];    /* netgroup entries tend to be big */
2457 	char *t;
2458 	char *cname = NULL;
2459 	entry_col ecol[4];
2460 	char *netg_tmp = NULL, *triplet_tmp = NULL;
2461 	int netgcount = 0, tripletcount = 0, retval = 1, i;
2462 	struct _ns_netgroups data;
2463 	int rc = GENENT_OK;
2464 
2465 	/* don't clobber our argument */
2466 	if (strlen(line) >= sizeof (buf)) {
2467 		(void) strcpy(parse_err_msg, "line too long");
2468 		return (GENENT_PARSEERR);
2469 	}
2470 	(void) strcpy(buf, line);
2471 
2472 	/* clear column data */
2473 	(void) memset((char *)ecol, 0, sizeof (ecol));
2474 
2475 	/*
2476 	 * process 1st minimal entry, to validate that there is no
2477 	 * parsing error.
2478 	 * start with comment(col 3)
2479 	 */
2480 	t = strchr(buf, '#');
2481 	if (t) {
2482 		*t++ = 0;
2483 		ecol[3].ec_value.ec_value_val = t;
2484 		ecol[3].ec_value.ec_value_len = strlen(t)+1;
2485 	} else {
2486 		ecol[3].ec_value.ec_value_val = "";
2487 		ecol[3].ec_value.ec_value_len = 0;
2488 	}
2489 
2490 	ecol[1].ec_value.ec_value_val = NULL;
2491 	ecol[2].ec_value.ec_value_val = NULL;
2492 
2493 	/* cname (col 0) */
2494 	if ((t = strtok(buf, " \t")) == 0) {
2495 		(void) strcpy(parse_err_msg, "no cname");
2496 		return (GENENT_PARSEERR);
2497 	}
2498 
2499 	ecol[0].ec_value.ec_value_val = t;
2500 	ecol[0].ec_value.ec_value_len = strlen(t)+1;
2501 	cname = t;
2502 
2503 	/* addr(col 1 and 2) */
2504 	if ((t = strtok(NULL, " \t")) == 0) {
2505 		(void) strcpy(parse_err_msg, "no members for netgroup");
2506 		return (GENENT_PARSEERR);
2507 	}
2508 
2509 	if (*t == '(') {
2510 		/* if token starts with '(' it must be a valid triplet */
2511 		if (is_triplet(t)) {
2512 			ecol[1].ec_value.ec_value_val = t;
2513 			ecol[1].ec_value.ec_value_len = strlen(t)+1;
2514 		} else {
2515 			(void) strcpy(parse_err_msg, "invalid triplet");
2516 			return (GENENT_PARSEERR);
2517 		}
2518 	} else {
2519 		ecol[2].ec_value.ec_value_val = t;
2520 		ecol[2].ec_value.ec_value_len = strlen(t)+1;
2521 	}
2522 
2523 	/*
2524 	 * now build entry.
2525 	 * start by clearing entry data
2526 	 */
2527 	(void) memset((struct _ns_netgroups *)&data, 0, sizeof (data));
2528 
2529 	data.name = strdup(ecol[0].ec_value.ec_value_val);
2530 
2531 	if (ecol[1].ec_value.ec_value_val != NULL) {
2532 		if ((data.triplet = calloc(1, sizeof (char **))) == NULL) {
2533 				(void) fprintf(stderr,
2534 					gettext("out of memory\n"));
2535 				exit(1);
2536 		}
2537 		data.triplet[tripletcount++] =
2538 		    strdup(ecol[1].ec_value.ec_value_val);
2539 	} else if (ecol[2].ec_value.ec_value_val != NULL) {
2540 			if ((data.netgroup = calloc(1, sizeof (char **)))
2541 			    == NULL) {
2542 					(void) fprintf(stderr,
2543 				    gettext("out of memory\n"));
2544 					exit(1);
2545 			}
2546 			data.netgroup[netgcount++] =
2547 			    strdup(ecol[2].ec_value.ec_value_val);
2548 	}
2549 
2550 	/*
2551 	 * we now have a valid entry (at least 1 netgroup name and
2552 	 * 1 netgroup member), proceed with the rest of the line
2553 	 */
2554 	while (rc == GENENT_OK && (t = strtok(NULL, " \t"))) {
2555 
2556 		/* if next token is equal to netgroup name, ignore */
2557 		if (t != cname && strcasecmp(t, cname) == 0)
2558 			continue;
2559 		if (strcasecmp(t, ecol[0].ec_value.ec_value_val) == 0)
2560 			continue;
2561 
2562 		if (*t == '(') {
2563 			if (is_triplet(t)) {
2564 				/* skip a triplet if it is added already */
2565 				for (i = 0; i < tripletcount &&
2566 					strcmp(t, data.triplet[i]); i++)
2567 					;
2568 				if (i < tripletcount)
2569 					continue;
2570 
2571 				tripletcount++;
2572 				triplet_tmp = strdup(t);
2573 				if ((data.triplet = (char **)realloc(
2574 					data.triplet,
2575 					tripletcount * sizeof (char **)))
2576 					== NULL) {
2577 					(void) fprintf(stderr,
2578 						gettext("out of memory\n"));
2579 					exit(1);
2580 				}
2581 				data.triplet[tripletcount-1] = triplet_tmp;
2582 			} else {
2583 				(void) strcpy(parse_err_msg, "invalid triplet");
2584 				rc = GENENT_PARSEERR;
2585 			}
2586 		} else {
2587 			/* skip a netgroup if it is added already */
2588 			for (i = 0; i < netgcount &&
2589 				strcmp(t, data.netgroup[i]); i++)
2590 				;
2591 			if (i < netgcount)
2592 				continue;
2593 
2594 			netgcount++;
2595 			netg_tmp = strdup(t);
2596 			if ((data.netgroup = (char **)realloc(data.netgroup,
2597 				netgcount * sizeof (char **))) == NULL) {
2598 				(void) fprintf(stderr,
2599 				gettext("out of memory\n"));
2600 				exit(1);
2601 			}
2602 			data.netgroup[netgcount-1] = netg_tmp;
2603 		}
2604 	}
2605 
2606 	/* End the list with NULL */
2607 	if ((data.triplet = (char **)realloc(data.triplet,
2608 		(tripletcount + 1) * sizeof (char **))) == NULL) {
2609 		(void) fprintf(stderr, gettext("out of memory\n"));
2610 		exit(1);
2611 	}
2612 	data.triplet[tripletcount] = NULL;
2613 	if ((data.netgroup = (char **)realloc(data.netgroup,
2614 		(netgcount + 1) * sizeof (char **))) == NULL) {
2615 		(void) fprintf(stderr, gettext("out of memory\n"));
2616 		exit(1);
2617 	}
2618 	data.netgroup[netgcount] = NULL;
2619 
2620 	if (rc == GENENT_OK) {
2621 		if (flags & F_VERBOSE)
2622 			(void) fprintf(stdout,
2623 			    gettext("Adding entry : %s\n"), data.name);
2624 
2625 		retval = (*cback)(&data, 0);
2626 
2627 		if (retval == LDAP_ALREADY_EXISTS) {
2628 			if (continue_onerror)
2629 				(void) fprintf(stderr, gettext(
2630 				"Entry: %s - already Exists, skipping it.\n"),
2631 				data.name);
2632 			else {
2633 				rc = GENENT_CBERR;
2634 				(void) fprintf(stderr,
2635 					gettext("Entry: %s - already Exists\n"),
2636 					data.name);
2637 			}
2638 		} else if (retval)
2639 			rc = GENENT_CBERR;
2640 	}
2641 
2642 	/* release memory allocated by strdup() */
2643 	for (i = 0; i < tripletcount; i++) {
2644 		free(data.triplet[i]);
2645 	}
2646 	for (i = 0; i < netgcount; i++) {
2647 		free(data.netgroup[i]);
2648 	}
2649 
2650 	free(data.name);
2651 	free(data.triplet);
2652 	free(data.netgroup);
2653 
2654 	return (rc);
2655 }
2656 
2657 static void
2658 dump_netgroup(ns_ldap_result_t *res)
2659 {
2660 	char	**value = NULL;
2661 	int	attr_count = 0;
2662 
2663 	value = __ns_ldap_getAttr(res->entry, "cn");
2664 	if ((value != NULL) && (value[0] != NULL))
2665 		(void) fprintf(stdout, "%s", value[0]);
2666 	else
2667 		return;
2668 	value = __ns_ldap_getAttr(res->entry, "nisNetgroupTriple");
2669 	if (value != NULL)
2670 		while (value[attr_count] != NULL) {
2671 			(void) fprintf(stdout, " %s", value[attr_count]);
2672 			attr_count++;
2673 		}
2674 	attr_count = 0;
2675 	value = __ns_ldap_getAttr(res->entry, "memberNisNetgroup");
2676 	if (value != NULL)
2677 		while (value[attr_count] != NULL) {
2678 			(void) fprintf(stdout, " %s", value[attr_count]);
2679 			attr_count++;
2680 		}
2681 	(void) fprintf(stdout, "\n");
2682 
2683 }
2684 
2685 static int
2686 genent_automount(char *line, int (*cback)())
2687 {
2688 	char buf[BUFSIZ+1];
2689 	char *t, *s;
2690 	entry_col ecol[2];
2691 	struct _ns_automount data;
2692 	int retval = 1;
2693 	int rc = GENENT_OK;
2694 
2695 	/*
2696 	 * don't clobber our argument
2697 	 */
2698 	if (strlen(line) >= sizeof (buf)) {
2699 		(void) strcpy(parse_err_msg, "line too long");
2700 		return (GENENT_PARSEERR);
2701 		}
2702 
2703 	/* replace every tabspace with single space */
2704 	replace_tab2space(line);
2705 	(void) strcpy(buf, line);
2706 
2707 	/*
2708 	 * clear column data
2709 	 */
2710 	(void) memset((char *)ecol, 0, sizeof (ecol));
2711 
2712 	/*
2713 	 * key (col 0)
2714 	 */
2715 	t = buf;
2716 	while (t[0] == ' ')
2717 		t++;
2718 
2719 	if ((s = strchr(t, ' ')) == 0) {
2720 		return (GENENT_PARSEERR);
2721 	}
2722 	*s++ = 0;
2723 
2724 	ecol[0].ec_value.ec_value_val = t;
2725 	ecol[0].ec_value.ec_value_len = strlen(t)+1;
2726 	t = s;
2727 
2728 	while (t[0] == ' ')
2729 		t++;
2730 
2731 	/*
2732 	 * mapentry (col 1)
2733 	 */
2734 
2735 	ecol[1].ec_value.ec_value_val = t;
2736 	ecol[1].ec_value.ec_value_len = strlen(t)+1;
2737 
2738 	data.mapname = strdup(databasetype);
2739 	data.key = strdup(ecol[0].ec_value.ec_value_val);
2740 	data.value = strdup(ecol[1].ec_value.ec_value_val);
2741 
2742 	if (flags & F_VERBOSE)
2743 		(void) fprintf(stdout,
2744 		    gettext("Adding entry : %s\n"), data.key);
2745 
2746 	retval = (*cback)(&data, 0);
2747 
2748 	if (retval == LDAP_ALREADY_EXISTS) {
2749 		if (continue_onerror)
2750 			(void) fprintf(stderr,
2751 			gettext("Entry: %s - already Exists, skipping it.\n"),
2752 			data.key);
2753 		else {
2754 			rc = GENENT_CBERR;
2755 			(void) fprintf(stderr,
2756 				gettext("Entry: %s - already Exists\n"),
2757 				data.key);
2758 		}
2759 	} else if (retval)
2760 		rc = GENENT_CBERR;
2761 
2762 	free(data.mapname);
2763 	free(data.key);
2764 	free(data.value);
2765 	return (rc);
2766 }
2767 
2768 static void
2769 dump_automount(ns_ldap_result_t *res)
2770 {
2771 	char	**value = NULL;
2772 
2773 	if (res == NULL)
2774 		return;
2775 
2776 	value = __ns_ldap_getAttr(res->entry, "automountKey");
2777 	if (value != NULL) {
2778 		(void) fprintf(stdout, "%s", value[0]);
2779 		value = __ns_ldap_getAttr(res->entry, "automountInformation");
2780 		if (value != NULL)
2781 			(void) fprintf(stdout, "	%s\n", value[0]);
2782 		else
2783 			(void) fprintf(stdout, "\n");
2784 	}
2785 }
2786 
2787 
2788 /*
2789  * /etc/passwd
2790  *
2791  */
2792 
2793 static int
2794 genent_passwd(char *line, int (*cback)())
2795 {
2796 	char buf[BUFSIZ+1];
2797 	char *s, *t;
2798 	entry_col ecol[8];
2799 	int retval = 1;
2800 	char pname[BUFSIZ];
2801 
2802 	struct passwd	data;
2803 	int rc = GENENT_OK;
2804 
2805 
2806 	/*
2807 	 * don't clobber our argument
2808 	 */
2809 	if (strlen(line) >= sizeof (buf)) {
2810 		(void) strcpy(parse_err_msg, "line too long");
2811 		return (GENENT_PARSEERR);
2812 	}
2813 	(void) strcpy(buf, line);
2814 	t = buf;
2815 
2816 	/* ignore empty entries */
2817 	if (*t == '\0')
2818 		return (GENENT_OK);
2819 
2820 	/*
2821 	 * clear column data
2822 	 */
2823 	(void) memset((char *)ecol, 0, sizeof (ecol));
2824 
2825 	/*
2826 	 * name (col 0)
2827 	 */
2828 	if ((s = strchr(t, ':')) == 0) {
2829 		(void) strcpy(parse_err_msg, "no password");
2830 		return (GENENT_PARSEERR);
2831 	}
2832 	*s++ = 0;
2833 	ecol[0].ec_value.ec_value_val = t;
2834 	ecol[0].ec_value.ec_value_len = strlen(t)+1;
2835 	t = s;
2836 
2837 	/*
2838 	 * passwd (col 1)
2839 	 */
2840 	if ((s = strchr(t, ':')) == 0) {
2841 		(void) strcpy(parse_err_msg, "no uid");
2842 		return (GENENT_PARSEERR);
2843 	}
2844 	*s++ = 0;
2845 
2846 	ecol[1].ec_value.ec_value_val = t;
2847 	ecol[1].ec_value.ec_value_len = strlen(t)+1;
2848 
2849 	t = s;
2850 
2851 	/*
2852 	 * uid (col 2)
2853 	 */
2854 	if ((s = strchr(t, ':')) == 0 || s == t) {
2855 		(void) strcpy(parse_err_msg, "no gid");
2856 		return (GENENT_PARSEERR);
2857 	}
2858 	*s++ = 0;
2859 	ecol[2].ec_value.ec_value_val = t;
2860 	ecol[2].ec_value.ec_value_len = strlen(t)+1;
2861 	t = s;
2862 
2863 	/*
2864 	 * gid (col 3)
2865 	 */
2866 	if ((s = strchr(t, ':')) == 0 || s == t) {
2867 		(void) strcpy(parse_err_msg, "no gcos");
2868 		return (GENENT_PARSEERR);
2869 	}
2870 	*s++ = 0;
2871 	ecol[3].ec_value.ec_value_val = t;
2872 	ecol[3].ec_value.ec_value_len = strlen(t)+1;
2873 	t = s;
2874 
2875 	/*
2876 	 * gcos (col 4)
2877 	 */
2878 	if ((s = strchr(t, ':')) == 0) {
2879 		(void) strcpy(parse_err_msg, "no home");
2880 		return (GENENT_PARSEERR);
2881 	}
2882 	*s++ = 0;
2883 	ecol[4].ec_value.ec_value_val = t;
2884 	ecol[4].ec_value.ec_value_len = strlen(t)+1;
2885 	t = s;
2886 
2887 	/*
2888 	 * home (col 5)
2889 	 */
2890 	if ((s = strchr(t, ':')) == 0) {
2891 		(void) strcpy(parse_err_msg, "no shell");
2892 		return (GENENT_PARSEERR);
2893 	}
2894 	*s++ = 0;
2895 	ecol[5].ec_value.ec_value_val = t;
2896 	ecol[5].ec_value.ec_value_len = strlen(t)+1;
2897 	t = s;
2898 
2899 	/*
2900 	 * shell (col 6)
2901 	 */
2902 	ecol[6].ec_value.ec_value_val = t;
2903 	ecol[6].ec_value.ec_value_len = strlen(t)+1;
2904 
2905 	/*
2906 	 * build entry
2907 	 */
2908 	data.pw_name = strdup(ecol[0].ec_value.ec_value_val);
2909 
2910 	if (flags & F_PASSWD) {
2911 		/* Add {crypt} before passwd entry */
2912 		(void) snprintf(pname, sizeof (pname), "{crypt}%s",
2913 		    ecol[1].ec_value.ec_value_val);
2914 		data.pw_passwd = strdup(pname);
2915 	}
2916 	else
2917 		data.pw_passwd = NULL;
2918 
2919 	if (ecol[2].ec_value.ec_value_val != NULL &&
2920 	    ecol[2].ec_value.ec_value_val[0] != '\0') {
2921 		data.pw_uid = ascii_to_int(ecol[2].ec_value.ec_value_val);
2922 		if (data.pw_uid == -1) {
2923 			(void) snprintf(parse_err_msg, sizeof (parse_err_msg),
2924 			    "invalid uid : %s", ecol[2].ec_value.ec_value_val);
2925 		return (GENENT_PARSEERR);
2926 		}
2927 	} else
2928 		data.pw_uid = -1;
2929 
2930 	if (ecol[3].ec_value.ec_value_val != NULL &&
2931 		ecol[3].ec_value.ec_value_val[0] != '\0') {
2932 
2933 		data.pw_gid = ascii_to_int(ecol[3].ec_value.ec_value_val);
2934 		if (data.pw_gid == -1) {
2935 			(void) snprintf(parse_err_msg, sizeof (parse_err_msg),
2936 			    "invalid gid : %s", ecol[3].ec_value.ec_value_val);
2937 		return (GENENT_PARSEERR);
2938 		}
2939 	} else
2940 		data.pw_gid = -1;
2941 
2942 	data.pw_age = NULL;
2943 	data.pw_comment = NULL;
2944 	data.pw_gecos = strdup(ecol[4].ec_value.ec_value_val);
2945 	data.pw_dir = strdup(ecol[5].ec_value.ec_value_val);
2946 	data.pw_shell = strdup(ecol[6].ec_value.ec_value_val);
2947 
2948 	if (flags & F_VERBOSE)
2949 		(void) fprintf(stdout,
2950 		    gettext("Adding entry : %s\n"), data.pw_name);
2951 
2952 	retval = (*cback)(&data, 0);
2953 
2954 	if (retval == LDAP_ALREADY_EXISTS) {
2955 		if (continue_onerror)
2956 			(void) fprintf(stderr,
2957 			gettext("Entry: %s - already Exists, skipping it.\n"),
2958 			data.pw_name);
2959 		else {
2960 			rc = GENENT_CBERR;
2961 			(void) fprintf(stderr,
2962 				gettext("Entry: %s - already Exists\n"),
2963 				data.pw_name);
2964 		}
2965 	} else if (retval)
2966 		rc = GENENT_CBERR;
2967 
2968 	free(data.pw_name);
2969 	free(data.pw_gecos);
2970 	free(data.pw_dir);
2971 	free(data.pw_shell);
2972 	return (rc);
2973 }
2974 
2975 
2976 static void
2977 dump_passwd(ns_ldap_result_t *res)
2978 {
2979 	char    **value = NULL;
2980 	char	pnam[256];
2981 
2982 	value = __ns_ldap_getAttr(res->entry, "uid");
2983 	if (value == NULL)
2984 		return;
2985 	else
2986 		(void) fprintf(stdout, "%s:", value[0]);
2987 	value = __ns_ldap_getAttr(res->entry, "userPassword");
2988 	if (value == NULL)
2989 		(void) fprintf(stdout, "*:");
2990 	else {
2991 		(void) strcpy(pnam, value[0]);
2992 		if (strncasecmp(value[0], "{crypt}", 7) == 0)
2993 		(void) fprintf(stdout, "%s:", (pnam+7));
2994 		else
2995 			(void) fprintf(stdout, "*:");
2996 	}
2997 	value = __ns_ldap_getAttr(res->entry, "uidNumber");
2998 	if (value && value[0])
2999 		(void) fprintf(stdout, "%s:", value[0]);
3000 	value = __ns_ldap_getAttr(res->entry, "gidNumber");
3001 	if (value && value[0])
3002 		(void) fprintf(stdout, "%s:", value[0]);
3003 	value = __ns_ldap_getAttr(res->entry, "gecos");
3004 	if (value == NULL)
3005 		(void) fprintf(stdout, ":");
3006 	else
3007 		(void) fprintf(stdout, "%s:", value[0]);
3008 	value = __ns_ldap_getAttr(res->entry, "homeDirectory");
3009 	if (value == NULL)
3010 		(void) fprintf(stdout, ":");
3011 	else
3012 		(void) fprintf(stdout, "%s:", value[0]);
3013 	value = __ns_ldap_getAttr(res->entry, "loginShell");
3014 	if (value == NULL)
3015 		(void) fprintf(stdout, "\n");
3016 	else
3017 		(void) fprintf(stdout, "%s\n", value[0]);
3018 
3019 }
3020 
3021 /*
3022  * /etc/shadow
3023  */
3024 
3025 static int
3026 genent_shadow(char *line, int (*cback)())
3027 {
3028 	char buf[BUFSIZ+1];
3029 	char *s, *t;
3030 	entry_col ecol[9];
3031 	char pname[BUFSIZ];
3032 
3033 	struct spwd	data;
3034 	int spflag;
3035 	int retval;
3036 
3037 
3038 	/*
3039 	 * don't clobber our argument
3040 	 */
3041 	if (strlen(line) >= sizeof (buf)) {
3042 		(void) strcpy(parse_err_msg, "line too long");
3043 		return (GENENT_PARSEERR);
3044 	}
3045 	(void) strcpy(buf, line);
3046 	t = buf;
3047 
3048 	/* ignore empty entries */
3049 	if (*t == '\0')
3050 		return (GENENT_OK);
3051 
3052 	/*
3053 	 * clear column data
3054 	 */
3055 	(void) memset((char *)ecol, 0, sizeof (ecol));
3056 
3057 	/*
3058 	 * name (col 0)
3059 	 */
3060 	if ((s = strchr(t, ':')) == 0) {
3061 		(void) strcpy(parse_err_msg, "no uid");
3062 		return (GENENT_PARSEERR);
3063 	}
3064 	*s++ = 0;
3065 	ecol[0].ec_value.ec_value_val = t;
3066 	ecol[0].ec_value.ec_value_len = strlen(t)+1;
3067 	t = s;
3068 
3069 	/*
3070 	 * passwd (col 1)
3071 	 */
3072 	if ((s = strchr(t, ':')) == 0) {
3073 		(void) strcpy(parse_err_msg, "Improper format");
3074 		return (GENENT_PARSEERR);
3075 	}
3076 	*s++ = 0;
3077 
3078 		ecol[1].ec_value.ec_value_val = t;
3079 		ecol[1].ec_value.ec_value_len = strlen(t)+1;
3080 
3081 	t = s;
3082 
3083 	/*
3084 	 * shadow last change (col 2)
3085 	 */
3086 	if ((s = strchr(t, ':')) == 0) {
3087 		(void) strcpy(parse_err_msg, "Improper format");
3088 		return (GENENT_PARSEERR);
3089 	}
3090 	*s++ = 0;
3091 	ecol[2].ec_value.ec_value_val = t;
3092 	ecol[2].ec_value.ec_value_len = strlen(t)+1;
3093 	t = s;
3094 
3095 	/*
3096 	 * shadow min (col 3)
3097 	 */
3098 	if ((s = strchr(t, ':')) == 0) {
3099 		(void) strcpy(parse_err_msg, "Improper format");
3100 		return (GENENT_PARSEERR);
3101 	}
3102 	*s++ = 0;
3103 	ecol[3].ec_value.ec_value_val = t;
3104 	ecol[3].ec_value.ec_value_len = strlen(t)+1;
3105 	t = s;
3106 
3107 	/*
3108 	 * shadow max (col 4)
3109 	 */
3110 	if ((s = strchr(t, ':')) == 0) {
3111 		(void) strcpy(parse_err_msg, "Improper format");
3112 		return (GENENT_PARSEERR);
3113 	}
3114 	*s++ = 0;
3115 	ecol[4].ec_value.ec_value_val = t;
3116 	ecol[4].ec_value.ec_value_len = strlen(t)+1;
3117 	t = s;
3118 
3119 	/*
3120 	 * shadow warn (col 5)
3121 	 */
3122 	if ((s = strchr(t, ':')) == 0) {
3123 		(void) strcpy(parse_err_msg, "Improper format");
3124 		return (GENENT_PARSEERR);
3125 	}
3126 	*s++ = 0;
3127 	ecol[5].ec_value.ec_value_val = t;
3128 	ecol[5].ec_value.ec_value_len = strlen(t)+1;
3129 	t = s;
3130 
3131 	/*
3132 	 * shadow inactive (col 6)
3133 	 */
3134 	if ((s = strchr(t, ':')) != 0) {
3135 	*s++ = 0;
3136 	ecol[6].ec_value.ec_value_val = t;
3137 	ecol[6].ec_value.ec_value_len = strlen(t)+1;
3138 	t = s;
3139 	}
3140 
3141 	/*
3142 	 * shadow expire  (col 7)
3143 	 */
3144 	if ((s = strchr(t, ':')) != 0) {
3145 	*s++ = 0;
3146 	ecol[7].ec_value.ec_value_val = t;
3147 	ecol[7].ec_value.ec_value_len = strlen(t)+1;
3148 	t = s;
3149 
3150 	/*
3151 	 * flag (col 8)
3152 	 */
3153 	ecol[8].ec_value.ec_value_val = t;
3154 	ecol[8].ec_value.ec_value_len = strlen(t)+1;
3155 	}
3156 
3157 	/*
3158 	 * build entry
3159 	 */
3160 
3161 	data.sp_namp = strdup(ecol[0].ec_value.ec_value_val);
3162 
3163 	if (ecol[1].ec_value.ec_value_val != NULL &&
3164 		ecol[1].ec_value.ec_value_val[0] != '\0') {
3165 		/* Add {crypt} before passwd entry */
3166 		(void) snprintf(pname, sizeof (pname), "{crypt}%s",
3167 		    ecol[1].ec_value.ec_value_val);
3168 		data.sp_pwdp = strdup(pname);
3169 	} else
3170 		data.sp_pwdp = NULL;
3171 
3172 	if (ecol[2].ec_value.ec_value_val != NULL &&
3173 		ecol[2].ec_value.ec_value_val[0] != '\0') {
3174 
3175 		data.sp_lstchg = ascii_to_int(ecol[2].ec_value.ec_value_val);
3176 		if (data.sp_lstchg < -1) {
3177 			(void) snprintf(parse_err_msg, sizeof (parse_err_msg),
3178 			    "invalid last changed date: %s",
3179 			    ecol[2].ec_value.ec_value_val);
3180 		return (GENENT_PARSEERR);
3181 		}
3182 	} else
3183 		data.sp_lstchg = -1;
3184 
3185 	if (ecol[3].ec_value.ec_value_val != NULL &&
3186 		ecol[3].ec_value.ec_value_val[0] != '\0') {
3187 
3188 		data.sp_min = ascii_to_int(ecol[3].ec_value.ec_value_val);
3189 		if (data.sp_min < -1) {
3190 			(void) snprintf(parse_err_msg, sizeof (parse_err_msg),
3191 			    "invalid sp_min : %s",
3192 			    ecol[3].ec_value.ec_value_val);
3193 		return (GENENT_PARSEERR);
3194 		}
3195 	} else
3196 		data.sp_min = -1;
3197 
3198 	if (ecol[4].ec_value.ec_value_val != NULL &&
3199 		ecol[4].ec_value.ec_value_val[0] != '\0') {
3200 
3201 		data.sp_max = ascii_to_int(ecol[4].ec_value.ec_value_val);
3202 		if (data.sp_max < -1) {
3203 			(void) snprintf(parse_err_msg, sizeof (parse_err_msg),
3204 			    "invalid sp_max : %s",
3205 			    ecol[4].ec_value.ec_value_val);
3206 		return (GENENT_PARSEERR);
3207 		}
3208 	} else
3209 		data.sp_max = -1;
3210 
3211 	if (ecol[5].ec_value.ec_value_val != NULL &&
3212 		ecol[5].ec_value.ec_value_val[0] != '\0') {
3213 
3214 		data.sp_warn = ascii_to_int(ecol[5].ec_value.ec_value_val);
3215 		if (data.sp_warn < -1) {
3216 			(void) snprintf(parse_err_msg, sizeof (parse_err_msg),
3217 			    "invalid sp_warn : %s",
3218 			    ecol[5].ec_value.ec_value_val);
3219 		return (GENENT_PARSEERR);
3220 		}
3221 	} else
3222 		data.sp_warn = -1;
3223 
3224 	if (ecol[6].ec_value.ec_value_val != NULL &&
3225 		ecol[6].ec_value.ec_value_val[0] != '\0') {
3226 
3227 		data.sp_inact = ascii_to_int(ecol[6].ec_value.ec_value_val);
3228 		if (data.sp_inact < -1) {
3229 			(void) snprintf(parse_err_msg, sizeof (parse_err_msg),
3230 			    "invalid sp_inact : %s",
3231 			    ecol[6].ec_value.ec_value_val);
3232 		return (GENENT_PARSEERR);
3233 		}
3234 	} else
3235 		data.sp_inact = -1;
3236 
3237 	if (ecol[7].ec_value.ec_value_val != NULL &&
3238 		ecol[7].ec_value.ec_value_val[0] != '\0') {
3239 
3240 		data.sp_expire = ascii_to_int(ecol[7].ec_value.ec_value_val);
3241 		if (data.sp_expire < -1) {
3242 			(void) snprintf(parse_err_msg, sizeof (parse_err_msg),
3243 			    "invalid login expiry date : %s",
3244 			    ecol[7].ec_value.ec_value_val);
3245 		return (GENENT_PARSEERR);
3246 		}
3247 	} else
3248 		data.sp_expire = -1;
3249 
3250 	if (ecol[8].ec_value.ec_value_val != NULL &&
3251 		ecol[8].ec_value.ec_value_val[0] != '\0') {
3252 
3253 		/*
3254 		 * data.sp_flag is an unsigned int,
3255 		 * assign -1 to it, make no sense.
3256 		 * Use spflag here to avoid lint warning.
3257 		 */
3258 		spflag = ascii_to_int(ecol[8].ec_value.ec_value_val);
3259 		if (spflag < 0) {
3260 			(void) snprintf(parse_err_msg, sizeof (parse_err_msg),
3261 			    "invalid flag value: %s",
3262 			    ecol[8].ec_value.ec_value_val);
3263 		return (GENENT_PARSEERR);
3264 		} else
3265 			data.sp_flag = spflag;
3266 	} else
3267 		data.sp_flag = 0;
3268 
3269 	if (flags & F_VERBOSE)
3270 		(void) fprintf(stdout,
3271 		    gettext("Adding entry : %s\n"), data.sp_namp);
3272 
3273 	retval = (*cback)(&data, 1);
3274 	if (retval != NS_LDAP_SUCCESS) {
3275 		if (retval == LDAP_NO_SUCH_OBJECT)
3276 			(void) fprintf(stdout,
3277 			gettext("Cannot add shadow entry (%s), "
3278 				"add passwd entry first\n"), data.sp_namp);
3279 		if (continue_onerror == 0)
3280 			return (GENENT_CBERR);
3281 	}
3282 
3283 	free(data.sp_namp);
3284 	free(data.sp_pwdp);
3285 	return (GENENT_OK);
3286 }
3287 
3288 static void
3289 dump_shadow(ns_ldap_result_t *res)
3290 {
3291 	char    **value = NULL;
3292 	char   pnam[256];
3293 
3294 	value = __ns_ldap_getAttr(res->entry, "uid");
3295 	if (value == NULL)
3296 		return;
3297 	else
3298 		(void) fprintf(stdout, "%s:", value[0]);
3299 	value = __ns_ldap_getAttr(res->entry, "userPassword");
3300 	if (value == NULL)
3301 		(void) fprintf(stdout, "*:");
3302 	else {
3303 		(void) strcpy(pnam, value[0]);
3304 		if (strncasecmp(value[0], "{crypt}", 7) == 0)
3305 		(void) fprintf(stdout, "%s:", (pnam+7));
3306 		else
3307 			(void) fprintf(stdout, "*:");
3308 	}
3309 	value = __ns_ldap_getAttr(res->entry, "shadowLastChange");
3310 	if (value == NULL)
3311 		(void) fprintf(stdout, ":");
3312 	else
3313 		(void) fprintf(stdout, "%s:", value[0]);
3314 	value = __ns_ldap_getAttr(res->entry, "shadowMin");
3315 	if (value == NULL)
3316 		(void) fprintf(stdout, ":");
3317 	else
3318 		(void) fprintf(stdout, "%s:", value[0]);
3319 	value = __ns_ldap_getAttr(res->entry, "shadowMax");
3320 	if (value == NULL)
3321 		(void) fprintf(stdout, ":");
3322 	else
3323 		(void) fprintf(stdout, "%s:", value[0]);
3324 
3325 	/* ignore shadowWarning, shadowInactive, shadowExpire, shadowFlag */
3326 	(void) fprintf(stdout, ":::\n");
3327 
3328 }
3329 
3330 
3331 static int
3332 genent_bootparams(char *line, int (*cback)())
3333 {
3334 	char buf[BUFSIZ+1];
3335 	char *t;
3336 	entry_col ecol[2];
3337 	int ctr = 0, retval = 1;
3338 
3339 	struct _ns_bootp data;
3340 	char *parameter;
3341 	int rc = GENENT_OK;
3342 
3343 	/*
3344 	 * don't clobber our argument
3345 	 */
3346 	if (strlen(line) >= sizeof (buf)) {
3347 		(void) strcpy(parse_err_msg, "line too long");
3348 		return (GENENT_PARSEERR);
3349 	}
3350 	(void) strcpy(buf, line);
3351 
3352 	/*
3353 	 * clear column data
3354 	 */
3355 	(void) memset((char *)ecol, 0, sizeof (ecol));
3356 
3357 
3358 	/*
3359 	 * cname (col 0)
3360 	 */
3361 	if ((t = strtok(buf, " \t")) == 0) {
3362 		(void) strcpy(parse_err_msg, "no cname");
3363 		return (GENENT_PARSEERR);
3364 	}
3365 	ecol[0].ec_value.ec_value_val = t;
3366 	ecol[0].ec_value.ec_value_len = strlen(t)+1;
3367 
3368 
3369 
3370 	/* build entry */
3371 	data.name = strdup(ecol[0].ec_value.ec_value_val);
3372 
3373 	/*
3374 	 * name (col 1)
3375 	 */
3376 
3377 	data.param = NULL;
3378 
3379 	while (t = strtok(NULL, " \t"))  {
3380 
3381 		/*
3382 		 * don't clobber comment in canonical entry
3383 		 */
3384 
3385 
3386 		ecol[1].ec_value.ec_value_val = t;
3387 		ecol[1].ec_value.ec_value_len = strlen(t)+1;
3388 
3389 		ctr++;
3390 		parameter = strdup(ecol[1].ec_value.ec_value_val);
3391 		if ((data.param = (char **)realloc(data.param,
3392 			(ctr + 1) * sizeof (char **))) == NULL) {
3393 			(void) fprintf(stderr, gettext("out of memory\n"));
3394 			exit(1);
3395 		}
3396 		data.param[ctr-1] = parameter;
3397 
3398 	}
3399 
3400 
3401 	/* End the list of all the aliases by NULL */
3402 	if ((data.param = (char **)realloc(data.param,
3403 		(ctr + 1) * sizeof (char **))) == NULL) {
3404 		(void) fprintf(stderr, gettext("out of memory\n"));
3405 		exit(1);
3406 	}
3407 	data.param[ctr] = NULL;
3408 
3409 	if (flags & F_VERBOSE)
3410 		(void) fprintf(stdout,
3411 		    gettext("Adding entry : %s\n"), data.name);
3412 
3413 	retval = (*cback)(&data, 0);
3414 
3415 	if (retval == LDAP_ALREADY_EXISTS) {
3416 		if (continue_onerror)
3417 			(void) fprintf(stderr,
3418 			gettext("Entry: %s - already Exists, skipping it.\n"),
3419 			data.name);
3420 		else {
3421 			rc = GENENT_CBERR;
3422 			(void) fprintf(stderr,
3423 				gettext("Entry: %s - already Exists\n"),
3424 				data.name);
3425 		}
3426 	} else if (retval)
3427 		rc = GENENT_CBERR;
3428 
3429 	free(data.name);
3430 	free(data.param);
3431 
3432 	return (rc);
3433 
3434 }
3435 
3436 
3437 static void
3438 dump_bootparams(ns_ldap_result_t *res)
3439 {
3440 	char	**value = NULL;
3441 	int		attr_count = 0;
3442 
3443 	value = __ns_ldap_getAttr(res->entry, "cn");
3444 	if (value[0] != NULL)
3445 		(void) fprintf(stdout, "%s", value[0]);
3446 	value = __ns_ldap_getAttr(res->entry, "bootParameter");
3447 	if (value != NULL)
3448 		while (value[attr_count] != NULL) {
3449 		(void) fprintf(stdout, "\t%s", value[attr_count]);
3450 			attr_count++;
3451 		}
3452 	(void) fprintf(stdout, "\n");
3453 
3454 
3455 }
3456 
3457 static char *
3458 fget_line_at(struct line_buf *line, int n, FILE *fp)
3459 {
3460 	int c;
3461 
3462 	line->len = n;
3463 
3464 	for (;;) {
3465 		c = fgetc(fp);
3466 		if (c == -1)
3467 			break;
3468 		if (line->len >= line->alloc)
3469 			line_buf_expand(line);
3470 		line->str[line->len++] = c;
3471 
3472 		if (c == '\n')
3473 			break;
3474 	}
3475 
3476 	/* Null Terminate */
3477 	if (line->len >= line->alloc)
3478 		line_buf_expand(line);
3479 	line->str[line->len++] = 0;
3480 
3481 	/* if no characters are read, return NULL to indicate EOF */
3482 	if (line->str[0] == '\0')
3483 		return (0);
3484 
3485 	return (line->str);
3486 }
3487 
3488 /*
3489  * return a line from the file, discarding comments and blank lines
3490  */
3491 static int
3492 filedbmline_comment(struct line_buf *line, FILE *etcf, int *lineno,
3493     struct file_loc *loc)
3494 {
3495 	int i, len = 0;
3496 
3497 	loc->offset = ftell(etcf);
3498 	for (;;) {
3499 		if (fget_line_at(line, len, etcf) == 0)
3500 			return (0);
3501 
3502 		if (lineno)
3503 			(*lineno)++;
3504 
3505 		len = strlen(line->str);
3506 		if (len >= 2 &&
3507 		    line->str[0] != '#' &&
3508 		    line->str[len-2] == '\\' && line->str[len-1] == '\n') {
3509 			line->str[len-2] = 0;
3510 			len -= 2;
3511 			continue;    /* append next line at end */
3512 		}
3513 
3514 		if (line->str[len-1] == '\n') {
3515 			line->str[len-1] = 0;
3516 			len -= 1;
3517 		}
3518 
3519 		/*
3520 		 * Skip lines where '#' is the first non-blank character.
3521 		 */
3522 		for (i = 0; i < len; i++) {
3523 			if (line->str[i] == '#') {
3524 				line->str[i] = '\0';
3525 				len = i;
3526 				break;
3527 			}
3528 			if (line->str[i] != ' ' && line->str[i] != '\t')
3529 				break;
3530 		}
3531 
3532 		/*
3533 		 * A line with one or more white space characters followed
3534 		 * by a comment will now be blank. The special case of a
3535 		 * line with '#' in the first byte will have len == 0.
3536 		 */
3537 		if (len > 0 && !blankline(line->str))
3538 			break;
3539 
3540 		len = 0;
3541 		loc->offset = ftell(etcf);
3542 	}
3543 
3544 	loc->size = len;
3545 	return (1);
3546 }
3547 
3548 /*
3549  * return a line from the file, discarding comments, blanks, and '+' lines
3550  */
3551 static int
3552 filedbmline_plus(struct line_buf *line, FILE *etcf, int *lineno,
3553     struct file_loc *loc)
3554 {
3555 	int len = 0;
3556 
3557 	loc->offset = ftell(etcf);
3558 	for (;;) {
3559 		if (fget_line_at(line, len, etcf) == 0)
3560 			return (0);
3561 
3562 		if (lineno)
3563 			(*lineno)++;
3564 
3565 		len = strlen(line->str);
3566 		if (line->str[len-1] == '\n') {
3567 			line->str[len-1] = 0;
3568 			len -= 1;
3569 		}
3570 
3571 		if (!blankline(line->str) &&
3572 		line->str[0] != '+' && line->str[0] != '-' &&
3573 		line->str[0] != '#')
3574 			break;
3575 
3576 		len = 0;
3577 		loc->offset = ftell(etcf);
3578 	}
3579 
3580 	loc->size = len;
3581 	return (1);
3582 }
3583 
3584 
3585 /* Populating the ttypelist structure */
3586 
3587 static struct ttypelist_t ttypelist[] = {
3588 	{ NS_LDAP_TYPE_HOSTS, genent_hosts, dump_hosts,
3589 		filedbmline_comment, "iphost" },
3590 	{ NS_LDAP_TYPE_IPNODES, genent_hosts, dump_hosts,
3591 		filedbmline_comment, "iphost" },
3592 	{ NS_LDAP_TYPE_RPC, genent_rpc, dump_rpc,
3593 		filedbmline_comment, "oncrpc" },
3594 	{ NS_LDAP_TYPE_PROTOCOLS, genent_protocols, dump_protocols,
3595 		filedbmline_comment, "ipprotocol" },
3596 	{ NS_LDAP_TYPE_NETWORKS, genent_networks, dump_networks,
3597 		filedbmline_comment, "ipnetwork"  },
3598 	{ NS_LDAP_TYPE_SERVICES, genent_services, dump_services,
3599 		filedbmline_comment, "ipservice" },
3600 	{ NS_LDAP_TYPE_GROUP, genent_group, dump_group,
3601 		filedbmline_plus, "posixgroup" },
3602 	{ NS_LDAP_TYPE_NETMASKS, genent_netmasks, dump_netmasks,
3603 		filedbmline_comment, "ipnetwork" },
3604 	{ NS_LDAP_TYPE_ETHERS, genent_ethers, dump_ethers,
3605 		filedbmline_comment, "ieee802Device" },
3606 	{ NS_LDAP_TYPE_NETGROUP, genent_netgroup, dump_netgroup,
3607 		filedbmline_comment, "nisnetgroup" },
3608 	{ NS_LDAP_TYPE_BOOTPARAMS, genent_bootparams, dump_bootparams,
3609 		filedbmline_comment, "bootableDevice" },
3610 	{ NS_LDAP_TYPE_PUBLICKEY, genent_publickey, NULL /* dump_publickey */,
3611 		filedbmline_comment, "niskeyobject" },
3612 	{ NS_LDAP_TYPE_PASSWD, genent_passwd, dump_passwd,
3613 		filedbmline_plus, "posixaccount" },
3614 	{ NS_LDAP_TYPE_SHADOW, genent_shadow, dump_shadow,
3615 		filedbmline_plus, "shadowaccount" },
3616 	{ NS_LDAP_TYPE_ALIASES, genent_aliases, dump_aliases,
3617 		filedbmline_plus, "mailGroup" },
3618 	{ NS_LDAP_TYPE_AUTOMOUNT, genent_automount, dump_automount,
3619 		filedbmline_comment, "automount" },
3620 	{ NS_LDAP_TYPE_USERATTR, genent_user_attr, dump_user_attr,
3621 		filedbmline_comment, "SolarisUserAttr" },
3622 	{ NS_LDAP_TYPE_PROFILE, genent_prof_attr, dump_prof_attr,
3623 		filedbmline_comment, "SolarisProfAttr" },
3624 	{ NS_LDAP_TYPE_EXECATTR, genent_exec_attr, dump_exec_attr,
3625 		filedbmline_comment, "SolarisExecAttr" },
3626 	{ NS_LDAP_TYPE_AUTHATTR, genent_auth_attr, dump_auth_attr,
3627 		filedbmline_comment, "SolarisAuthAttr" },
3628 	{ NS_LDAP_TYPE_AUUSER, genent_audit_user, dump_audit_user,
3629 		filedbmline_comment, "SolarisAuditUser" },
3630 	{ NS_LDAP_TYPE_TNRHDB, genent_tnrhdb, dump_tnrhdb,
3631 		filedbmline_comment, "ipTnetHost" },
3632 	{ NS_LDAP_TYPE_TNRHTP, genent_tnrhtp, dump_tnrhtp,
3633 		filedbmline_comment, "ipTnetTemplate" },
3634 	{ 0, 0, 0, 0, 0 }
3635 };
3636 
3637 
3638 
3639 
3640 static int lineno = 0;
3641 
3642 static	void
3643 addfile()
3644 {
3645 	struct line_buf line;
3646 	struct file_loc loc;
3647 
3648 	/* Initializing the Line Buffer */
3649 	line_buf_init(&line);
3650 
3651 	/* Loop through all the lines in the file */
3652 	while (tt->filedbmline(&line, etcf, &lineno, &loc)) {
3653 		switch ((*(tt->genent))(line.str, addentry)) {
3654 		case GENENT_OK:
3655 			break;
3656 		case GENENT_PARSEERR:
3657 			(void) fprintf(stderr,
3658 			    gettext("parse error: %s (line %d)\n"),
3659 			    parse_err_msg, lineno);
3660 			exit_val = 1;
3661 			break;
3662 		case GENENT_CBERR:
3663 			(void) fprintf(stderr,
3664 			    gettext("Error while adding line: %s\n"),
3665 			    line.str);
3666 			exit_val = 2;
3667 			free(line.str);
3668 			return;
3669 			break;
3670 		case GENENT_ERR:
3671 			(void) fprintf(stderr,
3672 			    gettext("Internal Error while adding line: %s\n"),
3673 			    line.str);
3674 			exit_val = 3;
3675 			free(line.str);
3676 			return;
3677 			break;
3678 		}
3679 	}
3680 	free(line.str);
3681 }
3682 
3683 static void
3684 dumptable(char *service)
3685 {
3686 
3687 	ns_ldap_result_t *eres = NULL;
3688 	ns_ldap_error_t *err = NULL;
3689 	int	rc = 0, success = 0;
3690 	char	filter[BUFSIZ];
3691 	int	done = 0;
3692 	void	*cookie = NULL;
3693 
3694 	/* set the appropriate filter */
3695 	if (strcmp(tt->ttype, NS_LDAP_TYPE_PROFILE) == 0) {
3696 		/*
3697 		 * prof_attr entries are SolarisProfAttr
3698 		 * without AUXILIARY SolarisExecAttr
3699 		 */
3700 		(void) snprintf(filter, sizeof (filter),
3701 		    "(&(objectclass=%s)(!(objectclass=SolarisExecAttr)))",
3702 		    tt->objclass);
3703 	} else if (strcmp(tt->ttype, NS_LDAP_TYPE_TNRHDB) == 0) {
3704 		/*
3705 		 * tnrhtp entries are ipTnet entries with SolarisAttrKeyValue
3706 		 */
3707 		(void) snprintf(filter, sizeof (filter),
3708 		    "(&(objectclass=%s)(SolarisAttrKeyValue=*)))",
3709 		    tt->objclass);
3710 	} else {
3711 		(void) snprintf(filter, sizeof (filter),
3712 		    "(objectclass=%s)", tt->objclass);
3713 	}
3714 
3715 	if (flags & F_VERBOSE)
3716 		(void) fprintf(stdout, gettext("FILTER = %s\n"), filter);
3717 
3718 	/* Pass cred only if supplied. Cred is not always needed for dump */
3719 	if (authority.cred.unix_cred.userID == NULL ||
3720 	    authority.cred.unix_cred.passwd == NULL)
3721 		rc = __ns_ldap_firstEntry(service, filter, NULL, NULL,
3722 		    NULL, NS_LDAP_HARD, &cookie, &eres, &err, NULL);
3723 	else
3724 		rc = __ns_ldap_firstEntry(service, filter, NULL, NULL,
3725 		    &authority, NS_LDAP_HARD, &cookie, &eres, &err, NULL);
3726 
3727 	switch (rc) {
3728 	case NS_LDAP_SUCCESS:
3729 		nent_add++;
3730 		success = 1;
3731 		if (eres != NULL) {
3732 			if (strcmp(databasetype, "publickey") == 0)
3733 				dump_publickey(eres, service);
3734 			else
3735 				(*(tt->dump))(eres);
3736 		}
3737 		else
3738 			(void) fprintf(stderr, gettext("No entries found.\n"));
3739 		break;
3740 
3741 	case NS_LDAP_OP_FAILED:
3742 		exit_val = 2;
3743 		(void) fprintf(stderr, gettext("operation failed.\n"));
3744 		break;
3745 
3746 	case NS_LDAP_INVALID_PARAM:
3747 		exit_val = 2;
3748 		(void) fprintf(stderr,
3749 		    gettext("invalid parameter(s) passed.\n"));
3750 		break;
3751 
3752 	case NS_LDAP_NOTFOUND:
3753 		exit_val = 2;
3754 		(void) fprintf(stderr, gettext("entry not found.\n"));
3755 		break;
3756 
3757 	case NS_LDAP_MEMORY:
3758 		exit_val = 2;
3759 		(void) fprintf(stderr,
3760 			gettext("internal memory allocation error.\n"));
3761 		break;
3762 
3763 	case NS_LDAP_CONFIG:
3764 		exit_val = 2;
3765 		(void) fprintf(stderr,
3766 			gettext("LDAP Configuration problem.\n"));
3767 		perr(err);
3768 		break;
3769 
3770 	case NS_LDAP_PARTIAL:
3771 		exit_val = 2;
3772 		(void) fprintf(stderr,
3773 			gettext("partial result returned\n"));
3774 		perr(err);
3775 		break;
3776 
3777 	case NS_LDAP_INTERNAL:
3778 		exit_val = 2;
3779 		(void) fprintf(stderr,
3780 			gettext("internal LDAP error occured.\n"));
3781 		perr(err);
3782 		break;
3783 	}
3784 
3785 	if (eres != NULL) {
3786 		(void) __ns_ldap_freeResult(&eres);
3787 		eres = NULL;
3788 	}
3789 
3790 	if (success) {
3791 		while (!done) {
3792 			rc = __ns_ldap_nextEntry(cookie, &eres, &err);
3793 			if (rc != NS_LDAP_SUCCESS || eres  == NULL) {
3794 				done = 1;
3795 				continue;
3796 			}
3797 
3798 			/* Print the result */
3799 			if (eres != NULL) {
3800 				if (strcmp(databasetype, "publickey") == 0)
3801 					dump_publickey(eres, service);
3802 				else
3803 					(*(tt->dump))(eres);
3804 				(void) __ns_ldap_freeResult(&eres);
3805 				eres = NULL;
3806 			}
3807 		}
3808 	}
3809 }
3810 
3811 int
3812 main(int argc, char **argv)
3813 {
3814 	char	*password;
3815 	int	c;
3816 	int	rc;
3817 	int	ldaprc;
3818 	int		authstried = 0;
3819 	int		supportedauth = 0;
3820 	int		op = OP_ADD;
3821 	char	*ttype, *authmech = 0, *etcfile = 0;
3822 	char	ps[LDAP_MAXNAMELEN]; /* Temporary password variable */
3823 	char	filter[BUFSIZ];
3824 	void	**paramVal = NULL;
3825 	ns_auth_t	**app;
3826 	ns_auth_t	**authpp = NULL;
3827 	ns_auth_t	*authp = NULL;
3828 	ns_ldap_error_t	*errorp = NULL;
3829 	ns_ldap_result_t *resultp;
3830 	ns_ldap_entry_t *e;
3831 	int	flag = 0;
3832 	int	version1 = 0;
3833 
3834 	(void) setlocale(LC_ALL, "");
3835 	(void) textdomain(TEXT_DOMAIN);
3836 
3837 	openlog("ldapaddent", LOG_PID, LOG_USER);
3838 
3839 	inputbasedn = NULL;
3840 	authority.cred.unix_cred.passwd = NULL;
3841 	authority.cred.unix_cred.userID = NULL;
3842 	authority.auth.type = NS_LDAP_AUTH_SIMPLE;
3843 
3844 	while ((c = getopt(argc, argv, "cdhvpf:D:w:b:a:")) != EOF) {
3845 		switch (c) {
3846 		case 'd':
3847 			if (op)
3848 				usage("no other option should be specified");
3849 			op = OP_DUMP;
3850 			break;
3851 		case 'c':
3852 			continue_onerror = 1;
3853 			break;
3854 		case 'v':
3855 			flags |= F_VERBOSE;
3856 			break;
3857 		case 'p':
3858 			flags |= F_PASSWD;
3859 			break;
3860 		case 'f':
3861 			etcfile = optarg;
3862 			break;
3863 		case 'D':
3864 			authority.cred.unix_cred.userID = strdup(optarg);
3865 			break;
3866 		case 'w':
3867 			authority.cred.unix_cred.passwd = strdup(optarg);
3868 			break;
3869 		case 'b':
3870 			inputbasedn = strdup(optarg);
3871 			break;
3872 		case 'a':
3873 			authmech = strdup(optarg);
3874 			break;
3875 
3876 		default:
3877 			usage(gettext("Invalid option"));
3878 		}
3879 	}
3880 
3881 
3882 	if (authority.cred.unix_cred.userID == NULL && op != OP_DUMP) {
3883 	    /* This is not an optional parameter. Exit */
3884 		(void) fprintf(stderr,
3885 			gettext("Distinguished Name to bind to directory"
3886 				" must be specified. use option -D.\n"));
3887 		exit(1);
3888 	}
3889 
3890 	if (authority.cred.unix_cred.passwd == NULL && op != OP_DUMP) {
3891 		/* If password is not specified, then prompt user for it. */
3892 		password = getpassphrase("Enter password:");
3893 		(void) strcpy(ps, password);
3894 		authority.cred.unix_cred.passwd = strdup(ps);
3895 	}
3896 
3897 	if (authmech != NULL) {
3898 		if (strcasecmp(authmech, "simple") == 0) {
3899 		authority.auth.type = NS_LDAP_AUTH_SIMPLE;
3900 		authority.auth.tlstype = NS_LDAP_TLS_NONE;
3901 		authority.auth.saslmech = NS_LDAP_SASL_NONE;
3902 		authority.auth.saslopt = NS_LDAP_SASLOPT_NONE;
3903 		supportedauth = 1;
3904 		}
3905 		if (strcasecmp(authmech, "sasl/CRAM-MD5") == 0) {
3906 		authority.auth.type = NS_LDAP_AUTH_SASL;
3907 		authority.auth.tlstype = NS_LDAP_TLS_SASL;
3908 		authority.auth.saslmech = NS_LDAP_SASL_CRAM_MD5;
3909 		authority.auth.saslopt = NS_LDAP_SASLOPT_NONE;
3910 		supportedauth = 1;
3911 		}
3912 		if (strcasecmp(authmech, "sasl/DIGEST-MD5") == 0) {
3913 		authority.auth.type = NS_LDAP_AUTH_SASL;
3914 		authority.auth.tlstype = NS_LDAP_TLS_SASL;
3915 		authority.auth.saslmech = NS_LDAP_SASL_DIGEST_MD5;
3916 		authority.auth.saslopt = NS_LDAP_SASLOPT_NONE;
3917 		supportedauth = 1;
3918 		}
3919 		if (strcasecmp(authmech, "tls:simple") == 0) {
3920 		authority.auth.type = NS_LDAP_AUTH_TLS;
3921 		authority.auth.tlstype = NS_LDAP_TLS_SIMPLE;
3922 		authority.auth.saslmech = NS_LDAP_SASL_NONE;
3923 		authority.auth.saslopt = NS_LDAP_SASLOPT_NONE;
3924 		supportedauth = 1;
3925 		}
3926 		if (strcasecmp(authmech, "tls:sasl/CRAM-MD5") == 0) {
3927 		authority.auth.type = NS_LDAP_AUTH_TLS;
3928 		authority.auth.tlstype = NS_LDAP_TLS_SASL;
3929 		authority.auth.saslmech = NS_LDAP_SASL_CRAM_MD5;
3930 		authority.auth.saslopt = NS_LDAP_SASLOPT_NONE;
3931 		supportedauth = 1;
3932 		}
3933 		if (strcasecmp(authmech, "tls:sasl/DIGEST-MD5") == 0) {
3934 		authority.auth.type = NS_LDAP_AUTH_TLS;
3935 		authority.auth.tlstype = NS_LDAP_TLS_SASL;
3936 		authority.auth.saslmech = NS_LDAP_SASL_DIGEST_MD5;
3937 		authority.auth.saslopt = NS_LDAP_SASLOPT_NONE;
3938 		supportedauth = 1;
3939 		}
3940 		if (!supportedauth) {
3941 			(void) fprintf(stderr,
3942 			gettext("Invalid authentication method specified"));
3943 			exit(1);
3944 		}
3945 	}
3946 
3947 	if (authmech == NULL) {
3948 		ldaprc = __ns_ldap_getParam(NS_LDAP_AUTH_P, (void ***)&authpp,
3949 			&errorp);
3950 		if (ldaprc != NS_LDAP_SUCCESS ||
3951 		    (authpp == NULL && op != OP_DUMP)) {
3952 			(void) fprintf(stderr,
3953 			    gettext("No legal authentication method "
3954 			    "configured.\n"));
3955 			(void) fprintf(stderr,
3956 			    gettext("Provide a legal authentication method "
3957 			    "using -a option\n"));
3958 			exit(1);
3959 		}
3960 
3961 		/* Use the first authentication method which is not none */
3962 		for (app = authpp; *app; app++) {
3963 			authp = *app;
3964 			if (authp->type != NS_LDAP_AUTH_NONE) {
3965 				authstried++;
3966 				authority.auth.type = authp->type;
3967 				authority.auth.tlstype = authp->tlstype;
3968 				authority.auth.saslmech = authp->saslmech;
3969 				authority.auth.saslopt = authp->saslopt;
3970 				break;
3971 			}
3972 		}
3973 		if (authstried == 0 && op != OP_DUMP) {
3974 			(void) fprintf(stderr,
3975 			gettext("No legal authentication method configured.\n"
3976 				"Provide a legal authentication method using "
3977 				"-a option"));
3978 			exit(1);
3979 		}
3980 	}
3981 
3982 	ttype = argv[optind++];
3983 
3984 	if (ttype == NULL) {
3985 		usage(gettext("No database type specified"));
3986 		exit(1);
3987 	}
3988 
3989 	if (strncasecmp(ttype, "automount", 9) == 0) {
3990 		(void) fprintf(stderr,
3991 		    gettext("automount is not a valid service for ldapaddent.\n"
3992 		    "Please use auto_*.\n"
3993 		    "e.g.  auto_home, auto_ws etc.\n "));
3994 		exit(1);
3995 	}
3996 
3997 	for (tt = ttypelist; tt->ttype; tt++) {
3998 		if (strcmp(tt->ttype, ttype) == 0)
3999 			break;
4000 		if (strcmp(tt->ttype, NS_LDAP_TYPE_AUTOMOUNT) == 0 &&
4001 		    strncmp(ttype, NS_LDAP_TYPE_AUTOMOUNT,
4002 		    sizeof (NS_LDAP_TYPE_AUTOMOUNT) - 1) == 0)
4003 			break;
4004 	}
4005 
4006 	if (tt->ttype == 0) {
4007 		(void) fprintf(stderr,
4008 		    gettext("database %s not supported;"
4009 		    " supported databases are:\n"), ttype);
4010 		for (tt = ttypelist; tt->ttype; tt++)
4011 			(void) fprintf(stderr, gettext("\t%s\n"), tt->ttype);
4012 		exit(1);
4013 	}
4014 
4015 	if (flags & F_VERBOSE)
4016 		(void) fprintf(stdout, gettext("SERVICE = %s\n"), tt->ttype);
4017 
4018 	databasetype = ttype;
4019 
4020 	if (strcmp(tt->ttype, NS_LDAP_TYPE_AUTOMOUNT) == 0) {
4021 		paramVal = NULL;
4022 		errorp = NULL;
4023 		rc = __ns_ldap_getParam(NS_LDAP_FILE_VERSION_P, &paramVal,
4024 			&errorp);
4025 		if (paramVal && *paramVal &&
4026 			strcasecmp(*paramVal, NS_LDAP_VERSION_1) == 0)
4027 			version1 = 1;
4028 		if (paramVal)
4029 			(void) __ns_ldap_freeParam(&paramVal);
4030 		if (errorp)
4031 			(void) __ns_ldap_freeError(&errorp);
4032 	}
4033 
4034 	/* Check if the container exists in first place */
4035 	(void) strcpy(&filter[0], "(objectclass=*)");
4036 
4037 	rc = __ns_ldap_list(databasetype, filter, NULL, (const char **)NULL,
4038 	    NULL, NS_LDAP_SCOPE_BASE, &resultp, &errorp, NULL, NULL);
4039 
4040 	/* create a container for auto_* if it does not exist already */
4041 	if ((rc == NS_LDAP_NOTFOUND) && (op == OP_ADD) &&
4042 	    (strcmp(tt->ttype, NS_LDAP_TYPE_AUTOMOUNT) == 0)) {
4043 		static	char *oclist[] = {NULL, "top", NULL};
4044 		if (version1)
4045 			oclist[0] = "nisMap";
4046 		else
4047 			oclist[0] = "automountMap";
4048 		e = __s_mk_entry(oclist, 3);
4049 		if (e == NULL) {
4050 			(void) fprintf(stderr,
4051 			    gettext("internal memory allocation error.\n"));
4052 			exit(1);
4053 		}
4054 		if (__s_add_attr(e,
4055 		    version1 ? "nisMapName" : "automountMapName",
4056 		    databasetype) != NS_LDAP_SUCCESS) {
4057 			(void) fprintf(stderr,
4058 			    gettext("internal memory allocation error.\n"));
4059 			ldap_freeEntry(e);
4060 			exit(1);
4061 		}
4062 
4063 		if (inputbasedn == NULL) {
4064 			if (get_basedn(databasetype, &inputbasedn) !=
4065 			    NS_LDAP_SUCCESS) {
4066 				(void) fprintf(stderr,
4067 				    gettext("Could not obtain basedn\n"));
4068 				ldap_freeEntry(e);
4069 				exit(1);
4070 			}
4071 		}
4072 		if (__ns_ldap_addEntry(databasetype, inputbasedn, e,
4073 		    &authority, flag, &errorp) != NS_LDAP_SUCCESS) {
4074 			(void) fprintf(stderr,
4075 			    gettext("Could not create container for %s\n"),
4076 			    databasetype);
4077 			ldap_freeEntry(e);
4078 		}
4079 	} else if (strcmp(databasetype, "publickey") != 0) {
4080 		if (rc == NS_LDAP_NOTFOUND) {
4081 			(void) fprintf(stderr,
4082 			    gettext("Container %s does not exist\n"),
4083 			    databasetype);
4084 			exit(1);
4085 		}
4086 	}
4087 
4088 	if (op == OP_DUMP) {
4089 		if (strcmp(databasetype, "publickey") == 0) {
4090 			dumptable("hosts");
4091 			dumptable("passwd");
4092 		} else {
4093 			dumptable(databasetype);
4094 		}
4095 		exit(exit_val);
4096 	}
4097 
4098 	if (etcfile) {
4099 		if ((etcf = fopen(etcfile, "r")) == 0) {
4100 			(void) fprintf(stderr,
4101 			    gettext("can't open file %s\n"), etcfile);
4102 			exit(1);
4103 		}
4104 	} else {
4105 		etcfile = "stdin";
4106 		etcf = stdin;
4107 	}
4108 
4109 	if (op == OP_ADD) {
4110 		(void) addfile();
4111 		(void) fprintf(stdout, gettext("%d entries added\n"), nent_add);
4112 	}
4113 
4114 	/* exit() -> return for make lint */
4115 	return (exit_val);
4116 }
4117 
4118 
4119 /*
4120  * This is called when service == auto_*.
4121  * It calls __ns_ldap_getSearchDescriptors
4122  * to generate the dn from SSD's base dn.
4123  * If there is no SSD available,
4124  * default base dn will be used
4125  * Only the first baseDN in the SSD is used
4126  */
4127 
4128 static int get_basedn(char *service, char **basedn) {
4129 	int rc = NS_LDAP_SUCCESS;
4130 	char *dn = NULL;
4131 	ns_ldap_search_desc_t **desc = NULL;
4132 	ns_ldap_error_t *errp = NULL;
4133 	void		**paramVal = NULL;
4134 	int		prepend_automountmapname = FALSE;
4135 
4136 	/*
4137 	 * Get auto_* SSD first
4138 	 */
4139 
4140 	if ((rc = __ns_ldap_getSearchDescriptors(
4141 			(const char *) service,
4142 			&desc, &errp))  == NS_LDAP_SUCCESS &&
4143 		desc != NULL) {
4144 
4145 		if (desc[0] != NULL && desc[0]->basedn != NULL) {
4146 			dn = strdup(desc[0]->basedn);
4147 			if (dn == NULL) {
4148 				(void) __ns_ldap_freeSearchDescriptors
4149 						(&desc);
4150 				return (NS_LDAP_MEMORY);
4151 			}
4152 		}
4153 	}
4154 
4155 	/* clean up */
4156 	if (desc) (void) __ns_ldap_freeSearchDescriptors(&desc);
4157 	if (errp) (void) __ns_ldap_freeError(&errp);
4158 
4159 	/*
4160 	 * If no dn is duplicated from auto_* SSD, try automount SSD
4161 	 */
4162 	if (dn == NULL) {
4163 		if ((rc = __ns_ldap_getSearchDescriptors(
4164 				"automount", &desc, &errp))
4165 				== NS_LDAP_SUCCESS && desc != NULL) {
4166 
4167 			if (desc[0] != NULL && desc[0]->basedn != NULL) {
4168 				dn = strdup(desc[0]->basedn);
4169 				if (dn == NULL) {
4170 					(void) __ns_ldap_freeSearchDescriptors
4171 							(&desc);
4172 					return (NS_LDAP_MEMORY);
4173 				}
4174 				prepend_automountmapname = TRUE;
4175 			}
4176 		}
4177 		/* clean up */
4178 		if (desc) (void) __ns_ldap_freeSearchDescriptors(&desc);
4179 		if (errp) (void) __ns_ldap_freeError(&errp);
4180 	}
4181 
4182 	/*
4183 	 * If no dn is duplicated from auto_* or automount SSD,
4184 	 * use default DN
4185 	 */
4186 
4187 	if (dn == NULL) {
4188 		if ((rc = __ns_ldap_getParam(NS_LDAP_SEARCH_BASEDN_P,
4189 			&paramVal, &errp)) == NS_LDAP_SUCCESS) {
4190 			dn = strdup((char *)paramVal[0]);
4191 			if (dn == NULL) {
4192 				(void) __ns_ldap_freeParam(&paramVal);
4193 				return (NS_LDAP_MEMORY);
4194 			}
4195 			prepend_automountmapname = TRUE;
4196 		}
4197 		if (paramVal) (void) __ns_ldap_freeParam(&paramVal);
4198 		if (errp) (void) __ns_ldap_freeError(&errp);
4199 	}
4200 
4201 
4202 	if (dn == NULL) {
4203 		return (NS_LDAP_OP_FAILED);
4204 	} else {
4205 		/*
4206 		 * If dn is duplicated from
4207 		 * automount SSD basedn or
4208 		 * default base dn
4209 		 * then prepend automountMapName=auto_xxx
4210 		 */
4211 		if (prepend_automountmapname)
4212 			rc = __s_api_prepend_automountmapname_to_dn(
4213 				service, &dn, &errp);
4214 
4215 		if (rc != NS_LDAP_SUCCESS) {
4216 			(void) __ns_ldap_freeError(&errp);
4217 			free(dn);
4218 			return (rc);
4219 		}
4220 
4221 		*basedn = dn;
4222 
4223 		return (NS_LDAP_SUCCESS);
4224 	}
4225 }
4226