/* Lookup a text. If it does not exist, create it. */ char * grecs_install_text(const char *str) { struct grecs_syment key; struct grecs_syment *ent; int install = 1; if (!text_table) { text_table = grecs_symtab_create_default( sizeof(struct grecs_syment)); if (!text_table) grecs_alloc_die(); } key.name = (char*) str; ent = grecs_symtab_lookup_or_install(text_table, &key, &install); if (!ent) grecs_alloc_die(); return ent->name; }
static void reset_point(struct grecs_locus_point *point, struct grecs_symtab *st) { struct grecs_syment *ent, key; int install = 1; if (!point->file) return; key.name = (char*) point->file; ent = grecs_symtab_lookup_or_install(st, &key, &install); if (!ent) grecs_alloc_die(); point->file = ent->name; }
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; }