|
Packit |
8480eb |
/* ----------------------------------------------------------------------- *
|
|
Packit |
8480eb |
*
|
|
Packit |
8480eb |
* parse_subs.c - misc parser subroutines
|
|
Packit |
8480eb |
* automounter map
|
|
Packit |
8480eb |
*
|
|
Packit |
8480eb |
* Copyright 1997 Transmeta Corporation - All Rights Reserved
|
|
Packit |
8480eb |
* Copyright 2000 Jeremy Fitzhardinge <jeremy@goop.org>
|
|
Packit |
8480eb |
* Copyright 2004-2006 Ian Kent <raven@themaw.net>
|
|
Packit |
8480eb |
*
|
|
Packit |
8480eb |
* This program is free software; you can redistribute it and/or modify
|
|
Packit |
8480eb |
* it under the terms of the GNU General Public License as published by
|
|
Packit |
8480eb |
* the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
|
|
Packit |
8480eb |
* USA; either version 2 of the License, or (at your option) any later
|
|
Packit |
8480eb |
* version; incorporated herein by reference.
|
|
Packit |
8480eb |
*
|
|
Packit |
8480eb |
* ----------------------------------------------------------------------- */
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
#include <stdlib.h>
|
|
Packit |
8480eb |
#include <string.h>
|
|
Packit |
8480eb |
#include <ctype.h>
|
|
Packit |
8480eb |
#include <sys/types.h>
|
|
Packit |
8480eb |
#include <sys/socket.h>
|
|
Packit |
8480eb |
#include <ifaddrs.h>
|
|
Packit |
8480eb |
#include <libgen.h>
|
|
Packit |
8480eb |
#include <net/if.h>
|
|
Packit |
8480eb |
#include <arpa/inet.h>
|
|
Packit |
8480eb |
#include <netdb.h>
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
#include "automount.h"
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
#define MAX_OPTIONS_LEN 256
|
|
Packit |
8480eb |
#define MAX_OPTION_LEN 40
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
#define MAX_NETWORK_LEN 255
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
#define MAX_IFC_BUF 2048
|
|
Packit |
8480eb |
static int volatile ifc_buf_len = MAX_IFC_BUF;
|
|
Packit |
8480eb |
static int volatile ifc_last_len = 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
#define MASK_A 0x7F000000
|
|
Packit |
8480eb |
#define MASK_B 0xBFFF0000
|
|
Packit |
8480eb |
#define MASK_C 0xDFFFFF00
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Get numeric value of the n bits starting at position p */
|
|
Packit |
8480eb |
#define getbits(x, p, n) ((x >> (p + 1 - n)) & ~(~0 << n))
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
#define EXPAND_LEADING_SLASH 0x0001
|
|
Packit |
8480eb |
#define EXPAND_TRAILING_SLASH 0x0002
|
|
Packit |
8480eb |
#define EXPAND_LEADING_DOT 0x0004
|
|
Packit |
8480eb |
#define EXPAND_TRAILING_DOT 0x0008
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
#define SELECTOR_HASH_SIZE 20
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static struct sel sel_table[] = {
|
|
Packit |
8480eb |
{ SEL_ARCH, "arch", SEL_FLAG_MACRO|SEL_FLAG_STR, NULL },
|
|
Packit |
8480eb |
{ SEL_KARCH, "karch", SEL_FLAG_MACRO|SEL_FLAG_STR, NULL },
|
|
Packit |
8480eb |
{ SEL_OS, "os", SEL_FLAG_MACRO|SEL_FLAG_STR, NULL },
|
|
Packit |
8480eb |
{ SEL_OSVER, "osver", SEL_FLAG_MACRO|SEL_FLAG_STR, NULL },
|
|
Packit |
8480eb |
{ SEL_FULL_OS, "full_os", SEL_FLAG_MACRO|SEL_FLAG_STR, NULL },
|
|
Packit |
8480eb |
{ SEL_VENDOR, "vendor", SEL_FLAG_MACRO|SEL_FLAG_STR, NULL },
|
|
Packit |
8480eb |
{ SEL_HOST, "host", SEL_FLAG_MACRO|SEL_FLAG_STR, NULL },
|
|
Packit |
8480eb |
{ SEL_HOSTD, "hostd", SEL_FLAG_MACRO|SEL_FLAG_STR, NULL },
|
|
Packit |
8480eb |
{ SEL_XHOST, "xhost", SEL_FLAG_FUNC1|SEL_FLAG_BOOL, NULL },
|
|
Packit |
8480eb |
{ SEL_DOMAIN, "domain", SEL_FLAG_MACRO|SEL_FLAG_STR, NULL },
|
|
Packit |
8480eb |
{ SEL_BYTE, "byte", SEL_FLAG_MACRO|SEL_FLAG_STR, NULL },
|
|
Packit |
8480eb |
{ SEL_CLUSTER, "cluster", SEL_FLAG_MACRO|SEL_FLAG_STR, NULL },
|
|
Packit |
8480eb |
{ SEL_NETGRP, "netgrp", SEL_FLAG_FUNC2|SEL_FLAG_BOOL, NULL },
|
|
Packit |
8480eb |
{ SEL_NETGRPD, "netgrpd", SEL_FLAG_FUNC2|SEL_FLAG_BOOL, NULL },
|
|
Packit |
8480eb |
{ SEL_IN_NETWORK, "in_network", SEL_FLAG_FUNC1|SEL_FLAG_BOOL, NULL },
|
|
Packit |
8480eb |
{ SEL_IN_NETWORK, "netnumber", SEL_FLAG_FUNC1|SEL_FLAG_BOOL, NULL },
|
|
Packit |
8480eb |
{ SEL_IN_NETWORK, "network", SEL_FLAG_FUNC1|SEL_FLAG_BOOL, NULL },
|
|
Packit |
8480eb |
{ SEL_IN_NETWORK, "wire", SEL_FLAG_FUNC1|SEL_FLAG_BOOL, NULL },
|
|
Packit |
8480eb |
{ SEL_UID, "uid", SEL_FLAG_MACRO|SEL_FLAG_NUM, NULL },
|
|
Packit |
8480eb |
{ SEL_GID, "gid", SEL_FLAG_MACRO|SEL_FLAG_NUM, NULL },
|
|
Packit |
8480eb |
{ SEL_KEY, "key", SEL_FLAG_MACRO|SEL_FLAG_STR, NULL },
|
|
Packit |
8480eb |
{ SEL_MAP, "map", SEL_FLAG_MACRO|SEL_FLAG_STR, NULL },
|
|
Packit |
8480eb |
{ SEL_PATH, "path", SEL_FLAG_MACRO|SEL_FLAG_STR, NULL },
|
|
Packit |
8480eb |
{ SEL_EXISTS, "exists", SEL_FLAG_FUNC1|SEL_FLAG_BOOL, NULL },
|
|
Packit |
8480eb |
{ SEL_AUTODIR, "autodir", SEL_FLAG_MACRO|SEL_FLAG_STR, NULL },
|
|
Packit |
8480eb |
{ SEL_DOLLAR, "dollar", SEL_FLAG_MACRO|SEL_FLAG_STR, NULL },
|
|
Packit |
8480eb |
{ SEL_TRUE, "true", SEL_FLAG_FUNC1|SEL_FLAG_BOOL, NULL },
|
|
Packit |
8480eb |
{ SEL_FALSE, "false", SEL_FLAG_FUNC1|SEL_FLAG_BOOL, NULL },
|
|
Packit |
8480eb |
};
|
|
Packit |
8480eb |
static unsigned int sel_count = sizeof(sel_table)/sizeof(struct sel);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static struct sel *sel_hash[SELECTOR_HASH_SIZE];
|
|
Packit |
8480eb |
static unsigned int sel_hash_init_done = 0;
|
|
Packit |
8480eb |
static pthread_mutex_t sel_hash_mutex = PTHREAD_MUTEX_INITIALIZER;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
struct types {
|
|
Packit |
8480eb |
char *type;
|
|
Packit |
8480eb |
unsigned int len;
|
|
Packit |
8480eb |
};
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static struct types map_type[] = {
|
|
Packit |
8480eb |
{ "file", 4 },
|
|
Packit |
8480eb |
{ "program", 7 },
|
|
Packit |
8480eb |
{ "yp", 2 },
|
|
Packit |
8480eb |
{ "nis", 3 },
|
|
Packit |
8480eb |
{ "nisplus", 7 },
|
|
Packit |
8480eb |
{ "ldap", 4 },
|
|
Packit |
8480eb |
{ "ldaps", 5 },
|
|
Packit |
8480eb |
{ "hesiod", 6 },
|
|
Packit |
8480eb |
{ "userdir", 7 },
|
|
Packit |
8480eb |
{ "hosts", 5 },
|
|
Packit |
8480eb |
};
|
|
Packit |
8480eb |
static unsigned int map_type_count = sizeof(map_type)/sizeof(struct types);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static struct types format_type[] = {
|
|
Packit |
8480eb |
{ "sun", 3 },
|
|
Packit |
8480eb |
{ "hesiod", 6 },
|
|
Packit |
8480eb |
{ "amd", 3},
|
|
Packit |
8480eb |
};
|
|
Packit |
8480eb |
static unsigned int format_type_count = sizeof(format_type)/sizeof(struct types);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static void sel_add(struct sel *sel)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
u_int32_t hval = hash(sel->name, SELECTOR_HASH_SIZE);
|
|
Packit |
8480eb |
struct sel *old;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
old = sel_hash[hval];
|
|
Packit |
8480eb |
sel_hash[hval] = sel;
|
|
Packit |
8480eb |
sel_hash[hval]->next = old;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
void sel_hash_init(void)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
int i;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
pthread_mutex_lock(&sel_hash_mutex);
|
|
Packit |
8480eb |
if (sel_hash_init_done) {
|
|
Packit |
8480eb |
pthread_mutex_unlock(&sel_hash_mutex);
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
for (i = 0; i < SELECTOR_HASH_SIZE; i++)
|
|
Packit |
8480eb |
sel_hash[i] = NULL;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
for (i = 0; i < sel_count; i++)
|
|
Packit |
8480eb |
sel_add(&sel_table[i]);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
sel_hash_init_done = 1;
|
|
Packit |
8480eb |
pthread_mutex_unlock(&sel_hash_mutex);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
struct sel *sel_lookup(const char *name)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
u_int32_t hval = hash(name, SELECTOR_HASH_SIZE);
|
|
Packit |
8480eb |
struct sel *sel;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
pthread_mutex_lock(&sel_hash_mutex);
|
|
Packit |
8480eb |
for (sel = sel_hash[hval]; sel != NULL; sel = sel->next) {
|
|
Packit |
8480eb |
if (strcmp(name, sel->name) == 0) {
|
|
Packit |
8480eb |
pthread_mutex_unlock(&sel_hash_mutex);
|
|
Packit |
8480eb |
return sel;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
pthread_mutex_unlock(&sel_hash_mutex);
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
struct selector *get_selector(char *name)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct sel *sel;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
sel = sel_lookup(name);
|
|
Packit |
8480eb |
if (sel) {
|
|
Packit |
8480eb |
struct selector *new = malloc(sizeof(struct selector));
|
|
Packit |
8480eb |
if (!new)
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
memset(new, 0, sizeof(*new));
|
|
Packit |
8480eb |
new->sel = sel;
|
|
Packit |
8480eb |
return new;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
void free_selector(struct selector *selector)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct selector *s = selector;
|
|
Packit |
8480eb |
struct selector *next = s;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
while (s) {
|
|
Packit |
8480eb |
next = s->next;
|
|
Packit |
8480eb |
if (s->sel->flags & SEL_FREE_VALUE_MASK)
|
|
Packit |
8480eb |
free(s->comp.value);
|
|
Packit |
8480eb |
if (s->sel->flags & SEL_FREE_ARG1_MASK)
|
|
Packit |
8480eb |
free(s->func.arg1);
|
|
Packit |
8480eb |
if (s->sel->flags & SEL_FREE_ARG2_MASK)
|
|
Packit |
8480eb |
free(s->func.arg2);
|
|
Packit |
8480eb |
s = next;
|
|
Packit |
8480eb |
}
|
|
Packit Service |
0f11ce |
free(selector);
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static unsigned int ipv6_mask_cmp(uint32_t *host, uint32_t *iface, uint32_t *mask)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
unsigned int ret = 1;
|
|
Packit |
8480eb |
unsigned int i;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
for (i = 0; i < 4; i++) {
|
|
Packit |
8480eb |
if ((host[i] & mask[i]) != (iface[i] & mask[i])) {
|
|
Packit |
8480eb |
ret = 0;
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
return ret;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
unsigned int get_proximity(struct sockaddr *host_addr)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct ifaddrs *ifa = NULL;
|
|
Packit |
8480eb |
struct ifaddrs *this;
|
|
Packit |
8480eb |
struct sockaddr_in *addr, *msk_addr, *if_addr;
|
|
Packit |
8480eb |
struct sockaddr_in6 *addr6, *msk6_addr, *if6_addr;
|
|
Packit |
8480eb |
struct in_addr *hst_addr;
|
|
Packit |
8480eb |
struct in6_addr *hst6_addr;
|
|
Packit |
8480eb |
int addr_len;
|
|
Packit |
8480eb |
char buf[MAX_ERR_BUF];
|
|
Packit |
8480eb |
uint32_t mask, ha, ia, *mask6, *ha6, *ia6;
|
|
Packit |
8480eb |
int ret;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
addr = NULL;
|
|
Packit |
8480eb |
addr6 = NULL;
|
|
Packit |
8480eb |
hst_addr = NULL;
|
|
Packit |
8480eb |
hst6_addr = NULL;
|
|
Packit |
8480eb |
mask6 = NULL;
|
|
Packit |
8480eb |
ha6 = NULL;
|
|
Packit |
8480eb |
ia6 = NULL;
|
|
Packit |
8480eb |
ha = 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
switch (host_addr->sa_family) {
|
|
Packit |
8480eb |
case AF_INET:
|
|
Packit |
8480eb |
addr = (struct sockaddr_in *) host_addr;
|
|
Packit |
8480eb |
hst_addr = (struct in_addr *) &addr->sin_addr;
|
|
Packit |
8480eb |
ha = ntohl((uint32_t) hst_addr->s_addr);
|
|
Packit |
8480eb |
addr_len = sizeof(*hst_addr);
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
case AF_INET6:
|
|
Packit |
8480eb |
#ifndef WITH_LIBTIRPC
|
|
Packit |
8480eb |
return PROXIMITY_UNSUPPORTED;
|
|
Packit |
8480eb |
#else
|
|
Packit |
8480eb |
addr6 = (struct sockaddr_in6 *) host_addr;
|
|
Packit |
8480eb |
hst6_addr = (struct in6_addr *) &addr6->sin6_addr;
|
|
Packit |
8480eb |
ha6 = &hst6_addr->s6_addr32[0];
|
|
Packit |
8480eb |
addr_len = sizeof(*hst6_addr);
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
#endif
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
default:
|
|
Packit |
8480eb |
return PROXIMITY_ERROR;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ret = getifaddrs(&ifa;;
|
|
Packit |
8480eb |
if (ret) {
|
|
Packit |
8480eb |
char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
|
|
Packit |
8480eb |
logerr("getifaddrs: %s", estr);
|
|
Packit |
8480eb |
return PROXIMITY_ERROR;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
this = ifa;
|
|
Packit |
8480eb |
while (this) {
|
|
Packit |
8480eb |
if (!(this->ifa_flags & IFF_UP) ||
|
|
Packit |
8480eb |
this->ifa_flags & IFF_POINTOPOINT ||
|
|
Packit |
8480eb |
this->ifa_addr == NULL) {
|
|
Packit |
8480eb |
this = this->ifa_next;
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
switch (this->ifa_addr->sa_family) {
|
|
Packit |
8480eb |
case AF_INET:
|
|
Packit |
8480eb |
if (host_addr->sa_family == AF_INET6)
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
if_addr = (struct sockaddr_in *) this->ifa_addr;
|
|
Packit |
8480eb |
ret = memcmp(&if_addr->sin_addr, hst_addr, addr_len);
|
|
Packit |
8480eb |
if (!ret) {
|
|
Packit |
8480eb |
freeifaddrs(ifa);
|
|
Packit |
8480eb |
return PROXIMITY_LOCAL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
case AF_INET6:
|
|
Packit |
8480eb |
#ifdef WITH_LIBTIRPC
|
|
Packit |
8480eb |
if (host_addr->sa_family == AF_INET)
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
if6_addr = (struct sockaddr_in6 *) this->ifa_addr;
|
|
Packit |
8480eb |
ret = memcmp(&if6_addr->sin6_addr, hst6_addr, addr_len);
|
|
Packit |
8480eb |
if (!ret) {
|
|
Packit |
8480eb |
freeifaddrs(ifa);
|
|
Packit |
8480eb |
return PROXIMITY_LOCAL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
#endif
|
|
Packit |
8480eb |
default:
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
this = this->ifa_next;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
this = ifa;
|
|
Packit |
8480eb |
while (this) {
|
|
Packit |
8480eb |
if (!(this->ifa_flags & IFF_UP) ||
|
|
Packit |
8480eb |
this->ifa_flags & IFF_POINTOPOINT ||
|
|
Packit |
8480eb |
this->ifa_addr == NULL) {
|
|
Packit |
8480eb |
this = this->ifa_next;
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
switch (this->ifa_addr->sa_family) {
|
|
Packit |
8480eb |
case AF_INET:
|
|
Packit |
8480eb |
if (host_addr->sa_family == AF_INET6)
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
if_addr = (struct sockaddr_in *) this->ifa_addr;
|
|
Packit |
8480eb |
ia = ntohl((uint32_t) if_addr->sin_addr.s_addr);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Is the address within a localy attached subnet */
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
msk_addr = (struct sockaddr_in *) this->ifa_netmask;
|
|
Packit |
8480eb |
mask = ntohl((uint32_t) msk_addr->sin_addr.s_addr);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if ((ia & mask) == (ha & mask)) {
|
|
Packit |
8480eb |
freeifaddrs(ifa);
|
|
Packit |
8480eb |
return PROXIMITY_SUBNET;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* Is the address within a local ipv4 network.
|
|
Packit |
8480eb |
*
|
|
Packit |
8480eb |
* Bit position 31 == 0 => class A.
|
|
Packit |
8480eb |
* Bit position 30 == 0 => class B.
|
|
Packit |
8480eb |
* Bit position 29 == 0 => class C.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!getbits(ia, 31, 1))
|
|
Packit |
8480eb |
mask = MASK_A;
|
|
Packit |
8480eb |
else if (!getbits(ia, 30, 1))
|
|
Packit |
8480eb |
mask = MASK_B;
|
|
Packit |
8480eb |
else if (!getbits(ia, 29, 1))
|
|
Packit |
8480eb |
mask = MASK_C;
|
|
Packit |
8480eb |
else
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if ((ia & mask) == (ha & mask)) {
|
|
Packit |
8480eb |
freeifaddrs(ifa);
|
|
Packit |
8480eb |
return PROXIMITY_NET;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
case AF_INET6:
|
|
Packit |
8480eb |
#ifdef WITH_LIBTIRPC
|
|
Packit |
8480eb |
if (host_addr->sa_family == AF_INET)
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
if6_addr = (struct sockaddr_in6 *) this->ifa_addr;
|
|
Packit |
8480eb |
ia6 = &if6_addr->sin6_addr.s6_addr32[0];
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Is the address within the network of the interface */
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
msk6_addr = (struct sockaddr_in6 *) this->ifa_netmask;
|
|
Packit |
8480eb |
mask6 = &msk6_addr->sin6_addr.s6_addr32[0];
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (ipv6_mask_cmp(ha6, ia6, mask6)) {
|
|
Packit |
8480eb |
freeifaddrs(ifa);
|
|
Packit |
8480eb |
return PROXIMITY_SUBNET;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* How do we define "local network" in ipv6? */
|
|
Packit |
8480eb |
#endif
|
|
Packit |
8480eb |
default:
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
this = this->ifa_next;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
freeifaddrs(ifa);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return PROXIMITY_OTHER;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static char *inet_fill_net(const char *net_num, char *net)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
char *np;
|
|
Packit |
8480eb |
int dots = 3;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (strlen(net_num) > INET_ADDRSTRLEN)
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!isdigit(*net_num))
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
*net = '\0';
|
|
Packit |
8480eb |
strcpy(net, net_num);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
np = net;
|
|
Packit |
8480eb |
while (*np++) {
|
|
Packit |
8480eb |
if (*np == '.') {
|
|
Packit |
8480eb |
np++;
|
|
Packit |
8480eb |
dots--;
|
|
Packit |
8480eb |
if (!*np && dots)
|
|
Packit |
8480eb |
strcat(net, "0");
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if ((*np && !isdigit(*np)) || dots < 0) {
|
|
Packit |
8480eb |
*net = '\0';
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
while (dots--)
|
|
Packit |
8480eb |
strcat(net, ".0");
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return net;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static char *get_network_number(const char *network)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct netent *netent;
|
|
Packit |
8480eb |
char cnet[MAX_NETWORK_LEN];
|
|
Packit |
8480eb |
uint32_t h_net;
|
|
Packit |
8480eb |
size_t len;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
len = strlen(network) + 1;
|
|
Packit |
8480eb |
if (len > MAX_NETWORK_LEN)
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
netent = getnetbyname(network);
|
|
Packit |
8480eb |
if (!netent)
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
h_net = ntohl(netent->n_net);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!inet_ntop(AF_INET, &h_net, cnet, INET_ADDRSTRLEN))
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return strdup(cnet);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
unsigned int get_network_proximity(const char *name)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct addrinfo hints;
|
|
Packit |
8480eb |
struct addrinfo *ni, *this;
|
|
Packit |
8480eb |
char name_or_num[NI_MAXHOST + 1];
|
|
Packit |
8480eb |
unsigned int proximity;
|
|
Packit |
8480eb |
char *net;
|
|
Packit |
8480eb |
int ret;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!name)
|
|
Packit |
8480eb |
return PROXIMITY_ERROR;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
net = get_network_number(name);
|
|
Packit |
8480eb |
if (net) {
|
|
Packit |
8480eb |
strcpy(name_or_num, net);
|
|
Packit |
8480eb |
free(net);
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
char this[NI_MAXHOST + 1];
|
|
Packit |
8480eb |
char *mask;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (strlen(name) > NI_MAXHOST)
|
|
Packit |
8480eb |
return PROXIMITY_ERROR;
|
|
Packit |
8480eb |
strcpy(this, name);
|
|
Packit |
8480eb |
if ((mask = strchr(this, '/')))
|
|
Packit |
8480eb |
*mask++ = '\0';
|
|
Packit |
8480eb |
if (!strchr(this, '.'))
|
|
Packit |
8480eb |
strcpy(name_or_num, this);
|
|
Packit |
8480eb |
else {
|
|
Packit |
8480eb |
char buf[NI_MAXHOST + 1], *new;
|
|
Packit |
8480eb |
new = inet_fill_net(this, buf);
|
|
Packit |
8480eb |
if (!new)
|
|
Packit |
8480eb |
return PROXIMITY_ERROR;
|
|
Packit |
8480eb |
strcpy(name_or_num, new);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
memset(&hints, 0, sizeof(struct addrinfo));
|
|
Packit |
8480eb |
hints.ai_family = AF_UNSPEC;
|
|
Packit |
8480eb |
hints.ai_socktype = SOCK_DGRAM;
|
|
Packit |
8480eb |
hints.ai_flags = AI_V4MAPPED | AI_ADDRCONFIG | AI_CANONNAME;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
ret = getaddrinfo(name_or_num, NULL, &hints, &ni);
|
|
Packit |
8480eb |
if (ret) {
|
|
Packit Service |
986c63 |
logerr("hostname lookup for %s failed: %s",
|
|
Packit Service |
986c63 |
name_or_num, gai_strerror(ret));
|
|
Packit |
8480eb |
return PROXIMITY_ERROR;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
proximity = PROXIMITY_OTHER;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
this = ni;
|
|
Packit |
8480eb |
while (this) {
|
|
Packit |
8480eb |
unsigned int prx = get_proximity(this->ai_addr);
|
|
Packit |
8480eb |
if (prx < proximity)
|
|
Packit |
8480eb |
proximity = prx;
|
|
Packit |
8480eb |
this = this->ai_next;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
freeaddrinfo(ni);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return proximity;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
unsigned int in_network(char *network)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
unsigned int proximity = get_network_proximity(network);
|
|
Packit |
8480eb |
if (proximity == PROXIMITY_ERROR ||
|
|
Packit |
8480eb |
proximity > PROXIMITY_SUBNET)
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
struct mapent *match_cached_key(struct autofs_point *ap,
|
|
Packit |
8480eb |
const char *err_prefix,
|
|
Packit |
8480eb |
struct map_source *source,
|
|
Packit |
8480eb |
const char *key)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
char buf[MAX_ERR_BUF];
|
|
Packit |
8480eb |
struct mapent_cache *mc;
|
|
Packit |
8480eb |
struct mapent *me;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
mc = source->mc;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!(source->flags & MAP_FLAG_FORMAT_AMD)) {
|
|
Packit |
8480eb |
int ret;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
me = cache_lookup(mc, key);
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* Stale mapent => check for entry in alternate source or
|
|
Packit |
8480eb |
* wildcard. Note, plus included direct mount map entries
|
|
Packit |
8480eb |
* are included as an instance (same map entry cache), not
|
|
Packit |
8480eb |
* in a distinct source.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
if (me && (!me->mapent ||
|
|
Packit |
8480eb |
(me->source != source && *me->key != '/'))) {
|
|
Packit |
8480eb |
while ((me = cache_lookup_key_next(me)))
|
|
Packit |
8480eb |
if (me->source == source)
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
if (!me)
|
|
Packit |
8480eb |
me = cache_lookup_distinct(mc, "*");
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!me)
|
|
Packit |
8480eb |
goto done;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* If this is a lookup add wildcard match for later validation
|
|
Packit |
8480eb |
* checks and negative cache lookups.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
if (!(ap->flags & MOUNT_FLAG_REMOUNT) &&
|
|
Packit |
8480eb |
ap->type == LKP_INDIRECT && *me->key == '*') {
|
|
Packit |
8480eb |
ret = cache_update(mc, source, key, me->mapent, me->age);
|
|
Packit |
8480eb |
if (!(ret & (CHE_OK | CHE_UPDATED)))
|
|
Packit |
8480eb |
me = NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
char *lkp_key = strdup(key);
|
|
Packit |
8480eb |
if (!lkp_key) {
|
|
Packit |
8480eb |
char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
|
|
Packit |
8480eb |
error(ap->logopt, "%s strdup: %s", err_prefix, estr);
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* If it's found we're done */
|
|
Packit |
8480eb |
me = cache_lookup_distinct(mc, lkp_key);
|
|
Packit |
8480eb |
if (me)
|
|
Packit |
8480eb |
goto free;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* Otherwise strip successive directory components and try
|
|
Packit |
8480eb |
* a match against map entries ending with a wildcard and
|
|
Packit |
8480eb |
* finally try the wilcard entry itself.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
while (!me) {
|
|
Packit |
8480eb |
char *prefix;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
while ((prefix = strrchr(lkp_key, '/'))) {
|
|
Packit |
8480eb |
*prefix = '\0';
|
|
Packit |
8480eb |
me = cache_partial_match_wild(mc, lkp_key);
|
|
Packit |
8480eb |
if (me)
|
|
Packit |
8480eb |
goto free;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
me = cache_lookup_distinct(mc, "*");
|
|
Packit |
8480eb |
if (me)
|
|
Packit |
8480eb |
goto free;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
free:
|
|
Packit |
8480eb |
free(lkp_key);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
done:
|
|
Packit |
8480eb |
return me;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* Skip whitespace in a string; if we hit a #, consider the rest of the
|
|
Packit |
8480eb |
* entry a comment.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
const char *skipspace(const char *whence)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
while (1) {
|
|
Packit |
8480eb |
switch (*whence) {
|
|
Packit |
8480eb |
case ' ':
|
|
Packit |
8480eb |
case '\b':
|
|
Packit |
8480eb |
case '\t':
|
|
Packit |
8480eb |
case '\n':
|
|
Packit |
8480eb |
case '\v':
|
|
Packit |
8480eb |
case '\f':
|
|
Packit |
8480eb |
case '\r':
|
|
Packit |
8480eb |
whence++;
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
case '#': /* comment: skip to end of string */
|
|
Packit |
8480eb |
while (*whence != '\0')
|
|
Packit |
8480eb |
whence++;
|
|
Packit |
8480eb |
/* FALLTHROUGH */
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
default:
|
|
Packit |
8480eb |
return whence;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* Check a string to see if a colon appears before the next '/'.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
int check_colon(const char *str)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
char *ptr = (char *) str;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Colon escape */
|
|
Packit |
8480eb |
if (!strncmp(ptr, ":/", 2))
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
while (*ptr && strncmp(ptr, ":/", 2))
|
|
Packit |
8480eb |
ptr++;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!*ptr)
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Get the length of a chunk delimitered by whitespace */
|
|
Packit |
8480eb |
int chunklen(const char *whence, int expect_colon)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
char *str = (char *) whence;
|
|
Packit |
8480eb |
int n = 0;
|
|
Packit |
8480eb |
int quote = 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
for (; *str; str++, n++) {
|
|
Packit |
8480eb |
switch (*str) {
|
|
Packit |
8480eb |
case '\\':
|
|
Packit |
8480eb |
if( quote ) {
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
quote = 1;
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
case '"':
|
|
Packit |
8480eb |
if (quote)
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
while (*str) {
|
|
Packit |
8480eb |
str++;
|
|
Packit |
8480eb |
n++;
|
|
Packit |
8480eb |
if (*str == '"')
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
if (!strncmp(str, ":/", 2))
|
|
Packit |
8480eb |
expect_colon = 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
case ':':
|
|
Packit |
8480eb |
if (expect_colon && !strncmp(str, ":/", 2))
|
|
Packit |
8480eb |
expect_colon = 0;
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
case ' ':
|
|
Packit |
8480eb |
case '\t':
|
|
Packit |
8480eb |
/* Skip space or tab if we expect a colon */
|
|
Packit |
8480eb |
if (expect_colon)
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
case '\b':
|
|
Packit |
8480eb |
case '\n':
|
|
Packit |
8480eb |
case '\v':
|
|
Packit |
8480eb |
case '\f':
|
|
Packit |
8480eb |
case '\r':
|
|
Packit |
8480eb |
case '\0':
|
|
Packit |
8480eb |
if (!quote)
|
|
Packit |
8480eb |
return n;
|
|
Packit |
8480eb |
/* FALLTHROUGH */
|
|
Packit |
8480eb |
default:
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
quote = 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return n;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* Compare str with pat. Return 0 if compare equal or
|
|
Packit |
8480eb |
* str is an abbreviation of pat of no less than mchr characters.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
int strmcmp(const char *str, const char *pat, int mchr)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
int nchr = 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
while (*str == *pat) {
|
|
Packit |
8480eb |
if (!*str)
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
str++;
|
|
Packit |
8480eb |
pat++;
|
|
Packit |
8480eb |
nchr++;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!*str && nchr > mchr)
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return *pat - *str;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
char *dequote(const char *str, int origlen, unsigned int logopt)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
char *ret = malloc(origlen + 1);
|
|
Packit |
8480eb |
char *cp = ret;
|
|
Packit |
8480eb |
const char *scp;
|
|
Packit |
8480eb |
int len = origlen;
|
|
Packit |
8480eb |
int quote = 0, dquote = 0;
|
|
Packit |
8480eb |
int i, j;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (ret == NULL)
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* first thing to do is strip white space from the end */
|
|
Packit |
8480eb |
i = len - 1;
|
|
Packit |
8480eb |
while (isspace(str[i])) {
|
|
Packit |
8480eb |
/* of course, we have to keep escaped white-space */
|
|
Packit |
8480eb |
j = i - 1;
|
|
Packit |
8480eb |
if (j > 0 && (str[j] == '\\' || str[j] == '"'))
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
i--;
|
|
Packit |
8480eb |
len--;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
for (scp = str; len > 0 && *scp; scp++, len--) {
|
|
Packit |
8480eb |
if (!quote) {
|
|
Packit |
8480eb |
if (*scp == '"') {
|
|
Packit |
8480eb |
if (dquote)
|
|
Packit |
8480eb |
dquote = 0;
|
|
Packit |
8480eb |
else
|
|
Packit |
8480eb |
dquote = 1;
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!dquote) {
|
|
Packit |
8480eb |
if (*scp == '\\') {
|
|
Packit |
8480eb |
quote = 1;
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
quote = 0;
|
|
Packit |
8480eb |
*cp++ = *scp;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
*cp = '\0';
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (dquote) {
|
|
Packit |
8480eb |
debug(logopt, "unmatched quote in %.*s", origlen, str);
|
|
Packit |
8480eb |
free(ret);
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return ret;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
int span_space(const char *str, unsigned int maxlen)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
const char *p = str;
|
|
Packit |
8480eb |
unsigned int len = 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
while (*p && !isblank(*p) && len < maxlen) {
|
|
Packit |
8480eb |
if (*p == '"') {
|
|
Packit |
8480eb |
while (*p++ && len++ < maxlen) {
|
|
Packit |
8480eb |
if (*p == '"')
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
} else if (*p == '\\') {
|
|
Packit |
8480eb |
p += 2;
|
|
Packit |
8480eb |
len += 2;
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
p++;
|
|
Packit |
8480eb |
len++;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
return len;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
char *sanitize_path(const char *path, int origlen, unsigned int type, unsigned int logopt)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
char *slash, *cp, *s_path;
|
|
Packit |
8480eb |
const char *scp;
|
|
Packit |
8480eb |
int len = origlen;
|
|
Packit |
8480eb |
unsigned int seen_slash = 0, quote = 0, dquote = 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (type & (LKP_INDIRECT | LKP_DIRECT)) {
|
|
Packit |
8480eb |
const char *tmp = path;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (*tmp == '"')
|
|
Packit |
8480eb |
tmp++;
|
|
Packit |
8480eb |
slash = strchr(tmp, '/');
|
|
Packit |
8480eb |
if (slash) {
|
|
Packit |
8480eb |
if (type == LKP_INDIRECT)
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
if (*tmp != '/')
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
if (type == LKP_DIRECT)
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
s_path = malloc(origlen + 1);
|
|
Packit |
8480eb |
if (!s_path)
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
for (cp = s_path, scp = path; len > 0; scp++, len--) {
|
|
Packit |
8480eb |
if (!quote) {
|
|
Packit |
8480eb |
if (*scp == '"') {
|
|
Packit |
8480eb |
if (dquote)
|
|
Packit |
8480eb |
dquote = 0;
|
|
Packit |
8480eb |
else
|
|
Packit |
8480eb |
dquote = 1;
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!dquote) {
|
|
Packit |
8480eb |
/* Badness in string - go away */
|
|
Packit |
8480eb |
if (*scp < 32) {
|
|
Packit |
8480eb |
free(s_path);
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (*scp == '\\') {
|
|
Packit |
8480eb |
quote = 1;
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* Not really proper but we get problems with
|
|
Packit |
8480eb |
* paths with multiple slashes. The kernel
|
|
Packit |
8480eb |
* compresses them so when we get a query there
|
|
Packit |
8480eb |
* should be only single slashes.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
if (*scp == '/') {
|
|
Packit |
8480eb |
if (seen_slash)
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
seen_slash = 1;
|
|
Packit |
8480eb |
} else
|
|
Packit |
8480eb |
seen_slash = 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
quote = 0;
|
|
Packit |
8480eb |
*cp++ = *scp;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
*cp = '\0';
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (dquote) {
|
|
Packit |
8480eb |
debug(logopt, "unmatched quote in %.*s", origlen, path);
|
|
Packit |
8480eb |
free(s_path);
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Remove trailing / but watch out for a quoted / alone */
|
|
Packit |
8480eb |
if (strlen(cp) > 1 && origlen > 1 && *(cp - 1) == '/')
|
|
Packit |
8480eb |
*(cp - 1) = '\0';
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return s_path;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static char *hasopt(const char *str, const char *opt)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
const size_t optlen = strlen(opt);
|
|
Packit |
8480eb |
char *rest = (char *) str, *p;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
while ((p = strstr(rest, opt)) != NULL) {
|
|
Packit |
8480eb |
if ((p == rest || p[-1] == ',') &&
|
|
Packit |
8480eb |
(p[optlen] == '\0' || p[optlen] == '=' ||
|
|
Packit |
8480eb |
p[optlen] == ','))
|
|
Packit |
8480eb |
return p;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
rest = strchr (p, ',');
|
|
Packit |
8480eb |
if (rest == NULL)
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
++rest;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
char *merge_options(const char *opt1, const char *opt2)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
char str[MAX_OPTIONS_LEN + 1];
|
|
Packit |
8480eb |
char result[MAX_OPTIONS_LEN + 1];
|
|
Packit |
8480eb |
char neg[MAX_OPTION_LEN + 1];
|
|
Packit |
8480eb |
char *tok, *ptr = NULL;
|
|
Packit |
8480eb |
size_t resultlen, len;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if ((!opt1 || !*opt1) && (!opt2 || !*opt2))
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!opt2 || !*opt2) {
|
|
Packit |
8480eb |
if (!*opt1)
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
return strdup(opt1);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!opt1 || !*opt1) {
|
|
Packit |
8480eb |
if (!*opt2)
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
return strdup(opt2);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!strcmp(opt1, opt2))
|
|
Packit |
8480eb |
return strdup(opt1);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (strlen(str) > MAX_OPTIONS_LEN)
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
memset(result, 0, sizeof(result));
|
|
Packit |
8480eb |
strcpy(str, opt1);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
resultlen = 0;
|
|
Packit |
8480eb |
tok = strtok_r(str, ",", &ptr);
|
|
Packit |
8480eb |
while (tok) {
|
|
Packit |
8480eb |
const char *this = (const char *) tok;
|
|
Packit |
8480eb |
char *eq = strchr(this, '=');
|
|
Packit |
8480eb |
if (eq) {
|
|
Packit |
8480eb |
*eq = '\0';
|
|
Packit |
8480eb |
if (!hasopt(opt2, this)) {
|
|
Packit |
8480eb |
if (resultlen + strlen(this) > MAX_OPTIONS_LEN)
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
*eq = '=';
|
|
Packit |
8480eb |
if (!*result)
|
|
Packit |
8480eb |
strcpy(result, this);
|
|
Packit |
8480eb |
else
|
|
Packit |
8480eb |
strcat(result, this);
|
|
Packit |
8480eb |
strcat(result, ",");
|
|
Packit |
8480eb |
resultlen += strlen(this) + 1;
|
|
Packit |
8480eb |
goto next;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!strcmp(this, "rw") && hasopt(opt2, "ro"))
|
|
Packit |
8480eb |
goto next;
|
|
Packit |
8480eb |
if (!strcmp(this, "ro") && hasopt(opt2, "rw"))
|
|
Packit |
8480eb |
goto next;
|
|
Packit |
8480eb |
if (!strcmp(this, "bg") && hasopt(opt2, "fg"))
|
|
Packit |
8480eb |
goto next;
|
|
Packit |
8480eb |
if (!strcmp(this, "fg") && hasopt(opt2, "bg"))
|
|
Packit |
8480eb |
goto next;
|
|
Packit |
8480eb |
if (!strcmp(this, "bg") && hasopt(opt2, "fg"))
|
|
Packit |
8480eb |
goto next;
|
|
Packit |
8480eb |
if (!strcmp(this, "soft") && hasopt(opt2, "hard"))
|
|
Packit |
8480eb |
goto next;
|
|
Packit |
8480eb |
if (!strcmp(this, "hard") && hasopt(opt2, "soft"))
|
|
Packit |
8480eb |
goto next;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!strncmp(this, "no", 2)) {
|
|
Packit |
8480eb |
if (strlen(this + 2) > MAX_OPTION_LEN)
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
strcpy(neg, this + 2);
|
|
Packit |
8480eb |
if (hasopt(opt2, neg))
|
|
Packit |
8480eb |
goto next;
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
if ((strlen(this) + 2) > MAX_OPTION_LEN)
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
strcpy(neg, "no");
|
|
Packit |
8480eb |
strcat(neg, this);
|
|
Packit |
8480eb |
if (hasopt(opt2, neg))
|
|
Packit |
8480eb |
goto next;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (hasopt(opt2, tok))
|
|
Packit |
8480eb |
goto next;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (resultlen + strlen(this) + 1 > MAX_OPTIONS_LEN)
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!*result)
|
|
Packit |
8480eb |
strcpy(result, this);
|
|
Packit |
8480eb |
else
|
|
Packit |
8480eb |
strcat(result, this);
|
|
Packit |
8480eb |
strcat(result, ",");
|
|
Packit |
8480eb |
resultlen =+ strlen(this) + 1;
|
|
Packit |
8480eb |
next:
|
|
Packit |
8480eb |
tok = strtok_r(NULL, ",", &ptr);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (resultlen + strlen(opt2) > MAX_OPTIONS_LEN)
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!*result)
|
|
Packit |
8480eb |
strcpy(result, opt2);
|
|
Packit |
8480eb |
else
|
|
Packit |
8480eb |
strcat(result, opt2);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
len = strlen(result);
|
|
Packit |
8480eb |
if (len && result[len - 1] == ',')
|
|
Packit |
8480eb |
result[len - 1] = '\0';
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return strdup(result);
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
static char *expand_slash_or_dot(char *str, unsigned int type)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
char *val = NULL;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!str)
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!type)
|
|
Packit |
8480eb |
return str;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (type & EXPAND_LEADING_SLASH)
|
|
Packit |
8480eb |
val = basename(str);
|
|
Packit |
8480eb |
else if (type & EXPAND_TRAILING_SLASH)
|
|
Packit |
8480eb |
val = dirname(str);
|
|
Packit |
8480eb |
else if (type & (EXPAND_LEADING_DOT | EXPAND_TRAILING_DOT)) {
|
|
Packit |
8480eb |
char *dot = strchr(str, '.');
|
|
Packit |
8480eb |
if (dot)
|
|
Packit |
8480eb |
*dot++ = '\0';
|
|
Packit |
8480eb |
if (type & EXPAND_LEADING_DOT)
|
|
Packit |
8480eb |
val = dot;
|
|
Packit |
8480eb |
else
|
|
Packit |
8480eb |
val = str;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return val;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/*
|
|
Packit |
8480eb |
* $-expand an amd-style map entry and return the length of the entry.
|
|
Packit |
8480eb |
* If "dst" is NULL, just count the length.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
int expandamdent(const char *src, char *dst, const struct substvar *svc)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
unsigned int flags = conf_amd_get_flags(NULL);
|
|
Packit |
8480eb |
const struct substvar *sv;
|
|
Packit |
8480eb |
const char *o_src = src;
|
|
Packit |
8480eb |
unsigned int squote = 0;
|
|
Packit |
8480eb |
int len, l;
|
|
Packit |
8480eb |
const char *p;
|
|
Packit |
8480eb |
char ch;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
len = 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
while ((ch = *src++)) {
|
|
Packit |
8480eb |
switch (ch) {
|
|
Packit |
8480eb |
case '$':
|
|
Packit |
8480eb |
if (*src == '{') {
|
|
Packit |
8480eb |
char *start, *end;
|
|
Packit |
8480eb |
unsigned int type = 0;
|
|
Packit |
8480eb |
p = strchr(++src, '}');
|
|
Packit |
8480eb |
if (!p) {
|
|
Packit |
8480eb |
/* Ignore rest of string */
|
|
Packit |
8480eb |
if (dst)
|
|
Packit |
8480eb |
*dst = '\0';
|
|
Packit |
8480eb |
return len;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
start = (char *) src;
|
|
Packit |
8480eb |
if (*src == '/' || *src == '.') {
|
|
Packit |
8480eb |
start++;
|
|
Packit |
8480eb |
type = EXPAND_LEADING_SLASH;
|
|
Packit |
8480eb |
if (*src == '.')
|
|
Packit |
8480eb |
type = EXPAND_LEADING_DOT;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
end = (char *) p;
|
|
Packit |
8480eb |
if (*(p - 1) == '/' || *(p - 1) == '.') {
|
|
Packit |
8480eb |
end--;
|
|
Packit |
8480eb |
type = EXPAND_TRAILING_SLASH;
|
|
Packit |
8480eb |
if (*(p - 1) == '.')
|
|
Packit |
8480eb |
type = EXPAND_TRAILING_DOT;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
sv = macro_findvar(svc, start, end - start);
|
|
Packit |
8480eb |
if (sv) {
|
|
Packit |
8480eb |
char *val;
|
|
Packit |
8480eb |
char *str = strdup(sv->val);
|
|
Packit |
8480eb |
val = expand_slash_or_dot(str, type);
|
|
Packit |
8480eb |
if (!val)
|
|
Packit |
8480eb |
val = sv->val;
|
|
Packit |
8480eb |
l = strlen(val);
|
|
Packit |
8480eb |
if (dst) {
|
|
Packit |
8480eb |
if (*dst)
|
|
Packit |
8480eb |
strcat(dst, val);
|
|
Packit |
8480eb |
else
|
|
Packit |
8480eb |
strcpy(dst, val);
|
|
Packit |
8480eb |
dst += l;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
len += l;
|
|
Packit |
8480eb |
if (str)
|
|
Packit |
8480eb |
free(str);
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
if (dst) {
|
|
Packit |
8480eb |
*dst++ = ch;
|
|
Packit |
8480eb |
*dst++ = '{';
|
|
Packit |
8480eb |
strncat(dst, src, p - src);
|
|
Packit |
8480eb |
dst += (p - src);
|
|
Packit |
8480eb |
*dst++ = '}';
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
len += 1 + 1 + (p - src) + 1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
src = p + 1;
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
if (dst)
|
|
Packit |
8480eb |
*(dst++) = ch;
|
|
Packit |
8480eb |
len++;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
case '\\':
|
|
Packit |
8480eb |
if (squote || !(flags & CONF_NORMALIZE_SLASHES)) {
|
|
Packit |
8480eb |
len++;
|
|
Packit |
8480eb |
if (dst)
|
|
Packit |
8480eb |
*dst++ = ch;
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (*src) {
|
|
Packit |
8480eb |
len++;
|
|
Packit |
8480eb |
if (dst)
|
|
Packit |
8480eb |
*dst++ = *src;
|
|
Packit |
8480eb |
src++;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
case '/':
|
|
Packit |
8480eb |
len++;
|
|
Packit |
8480eb |
if (dst)
|
|
Packit |
8480eb |
*dst++ = ch;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (squote || !(flags & CONF_NORMALIZE_SLASHES))
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Double slash at start is allowed */
|
|
Packit |
8480eb |
if (src == (o_src + 1) && *src == '/') {
|
|
Packit |
8480eb |
len++;
|
|
Packit |
8480eb |
if (dst)
|
|
Packit |
8480eb |
*dst++ = *src;
|
|
Packit |
8480eb |
src++;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
while (*src == '/')
|
|
Packit |
8480eb |
src++;
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* 39 is single quote */
|
|
Packit |
8480eb |
case 39:
|
|
Packit |
8480eb |
len++;
|
|
Packit |
8480eb |
if (dst)
|
|
Packit |
8480eb |
*dst++ = ch;
|
|
Packit |
8480eb |
squote = !squote;
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
default:
|
|
Packit |
8480eb |
if (dst)
|
|
Packit |
8480eb |
*(dst++) = ch;
|
|
Packit |
8480eb |
len++;
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
if (dst)
|
|
Packit |
8480eb |
*dst = '\0';
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return len;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
int expand_selectors(struct autofs_point *ap,
|
|
Packit |
8480eb |
const char *mapstr, char **pmapstr,
|
|
Packit |
8480eb |
struct substvar *sv)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
char buf[MAX_ERR_BUF];
|
|
Packit |
8480eb |
char *expand;
|
|
Packit |
8480eb |
size_t len;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!mapstr)
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
len = expandamdent(mapstr, NULL, sv);
|
|
Packit |
8480eb |
if (len == 0) {
|
|
Packit |
8480eb |
error(ap->logopt, "failed to expand map entry");
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
expand = malloc(len + 1);
|
|
Packit |
8480eb |
if (!expand) {
|
|
Packit |
8480eb |
char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
|
|
Packit |
8480eb |
error(ap->logopt, "malloc: %s", estr);
|
|
Packit |
8480eb |
return 0;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
memset(expand, 0, len + 1);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
expandamdent(mapstr, expand, sv);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
*pmapstr = expand;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return len;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Get next space seperated argument, arguments containing
|
|
Packit |
8480eb |
* space characters may be single quoted.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
static char *next_arg(char *str, char **next)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
char *start;
|
|
Packit |
8480eb |
char *ptr;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!*str)
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
start = ptr = str;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* The amd map format parser should ensure there
|
|
Packit |
8480eb |
* are matching single quotes.
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
if (*start == 39) {
|
|
Packit |
8480eb |
start++;
|
|
Packit |
8480eb |
ptr++;
|
|
Packit |
8480eb |
while (*ptr && *ptr != 39)
|
|
Packit |
8480eb |
ptr++;
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
while (*ptr && *ptr != ' ')
|
|
Packit |
8480eb |
ptr++;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (*ptr)
|
|
Packit |
8480eb |
*ptr++ = 0;
|
|
Packit |
8480eb |
*next = ptr;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return start;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Construct program path name plus argument array for use with
|
|
Packit |
8480eb |
* execv(3).
|
|
Packit |
8480eb |
*/
|
|
Packit |
8480eb |
int construct_argv(char *str, char **prog, char ***argv)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
char *program = NULL;
|
|
Packit |
8480eb |
char *start, *next;
|
|
Packit |
8480eb |
char **args, *arg;
|
|
Packit |
8480eb |
int argc;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
start = str;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
args = malloc(sizeof(char *));
|
|
Packit |
8480eb |
if (!args)
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
args[0] = NULL;
|
|
Packit |
8480eb |
argc = 0;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
next = NULL;
|
|
Packit |
8480eb |
program = next_arg(str, &next;;
|
|
Packit |
8480eb |
if (!program) {
|
|
Packit |
8480eb |
free(args);
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
start = next;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
while (1) {
|
|
Packit |
8480eb |
if (!*next)
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
arg = next_arg(start, &next;;
|
|
Packit |
8480eb |
if (arg) {
|
|
Packit |
8480eb |
argc++;
|
|
Packit |
8480eb |
args = add_argv(argc, args, arg);
|
|
Packit |
8480eb |
if (!args)
|
|
Packit |
8480eb |
return -1;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
start = next;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
*prog = program;
|
|
Packit |
8480eb |
*argv = args;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return argc;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
void free_map_type_info(struct map_type_info *info)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
if (info->type)
|
|
Packit |
8480eb |
free(info->type);
|
|
Packit |
8480eb |
if (info->format)
|
|
Packit |
8480eb |
free(info->format);
|
|
Packit |
8480eb |
if (info->map)
|
|
Packit |
8480eb |
free(info->map);
|
|
Packit |
8480eb |
free(info);
|
|
Packit |
8480eb |
return;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
struct map_type_info *parse_map_type_info(const char *str)
|
|
Packit |
8480eb |
{
|
|
Packit |
8480eb |
struct map_type_info *info;
|
|
Packit |
8480eb |
char *buf, *type, *fmt, *map, *tmp;
|
|
Packit |
8480eb |
char *pos;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
buf = strdup(str);
|
|
Packit |
8480eb |
if (!buf)
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
info = malloc(sizeof(struct map_type_info));
|
|
Packit |
8480eb |
if (!info) {
|
|
Packit |
8480eb |
free(buf);
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
memset(info, 0, sizeof(struct map_type_info));
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
type = fmt = map = NULL;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
tmp = strchr(buf, ':');
|
|
Packit |
8480eb |
if (!tmp) {
|
|
Packit |
8480eb |
pos = buf;
|
|
Packit |
8480eb |
while (*pos == ' ')
|
|
Packit |
8480eb |
*pos++ = '\0';
|
|
Packit |
8480eb |
map = pos;
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
int i, j;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
for (i = 0; i < map_type_count; i++) {
|
|
Packit |
8480eb |
char *m_type = map_type[i].type;
|
|
Packit |
8480eb |
unsigned int m_len = map_type[i].len;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
pos = buf;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (strncmp(m_type, pos, m_len))
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
type = pos;
|
|
Packit |
8480eb |
pos += m_len;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (*pos == ' ' || *pos == ':') {
|
|
Packit |
8480eb |
while (*pos == ' ')
|
|
Packit |
8480eb |
*pos++ = '\0';
|
|
Packit |
8480eb |
if (*pos != ':') {
|
|
Packit |
8480eb |
free(buf);
|
|
Packit |
8480eb |
free(info);
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
*pos++ = '\0';
|
|
Packit |
8480eb |
while (*pos && *pos == ' ')
|
|
Packit |
8480eb |
*pos++ = '\0';
|
|
Packit |
8480eb |
map = pos;
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (*pos == ',') {
|
|
Packit |
8480eb |
*pos++ = '\0';
|
|
Packit |
8480eb |
for (j = 0; j < format_type_count; j++) {
|
|
Packit |
8480eb |
char *f_type = format_type[j].type;
|
|
Packit |
8480eb |
unsigned int f_len = format_type[j].len;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (strncmp(f_type, pos, f_len))
|
|
Packit |
8480eb |
continue;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
fmt = pos;
|
|
Packit |
8480eb |
pos += f_len;
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (*pos == ' ' || *pos == ':') {
|
|
Packit |
8480eb |
while (*pos == ' ')
|
|
Packit |
8480eb |
*pos++ = '\0';
|
|
Packit |
8480eb |
if (*pos != ':') {
|
|
Packit |
8480eb |
free(buf);
|
|
Packit |
8480eb |
free(info);
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
} else {
|
|
Packit |
8480eb |
*pos++ = '\0';
|
|
Packit |
8480eb |
while (*pos && *pos == ' ')
|
|
Packit |
8480eb |
*pos++ = '\0';
|
|
Packit |
8480eb |
map = pos;
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (!type) {
|
|
Packit |
8480eb |
pos = buf;
|
|
Packit |
8480eb |
while (*pos == ' ')
|
|
Packit |
8480eb |
*pos++ = '\0';
|
|
Packit |
8480eb |
map = pos;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
/* Look for space terminator - ignore local options */
|
|
Packit |
8480eb |
for (tmp = buf; *tmp; tmp++) {
|
|
Packit |
8480eb |
if (*tmp == ' ') {
|
|
Packit |
8480eb |
*tmp = '\0';
|
|
Packit |
8480eb |
break;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
if (*tmp == '\\')
|
|
Packit |
8480eb |
tmp++;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (type) {
|
|
Packit |
8480eb |
info->type = strdup(type);
|
|
Packit |
8480eb |
if (!info->type) {
|
|
Packit |
8480eb |
free(buf);
|
|
Packit |
8480eb |
free_map_type_info(info);
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (fmt) {
|
|
Packit |
8480eb |
info->format = strdup(fmt);
|
|
Packit |
8480eb |
if (!info->format) {
|
|
Packit |
8480eb |
free(buf);
|
|
Packit |
8480eb |
free_map_type_info(info);
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
if (map) {
|
|
Packit |
8480eb |
info->map = strdup(map);
|
|
Packit |
8480eb |
if (!info->map) {
|
|
Packit |
8480eb |
free(buf);
|
|
Packit |
8480eb |
free_map_type_info(info);
|
|
Packit |
8480eb |
return NULL;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
free(buf);
|
|
Packit |
8480eb |
|
|
Packit |
8480eb |
return info;
|
|
Packit |
8480eb |
}
|
|
Packit |
8480eb |
|