map.c
上传用户:xu_441
上传日期:2007-01-04
资源大小:1640k
文件大小:144k
- (lmap->ldap_binddn == NULL ? 0 : strlen(lmap->ldap_binddn)) +
- 1 +
- (lmap->ldap_secret == NULL ? 0 : strlen(lmap->ldap_secret)) +
- 1;
- nbuf = xalloc(len);
- snprintf(nbuf, len, "%s%c%d%c%s%c%s",
- (lmap->ldap_host == NULL ? "localhost" : lmap->ldap_host),
- CONDELSE,
- lmap->ldap_port,
- CONDELSE,
- (lmap->ldap_binddn == NULL ? "" : lmap->ldap_binddn),
- CONDELSE,
- (lmap->ldap_secret == NULL ? "" : lmap->ldap_secret));
- s = stab(nbuf, ST_LDAP, ST_ENTER);
- free(nbuf);
- return s;
- }
- /*
- ** LDAPMAP_SETOPTS -- set LDAP options
- **
- ** Parameters:
- ** ld -- LDAP session handle
- ** lmap -- LDAP map information
- **
- ** Returns:
- ** None.
- **
- */
- static void
- ldapmap_setopts(ld, lmap)
- LDAP *ld;
- LDAPMAP_STRUCT *lmap;
- {
- # if USE_LDAP_SET_OPTION
- ldap_set_option(ld, LDAP_OPT_DEREF, &lmap->ldap_deref);
- if (bitset(LDAP_OPT_REFERRALS, lmap->ldap_options))
- ldap_set_option(ld, LDAP_OPT_REFERRALS, LDAP_OPT_ON);
- else
- ldap_set_option(ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF);
- ldap_set_option(ld, LDAP_OPT_SIZELIMIT, &lmap->ldap_sizelimit);
- ldap_set_option(ld, LDAP_OPT_TIMELIMIT, &lmap->ldap_timelimit);
- # else /* USE_LDAP_SET_OPTION */
- /* From here on in we can use ldap internal timelimits */
- ld->ld_deref = lmap->ldap_deref;
- ld->ld_options = lmap->ldap_options;
- ld->ld_sizelimit = lmap->ldap_sizelimit;
- ld->ld_timelimit = lmap->ldap_timelimit;
- # endif /* USE_LDAP_SET_OPTION */
- }
- /*
- ** LDAPMAP_GETERRNO -- get ldap errno value
- **
- ** Parameters:
- ** ld -- LDAP session handle
- **
- ** Returns:
- ** LDAP errno.
- **
- */
- static int
- ldapmap_geterrno(ld)
- LDAP *ld;
- {
- int err = LDAP_SUCCESS;
- # if defined(LDAP_VERSION_MAX) && LDAP_VERSION_MAX >= 3
- (void) ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &err);
- # else /* defined(LDAP_VERSION_MAX) && LDAP_VERSION_MAX >= 3 */
- # ifdef LDAP_OPT_SIZELIMIT
- err = ldap_get_lderrno(ld, NULL, NULL);
- # else /* LDAP_OPT_SIZELIMIT */
- err = ld->ld_errno;
- /*
- ** Reset value to prevent lingering LDAP_DECODING_ERROR due to
- ** OpenLDAP 1.X's hack (see above)
- */
- ld->ld_errno = LDAP_SUCCESS;
- # endif /* LDAP_OPT_SIZELIMIT */
- # endif /* defined(LDAP_VERSION_MAX) && LDAP_VERSION_MAX >= 3 */
- return err;
- }
- /*
- ** LDAPX_MAP_PARSEARGS -- print warning about use of ldapx map.
- */
- bool
- ldapx_map_parseargs(map, args)
- MAP *map;
- char *args;
- {
- printf("Warning: The "ldapx" map class is deprecated and will be removed in a futuren");
- printf(" version. Use the "ldap" map class instead for map "%s".n",
- map->map_mname);
- return ldapmap_parseargs(map, args);
- }
- /*
- ** LDAPMAP_PARSEARGS -- parse ldap map definition args.
- */
- struct lamvalues LDAPAuthMethods[] =
- {
- { "none", LDAP_AUTH_NONE },
- { "simple", LDAP_AUTH_SIMPLE },
- { "krbv4", LDAP_AUTH_KRBV4 },
- { NULL, 0 }
- };
- struct ladvalues LDAPAliasDereference[] =
- {
- { "never", LDAP_DEREF_NEVER },
- { "always", LDAP_DEREF_ALWAYS },
- { "search", LDAP_DEREF_SEARCHING },
- { "find", LDAP_DEREF_FINDING },
- { NULL, 0 }
- };
- struct lssvalues LDAPSearchScope[] =
- {
- { "base", LDAP_SCOPE_BASE },
- { "one", LDAP_SCOPE_ONELEVEL },
- { "sub", LDAP_SCOPE_SUBTREE },
- { NULL, 0 }
- };
- bool
- ldapmap_parseargs(map, args)
- MAP *map;
- char *args;
- {
- bool secretread = TRUE;
- int i;
- register char *p = args;
- LDAPMAP_STRUCT *lmap;
- struct lamvalues *lam;
- struct ladvalues *lad;
- struct lssvalues *lss;
- char m_tmp[MAXPATHLEN + LDAPMAP_MAX_PASSWD];
- /* Get ldap struct pointer from map */
- lmap = (LDAPMAP_STRUCT *) map->map_db1;
- /* Check if setting the initial LDAP defaults */
- if (lmap == NULL || lmap != LDAPDefaults)
- {
- /* We need to alloc an LDAPMAP_STRUCT struct */
- lmap = (LDAPMAP_STRUCT *) xalloc(sizeof *lmap);
- if (LDAPDefaults == NULL)
- ldapmap_clear(lmap);
- else
- STRUCTCOPY(*LDAPDefaults, *lmap);
- }
- /* there is no check whether there is really an argument */
- map->map_mflags |= MF_TRY0NULL|MF_TRY1NULL;
- map->map_spacesub = SpaceSub; /* default value */
- for (;;)
- {
- while (isascii(*p) && isspace(*p))
- p++;
- if (*p != '-')
- break;
- switch (*++p)
- {
- case 'N':
- map->map_mflags |= MF_INCLNULL;
- map->map_mflags &= ~MF_TRY0NULL;
- break;
- case 'O':
- map->map_mflags &= ~MF_TRY1NULL;
- break;
- case 'o':
- map->map_mflags |= MF_OPTIONAL;
- break;
- case 'f':
- map->map_mflags |= MF_NOFOLDCASE;
- break;
- case 'm':
- map->map_mflags |= MF_MATCHONLY;
- break;
- case 'A':
- map->map_mflags |= MF_APPEND;
- break;
- case 'q':
- map->map_mflags |= MF_KEEPQUOTES;
- break;
- case 'a':
- map->map_app = ++p;
- break;
- case 'T':
- map->map_tapp = ++p;
- break;
- case 't':
- map->map_mflags |= MF_NODEFER;
- break;
- case 'S':
- map->map_spacesub = *++p;
- break;
- case 'D':
- map->map_mflags |= MF_DEFER;
- break;
- case 'z':
- if (*++p != '\')
- map->map_coldelim = *p;
- else
- {
- switch (*++p)
- {
- case 'n':
- map->map_coldelim = 'n';
- break;
- case 't':
- map->map_coldelim = 't';
- break;
- default:
- map->map_coldelim = '\';
- }
- }
- break;
- /* Start of ldapmap specific args */
- case 'k': /* search field */
- while (isascii(*++p) && isspace(*p))
- continue;
- lmap->ldap_filter = p;
- break;
- case 'v': /* attr to return */
- while (isascii(*++p) && isspace(*p))
- continue;
- lmap->ldap_attr[0] = p;
- lmap->ldap_attr[1] = NULL;
- break;
- case '1':
- map->map_mflags |= MF_SINGLEMATCH;
- break;
- /* args stolen from ldapsearch.c */
- case 'R': /* don't auto chase referrals */
- # ifdef LDAP_REFERRALS
- lmap->ldap_options &= ~LDAP_OPT_REFERRALS;
- # else /* LDAP_REFERRALS */
- syserr("compile with -DLDAP_REFERRALS for referral supportn");
- # endif /* LDAP_REFERRALS */
- break;
- case 'n': /* retrieve attribute names only */
- lmap->ldap_attrsonly = LDAPMAP_TRUE;
- break;
- case 'r': /* alias dereferencing */
- while (isascii(*++p) && isspace(*p))
- continue;
- if (strncasecmp(p, "LDAP_DEREF_", 11) == 0)
- p += 11;
- for (lad = LDAPAliasDereference;
- lad != NULL && lad->lad_name != NULL; lad++)
- {
- if (strncasecmp(p, lad->lad_name,
- strlen(lad->lad_name)) == 0)
- break;
- }
- if (lad->lad_name != NULL)
- lmap->ldap_deref = lad->lad_code;
- else
- {
- /* bad config line */
- if (!bitset(MCF_OPTFILE,
- map->map_class->map_cflags))
- {
- char *ptr;
- if ((ptr = strchr(p, ' ')) != NULL)
- *ptr = ' ';
- syserr("Deref must be [never|always|search|find] not %s in map %s",
- p, map->map_mname);
- if (ptr != NULL)
- *ptr = ' ';
- return FALSE;
- }
- }
- break;
- case 's': /* search scope */
- while (isascii(*++p) && isspace(*p))
- continue;
- if (strncasecmp(p, "LDAP_SCOPE_", 11) == 0)
- p += 11;
- for (lss = LDAPSearchScope;
- lss != NULL && lss->lss_name != NULL; lss++)
- {
- if (strncasecmp(p, lss->lss_name,
- strlen(lss->lss_name)) == 0)
- break;
- }
- if (lss->lss_name != NULL)
- lmap->ldap_scope = lss->lss_code;
- else
- {
- /* bad config line */
- if (!bitset(MCF_OPTFILE,
- map->map_class->map_cflags))
- {
- char *ptr;
- if ((ptr = strchr(p, ' ')) != NULL)
- *ptr = ' ';
- syserr("Scope must be [base|one|sub] not %s in map %s",
- p, map->map_mname);
- if (ptr != NULL)
- *ptr = ' ';
- return FALSE;
- }
- }
- break;
- case 'h': /* ldap host */
- while (isascii(*++p) && isspace(*p))
- continue;
- lmap->ldap_host = p;
- break;
- case 'b': /* search base */
- while (isascii(*++p) && isspace(*p))
- continue;
- lmap->ldap_base = p;
- break;
- case 'p': /* ldap port */
- while (isascii(*++p) && isspace(*p))
- continue;
- lmap->ldap_port = atoi(p);
- break;
- case 'l': /* time limit */
- while (isascii(*++p) && isspace(*p))
- continue;
- lmap->ldap_timelimit = atoi(p);
- lmap->ldap_timeout.tv_sec = lmap->ldap_timelimit;
- break;
- case 'Z':
- while (isascii(*++p) && isspace(*p))
- continue;
- lmap->ldap_sizelimit = atoi(p);
- break;
- case 'd': /* Dn to bind to server as */
- while (isascii(*++p) && isspace(*p))
- continue;
- lmap->ldap_binddn = p;
- break;
- case 'M': /* Method for binding */
- while (isascii(*++p) && isspace(*p))
- continue;
- if (strncasecmp(p, "LDAP_AUTH_", 10) == 0)
- p += 10;
- for (lam = LDAPAuthMethods;
- lam != NULL && lam->lam_name != NULL; lam++)
- {
- if (strncasecmp(p, lam->lam_name,
- strlen(lam->lam_name)) == 0)
- break;
- }
- if (lam->lam_name != NULL)
- lmap->ldap_method = lam->lam_code;
- else
- {
- /* bad config line */
- if (!bitset(MCF_OPTFILE,
- map->map_class->map_cflags))
- {
- char *ptr;
- if ((ptr = strchr(p, ' ')) != NULL)
- *ptr = ' ';
- syserr("Method for binding must be [none|simple|krbv4] not %s in map %s",
- p, map->map_mname);
- if (ptr != NULL)
- *ptr = ' ';
- return FALSE;
- }
- }
- break;
- /*
- ** This is a string that is dependent on the
- ** method used defined above.
- */
- case 'P': /* Secret password for binding */
- while (isascii(*++p) && isspace(*p))
- continue;
- lmap->ldap_secret = p;
- secretread = FALSE;
- break;
- default:
- syserr("Illegal option %c map %s", *p, map->map_mname);
- break;
- }
- /* need to account for quoted strings here */
- while (*p != ' ' && !(isascii(*p) && isspace(*p)))
- {
- if (*p == '"')
- {
- while (*++p != '"' && *p != ' ')
- continue;
- if (*p != ' ')
- p++;
- }
- else
- p++;
- }
- if (*p != ' ')
- *p++ = ' ';
- }
- if (map->map_app != NULL)
- map->map_app = newstr(ldapmap_dequote(map->map_app));
- if (map->map_tapp != NULL)
- map->map_tapp = newstr(ldapmap_dequote(map->map_tapp));
- /*
- ** We need to swallow up all the stuff into a struct
- ** and dump it into map->map_dbptr1
- */
- if (lmap->ldap_host != NULL)
- lmap->ldap_host = newstr(ldapmap_dequote(lmap->ldap_host));
- map->map_domain = lmap->ldap_host;
- if (lmap->ldap_binddn != NULL)
- lmap->ldap_binddn = newstr(ldapmap_dequote(lmap->ldap_binddn));
- if (lmap->ldap_secret != NULL)
- {
- FILE *sfd;
- long sff = SFF_OPENASROOT|SFF_ROOTOK|SFF_NOWLINK|SFF_NOWWFILES|SFF_NOGWFILES;
- if (DontLockReadFiles)
- sff |= SFF_NOLOCK;
- /* need to use method to map secret to passwd string */
- switch (lmap->ldap_method)
- {
- case LDAP_AUTH_NONE:
- /* Do nothing */
- break;
- case LDAP_AUTH_SIMPLE:
- /*
- ** Secret is the name of a file with
- ** the first line as the password.
- */
- /* Already read in the secret? */
- if (secretread)
- break;
- sfd = safefopen(ldapmap_dequote(lmap->ldap_secret),
- O_RDONLY, 0, sff);
- if (sfd == NULL)
- {
- syserr("LDAP map: cannot open secret %s",
- ldapmap_dequote(lmap->ldap_secret));
- return FALSE;
- }
- lmap->ldap_secret = sfgets(m_tmp, LDAPMAP_MAX_PASSWD,
- sfd, 0, "ldapmap_parseargs");
- (void) fclose(sfd);
- if (lmap->ldap_secret != NULL &&
- strlen(m_tmp) > 0)
- {
- /* chomp newline */
- if (m_tmp[strlen(m_tmp) - 1] == 'n')
- m_tmp[strlen(m_tmp) - 1] = ' ';
- lmap->ldap_secret = m_tmp;
- }
- break;
- case LDAP_AUTH_KRBV4:
- /*
- ** Secret is where the ticket file is
- ** stashed
- */
- snprintf(m_tmp, MAXPATHLEN + LDAPMAP_MAX_PASSWD,
- "KRBTKFILE=%s",
- ldapmap_dequote(lmap->ldap_secret));
- lmap->ldap_secret = m_tmp;
- break;
- default: /* Should NEVER get here */
- syserr("LDAP map: Illegal value in lmap method");
- return FALSE;
- break;
- }
- }
- if (lmap->ldap_secret != NULL)
- lmap->ldap_secret = newstr(ldapmap_dequote(lmap->ldap_secret));
- if (lmap->ldap_base != NULL)
- lmap->ldap_base = newstr(ldapmap_dequote(lmap->ldap_base));
- /*
- ** Save the server from extra work. If request is for a single
- ** match, tell the server to only return enough records to
- ** determine if there is a single match or not. This can not
- ** be one since the server would only return one and we wouldn't
- ** know if there were others available.
- */
- if (bitset(MF_SINGLEMATCH, map->map_mflags))
- lmap->ldap_sizelimit = 2;
- /* If setting defaults, don't process ldap_filter and ldap_attr */
- if (lmap == LDAPDefaults)
- return TRUE;
- if (lmap->ldap_filter != NULL)
- lmap->ldap_filter = newstr(ldapmap_dequote(lmap->ldap_filter));
- else
- {
- if (!bitset(MCF_OPTFILE, map->map_class->map_cflags))
- {
- syserr("No filter given in map %s", map->map_mname);
- return FALSE;
- }
- }
- if (lmap->ldap_attr[0] != NULL)
- {
- i = 0;
- p = lmap->ldap_attr[0];
- lmap->ldap_attr[0] = NULL;
- while (p != NULL)
- {
- char *v;
- while (isascii(*p) && isspace(*p))
- p++;
- if (*p == ' ')
- break;
- v = p;
- p = strchr(v, ',');
- if (p != NULL)
- *p++ = ' ';
- if (i == LDAPMAP_MAX_ATTR)
- {
- if (bitset(MCF_OPTFILE, map->map_class->map_cflags))
- {
- syserr("Too many return attributes in %s (max %d)",
- map->map_mname, LDAPMAP_MAX_ATTR);
- return FALSE;
- }
- else
- break;
- }
- if (*v != ' ')
- lmap->ldap_attr[i++] = newstr(v);
- }
- lmap->ldap_attr[i] = NULL;
- }
- map->map_db1 = (ARBPTR_T) lmap;
- return TRUE;
- }
- /*
- ** LDAPMAP_CLEAR -- set default values for LDAPMAP_STRUCT
- **
- ** Parameters:
- ** lmap -- pointer to LDAPMAP_STRUCT to clear
- **
- ** Returns:
- ** None.
- **
- */
- static void
- ldapmap_clear(lmap)
- LDAPMAP_STRUCT *lmap;
- {
- lmap->ldap_host = NULL;
- lmap->ldap_port = LDAP_PORT;
- lmap->ldap_deref = LDAP_DEREF_NEVER;
- lmap->ldap_timelimit = LDAP_NO_LIMIT;
- lmap->ldap_sizelimit = LDAP_NO_LIMIT;
- # ifdef LDAP_REFERRALS
- lmap->ldap_options = LDAP_OPT_REFERRALS;
- # else /* LDAP_REFERRALS */
- lmap->ldap_options = 0;
- # endif /* LDAP_REFERRALS */
- lmap->ldap_binddn = NULL;
- lmap->ldap_secret = NULL;
- lmap->ldap_method = LDAP_AUTH_SIMPLE;
- lmap->ldap_base = NULL;
- lmap->ldap_scope = LDAP_SCOPE_SUBTREE;
- lmap->ldap_attrsonly = LDAPMAP_FALSE;
- lmap->ldap_timeout.tv_sec = 0;
- lmap->ldap_timeout.tv_usec = 0;
- lmap->ldap_ld = NULL;
- lmap->ldap_filter = NULL;
- lmap->ldap_attr[0] = NULL;
- lmap->ldap_res = NULL;
- }
- /*
- ** LDAPMAP_SET_DEFAULTS -- Read default map spec from LDAPDefaults in .cf
- **
- ** Parameters:
- ** spec -- map argument string from LDAPDefaults option
- **
- ** Returns:
- ** None.
- **
- */
- void
- ldapmap_set_defaults(spec)
- char *spec;
- {
- MAP map;
- /* Allocate and set the default values */
- if (LDAPDefaults == NULL)
- LDAPDefaults = (LDAPMAP_STRUCT *) xalloc(sizeof *LDAPDefaults);
- ldapmap_clear(LDAPDefaults);
- memset(&map, ' ', sizeof map);
- map.map_db1 = (ARBPTR_T) LDAPDefaults;
- (void) ldapmap_parseargs(&map, spec);
- /* These should never be set in LDAPDefaults */
- if (map.map_mflags != (MF_TRY0NULL|MF_TRY1NULL) ||
- map.map_spacesub != SpaceSub ||
- map.map_app != NULL ||
- map.map_tapp != NULL)
- {
- syserr("readcf: option LDAPDefaultSpec: Do not set non-LDAP specific flags");
- if (map.map_app != NULL)
- {
- free(map.map_app);
- map.map_app = NULL;
- }
- if (map.map_tapp != NULL)
- {
- free(map.map_tapp);
- map.map_tapp = NULL;
- }
- }
- if (LDAPDefaults->ldap_filter != NULL)
- {
- syserr("readcf: option LDAPDefaultSpec: Do not set the LDAP search filter");
- /* don't free, it isn't malloc'ed in parseargs */
- LDAPDefaults->ldap_filter = NULL;
- }
- if (LDAPDefaults->ldap_attr[0] != NULL)
- {
- syserr("readcf: option LDAPDefaultSpec: Do not set the requested LDAP attributes");
- /* don't free, they aren't malloc'ed in parseargs */
- LDAPDefaults->ldap_attr[0] = NULL;
- }
- }
- #endif /* LDAPMAP */
- /*
- ** PH map
- */
- #ifdef PH_MAP
- /*
- ** Support for the CCSO Nameserver (ph/qi).
- ** This code is intended to replace the so-called "ph mailer".
- ** Contributed by Mark D. Roth <roth@uiuc.edu>. Contact him for support.
- */
- # include <qiapi.h>
- # include <qicode.h>
- /*
- ** PH_MAP_PARSEARGS -- parse ph map definition args.
- */
- bool
- ph_map_parseargs(map, args)
- MAP *map;
- char *args;
- {
- int i;
- register int done;
- PH_MAP_STRUCT *pmap = NULL;
- register char *p = args;
- pmap = (PH_MAP_STRUCT *) xalloc(sizeof *pmap);
- /* defaults */
- pmap->ph_servers = NULL;
- pmap->ph_field_list = NULL;
- pmap->ph_to_server = NULL;
- pmap->ph_from_server = NULL;
- pmap->ph_sockfd = -1;
- pmap->ph_timeout = 0;
- map->map_mflags |= MF_TRY0NULL|MF_TRY1NULL;
- for (;;)
- {
- while (isascii(*p) && isspace(*p))
- p++;
- if (*p != '-')
- break;
- switch (*++p)
- {
- case 'N':
- map->map_mflags |= MF_INCLNULL;
- map->map_mflags &= ~MF_TRY0NULL;
- break;
- case 'O':
- map->map_mflags &= ~MF_TRY1NULL;
- break;
- case 'o':
- map->map_mflags |= MF_OPTIONAL;
- break;
- case 'f':
- map->map_mflags |= MF_NOFOLDCASE;
- break;
- case 'm':
- map->map_mflags |= MF_MATCHONLY;
- break;
- case 'A':
- map->map_mflags |= MF_APPEND;
- break;
- case 'q':
- map->map_mflags |= MF_KEEPQUOTES;
- break;
- case 't':
- map->map_mflags |= MF_NODEFER;
- break;
- case 'a':
- map->map_app = ++p;
- break;
- case 'T':
- map->map_tapp = ++p;
- break;
- #if _FFR_PHMAP_TIMEOUT
- case 'l':
- while (isascii(*++p) && isspace(*p))
- continue;
- pmap->ph_timeout = atoi(p);
- break;
- #endif /* _FFR_PHMAP_TIMEOUT */
- case 'S':
- map->map_spacesub = *++p;
- break;
- case 'D':
- map->map_mflags |= MF_DEFER;
- break;
- case 'h': /* PH server list */
- while (isascii(*++p) && isspace(*p))
- continue;
- pmap->ph_servers = p;
- break;
- case 'v': /* fields to search for */
- while (isascii(*++p) && isspace(*p))
- continue;
- pmap->ph_field_list = p;
- break;
- default:
- syserr("ph_map_parseargs: unknown option -%cn", *p);
- }
- /* try to account for quoted strings */
- done = isascii(*p) && isspace(*p);
- while (*p != ' ' && !done)
- {
- if (*p == '"')
- {
- while (*++p != '"' && *p != ' ')
- continue;
- if (*p != ' ')
- p++;
- }
- else
- p++;
- done = isascii(*p) && isspace(*p);
- }
- if (*p != ' ')
- *p++ = ' ';
- }
- if (map->map_app != NULL)
- map->map_app = newstr(ph_map_dequote(map->map_app));
- if (map->map_tapp != NULL)
- map->map_tapp = newstr(ph_map_dequote(map->map_tapp));
- if (pmap->ph_field_list != NULL)
- pmap->ph_field_list = newstr(ph_map_dequote(pmap->ph_field_list));
- else
- pmap->ph_field_list = DEFAULT_PH_MAP_FIELDS;
- if (pmap->ph_servers != NULL)
- pmap->ph_servers = newstr(ph_map_dequote(pmap->ph_servers));
- else
- {
- syserr("ph_map_parseargs: -h flag is required");
- return FALSE;
- }
- map->map_db1 = (ARBPTR_T) pmap;
- return TRUE;
- }
- #if _FFR_PHMAP_TIMEOUT
- /*
- ** PH_MAP_CLOSE -- close the connection to the ph server
- */
- static void
- ph_map_safeclose(map)
- MAP *map;
- {
- int save_errno = errno;
- PH_MAP_STRUCT *pmap;
- pmap = (PH_MAP_STRUCT *)map->map_db1;
- if (pmap->ph_sockfd != -1)
- {
- (void) close(pmap->ph_sockfd);
- pmap->ph_sockfd = -1;
- }
- if (pmap->ph_from_server != NULL)
- {
- (void) fclose(pmap->ph_from_server);
- pmap->ph_from_server = NULL;
- }
- if (pmap->ph_to_server != NULL)
- {
- (void) fclose(pmap->ph_to_server);
- pmap->ph_to_server = NULL;
- }
- map->map_mflags &= ~(MF_OPEN|MF_WRITABLE);
- errno = save_errno;
- }
- void
- ph_map_close(map)
- MAP *map;
- {
- PH_MAP_STRUCT *pmap;
- pmap = (PH_MAP_STRUCT *)map->map_db1;
- (void) fprintf(pmap->ph_to_server, "quitn");
- (void) fflush(pmap->ph_to_server);
- ph_map_safeclose(map);
- }
- static jmp_buf PHTimeout;
- /* ARGSUSED */
- static void
- ph_timeout_func(sig_no)
- int sig_no;
- {
- longjmp(PHTimeout, 1);
- }
- #else /* _FFR_PHMAP_TIMEOUT */
- /*
- ** PH_MAP_CLOSE -- close the connection to the ph server
- */
- void
- ph_map_close(map)
- MAP *map;
- {
- PH_MAP_STRUCT *pmap;
- pmap = (PH_MAP_STRUCT *)map->map_db1;
- CloseQi(pmap->ph_to_server, pmap->ph_from_server);
- pmap->ph_to_server = NULL;
- pmap->ph_from_server = NULL;
- }
- #endif /* _FFR_PHMAP_TIMEOUT */
- /*
- ** PH_MAP_OPEN -- sub for opening PH map
- */
- bool
- ph_map_open(map, mode)
- MAP *map;
- int mode;
- {
- #if !_FFR_PHMAP_TIMEOUT
- int save_errno = 0;
- #endif /* !_FFR_PHMAP_TIMEOUT */
- int j;
- char *hostlist, *tmp;
- QIR *server_data = NULL;
- PH_MAP_STRUCT *pmap;
- #if _FFR_PHMAP_TIMEOUT
- register EVENT *ev = NULL;
- #endif /* _FFR_PHMAP_TIMEOUT */
- if (tTd(38, 2))
- dprintf("ph_map_open(%s)n", map->map_mname);
- mode &= O_ACCMODE;
- if (mode != O_RDONLY)
- {
- /* issue a pseudo-error message */
- # ifdef ENOSYS
- errno = ENOSYS;
- # else /* ENOSYS */
- # ifdef EFTYPE
- errno = EFTYPE;
- # else /* EFTYPE */
- errno = ENXIO;
- # endif /* EFTYPE */
- # endif /* ENOSYS */
- return FALSE;
- }
- pmap = (PH_MAP_STRUCT *)map->map_db1;
- hostlist = newstr(pmap->ph_servers);
- tmp = strtok(hostlist, " ");
- do {
- #if _FFR_PHMAP_TIMEOUT
- if (pmap->ph_timeout != 0)
- {
- if (setjmp(PHTimeout) != 0)
- {
- ev = NULL;
- if (LogLevel > 1)
- sm_syslog(LOG_NOTICE, CurEnv->e_id,
- "timeout connecting to PH server %.100s",
- tmp);
- # ifdef ETIMEDOUT
- errno = ETIMEDOUT;
- # else /* ETIMEDOUT */
- errno = 0;
- # endif /* ETIMEDOUT */
- goto ph_map_open_abort;
- }
- ev = setevent(pmap->ph_timeout, ph_timeout_func, 0);
- }
- if (!OpenQiSock(tmp, &(pmap->ph_sockfd)) &&
- !Sock2FILEs(pmap->ph_sockfd, &(pmap->ph_to_server),
- &(pmap->ph_from_server)) &&
- fprintf(pmap->ph_to_server, "id sendmail+phmapn") >= 0 &&
- fflush(pmap->ph_to_server) == 0 &&
- (server_data = ReadQi(pmap->ph_from_server, &j)) != NULL &&
- server_data->code == 200)
- {
- if (ev != NULL)
- clrevent(ev);
- FreeQIR(server_data);
- #else /* _FFR_PHMAP_TIMEOUT */
- if (OpenQi(tmp, &(pmap->ph_to_server),
- &(pmap->ph_from_server)) >= 0)
- {
- if (fprintf(pmap->ph_to_server,
- "id sendmail+phmapn") < 0 ||
- fflush(pmap->ph_to_server) < 0 ||
- (server_data = ReadQi(pmap->ph_from_server,
- &j)) == NULL ||
- server_data->code != 200)
- {
- save_errno = errno;
- CloseQi(pmap->ph_to_server,
- pmap->ph_from_server);
- continue;
- }
- if (server_data != NULL)
- free(server_data);
- #endif /* _FFR_PHMAP_TIMEOUT */
- free(hostlist);
- return TRUE;
- }
- #if _FFR_PHMAP_TIMEOUT
- ph_map_open_abort:
- if (ev != NULL)
- clrevent(ev);
- ph_map_safeclose(map);
- if (server_data != NULL)
- {
- FreeQIR(server_data);
- server_data = NULL;
- }
- #else /* _FFR_PHMAP_TIMEOUT */
- save_errno = errno;
- #endif /* _FFR_PHMAP_TIMEOUT */
- } while (tmp = strtok(NULL, " "));
- #if !_FFR_PHMAP_TIMEOUT
- errno = save_errno;
- #endif /* !_FFR_PHMAP_TIMEOUT */
- if (!bitset(MF_OPTIONAL, map->map_mflags))
- {
- if (errno == 0 && !bitset(MF_NODEFER,map->map_mflags))
- errno = EAGAIN;
- syserr("ph_map_open: cannot connect to PH server");
- }
- else if (LogLevel > 1)
- sm_syslog(LOG_NOTICE, CurEnv->e_id,
- "ph_map_open: cannot connect to PH server");
- free(hostlist);
- return FALSE;
- }
- /*
- ** PH_MAP_LOOKUP -- look up key from ph server
- */
- #if _FFR_PHMAP_TIMEOUT
- # define MAX_PH_FIELDS 20
- #endif /* _FFR_PHMAP_TIMEOUT */
- char *
- ph_map_lookup(map, key, args, pstat)
- MAP *map;
- char *key;
- char **args;
- int *pstat;
- {
- int j;
- size_t sz;
- char *tmp, *tmp2;
- char *message = NULL, *field = NULL, *fmtkey;
- QIR *server_data = NULL;
- char keybuf[MAXKEY + 1], fieldbuf[101];
- #if _FFR_PHMAP_TIMEOUT
- QIR *hold_data[MAX_PH_FIELDS];
- int hold_data_idx = 0;
- register EVENT *ev = NULL;
- #endif /* _FFR_PHMAP_TIMEOUT */
- PH_MAP_STRUCT *pmap;
- pmap = (PH_MAP_STRUCT *)map->map_db1;
- *pstat = EX_OK;
- #if _FFR_PHMAP_TIMEOUT
- if (pmap->ph_timeout != 0)
- {
- if (setjmp(PHTimeout) != 0)
- {
- ev = NULL;
- if (LogLevel > 1)
- sm_syslog(LOG_NOTICE, CurEnv->e_id,
- "timeout during PH lookup of %.100s",
- key);
- # ifdef ETIMEDOUT
- errno = ETIMEDOUT;
- # else /* ETIMEDOUT */
- errno = 0;
- # endif /* ETIMEDOUT */
- *pstat = EX_TEMPFAIL;
- goto ph_map_lookup_abort;
- }
- ev = setevent(pmap->ph_timeout, ph_timeout_func, 0);
- }
- #endif /* _FFR_PHMAP_TIMEOUT */
- /* check all relevant fields */
- tmp = pmap->ph_field_list;
- do {
- #if _FFR_PHMAP_TIMEOUT
- server_data = NULL;
- #endif /* _FFR_PHMAP_TIMEOUT */
- while (isascii(*tmp) && isspace(*tmp))
- tmp++;
- if (*tmp == ' ')
- break;
- sz = strcspn(tmp, " ") + 1;
- if (sz > sizeof fieldbuf)
- sz = sizeof fieldbuf;
- (void) strlcpy(fieldbuf, tmp, sz);
- field = fieldbuf;
- tmp += sz;
- (void) strlcpy(keybuf, key, sizeof keybuf);
- fmtkey = keybuf;
- if (strcmp(field, "alias") == 0)
- {
- /*
- ** for alias lookups, replace any punctuation
- ** characters with '-'
- */
- for (tmp2 = fmtkey; *tmp2 != ' '; tmp2++)
- {
- if (ispunct(*tmp2))
- *tmp2 = '-';
- }
- tmp2 = field;
- }
- else if (strcmp(field,"spacedname") == 0)
- {
- /*
- ** for "spaced" name lookups, replace any
- ** punctuation characters with a space
- */
- for (tmp2 = fmtkey; *tmp2 != ' '; tmp2++)
- if (ispunct(*tmp2) && *tmp2 != '*')
- *tmp2 = ' ';
- tmp2 = &(field[6]);
- }
- else
- tmp2 = field;
- if (LogLevel > 9)
- sm_syslog(LOG_NOTICE, CurEnv->e_id,
- "ph_map_lookup: query %s="%s" return email",
- tmp2, fmtkey);
- if (tTd(38, 20))
- dprintf("ph_map_lookup: query %s="%s" return emailn",
- tmp2, fmtkey);
- j = 0;
- if (fprintf(pmap->ph_to_server, "query %s=%s return emailn",
- tmp2, fmtkey) < 0)
- message = "qi query command failed";
- else if (fflush(pmap->ph_to_server) < 0)
- message = "qi fflush failed";
- else if ((server_data = ReadQi(pmap->ph_from_server,
- &j)) == NULL)
- message = "ReadQi() returned NULL";
- #if _FFR_PHMAP_TIMEOUT
- if ((hold_data[hold_data_idx] = server_data) != NULL)
- {
- /* save pointer for later free() */
- hold_data_idx++;
- }
- #endif /* _FFR_PHMAP_TIMEOUT */
- if (server_data == NULL ||
- (server_data->code >= 400 &&
- server_data->code < 500))
- {
- /* temporary failure */
- *pstat = EX_TEMPFAIL;
- #if _FFR_PHMAP_TIMEOUT
- break;
- #else /* _FFR_PHMAP_TIMEOUT */
- if (server_data != NULL)
- {
- free(server_data);
- server_data = NULL;
- }
- return NULL;
- #endif /* _FFR_PHMAP_TIMEOUT */
- }
- /*
- ** if we found a single match, break out.
- ** otherwise, try the next field.
- */
- if (j == 1)
- break;
- #if _FFR_PHMAP_TIMEOUT
- } while (*tmp != ' ' && hold_data_idx < MAX_PH_FIELDS);
- #else /* _FFR_PHMAP_TIMEOUT */
- } while (*tmp != ' ');
- #endif /* _FFR_PHMAP_TIMEOUT */
- #if _FFR_PHMAP_TIMEOUT
- ph_map_lookup_abort:
- if (ev != NULL)
- clrevent(ev);
- /*
- ** Return EX_TEMPFAIL if the timer popped
- ** or we got a temporary PH error
- */
- if (*pstat == EX_TEMPFAIL)
- ph_map_safeclose(map);
- /* if we didn't find a single match, bail out */
- if (*pstat == EX_OK && j != 1)
- *pstat = EX_UNAVAILABLE;
- if (*pstat == EX_OK)
- {
- if (tTd(38,20))
- dprintf("ph_map_lookup: %s => %sn",
- key, server_data->message);
- if (bitset(MF_MATCHONLY, map->map_mflags))
- message = map_rewrite(map, key, strlen(key), NULL);
- else
- message = map_rewrite(map, server_data->message,
- strlen(server_data->message),
- args);
- }
- /*
- ** Deferred free() of returned server_data values
- ** the deferral is to avoid the risk of a free() being
- ** interrupted by the event timer. By now the timeout event
- ** has been cleared and none of the data is still in use.
- */
- while (--hold_data_idx >= 0)
- {
- if (hold_data[hold_data_idx] != NULL)
- FreeQIR(hold_data[hold_data_idx]);
- }
- if (*pstat == EX_OK)
- return message;
- return NULL;
- #else /* _FFR_PHMAP_TIMEOUT */
- /* if we didn't find a single match, bail out */
- if (j != 1)
- {
- *pstat = EX_UNAVAILABLE;
- if (server_data != NULL)
- {
- free(server_data);
- server_data = NULL;
- }
- return NULL;
- }
- if (tTd(38,20))
- dprintf("ph_map_lookup: %s => %sn",
- key, server_data->message);
- if (bitset(MF_MATCHONLY, map->map_mflags))
- message = map_rewrite(map, key, strlen(key), NULL);
- else
- message = map_rewrite(map, server_data->message,
- strlen(server_data->message), args);
- if (server_data != NULL)
- {
- free(server_data);
- server_data = NULL;
- }
- return message;
- #endif /* _FFR_PHMAP_TIMEOUT */
- }
- #endif /* PH_MAP */
- /*
- ** syslog map
- */
- #define map_prio map_lockfd /* overload field */
- /*
- ** SYSLOG_MAP_PARSEARGS -- check for priority level to syslog messages.
- */
- bool
- syslog_map_parseargs(map, args)
- MAP *map;
- char *args;
- {
- char *p = args;
- char *priority = NULL;
- /* there is no check whether there is really an argument */
- while (*p != ' ')
- {
- while (isascii(*p) && isspace(*p))
- p++;
- if (*p != '-')
- break;
- ++p;
- if (*p == 'D')
- {
- map->map_mflags |= MF_DEFER;
- ++p;
- }
- else if (*p == 'S')
- {
- map->map_spacesub = *++p;
- if (*p != ' ')
- p++;
- }
- else if (*p == 'L')
- {
- while (*++p != ' ' && isascii(*p) && isspace(*p))
- continue;
- if (*p == ' ')
- break;
- priority = p;
- while (*p != ' ' && !(isascii(*p) && isspace(*p)))
- p++;
- if (*p != ' ')
- *p++ = ' ';
- }
- else
- {
- syserr("Illegal option %c map syslog", *p);
- ++p;
- }
- }
- if (priority == NULL)
- map->map_prio = LOG_INFO;
- else
- {
- if (strncasecmp("LOG_", priority, 4) == 0)
- priority += 4;
- #ifdef LOG_EMERG
- if (strcasecmp("EMERG", priority) == 0)
- map->map_prio = LOG_EMERG;
- else
- #endif /* LOG_EMERG */
- #ifdef LOG_ALERT
- if (strcasecmp("ALERT", priority) == 0)
- map->map_prio = LOG_ALERT;
- else
- #endif /* LOG_ALERT */
- #ifdef LOG_CRIT
- if (strcasecmp("CRIT", priority) == 0)
- map->map_prio = LOG_CRIT;
- else
- #endif /* LOG_CRIT */
- #ifdef LOG_ERR
- if (strcasecmp("ERR", priority) == 0)
- map->map_prio = LOG_ERR;
- else
- #endif /* LOG_ERR */
- #ifdef LOG_WARNING
- if (strcasecmp("WARNING", priority) == 0)
- map->map_prio = LOG_WARNING;
- else
- #endif /* LOG_WARNING */
- #ifdef LOG_NOTICE
- if (strcasecmp("NOTICE", priority) == 0)
- map->map_prio = LOG_NOTICE;
- else
- #endif /* LOG_NOTICE */
- #ifdef LOG_INFO
- if (strcasecmp("INFO", priority) == 0)
- map->map_prio = LOG_INFO;
- else
- #endif /* LOG_INFO */
- #ifdef LOG_DEBUG
- if (strcasecmp("DEBUG", priority) == 0)
- map->map_prio = LOG_DEBUG;
- else
- #endif /* LOG_DEBUG */
- {
- syserr("syslog_map_parseargs: Unknown priority %sn",
- priority);
- return FALSE;
- }
- }
- return TRUE;
- }
- /*
- ** SYSLOG_MAP_LOOKUP -- rewrite and syslog message. Always return empty string
- */
- char *
- syslog_map_lookup(map, string, args, statp)
- MAP *map;
- char *string;
- char **args;
- int *statp;
- {
- char *ptr = map_rewrite(map, string, strlen(string), args);
- if (ptr != NULL)
- {
- if (tTd(38, 20))
- dprintf("syslog_map_lookup(%s (priority %d): %sn",
- map->map_mname, map->map_prio, ptr);
- sm_syslog(map->map_prio, CurEnv->e_id, "%s", ptr);
- }
- *statp = EX_OK;
- return "";
- }
- /*
- ** HESIOD Modules
- */
- #ifdef HESIOD
- bool
- hes_map_open(map, mode)
- MAP *map;
- int mode;
- {
- if (tTd(38, 2))
- dprintf("hes_map_open(%s, %s, %d)n",
- map->map_mname, map->map_file, mode);
- if (mode != O_RDONLY)
- {
- /* issue a pseudo-error message */
- # ifdef ENOSYS
- errno = ENOSYS;
- # else /* ENOSYS */
- # ifdef EFTYPE
- errno = EFTYPE;
- # else /* EFTYPE */
- errno = ENXIO;
- # endif /* EFTYPE */
- # endif /* ENOSYS */
- return FALSE;
- }
- # ifdef HESIOD_INIT
- if (HesiodContext != NULL || hesiod_init(&HesiodContext) == 0)
- return TRUE;
- if (!bitset(MF_OPTIONAL, map->map_mflags))
- syserr("421 4.0.0 cannot initialize Hesiod map (%s)",
- errstring(errno));
- return FALSE;
- # else /* HESIOD_INIT */
- if (hes_error() == HES_ER_UNINIT)
- hes_init();
- switch (hes_error())
- {
- case HES_ER_OK:
- case HES_ER_NOTFOUND:
- return TRUE;
- }
- if (!bitset(MF_OPTIONAL, map->map_mflags))
- syserr("421 4.0.0 cannot initialize Hesiod map (%d)", hes_error());
- return FALSE;
- # endif /* HESIOD_INIT */
- }
- char *
- hes_map_lookup(map, name, av, statp)
- MAP *map;
- char *name;
- char **av;
- int *statp;
- {
- char **hp;
- if (tTd(38, 20))
- dprintf("hes_map_lookup(%s, %s)n", map->map_file, name);
- if (name[0] == '\')
- {
- char *np;
- int nl;
- char nbuf[MAXNAME];
- nl = strlen(name);
- if (nl < sizeof nbuf - 1)
- np = nbuf;
- else
- np = xalloc(strlen(name) + 2);
- np[0] = '\';
- (void) strlcpy(&np[1], name, (sizeof nbuf) - 1);
- # ifdef HESIOD_INIT
- hp = hesiod_resolve(HesiodContext, np, map->map_file);
- # else /* HESIOD_INIT */
- hp = hes_resolve(np, map->map_file);
- # endif /* HESIOD_INIT */
- if (np != nbuf)
- free(np);
- }
- else
- {
- # ifdef HESIOD_INIT
- hp = hesiod_resolve(HesiodContext, name, map->map_file);
- # else /* HESIOD_INIT */
- hp = hes_resolve(name, map->map_file);
- # endif /* HESIOD_INIT */
- }
- # ifdef HESIOD_INIT
- if (hp == NULL)
- return NULL;
- if (*hp == NULL)
- {
- hesiod_free_list(HesiodContext, hp);
- switch (errno)
- {
- case ENOENT:
- *statp = EX_NOTFOUND;
- break;
- case ECONNREFUSED:
- case EMSGSIZE:
- *statp = EX_TEMPFAIL;
- break;
- case ENOMEM:
- default:
- *statp = EX_UNAVAILABLE;
- break;
- }
- return NULL;
- }
- # else /* HESIOD_INIT */
- if (hp == NULL || hp[0] == NULL)
- {
- switch (hes_error())
- {
- case HES_ER_OK:
- *statp = EX_OK;
- break;
- case HES_ER_NOTFOUND:
- *statp = EX_NOTFOUND;
- break;
- case HES_ER_CONFIG:
- *statp = EX_UNAVAILABLE;
- break;
- case HES_ER_NET:
- *statp = EX_TEMPFAIL;
- break;
- }
- return NULL;
- }
- # endif /* HESIOD_INIT */
- if (bitset(MF_MATCHONLY, map->map_mflags))
- return map_rewrite(map, name, strlen(name), NULL);
- else
- return map_rewrite(map, hp[0], strlen(hp[0]), av);
- }
- #endif /* HESIOD */
- /*
- ** NeXT NETINFO Modules
- */
- #if NETINFO
- # define NETINFO_DEFAULT_DIR "/aliases"
- # define NETINFO_DEFAULT_PROPERTY "members"
- /*
- ** NI_MAP_OPEN -- open NetInfo Aliases
- */
- bool
- ni_map_open(map, mode)
- MAP *map;
- int mode;
- {
- if (tTd(38, 2))
- dprintf("ni_map_open(%s, %s, %d)n",
- map->map_mname, map->map_file, mode);
- mode &= O_ACCMODE;
- if (*map->map_file == ' ')
- map->map_file = NETINFO_DEFAULT_DIR;
- if (map->map_valcolnm == NULL)
- map->map_valcolnm = NETINFO_DEFAULT_PROPERTY;
- if (map->map_coldelim == ' ' && bitset(MF_ALIAS, map->map_mflags))
- map->map_coldelim = ',';
- return TRUE;
- }
- /*
- ** NI_MAP_LOOKUP -- look up a datum in NetInfo
- */
- char *
- ni_map_lookup(map, name, av, statp)
- MAP *map;
- char *name;
- char **av;
- int *statp;
- {
- char *res;
- char *propval;
- if (tTd(38, 20))
- dprintf("ni_map_lookup(%s, %s)n", map->map_mname, name);
- propval = ni_propval(map->map_file, map->map_keycolnm, name,
- map->map_valcolnm, map->map_coldelim);
- if (propval == NULL)
- return NULL;
- if (bitset(MF_MATCHONLY, map->map_mflags))
- res = map_rewrite(map, name, strlen(name), NULL);
- else
- res = map_rewrite(map, propval, strlen(propval), av);
- free(propval);
- return res;
- }
- static bool
- ni_getcanonname(name, hbsize, statp)
- char *name;
- int hbsize;
- int *statp;
- {
- char *vptr;
- char *ptr;
- char nbuf[MAXNAME + 1];
- if (tTd(38, 20))
- dprintf("ni_getcanonname(%s)n", name);
- if (strlcpy(nbuf, name, sizeof nbuf) >= sizeof nbuf)
- {
- *statp = EX_UNAVAILABLE;
- return FALSE;
- }
- shorten_hostname(nbuf);
- /* we only accept single token search key */
- if (strchr(nbuf, '.'))
- {
- *statp = EX_NOHOST;
- return FALSE;
- }
- /* Do the search */
- vptr = ni_propval("/machines", NULL, nbuf, "name", 'n');
- if (vptr == NULL)
- {
- *statp = EX_NOHOST;
- return FALSE;
- }
- /* Only want the first machine name */
- if ((ptr = strchr(vptr, 'n')) != NULL)
- *ptr = ' ';
- if (hbsize >= strlen(vptr))
- {
- (void) strlcpy(name, vptr, hbsize);
- free(vptr);
- *statp = EX_OK;
- return TRUE;
- }
- *statp = EX_UNAVAILABLE;
- free(vptr);
- return FALSE;
- }
- /*
- ** NI_PROPVAL -- NetInfo property value lookup routine
- **
- ** Parameters:
- ** keydir -- the NetInfo directory name in which to search
- ** for the key.
- ** keyprop -- the name of the property in which to find the
- ** property we are interested. Defaults to "name".
- ** keyval -- the value for which we are really searching.
- ** valprop -- the property name for the value in which we
- ** are interested.
- ** sepchar -- if non-nil, this can be multiple-valued, and
- ** we should return a string separated by this
- ** character.
- **
- ** Returns:
- ** NULL -- if:
- ** 1. the directory is not found
- ** 2. the property name is not found
- ** 3. the property contains multiple values
- ** 4. some error occurred
- ** else -- the value of the lookup.
- **
- ** Example:
- ** To search for an alias value, use:
- ** ni_propval("/aliases", "name", aliasname, "members", ',')
- **
- ** Notes:
- ** Caller should free the return value of ni_proval
- */
- # include <netinfo/ni.h>
- # define LOCAL_NETINFO_DOMAIN "."
- # define PARENT_NETINFO_DOMAIN ".."
- # define MAX_NI_LEVELS 256
- char *
- ni_propval(keydir, keyprop, keyval, valprop, sepchar)
- char *keydir;
- char *keyprop;
- char *keyval;
- char *valprop;
- int sepchar;
- {
- char *propval = NULL;
- int i;
- int j, alen, l;
- void *ni = NULL;
- void *lastni = NULL;
- ni_status nis;
- ni_id nid;
- ni_namelist ninl;
- register char *p;
- char keybuf[1024];
- /*
- ** Create the full key from the two parts.
- **
- ** Note that directory can end with, e.g., "name=" to specify
- ** an alternate search property.
- */
- i = strlen(keydir) + strlen(keyval) + 2;
- if (keyprop != NULL)
- i += strlen(keyprop) + 1;
- if (i >= sizeof keybuf)
- return NULL;
- (void) strlcpy(keybuf, keydir, sizeof keybuf);
- (void) strlcat(keybuf, "/", sizeof keybuf);
- if (keyprop != NULL)
- {
- (void) strlcat(keybuf, keyprop, sizeof keybuf);
- (void) strlcat(keybuf, "=", sizeof keybuf);
- }
- (void) strlcat(keybuf, keyval, sizeof keybuf);
- if (tTd(38, 21))
- dprintf("ni_propval(%s, %s, %s, %s, %d) keybuf='%s'n",
- keydir, keyprop, keyval, valprop, sepchar, keybuf);
- /*
- ** If the passed directory and property name are found
- ** in one of netinfo domains we need to search (starting
- ** from the local domain moving all the way back to the
- ** root domain) set propval to the property's value
- ** and return it.
- */
- for (i = 0; i < MAX_NI_LEVELS && propval == NULL; i++)
- {
- if (i == 0)
- {
- nis = ni_open(NULL, LOCAL_NETINFO_DOMAIN, &ni);
- if (tTd(38, 20))
- dprintf("ni_open(LOCAL) = %dn", nis);
- }
- else
- {
- if (lastni != NULL)
- ni_free(lastni);
- lastni = ni;
- nis = ni_open(lastni, PARENT_NETINFO_DOMAIN, &ni);
- if (tTd(38, 20))
- dprintf("ni_open(PARENT) = %dn", nis);
- }
- /*
- ** Don't bother if we didn't get a handle on a
- ** proper domain. This is not necessarily an error.
- ** We would get a positive ni_status if, for instance
- ** we never found the directory or property and tried
- ** to open the parent of the root domain!
- */
- if (nis != 0)
- break;
- /*
- ** Find the path to the server information.
- */
- if (ni_pathsearch(ni, &nid, keybuf) != 0)
- continue;
- /*
- ** Find associated value information.
- */
- if (ni_lookupprop(ni, &nid, valprop, &ninl) != 0)
- continue;
- if (tTd(38, 20))
- dprintf("ni_lookupprop: len=%dn",
- ninl.ni_namelist_len);
- /*
- ** See if we have an acceptable number of values.
- */
- if (ninl.ni_namelist_len <= 0)
- continue;
- if (sepchar == ' ' && ninl.ni_namelist_len > 1)
- {
- ni_namelist_free(&ninl);
- continue;
- }
- /*
- ** Calculate number of bytes needed and build result
- */
- alen = 1;
- for (j = 0; j < ninl.ni_namelist_len; j++)
- alen += strlen(ninl.ni_namelist_val[j]) + 1;
- propval = p = xalloc(alen);
- for (j = 0; j < ninl.ni_namelist_len; j++)
- {
- (void) strlcpy(p, ninl.ni_namelist_val[j], alen);
- l = strlen(p);
- p += l;
- *p++ = sepchar;
- alen -= l + 1;
- }
- *--p = ' ';
- ni_namelist_free(&ninl);
- }
- /*
- ** Clean up.
- */
- if (ni != NULL)
- ni_free(ni);
- if (lastni != NULL && ni != lastni)
- ni_free(lastni);
- if (tTd(38, 20))
- dprintf("ni_propval returns: '%s'n", propval);
- return propval;
- }
- #endif /* NETINFO */
- /*
- ** TEXT (unindexed text file) Modules
- **
- ** This code donated by Sun Microsystems.
- */
- #define map_sff map_lockfd /* overload field */
- /*
- ** TEXT_MAP_OPEN -- open text table
- */
- bool
- text_map_open(map, mode)
- MAP *map;
- int mode;
- {
- long sff;
- int i;
- if (tTd(38, 2))
- dprintf("text_map_open(%s, %s, %d)n",
- map->map_mname, map->map_file, mode);
- mode &= O_ACCMODE;
- if (mode != O_RDONLY)
- {
- errno = EPERM;
- return FALSE;
- }
- if (*map->map_file == ' ')
- {
- syserr("text map "%s": file name required",
- map->map_mname);
- return FALSE;
- }
- if (map->map_file[0] != '/')
- {
- syserr("text map "%s": file name must be fully qualified",
- map->map_mname);
- return FALSE;
- }
- sff = SFF_ROOTOK|SFF_REGONLY;
- if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail))
- sff |= SFF_NOWLINK;
- if (!bitnset(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail))
- sff |= SFF_SAFEDIRPATH;
- if ((i = safefile(map->map_file, RunAsUid, RunAsGid, RunAsUserName,
- sff, S_IRUSR, NULL)) != 0)
- {
- int save_errno = errno;
- /* cannot open this map */
- if (tTd(38, 2))
- dprintf("tunsafe map file: %dn", i);
- errno = save_errno;
- if (!bitset(MF_OPTIONAL, map->map_mflags))
- syserr("text map "%s": unsafe map file %s",
- map->map_mname, map->map_file);
- return FALSE;
- }
- if (map->map_keycolnm == NULL)
- map->map_keycolno = 0;
- else
- {
- if (!(isascii(*map->map_keycolnm) && isdigit(*map->map_keycolnm)))
- {
- syserr("text map "%s", file %s: -k should specify a number, not %s",
- map->map_mname, map->map_file,
- map->map_keycolnm);
- return FALSE;
- }
- map->map_keycolno = atoi(map->map_keycolnm);
- }
- if (map->map_valcolnm == NULL)
- map->map_valcolno = 0;
- else
- {
- if (!(isascii(*map->map_valcolnm) && isdigit(*map->map_valcolnm)))
- {
- syserr("text map "%s", file %s: -v should specify a number, not %s",
- map->map_mname, map->map_file,
- map->map_valcolnm);
- return FALSE;
- }
- map->map_valcolno = atoi(map->map_valcolnm);
- }
- if (tTd(38, 2))
- {
- dprintf("text_map_open(%s, %s): delimiter = ",
- map->map_mname, map->map_file);
- if (map->map_coldelim == ' ')
- dprintf("(white space)n");
- else
- dprintf("%cn", map->map_coldelim);
- }
- map->map_sff = sff;
- return TRUE;
- }
- /*
- ** TEXT_MAP_LOOKUP -- look up a datum in a TEXT table
- */
- char *
- text_map_lookup(map, name, av, statp)
- MAP *map;
- char *name;
- char **av;
- int *statp;
- {
- char *vp;
- auto int vsize;
- int buflen;
- FILE *f;
- char delim;
- int key_idx;
- bool found_it;
- long sff = map->map_sff;
- char search_key[MAXNAME + 1];
- char linebuf[MAXLINE];
- char buf[MAXNAME + 1];
- found_it = FALSE;
- if (tTd(38, 20))
- dprintf("text_map_lookup(%s, %s)n", map->map_mname, name);
- buflen = strlen(name);
- if (buflen > sizeof search_key - 1)
- buflen = sizeof search_key - 1;
- memmove(search_key, name, buflen);
- search_key[buflen] = ' ';
- if (!bitset(MF_NOFOLDCASE, map->map_mflags))
- makelower(search_key);
- f = safefopen(map->map_file, O_RDONLY, FileMode, sff);
- if (f == NULL)
- {
- map->map_mflags &= ~(MF_VALID|MF_OPEN);
- *statp = EX_UNAVAILABLE;
- return NULL;
- }
- key_idx = map->map_keycolno;
- delim = map->map_coldelim;
- while (fgets(linebuf, MAXLINE, f) != NULL)
- {
- char *p;
- /* skip comment line */
- if (linebuf[0] == '#')
- continue;
- p = strchr(linebuf, 'n');
- if (p != NULL)
- *p = ' ';
- p = get_column(linebuf, key_idx, delim, buf, sizeof buf);
- if (p != NULL && strcasecmp(search_key, p) == 0)
- {
- found_it = TRUE;
- break;
- }
- }
- (void) fclose(f);
- if (!found_it)
- {
- *statp = EX_NOTFOUND;
- return NULL;
- }
- vp = get_column(linebuf, map->map_valcolno, delim, buf, sizeof buf);
- if (vp == NULL)
- {
- *statp = EX_NOTFOUND;
- return NULL;
- }
- vsize = strlen(vp);
- *statp = EX_OK;
- if (bitset(MF_MATCHONLY, map->map_mflags))
- return map_rewrite(map, name, strlen(name), NULL);
- else
- return map_rewrite(map, vp, vsize, av);
- }
- /*
- ** TEXT_GETCANONNAME -- look up canonical name in hosts file
- */
- static bool
- text_getcanonname(name, hbsize, statp)
- char *name;
- int hbsize;
- int *statp;
- {
- bool found;
- FILE *f;
- char linebuf[MAXLINE];
- char cbuf[MAXNAME + 1];
- char nbuf[MAXNAME + 1];
- if (tTd(38, 20))
- dprintf("text_getcanonname(%s)n", name);
- if (strlen(name) >= (SIZE_T) sizeof nbuf)
- {
- *statp = EX_UNAVAILABLE;
- return FALSE;
- }
- (void) strlcpy(nbuf, name, sizeof nbuf);
- shorten_hostname(nbuf);
- f = fopen(HostsFile, "r");
- if (f == NULL)
- {
- *statp = EX_UNAVAILABLE;
- return FALSE;
- }
- found = FALSE;
- while (!found && fgets(linebuf, MAXLINE, f) != NULL)
- {
- char *p = strpbrk(linebuf, "#n");
- if (p != NULL)
- *p = ' ';
- if (linebuf[0] != ' ')
- found = extract_canonname(nbuf, linebuf, cbuf, sizeof cbuf);
- }
- (void) fclose(f);
- if (!found)
- {
- *statp = EX_NOHOST;
- return FALSE;
- }
- if ((SIZE_T) hbsize >= strlen(cbuf))
- {
- (void) strlcpy(name, cbuf, hbsize);
- *statp = EX_OK;
- return TRUE;
- }
- *statp = EX_UNAVAILABLE;
- return FALSE;
- }
- /*
- ** STAB (Symbol Table) Modules
- */
- /*
- ** STAB_MAP_LOOKUP -- look up alias in symbol table
- */
- /* ARGSUSED2 */
- char *
- stab_map_lookup(map, name, av, pstat)
- register MAP *map;
- char *name;
- char **av;
- int *pstat;
- {
- register STAB *s;
- if (tTd(38, 20))
- dprintf("stab_lookup(%s, %s)n",
- map->map_mname, name);
- s = stab(name, ST_ALIAS, ST_FIND);
- if (s != NULL)
- return s->s_alias;
- return NULL;
- }
- /*
- ** STAB_MAP_STORE -- store in symtab (actually using during init, not rebuild)
- */
- void
- stab_map_store(map, lhs, rhs)
- register MAP *map;
- char *lhs;
- char *rhs;
- {
- register STAB *s;
- s = stab(lhs, ST_ALIAS, ST_ENTER);
- s->s_alias = newstr(rhs);
- }
- /*
- ** STAB_MAP_OPEN -- initialize (reads data file)
- **
- ** This is a wierd case -- it is only intended as a fallback for
- ** aliases. For this reason, opens for write (only during a
- ** "newaliases") always fails, and opens for read open the
- ** actual underlying text file instead of the database.
- */
- bool
- stab_map_open(map, mode)
- register MAP *map;
- int mode;
- {
- FILE *af;
- long sff;
- struct stat st;
- if (tTd(38, 2))
- dprintf("stab_map_open(%s, %s, %d)n",
- map->map_mname, map->map_file, mode);
- mode &= O_ACCMODE;
- if (mode != O_RDONLY)
- {
- errno = EPERM;
- return FALSE;
- }
- sff = SFF_ROOTOK|SFF_REGONLY;
- if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail))
- sff |= SFF_NOWLINK;
- if (!bitnset(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail))
- sff |= SFF_SAFEDIRPATH;
- af = safefopen(map->map_file, O_RDONLY, 0444, sff);
- if (af == NULL)
- return FALSE;
- readaliases(map, af, FALSE, FALSE);
- if (fstat(fileno(af), &st) >= 0)
- map->map_mtime = st.st_mtime;
- (void) fclose(af);
- return TRUE;
- }
- /*
- ** Implicit Modules
- **
- ** Tries several types. For back compatibility of aliases.
- */
- /*
- ** IMPL_MAP_LOOKUP -- lookup in best open database
- */
- char *
- impl_map_lookup(map, name, av, pstat)
- MAP *map;
- char *name;
- char **av;
- int *pstat;
- {
- if (tTd(38, 20))
- dprintf("impl_map_lookup(%s, %s)n",
- map->map_mname, name);
- #ifdef NEWDB
- if (bitset(MF_IMPL_HASH, map->map_mflags))
- return db_map_lookup(map, name, av, pstat);
- #endif /* NEWDB */
- #ifdef NDBM
- if (bitset(MF_IMPL_NDBM, map->map_mflags))
- return ndbm_map_lookup(map, name, av, pstat);
- #endif /* NDBM */
- return stab_map_lookup(map, name, av, pstat);
- }
- /*
- ** IMPL_MAP_STORE -- store in open databases
- */
- void
- impl_map_store(map, lhs, rhs)
- MAP *map;
- char *lhs;
- char *rhs;
- {
- if (tTd(38, 12))
- dprintf("impl_map_store(%s, %s, %s)n",
- map->map_mname, lhs, rhs);
- #ifdef NEWDB
- if (bitset(MF_IMPL_HASH, map->map_mflags))
- db_map_store(map, lhs, rhs);
- #endif /* NEWDB */
- #ifdef NDBM
- if (bitset(MF_IMPL_NDBM, map->map_mflags))
- ndbm_map_store(map, lhs, rhs);
- #endif /* NDBM */
- stab_map_store(map, lhs, rhs);
- }
- /*
- ** IMPL_MAP_OPEN -- implicit database open
- */
- bool
- impl_map_open(map, mode)
- MAP *map;
- int mode;
- {
- if (tTd(38, 2))
- dprintf("impl_map_open(%s, %s, %d)n",
- map->map_mname, map->map_file, mode);
- mode &= O_ACCMODE;
- #ifdef NEWDB
- map->map_mflags |= MF_IMPL_HASH;
- if (hash_map_open(map, mode))
- {
- # ifdef NDBM_YP_COMPAT
- if (mode == O_RDONLY || strstr(map->map_file, "/yp/") == NULL)
- # endif /* NDBM_YP_COMPAT */
- return TRUE;
- }
- else
- map->map_mflags &= ~MF_IMPL_HASH;
- #endif /* NEWDB */
- #ifdef NDBM
- map->map_mflags |= MF_IMPL_NDBM;
- if (ndbm_map_open(map, mode))
- {
- return TRUE;
- }
- else
- map->map_mflags &= ~MF_IMPL_NDBM;
- #endif /* NDBM */
- #if defined(NEWDB) || defined(NDBM)
- if (Verbose)
- message("WARNING: cannot open alias database %s%s",
- map->map_file,
- mode == O_RDONLY ? "; reading text version" : "");
- #else /* defined(NEWDB) || defined(NDBM) */
- if (mode != O_RDONLY)
- usrerr("Cannot rebuild aliases: no database format defined");
- #endif /* defined(NEWDB) || defined(NDBM) */
- if (mode == O_RDONLY)
- return stab_map_open(map, mode);
- else
- return FALSE;
- }
- /*
- ** IMPL_MAP_CLOSE -- close any open database(s)
- */
- void
- impl_map_close(map)
- MAP *map;
- {
- if (tTd(38, 9))
- dprintf("impl_map_close(%s, %s, %lx)n",
- map->map_mname, map->map_file, map->map_mflags);
- #ifdef NEWDB
- if (bitset(MF_IMPL_HASH, map->map_mflags))
- {
- db_map_close(map);
- map->map_mflags &= ~MF_IMPL_HASH;
- }
- #endif /* NEWDB */
- #ifdef NDBM
- if (bitset(MF_IMPL_NDBM, map->map_mflags))
- {
- ndbm_map_close(map);
- map->map_mflags &= ~MF_IMPL_NDBM;
- }
- #endif /* NDBM */
- }
- /*
- ** User map class.
- **
- ** Provides access to the system password file.
- */
- /*
- ** USER_MAP_OPEN -- open user map
- **
- ** Really just binds field names to field numbers.
- */
- bool
- user_map_open(map, mode)
- MAP *map;
- int mode;
- {
- if (tTd(38, 2))
- dprintf("user_map_open(%s, %d)n",
- map->map_mname, mode);
- mode &= O_ACCMODE;
- if (mode != O_RDONLY)
- {
- /* issue a pseudo-error message */
- #ifdef ENOSYS
- errno = ENOSYS;
- #else /* ENOSYS */
- # ifdef EFTYPE
- errno = EFTYPE;
- # else /* EFTYPE */
- errno = ENXIO;
- # endif /* EFTYPE */
- #endif /* ENOSYS */
- return FALSE;
- }
- if (map->map_valcolnm == NULL)
- /* EMPTY */
- /* nothing */ ;
- else if (strcasecmp(map->map_valcolnm, "name") == 0)
- map->map_valcolno = 1;
- else if (strcasecmp(map->map_valcolnm, "passwd") == 0)
- map->map_valcolno = 2;
- else if (strcasecmp(map->map_valcolnm, "uid") == 0)
- map->map_valcolno = 3;
- else if (strcasecmp(map->map_valcolnm, "gid") == 0)
- map->map_valcolno = 4;
- else if (strcasecmp(map->map_valcolnm, "gecos") == 0)
- map->map_valcolno = 5;
- else if (strcasecmp(map->map_valcolnm, "dir") == 0)
- map->map_valcolno = 6;
- else if (strcasecmp(map->map_valcolnm, "shell") == 0)
- map->map_valcolno = 7;
- else
- {
- syserr("User map %s: unknown column name %s",
- map->map_mname, map->map_valcolnm);
- return FALSE;
- }
- return TRUE;
- }
- /*
- ** USER_MAP_LOOKUP -- look up a user in the passwd file.
- */
- /* ARGSUSED3 */
- char *
- user_map_lookup(map, key, av, statp)
- MAP *map;
- char *key;
- char **av;
- int *statp;
- {
- struct passwd *pw;
- auto bool fuzzy;
- if (tTd(38, 20))
- dprintf("user_map_lookup(%s, %s)n",
- map->map_mname, key);
- pw = finduser(key, &fuzzy);
- if (pw == NULL)
- return NULL;
- if (bitset(MF_MATCHONLY, map->map_mflags))
- return map_rewrite(map, key, strlen(key), NULL);
- else
- {
- char *rwval = NULL;
- char buf[30];
- switch (map->map_valcolno)
- {
- case 0:
- case 1:
- rwval = pw->pw_name;
- break;
- case 2:
- rwval = pw->pw_passwd;
- break;
- case 3:
- snprintf(buf, sizeof buf, "%d", (int) pw->pw_uid);
- rwval = buf;
- break;
- case 4:
- snprintf(buf, sizeof buf, "%d", (int) pw->pw_gid);
- rwval = buf;
- break;
- case 5:
- rwval = pw->pw_gecos;
- break;
- case 6:
- rwval = pw->pw_dir;
- break;
- case 7:
- rwval = pw->pw_shell;
- break;
- }
- return map_rewrite(map, rwval, strlen(rwval), av);
- }
- }
- /*
- ** Program map type.
- **
- ** This provides access to arbitrary programs. It should be used
- ** only very sparingly, since there is no way to bound the cost
- ** of invoking an arbitrary program.
- */
- char *
- prog_map_lookup(map, name, av, statp)
- MAP *map;
- char *name;
- char **av;
- int *statp;
- {
- int i;
- int save_errno;
- int fd;
- int status;
- auto pid_t pid;
- register char *p;
- char *rval;
- char *argv[MAXPV + 1];
- char buf[MAXLINE];
- if (tTd(38, 20))
- dprintf("prog_map_lookup(%s, %s) %sn",
- map->map_mname, name, map->map_file);
- i = 0;
- argv[i++] = map->map_file;
- if (map->map_rebuild != NULL)
- {
- snprintf(buf, sizeof buf, "%s", map->map_rebuild);
- for (p = strtok(buf, " t"); p != NULL; p = strtok(NULL, " t"))
- {
- if (i >= MAXPV - 1)
- break;
- argv[i++] = p;
- }
- }
- argv[i++] = name;
- argv[i] = NULL;
- if (tTd(38, 21))
- {
- dprintf("prog_open:");
- for (i = 0; argv[i] != NULL; i++)
- dprintf(" %s", argv[i]);
- dprintf("n");
- }
- (void) blocksignal(SIGCHLD);
- pid = prog_open(argv, &fd, CurEnv);
- if (pid < 0)
- {
- if (!bitset(MF_OPTIONAL, map->map_mflags))
- syserr("prog_map_lookup(%s) failed (%s) -- closing",
- map->map_mname, errstring(errno));
- else if (tTd(38, 9))
- dprintf("prog_map_lookup(%s) failed (%s) -- closing",
- map->map_mname, errstring(errno));
- map->map_mflags &= ~(MF_VALID|MF_OPEN);
- *statp = EX_OSFILE;
- return NULL;
- }
- i = read(fd, buf, sizeof buf - 1);
- if (i < 0)
- {
- syserr("prog_map_lookup(%s): read error %sn",
- map->map_mname, errstring(errno));
- rval = NULL;
- }
- else if (i == 0)
- {
- if (tTd(38, 20))
- dprintf("prog_map_lookup(%s): empty answern",
- map->map_mname);
- rval = NULL;
- }
- else
- {
- buf[i] = ' ';
- p = strchr(buf, 'n');
- if (p != NULL)
- *p = ' ';
- /* collect the return value */
- if (bitset(MF_MATCHONLY, map->map_mflags))
- rval = map_rewrite(map, name, strlen(name), NULL);
- else
- rval = map_rewrite(map, buf, strlen(buf), NULL);
- /* now flush any additional output */
- while ((i = read(fd, buf, sizeof buf)) > 0)
- continue;
- }
- /* wait for the process to terminate */
- (void) close(fd);
- status = waitfor(pid);
- save_errno = errno;
- (void) releasesignal(SIGCHLD);
- errno = save_errno;
- if (status == -1)
- {
- syserr("prog_map_lookup(%s): wait error %sn",
- map->map_mname, errstring(errno));
- *statp = EX_SOFTWARE;
- rval = NULL;
- }
- else if (WIFEXITED(status))
- {
- if ((*statp = WEXITSTATUS(status)) != EX_OK)
- rval = NULL;
- }
- else
- {
- syserr("prog_map_lookup(%s): child died on signal %d",
- map->map_mname, status);
- *statp = EX_UNAVAILABLE;
- rval = NULL;
- }
- return rval;
- }
- /*
- ** Sequenced map type.
- **
- ** Tries each map in order until something matches, much like
- ** implicit. Stores go to the first map in the list that can
- ** support storing.
- **
- ** This is slightly unusual in that there are two interfaces.
- ** The "sequence" interface lets you stack maps arbitrarily.
- ** The "switch" interface builds a sequence map by looking
- ** at a system-dependent configuration file such as
- ** /etc/nsswitch.conf on Solaris or /etc/svc.conf on Ultrix.
- **
- ** We don't need an explicit open, since all maps are
- ** opened during startup, including underlying maps.
- */
- /*
- ** SEQ_MAP_PARSE -- Sequenced map parsing
- */
- bool
- seq_map_parse(map, ap)
- MAP *map;
- char *ap;
- {
- int maxmap;
- if (tTd(38, 2))
- dprintf("seq_map_parse(%s, %s)n", map->map_mname, ap);
- maxmap = 0;
- while (*ap != ' ')
- {
- register char *p;
- STAB *s;
- /* find beginning of map name */
- while (isascii(*ap) && isspace(*ap))
- ap++;
- for (p = ap; isascii(*p) && isalnum(*p); p++)
- continue;
- if (*p != ' ')
- *p++ = ' ';
- while (*p != ' ' && (!isascii(*p) || !isalnum(*p)))
- p++;
- if (*ap == ' ')
- {
- ap = p;
- continue;
- }
- s = stab(ap, ST_MAP, ST_FIND);
- if (s == NULL)
- {
- syserr("Sequence map %s: unknown member map %s",
- map->map_mname, ap);
- }
- else if (maxmap == MAXMAPSTACK)
- {
- syserr("Sequence map %s: too many member maps (%d max)",
- map->map_mname, MAXMAPSTACK);
- maxmap++;
- }
- else if (maxmap < MAXMAPSTACK)
- {
- map->map_stack[maxmap++] = &s->s_map;
- }
- ap = p;
- }
- return TRUE;
- }
- /*
- ** SWITCH_MAP_OPEN -- open a switched map
- **
- ** This looks at the system-dependent configuration and builds
- ** a sequence map that does the same thing.
- **
- ** Every system must define a switch_map_find routine in conf.c
- ** that will return the list of service types associated with a
- ** given service class.
- */
- bool
- switch_map_open(map, mode)
- MAP *map;
- int mode;
- {
- int mapno;
- int nmaps;
- char *maptype[MAXMAPSTACK];
- if (tTd(38, 2))
- dprintf("switch_map_open(%s, %s, %d)n",
- map->map_mname, map->map_file, mode);
- mode &= O_ACCMODE;
- nmaps = switch_map_find(map->map_file, maptype, map->map_return);
- if (tTd(38, 19))
- {
- dprintf("tswitch_map_find => %dn", nmaps);
- for (mapno = 0; mapno < nmaps; mapno++)
- dprintf("tt%sn", maptype[mapno]);
- }
- if (nmaps <= 0 || nmaps > MAXMAPSTACK)
- return FALSE;
- for (mapno = 0; mapno < nmaps; mapno++)
- {
- register STAB *s;
- char nbuf[MAXNAME + 1];
- if (maptype[mapno] == NULL)
- continue;
- (void) snprintf(nbuf, sizeof nbuf, "%s.%s",
- map->map_mname, maptype[mapno]);
- s = stab(nbuf, ST_MAP, ST_FIND);
- if (s == NULL)
- {
- syserr("Switch map %s: unknown member map %s",
- map->map_mname, nbuf);
- }
- else
- {
- map->map_stack[mapno] = &s->s_map;
- if (tTd(38, 4))
- dprintf("tmap_stack[%d] = %s:%sn",
- mapno, s->s_map.map_class->map_cname,
- nbuf);
- }
- }
- return TRUE;
- }
- /*
- ** SEQ_MAP_CLOSE -- close all underlying maps
- */
- void
- seq_map_close(map)
- MAP *map;
- {
- int mapno;
- if (tTd(38, 9))
- dprintf("seq_map_close(%s)n", map->map_mname);
- for (mapno = 0; mapno < MAXMAPSTACK; mapno++)
- {
- MAP *mm = map->map_stack[mapno];
- if (mm == NULL || !bitset(MF_OPEN, mm->map_mflags))
- continue;
- mm->map_class->map_close(mm);
- mm->map_mflags &= ~(MF_OPEN|MF_WRITABLE);
- }
- }
- /*
- ** SEQ_MAP_LOOKUP -- sequenced map lookup
- */
- char *
- seq_map_lookup(map, key, args, pstat)
- MAP *map;
- char *key;
- char **args;
- int *pstat;
- {
- int mapno;
- int mapbit = 0x01;
- bool tempfail = FALSE;
- if (tTd(38, 20))
- dprintf("seq_map_lookup(%s, %s)n", map->map_mname, key);
- for (mapno = 0; mapno < MAXMAPSTACK; mapbit <<= 1, mapno++)
- {
- MAP *mm = map->map_stack[mapno];
- char *rv;
- if (mm == NULL)
- continue;
- if (!bitset(MF_OPEN, mm->map_mflags) &&
- !openmap(mm))
- {
- if (bitset(mapbit, map->map_return[MA_UNAVAIL]))
- {
- *pstat = EX_UNAVAILABLE;
- return NULL;
- }
- continue;
- }
- *pstat = EX_OK;
- rv = mm->map_class->map_lookup(mm, key, args, pstat);
- if (rv != NULL)
- return rv;
- if (*pstat == EX_TEMPFAIL)
- {
- if (bitset(mapbit, map->map_return[MA_TRYAGAIN]))
- return NULL;
- tempfail = TRUE;
- }
- else if (bitset(mapbit, map->map_return[MA_NOTFOUND]))
- break;
- }
- if (tempfail)
- *pstat = EX_TEMPFAIL;
- else if (*pstat == EX_OK)
- *pstat = EX_NOTFOUND;
- return NULL;
- }
- /*
- ** SEQ_MAP_STORE -- sequenced map store
- */
- void
- seq_map_store(map, key, val)
- MAP *map;
- char *key;
- char *val;
- {
- int mapno;
- if (tTd(38, 12))
- dprintf("seq_map_store(%s, %s, %s)n",
- map->map_mname, key, val);
- for (mapno = 0; mapno < MAXMAPSTACK; mapno++)
- {
- MAP *mm = map->map_stack[mapno];
- if (mm == NULL || !bitset(MF_WRITABLE, mm->map_mflags))
- continue;
- mm->map_class->map_store(mm, key, val);
- return;
- }
- syserr("seq_map_store(%s, %s, %s): no writable map",
- map->map_mname, key, val);
- }
- /*
- ** NULL stubs
- */
- /* ARGSUSED */
- bool
- null_map_open(map, mode)
- MAP *map;
- int mode;
- {
- return TRUE;
- }
- /* ARGSUSED */
- void
- null_map_close(map)
- MAP *map;
- {
- return;
- }
- char *
- null_map_lookup(map, key, args, pstat)
- MAP *map;
- char *key;
- char **args;
- int *pstat;
- {
- *pstat = EX_NOTFOUND;
- return NULL;
- }
- /* ARGSUSED */
- void
- null_map_store(map, key, val)
- MAP *map;
- char *key;
- char *val;
- {
- return;
- }
- /*
- ** BOGUS stubs
- */
- char *
- bogus_map_lookup(map, key, args, pstat)
- MAP *map;
- char *key;
- char **args;
- int *pstat;
- {
- *pstat = EX_TEMPFAIL;
- return NULL;
- }
- MAPCLASS BogusMapClass =
- {
- "bogus-map", NULL, 0,
- NULL, bogus_map_lookup, null_map_store,
- null_map_open, null_map_close,
- };
- /*
- ** MACRO modules
- */
- char *
- macro_map_lookup(map, name, av, statp)
- MAP *map;
- char *name;
- char **av;
- int *statp;
- {
- int mid;
- if (tTd(38, 20))
- dprintf("macro_map_lookup(%s, %s)n", map->map_mname,
- name == NULL ? "NULL" : name);
- if (name == NULL ||
- *name == ' ' ||
- (mid = macid(name, NULL)) == ' ')
- {
- *statp = EX_CONFIG;
- return NULL;
- }
- if (av[1] == NULL)
- define(mid, NULL, CurEnv);
- else
- define(mid, newstr(av[1]), CurEnv);
- *statp = EX_OK;
- return "";
- }
- /*
- ** REGEX modules
- */
- #ifdef MAP_REGEX
- # include <regex.h>
- # define DEFAULT_DELIM CONDELSE
- # define END_OF_FIELDS -1
- # define ERRBUF_SIZE 80
- # define MAX_MATCH 32
- # define xnalloc(s) memset(xalloc(s), ' ', s);
- struct regex_map
- {
- regex_t regex_pattern_buf; /* xalloc it */
- int *regex_subfields; /* move to type MAP */
- char *regex_delim; /* move to type MAP */
- };
- static int
- parse_fields(s, ibuf, blen, nr_substrings)
- char *s;
- int *ibuf; /* array */
- int blen; /* number of elements in ibuf */
- int nr_substrings; /* number of substrings in the pattern */
- {
- register char *cp;
- int i = 0;
- bool lastone = FALSE;
- blen--; /* for terminating END_OF_FIELDS */
- cp = s;
- do
- {
- for (;; cp++)
- {
- if (*cp == ',')
- {
- *cp = ' ';
- break;
- }
- if (*cp == ' ')
- {
- lastone = TRUE;
- break;
- }
- }
- if (i < blen)
- {
- int val = atoi(s);
- if (val < 0 || val >= nr_substrings)
- {
- syserr("field (%d) out of range, only %d substrings in pattern",
- val, nr_substrings);
- return -1;
- }
- ibuf[i++] = val;
- }
- else
- {
- syserr("too many fields, %d maxn", blen);
- return -1;
- }
- s = ++cp;
- } while (!lastone);
- ibuf[i] = END_OF_FIELDS;
- return i;
- }
- bool
- regex_map_init(map, ap)
- MAP *map;
- char *ap;
- {
- int regerr;
- struct regex_map *map_p;
- register char *p;
- char *sub_param = NULL;
- int pflags;
- static char defdstr[] = { (char)DEFAULT_DELIM, ' ' };
- if (tTd(38, 2))
- dprintf("regex_map_init: mapname '%s', args '%s'n",
- map->map_mname, ap);
- pflags = REG_ICASE | REG_EXTENDED | REG_NOSUB;
- p = ap;
- map_p = (struct regex_map *) xnalloc(sizeof *map_p);
- for (;;)
- {
- while (isascii(*p) && isspace(*p))
- p++;
- if (*p != '-')
- break;
- switch (*++p)
- {
- case 'n': /* not */
- map->map_mflags |= MF_REGEX_NOT;
- break;
- case 'f': /* case sensitive */
- map->map_mflags |= MF_NOFOLDCASE;
- pflags &= ~REG_ICASE;
- break;
- case 'b': /* basic regular expressions */
- pflags &= ~REG_EXTENDED;
- break;
- case 's': /* substring match () syntax */
- sub_param = ++p;
- pflags &= ~REG_NOSUB;
- break;
- case 'd': /* delimiter */
- map_p->regex_delim = ++p;
- break;
- case 'a': /* map append */
- map->map_app = ++p;
- break;
- case 'm': /* matchonly */
- map->map_mflags |= MF_MATCHONLY;
- break;
- case 'S':
- map->map_spacesub = *++p;
- break;
- case 'D':
- map->map_mflags |= MF_DEFER;
- break;
- }
- while (*p != ' ' && !(isascii(*p) && isspace(*p)))
- p++;
- if (*p != ' ')
- *p++ = ' ';
- }
- if (tTd(38, 3))
- dprintf("regex_map_init: compile '%s' 0x%xn", p, pflags);
- if ((regerr = regcomp(&(map_p->regex_pattern_buf), p, pflags)) != 0)
- {
- /* Errorhandling */
- char errbuf[ERRBUF_SIZE];
- (void) regerror(regerr, &(map_p->regex_pattern_buf),
- errbuf, ERRBUF_SIZE);
- syserr("pattern-compile-error: %sn", errbuf);
- free(map_p);
- return FALSE;
- }
- if (map->map_app != NULL)
- map->map_app = newstr(map->map_app);
- if (map_p->regex_delim != NULL)
- map_p->regex_delim = newstr(map_p->regex_delim);
- else
- map_p->regex_delim = defdstr;
- if (!bitset(REG_NOSUB, pflags))
- {
- /* substring matching */
- int substrings;
- int *fields = (int *) xalloc(sizeof(int) * (MAX_MATCH + 1));
- substrings = map_p->regex_pattern_buf.re_nsub + 1;
- if (tTd(38, 3))
- dprintf("regex_map_init: nr of substrings %dn",
- substrings);
- if (substrings >= MAX_MATCH)
- {
- syserr("too many substrings, %d maxn", MAX_MATCH);
- free(map_p);
- return FALSE;
- }
- if (sub_param != NULL && sub_param[0] != ' ')
- {
- /* optional parameter -sfields */
- if (parse_fields(sub_param, fields,
- MAX_MATCH + 1, substrings) == -1)
- return FALSE;
- }
- else
- {
- /* set default fields */
- int i;
- for (i = 0; i < substrings; i++)
- fields[i] = i;
- fields[i] = END_OF_FIELDS;
- }
- map_p->regex_subfields = fields;
- if (tTd(38, 3))
- {
- int *ip;
- dprintf("regex_map_init: subfields");
- for (ip = fields; *ip != END_OF_FIELDS; ip++)
- dprintf(" %d", *ip);
- dprintf("n");
- }
- }
- map->map_db1 = (ARBPTR_T)map_p; /* dirty hack */
- return TRUE;
- }
- static char *
- regex_map_rewrite(map, s, slen, av)
- MAP *map;
- const char *s;
- size_t slen;
- char **av;
- {
- if (bitset(MF_MATCHONLY, map->map_mflags))
- return map_rewrite(map, av[0], strlen(av[0]), NULL);
- else
- return map_rewrite(map, s, slen, NULL);
- }
- char *
- regex_map_lookup(map, name, av, statp)
- MAP *map;
- char *name;
- char **av;
- int *statp;
- {
- int reg_res;
- struct regex_map *map_p;
- regmatch_t pmatch[MAX_MATCH];
- if (tTd(38, 20))
- {
- char **cpp;
- dprintf("regex_map_lookup: key '%s'n", name);
- for (cpp = av; cpp != NULL && *cpp != NULL; cpp++)
- dprintf("regex_map_lookup: arg '%s'n", *cpp);
- }
- map_p = (struct regex_map *)(map->map_db1);
- reg_res = regexec(&(map_p->regex_pattern_buf),
- name, MAX_MATCH, pmatch, 0);
- if (bitset(MF_REGEX_NOT, map->map_mflags))
- {
- /* option -n */
- if (reg_res == REG_NOMATCH)
- return regex_map_rewrite(map, "", (size_t)0, av);
- else
- return NULL;
- }
- if (reg_res == REG_NOMATCH)
- return NULL;
- if (map_p->regex_subfields != NULL)
- {
- /* option -s */
- static char retbuf[MAXNAME];
- int fields[MAX_MATCH + 1];
- bool first = TRUE;
- int anglecnt = 0, cmntcnt = 0, spacecnt = 0;
- bool quotemode = FALSE, bslashmode = FALSE;
- register char *dp, *sp;
- char *endp, *ldp;
- int *ip;
- dp = retbuf;
- ldp = retbuf + sizeof(retbuf) - 1;
- if (av[1] != NULL)
- {
- if (parse_fields(av[1], fields, MAX_MATCH + 1,
- (int) map_p->regex_pattern_buf.re_nsub + 1) == -1)
- {
- *statp = EX_CONFIG;
- return NULL;
- }
- ip = fields;
- }
- else
- ip = map_p->regex_subfields;
- for ( ; *ip != END_OF_FIELDS; ip++)
- {
- if (!first)
- {
- for (sp = map_p->regex_delim; *sp; sp++)
- {
- if (dp < ldp)
- *dp++ = *sp;
- }
- }
- else
- first = FALSE;
- if (pmatch[*ip].rm_so < 0 || pmatch[*ip].rm_eo < 0)
- continue;
- sp = name + pmatch[*ip].rm_so;
- endp = name + pmatch[*ip].rm_eo;
- for (; endp > sp; sp++)
- {
- if (dp < ldp)
- {
- if (bslashmode)
- {
- *dp++ = *sp;
- bslashmode = FALSE;
- }
- else if (quotemode && *sp != '"' &&
- *sp != '\')
- {
- *dp++ = *sp;
- }
- else switch(*dp++ = *sp)
- {
- case '\':
- bslashmode = TRUE;
- break;
- case '(':
- cmntcnt++;
- break;
- case ')':
- cmntcnt--;
- break;
- case '<':
- anglecnt++;
- break;
- case '>':
- anglecnt--;
- break;
- case ' ':
- spacecnt++;
- break;
- case '"':
- quotemode = !quotemode;
- break;
- }
- }
- }
- }
- if (anglecnt != 0 || cmntcnt != 0 || quotemode ||
- bslashmode || spacecnt != 0)
- {
- sm_syslog(LOG_WARNING, NOQID,
- "Warning: regex may cause prescan() failure map=%s lookup=%s",
- map->map_mname, name);
- return NULL;
- }
- *dp = ' ';
- return regex_map_rewrite(map, retbuf, strlen(retbuf), av);
- }
- return regex_map_rewrite(map, "", (size_t)0, av);
- }
- #endif /* MAP_REGEX */
- /*
- ** NSD modules
- */
- #ifdef MAP_NSD
- # include <ndbm.h>
- # define _DATUM_DEFINED
- # include <ns_api.h>
- typedef struct ns_map_list
- {
- ns_map_t *map;
- char *mapname;
- struct ns_map_list *next;
- } ns_map_list_t;
- static ns_map_t *
- ns_map_t_find(mapname)
- char *mapname;
- {
- static ns_map_list_t *ns_maps = NULL;
- ns_map_list_t *ns_map;
- /* walk the list of maps looking for the correctly named map */
- for (ns_map = ns_maps; ns_map != NULL; ns_map = ns_map->next)
- {
- if (strcmp(ns_map->mapname, mapname) == 0)
- break;
- }
- /* if we are looking at a NULL ns_map_list_t, then create a new one */
- if (ns_map == NULL)
- {
- ns_map = (ns_map_list_t *) xalloc(sizeof *ns_map);
- ns_map->mapname = newstr(mapname);
- ns_map->map = (ns_map_t *) xalloc(sizeof *ns_map->map);
- ns_map->next = ns_maps;
- ns_maps = ns_map;
- }
- return ns_map->map;
- }
- char *
- nsd_map_lookup(map, name, av, statp)
- MAP *map;
- char *name;
- char **av;
- int *statp;
- {
- int buflen;
- char *p;
- ns_map_t *ns_map;
- char keybuf[MAXNAME + 1];
- char buf[MAXLINE];
- if (tTd(38, 20))
- dprintf("nsd_map_lookup(%s, %s)n", map->map_mname, name);
- buflen = strlen(name);
- if (buflen > sizeof keybuf - 1)
- buflen = sizeof keybuf - 1;
- memmove(keybuf, name, buflen);
- keybuf[buflen] = ' ';
- if (!bitset(MF_NOFOLDCASE, map->map_mflags))
- makelower(keybuf);
- ns_map = ns_map_t_find(map->map_file);
- if (ns_map == NULL)
- {
- if (tTd(38, 20))
- dprintf("nsd_map_t_find failedn");
- return NULL;
- }
- if (ns_lookup(ns_map, NULL, map->map_file,
- keybuf, NULL, buf, MAXLINE) == NULL)
- return NULL;
- /* Null out trailing n */
- if ((p = strchr(buf, 'n')) != NULL)
- *p = ' ';
- return map_rewrite(map, buf, strlen(buf), av);
- }
- #endif /* MAP_NSD */
- char *
- arith_map_lookup(map, name, av, statp)
- MAP *map;
- char *name;
- char **av;
- int *statp;
- {
- int r, v[2];
- bool boolres;
- static char result[16];
- char **cpp;
- if (tTd(38, 2))
- {
- dprintf("arith_map_lookup: key '%s'n", name);
- for (cpp = av; cpp != NULL && *cpp != NULL; cpp++)
- dprintf("arith_map_lookup: arg '%s'n", *cpp);
- }
- r = 0;
- boolres = FALSE;
- cpp = av;
- *statp = EX_OK;
- /*
- ** read arguments for arith map
- ** - no check is made whether they are really numbers
- ** - just ignores args after the second
- */
- for (++cpp; cpp != NULL && *cpp != NULL && r < 2; cpp++)
- v[r++] = atoi(*cpp);
- /* operator and (at least) two operands given? */
- if (name != NULL && r == 2)
- {
- switch(*name)
- {
- case '+':
- r = v[0] + v[1];
- break;
- case '-':
- r = v[0] - v[1];
- break;
- case '*':
- r = v[0] * v[1];
- break;
- case '/':
- if (v[1] == 0)
- return NULL;
- r = v[0] / v[1];
- break;
- case 'l':
- r = v[0] < v[1];
- boolres = TRUE;
- break;
- case '=':
- r = v[0] == v[1];
- boolres = TRUE;
- break;
- default:
- /* XXX */
- *statp = EX_CONFIG;
- if (LogLevel > 10)
- sm_syslog(LOG_WARNING, NOQID,
- "arith_map: unknown operator %c",
- isprint(*name) ? *name : '?');
- return NULL;
- }
- if (boolres)
- snprintf(result, sizeof result, r ? "TRUE" : "FALSE");
- else
- snprintf(result, sizeof result, "%d", r);
- return result;
- }
- *statp = EX_CONFIG;
- return NULL;
- }