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