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