int alias_install(const char *kw, int argc, char **argv, grecs_locus_t *ploc) { struct alias *sample = xmalloc(sizeof(*sample)), *ap; sample->kw = xstrdup(kw); sample->argc = argc; sample->argv = argv; sample->locus = *ploc; if (! ((alias_table || (alias_table = hash_initialize(0, 0, alias_hasher, alias_compare, NULL))) && (ap = hash_insert(alias_table, sample)))) xalloc_die(); if (ap != sample) { free(sample->kw); free(sample); grecs_error(ploc, 0, _("alias `%s' already defined"), kw); grecs_error(&ap->locus, 0, _("this is the location of the previous definition")); return 1; /* Found */ } return 0; }
int grecs_str_to_sockaddr(struct grecs_sockaddr **sap, const char *arg, struct grecs_sockaddr_hints *gh, grecs_locus_t const *locus) { char *p; struct grecs_sockaddr_hints ghints; if (!gh) { memset(&ghints, 0, sizeof(ghints)); if (grecs_default_port) { ghints.flags = GRECS_HINT_PORT; ghints.port = ntohs(grecs_default_port); } gh = &ghints; } p = strchr(arg, ':'); if (p && p > arg && p[1] == '/' && p[2] == '/') { size_t len = p - arg; struct schemetab *sp; for (sp = schemetab; sp->scheme; sp++) if (len == sp->len && memcmp(arg, sp->scheme, len) == 0) return sp->parser(sap, arg, p + 3, gh, locus); grecs_error(locus, 0, _("unknown or unsupported scheme: %s"), arg); return -1; } if (arg[0] == '/') return parse_unix(sap, arg, arg, gh, locus); else if (strlen(arg) > 5 && memcmp(arg, "unix:", 5) == 0) { if (arg[5] != '/') grecs_error(locus, 0, _("%s: UNIX socket must be an absolute file name"), arg); return parse_unix(sap, arg, arg + 5, gh, locus); } return parse_inet(sap, AF_UNSPEC, arg, arg, gh, locus); }
dico_list_t dicod_string_list_from_grecs(struct grecs_list *inlist) { struct grecs_list_entry *ep; dico_list_t list = xdico_list_create(); dico_list_set_free_item(list, dicod_free_item, NULL); for (ep = inlist->head; ep; ep = ep->next) { grecs_value_t *vp = ep->data; if (vp->type != GRECS_TYPE_STRING) { grecs_error(&vp->locus, 0, _("expected string")); break; } xdico_list_append(list, xstrdup(vp->v.string)); } return list; }
static int parse_unix(struct grecs_sockaddr **ret, const char *arg, const char *addrstr, struct grecs_sockaddr_hints *gh, grecs_locus_t const *locus) { struct sockaddr_un *s_un; size_t slen = strlen(addrstr); struct grecs_sockaddr *sp; if (slen >= sizeof s_un->sun_path) { grecs_error(locus, 0, _("socket path name too long: %s"), arg); return -1; } sp = grecs_sockaddr_new(sizeof(s_un[0])); s_un = (struct sockaddr_un *) sp->sa; s_un->sun_family = AF_UNIX; strcpy(s_un->sun_path, addrstr); *ret = sp; return 0; }
struct grecs_node * grecs_path_parser(const char *name, int traceflags) { struct grecs_node *root, *subtree = NULL, *node; FILE *infile; struct grecs_txtacc *acc = NULL; char *kw, *val; grecs_locus_t kwloc, valloc, rootloc; int inquote; int lookahead; int err = 0; unsigned prev_col; infile = fopen(name, "r"); if (!infile) { grecs_error(NULL, errno, _("cannot open `%s'"), name); return NULL; } grecs_current_locus_point.file = grecs_install_text(name); grecs_current_locus_point.line = 1; grecs_current_locus_point.col = 0; rootloc.beg = grecs_current_locus_point; rootloc.beg.col++; acc = grecs_txtacc_create(); while ((lookahead = next_char(infile)) > 0) { while (1) { while (lookahead == ' ' || lookahead == '\t') lookahead = next_char(infile); if (lookahead == '#') { while ((lookahead = next_char(infile)) && lookahead != '\n') ; continue; } break; } if (lookahead <= 0) break; kwloc.beg = grecs_current_locus_point; inquote = 0; for (; lookahead > 0 && lookahead != ':'; lookahead = next_char(infile)) { if (inquote) { if (inquote == '"' && lookahead == '\\') { lookahead = next_char(infile); if (lookahead <= 0) break; } else if (lookahead == inquote) inquote = 0; } else if (lookahead == '\'' || lookahead == '"') inquote = lookahead; grecs_txtacc_grow_char(acc, lookahead); } if (lookahead <= 0) { grecs_error(&kwloc, 0, _("unexpected end of file")); err = 1; break; } grecs_txtacc_grow_char(acc, 0); kw = grecs_txtacc_finish(acc, 0); kwloc.end = grecs_current_locus_point; kwloc.end.col--; while ((lookahead = next_char(infile)) > 0 && (lookahead == ' ' || lookahead == '\t')); if (lookahead <= 0) { grecs_error(&kwloc, 0, _("unexpected end of file")); err = 1; break; } valloc.beg = grecs_current_locus_point; do { grecs_txtacc_grow_char(acc, lookahead); prev_col = grecs_current_locus_point.col; } while ((lookahead = next_char(infile)) > 0 && lookahead != '\n'); valloc.end = grecs_current_locus_point; valloc.end.line--; valloc.end.col = prev_col; grecs_txtacc_grow_char(acc, 0); val = grecs_txtacc_finish(acc, 0); node = grecs_node_from_path_locus(kw, val, &kwloc, &valloc); if (!node) { grecs_error(&kwloc, 0, _("parse error")); err = 1; break; } node->locus.end = valloc.end; node->idloc = kwloc; if (!subtree) subtree = node; else grecs_node_bind(subtree, node, 0); grecs_txtacc_free_string(acc, kw); grecs_txtacc_free_string(acc, val); } fclose(infile); grecs_txtacc_free(acc); if (err) { grecs_tree_free(subtree); root = NULL; } else { rootloc.end = grecs_current_locus_point; root = grecs_node_create(grecs_node_root, &rootloc); root->v.texttab = grecs_text_table(); grecs_node_bind(root, subtree, 1); grecs_tree_reduce(root, NULL, 0); } return root; }
static int parse_inet(struct grecs_sockaddr **ret, int family, const char *arg, const char *addrstr, struct grecs_sockaddr_hints *gh, grecs_locus_t const *locus) { int rc; struct addrinfo hints; struct addrinfo *res, *ap; const char *node = NULL; char *nodebuf = NULL; const char *service = NULL; struct grecs_sockaddr *head = NULL, *tail = NULL; char portbuf[64]; memset(&hints, 0, sizeof(hints)); hints.ai_family = family; hints.ai_socktype = SOCK_STREAM; if ((family == AF_INET6 || family == AF_UNSPEC) && addrstr[0] == '[') { char *p = strchr(addrstr + 1, ']'); if (p && p > addrstr + 1) { size_t len; addrstr++; len = p - addrstr; nodebuf = grecs_malloc(len + 1); memcpy(nodebuf, addrstr, len); nodebuf[len] = 0; node = nodebuf; service = p + 1; family = AF_INET6; } else service = strchr(addrstr, ':'); } else service = strrchr(addrstr, ':'); if (service && *service) { if (*service != ':') { grecs_error(locus, 0, _("%s: garbage near %s"), arg, service); return -1; } service++; } if (!node) { if (service) { size_t len = service - addrstr - 1; if (len == 0) node = NULL; else { nodebuf = grecs_malloc(len + 1); memcpy(nodebuf, addrstr, len); nodebuf[len] = 0; node = nodebuf; } } else { if (grecs_str_is_ipaddr(addrstr)) node = addrstr; else if (grecs_str_is_num(addrstr)) { service = addrstr; hints.ai_flags |= AI_NUMERICSERV; } } } if (!service || !*service) { if (!node && addrstr[0]) node = addrstr; if (gh->flags & GRECS_HINT_SERVICE) { service = gh->service; } else if (gh->flags & GRECS_HINT_PORT) { snprintf(portbuf, sizeof portbuf, "%hu", gh->port); service = portbuf; hints.ai_flags |= AI_NUMERICSERV; } else if (!(gh->flags & GRECS_AH_PASSIVE)) { grecs_error(locus, 0, _("service not specified: %s"), arg); return -1; } } if (!node) { if (gh->flags & GRECS_AH_PASSIVE) hints.ai_flags |= AI_PASSIVE; } rc = getaddrinfo(node, service, &hints, &res); free(nodebuf); switch (rc) { case 0: break; case EAI_SYSTEM: grecs_error(locus, 0, _("%s: cannot parse address: %s"), arg, strerror(errno)); break; case EAI_BADFLAGS: case EAI_SOCKTYPE: grecs_error(locus, 0, "%s:%d: internal error converting %s", __FILE__,__LINE__,arg); break; case EAI_MEMORY: grecs_alloc_die(); default: grecs_error(locus, 0, "%s: %s", arg, gai_strerror(rc)); return -1; } for (ap = res; ap; ap = ap->ai_next) { if (family == AF_UNSPEC || ap->ai_addr->sa_family == family) { struct grecs_sockaddr *sp = grecs_sockaddr_new(ap->ai_addrlen); memcpy(sp->sa, ap->ai_addr, ap->ai_addrlen); sp->len = ap->ai_addrlen; if (!head) head = sp; else tail->next = sp; tail = sp; } } freeaddrinfo(res); *ret = head; return 0; }
static int _parse_sockaddr(struct acl_entry *entry, grecs_value_t *value) { struct dicod_sockaddr *sptr; const char *string; if (value->type != GRECS_TYPE_STRING) { grecs_error(&entry->locus, 0, _("expected string but found list")); return 1; } string = value->v.string; if (string[0] == '/') { size_t len; struct sockaddr_un *s_un; len = strlen (string); if (len >= sizeof(s_un->sun_path)) { grecs_error(&entry->locus, 0, _("socket name too long: `%s'"), string); return 1; } sptr = create_acl_sockaddr(AF_UNIX, sizeof(s_un)); s_un = (struct sockaddr_un *) &sptr->sa; memcpy(s_un->sun_path, string, len); s_un->sun_path[len] = 0; } else { struct in_addr addr; struct sockaddr_in *s_in; char *p = strchr(string, '/'); if (p) *p = 0; if (inet_aton(string, &addr) == 0) { struct hostent *hp = gethostbyname(string); if (!hp) { grecs_error(&entry->locus, 0, _("cannot resolve host name: `%s'"), string); if (p) *p = '/'; return 1; } memcpy(&addr.s_addr, hp->h_addr, sizeof(addr.s_addr)); } addr.s_addr = ntohl(addr.s_addr); sptr = create_acl_sockaddr(AF_INET, sizeof(s_in)); s_in = (struct sockaddr_in *) &sptr->sa; s_in->sin_addr = addr; if (p) { *p++ = '/'; char *q; unsigned netlen; netlen = strtoul(p, &q, 10); if (*q == 0) { if (netlen == 0) sptr->netmask = 0; else { sptr->netmask = 0xfffffffful >> (32 - netlen); sptr->netmask <<= (32 - netlen); } } else if (*q == '.') { struct in_addr addr; if (inet_aton(p, &addr) == 0) { grecs_error(&entry->locus, 0, _("invalid netmask: `%s'"), p); return 1; } sptr->netmask = addr.s_addr; } else { grecs_error(&entry->locus, 0, _("invalid netmask: `%s'"), p); return 1; } } else