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