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