nis_names.c revision e8031f0a8ed0e45c6d8847c5e09424e66fd34a4b
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include "mt.h"
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <malloc.h>
#include "nis_local.h"
#ifdef ORGDIR
#endif
/* Counts and returns the number of dots in the given string. */
static int
dots_in_name(char *name)
{
int i, ndots;
#ifdef QUOTES
int in_quotes = 0;
/* Commented out the quoted quotes stuff for 1202807 */
#endif
#ifdef QUOTES
/* Commented out the quoted quotes stuff for 1202807 */
/* Entering a quotation? */
if (name[i] == '"') {
/* No. This is "", i.e. a quoted quote */
i++; /* skip the next quote, else will */
continue; /* think it's only one quote */
} else {
/* Entering quotes. Ignore all dots in here. */
}
}
/* If not in quotes, then increment counter */
#endif
/* Increment counter */
if (name[i] == '.')
++ndots;
}
return (ndots);
}
/*
* parse_default()
*
* This function takes the default domain and creates a possible set of
* candidate names from it. (similar to the DNS server)
*/
static int
int rmax) /* max array value */
{
int comps = 0; /* # of new components */
/* There is a trailing dot, we're done */
if (!temp)
return (0); /* out-of-memory or something */
return (comps); /* return how many we made */
}
if (!dom)
return (0); /* out-of-memory or something */
/*
* The main reason for the following if statement is to make an
* intelligent "guess" as to what the user/application intended
* as the fully-qualified (FQ) object pathname, given a partially-
* qualified (PQ) one. If there is a successful search found, a
* single entry, result[0], is initialized with that object name
* before proceeding with the normal method of creating names by
* continuously stripping off parts of the domain name until we've
* exhausted all possibilities. If there is no resulting "guess,"
* the program proceeds as normal.
*
* If 'name' is not a substring of domain, then keep stripping off
* the labels to check for substrings of the domain. If we've
* reached the end with no matches, that's okay, we just proceed
* as normal down below, otherwise, if there is a match, then make
* the assign to the first result what we think the user intended
* as the valid object. Proceed as normal below.
*
* Examples: PQ OBJ (dynam) DOMAIN NAME (static) ACTION
* -------------- -------------------- ------
* 1) org_dir.foo foo.bar.sun.com. (continue)
* foo " (done)
* (name is a substring of domainname, so
* guess is org_dir.foo.bar.sun.com.)
*
* 2) x.foo.eng foo.bar.sun.com. (continue)
* foo.eng " (done)
* (guess is x.foo.bar.sun.com.)
*
* 3) hosts foo.bar.sun.com. (continue)
* " (done)
* (reached end of name, no guess)
*/
/*
* Don't go past end of 'name'! The rest of this
* routine incrementally takes labels from 'name'
* and stores them in a buffer until what remains
* of name is a substring of the domain name.
*
* 'tmpnam' is the temporary name pointer, and the
* condition in the while statement checks whether
* the address has passed the end of 'name'.
*/
/* save first label */
sizeof (buf)) {
return (0);
}
return (0);
}
/* strip first label from rest of name */
break;
/* if there's a '.' skip past it for next label */
if (*tmpnam == '.')
tmpnam++;
/* reached end without a dot, i.e. "hosts" */
if (*tmpnam == '\0')
break;
/*
* If remainder is a substring of domain, break out.
* Move the domain pointer up to just past where the
* match from 'name' ends, and copy all of what
* matches into 'name'.
*
* Example: (see example 1 in comments above)
*
* buf = org_dir
* tmpnam = foo ('org_dir' stripped off to buf)
* tmpdom = foo.bar.sun.com.
* ^
* mkr
*
* We check to make sure that 'mkr' points to a
* '.', otherwise, the match isn't correct, i.e.
* "foo" is not a label of "foo500" though
* it's a substring, hence not-a-match here.
*/
char *temp; /* very temporary */
/* add label: buf = buf + tmpnam */
sizeof (buf)) {
return (0);
}
/* replace name: name = buf */
/* add domain: buf = name + tmpdom */
return (0);
}
/* write guess: result[0] = buf */
if (!temp) {
return (0); /* out-of-memory */
}
break;
}
}
} else {
/*
* If 'name' is a proper substring of the current domain name,
* chop off the entire name from the domain name up to the point
* where they do not match. Store the item as the first result.
*
* Ex: PQ OBJ (static) DOMAIN NAME (dynamic) ACTION
* --------------- --------------------- ------
* foo.bar.sun foo.bar.sun.com. (continue)
* com. (done)
* (guess is foo.bar.sun.com.)
*/
/*
* Assign this one only if we've actually moved up the tmpdom
* past the match *and* that the tail part of name was really
* a label, i.e. "eng", instead of a substring, "en". If it
* was really a label, then the next character would be a '.'.
*/
if (*tmpdom == '.') {
char *temp; /* very temporary */
sizeof (buf)) {
return (0);
}
if (!temp) {
return (0); /* out-of-memory or something */
}
}
}
/* build the list */
/* bail if domain name has less than 2 labels */
break;
/* put (name + '.' + domain name) together */
sizeof (buf)) {
return (0);
}
/* bail if total name has less than 3 labels */
break;
/* assign slot if it doesn't match the first elmt */
comps--;
} else {
if (!temp) {
return (0); /* out-of-memory or something */
}
}
/* out of memory or something */
break;
/* truncate prefix domain, return rest with '.' in front */
/* skip past the "." in the new domain name */
if (*dom == '.')
dom++;
}
return (comps); /* return how many we made */
}
/*
* __nis_parse_path()
*
* This function consumes "path" and parses it into a list of
* names. Pointers to those names are stored in the array of nis_names
* passed as 'list'. 'max' is the length of the array 'list'.
*
* It malloc's no memory, it only uses the array passed and the string
* in path.
*/
int
{
char *s;
int cur;
/* parse a colon separated list into individual table names */
/* walk through s until EOS or ':' */
while ((*s != ':') && (*s != '\0')) {
s++;
#ifdef QUOTES
/* Commented out the quoted quotes stuff for 1202807 */
if (*s == '"') {
if (*(s+1) == '"') { /* escaped quote */
s += 2;
} else {
/* skip quoted string */
s++;
while (1) {
if (*s == '\0')
break;
/* embedded quote quote */
if ((*s == '"') &&
(*(s+1) == '"')) {
s = s+2;
continue;
}
if (*s == '"')
break;
s++;
}
if (*s == '"')
s++;
}
} else
s++;
#endif
}
if (*s == ':') {
*s = '\0';
s++;
}
}
return (cur);
}
/*
* parse_path()
*
* This function returns the number of names it parsed out
* of the string.
*/
static int
{
/* parse a colon separated list into individual path names */
/* expand "special" names in the path based on $ and + */
/* if path element is just '$' by itself... */
break; /* finish early */
/* otherwise it's something like org_dir.$ or groups_dir.$ */
} else {
/* is last character a $? */
} else
/* force ending dot */
else
break; /* finish early */
break; /* finish early */
break; /* finish early */
}
}
return (cur);
}
#ifdef ORGDIR
/*
* This function will append "org_dir" to the standard tables
* if already not present ie standard table name is not preceded
* by ANY directory name.
*/
static void
{
int append = 0;
return;
switch (*p1) {
/* auto_* tables */
case 'a':
p1++;
append = 1;
break;
/* bootparams */
case 'b':
p1++;
append = 1;
break;
/* cred */
case 'c':
p1++;
append = 1;
break;
/* ethers */
case 'e':
p1++;
append = 1;
break;
/* group */
case 'g':
p1++;
append = 1;
break;
/* hosts */
case 'h':
p1++;
append = 1;
break;
case 'm':
p1++;
append = 1;
break;
/* netgroup, netmasks, networks */
case 'n':
p1++;
switch (*p1) {
case 'g':
p1++;
append = 1;
break;
case 'm':
p1++;
append = 1;
break;
case 'w':
p1++;
append = 1;
break;
}
}
break;
/* passwd, protocols */
case 'p':
p1++;
switch (*p1) {
case 'a':
p1++;
append = 1;
break;
case 'r':
p1++;
append = 1;
break;
}
break;
/* rpc */
case 'r':
p1++;
append = 1;
break;
/* services */
case 's':
p1++;
append = 1;
break;
/* timezone */
case 't':
p1++;
append = 1;
break;
}
if (append)
}
#endif
/*
* This function is called only when the NIS_PATH is set.
* It checks for org_dir.org_dir in the pathname. If "org_dir.org_dir"
* is present it either removes that entry from the name list(
* because if count > 1 there will be a duplicate entry)
* otherwise substitute org_dir in place of org_dir.org_dir.
* In case the count is 1 we cannot remove the entry, rather
* use substitution. This would happen if NIS_PATH = org_dir.$.
*/
static void
{
int i;
for (i = 0; i < count; i++) {
for (; i < count; i++) {
if (count > 1) {
} else {
p2++;
*p2 = 0;
}
}
}
}
}
/*
* __nis_getnames(nis_name name, nis_error *nis_err)
*
* This function extends the functionality as nis_getnames() to
* return the appropriate error in the case of failure. nis_err
* is undefined when a non-NULL value is returned.
*/
nis_name *
{
int i = 0;
char buf[NIS_MAXSRCHLEN];
if (!name) {
*nis_err = NIS_BADNAME;
return (NULL);
}
*nis_err = NIS_NOMEMORY;
return (NULL);
}
*nis_err = NIS_BADNAME;
return (NULL);
}
#ifdef ORGDIR
#endif
if (!path)
/* if can't get local_dir, no need to continue */
if (!(local = nis_local_directory())) {
*nis_err = NIS_NOMEMORY;
return (NULL);
}
/* parse the path into segments */
/* check case were name is "near" the root. */
if (i == 0) {
*nis_err = NIS_BADNAME;
return (NULL);
}
*nis_err = NIS_BADNAME;
return (NULL);
}
}
/* only if NIS_PATH is set */
if (tmp_path)
check_dup_dnames(result, i);
} else {
/* the simple case for a fully-qualified path */
if (!result) {
*nis_err = NIS_NOMEMORY;
return (NULL);
}
}
*nis_err = NIS_SUCCESS;
return (result);
}
/*
* nis_getnames(name, nis_error *nis_err)
*
* This function returns a list of candidate NIS+ names given an
* non fully qualified NIS name. Note it is HOST RFC compliant
* in that it stops generating names when the resulting name would
* have 2 or fewer dots in it. This helps avoid banging on the root
* name servers.
*/
nis_name *
{
}
/* free an entire list, one at a time */
void
{
int i = 0;
while (namelist[i])
}