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