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