spif_bool_t spif_socket_send(spif_socket_t self, spif_str_t data) { size_t len; int num_written; struct timeval tv = { 0, 0 }; ASSERT_RVAL(!SPIF_SOCKET_ISNULL(self), FALSE); REQUIRE_RVAL(!SPIF_STR_ISNULL(data), FALSE); len = spif_str_get_len(data); REQUIRE_RVAL(len > 0, FALSE); num_written = write(self->fd, SPIF_STR_STR(data), len); for (; (num_written < 0) && ((errno == EAGAIN) || (errno == EINTR)); ) { tv.tv_usec += 10000; if (tv.tv_usec == 1000000) { tv.tv_usec = 0; tv.tv_sec++; } select(0, NULL, NULL, NULL, &tv); num_written = write(self->fd, SPIF_STR_STR(data), len); } if (num_written < 0) { D_OBJ(("Unable to write to socket %d -- %s\n", self->fd, strerror(errno))); switch (errno) { case EFBIG: { spif_bool_t b; spif_str_t tmp_buf; spif_charptr_t s; long left; for (left = len, s = SPIF_CHARPTR(SPIF_STR_STR(data)); left > 0; s += 1024, left -= 1024) { tmp_buf = spif_str_new_from_buff(s, 1024); b = spif_socket_send(self, tmp_buf); if (b == FALSE) { spif_str_del(tmp_buf); return b; } } } break; case EIO: case EPIPE: close(self->fd); /* Drop */ case EBADF: case EINVAL: default: self->fd = -1; SPIF_SOCKET_FLAGS_CLEAR(self, SPIF_SOCKET_FLAGS_IOSTATE); return FALSE; break; } } return TRUE; }
spif_cmp_t spif_str_ncmp(spif_str_t self, spif_str_t other, spif_stridx_t cnt) { int c; SPIF_OBJ_COMP_CHECK_NULL(self, other); c = strncmp((char *) SPIF_STR_STR(self), (char *) SPIF_STR_STR(other), cnt); return SPIF_CMP_FROM_INT(c); }
spif_cmp_t spif_str_casecmp(spif_str_t self, spif_str_t other) { int c; SPIF_OBJ_COMP_CHECK_NULL(self, other); c = strcasecmp((char *) SPIF_STR_STR(self), (char *) SPIF_STR_STR(other)); return SPIF_CMP_FROM_INT(c); }
spif_stridx_t spif_str_rindex(spif_str_t self, spif_char_t c) { char *tmp; ASSERT_RVAL(!SPIF_STR_ISNULL(self), ((spif_stridx_t) -1)); tmp = rindex((const char *) SPIF_STR_STR(self), c); if (tmp) { return (spif_stridx_t) ((spif_long_t) tmp - (spif_long_t) (SPIF_STR_STR(self))); } else { return (spif_stridx_t) (self->len); } }
spif_stridx_t spif_str_find_from_ptr(spif_str_t self, spif_charptr_t other) { char *tmp; ASSERT_RVAL(!SPIF_STR_ISNULL(self), ((spif_stridx_t) -1)); REQUIRE_RVAL((other != (spif_charptr_t) NULL), ((spif_stridx_t) -1)); tmp = strstr((const char *) SPIF_STR_STR(self), (const char *) other); if (tmp) { return (spif_stridx_t) ((spif_long_t) tmp - (spif_long_t) (SPIF_STR_STR(self))); } else { return (spif_stridx_t) (self->len); } }
static spif_bool_t action_handle_echo(event_t *ev, spif_eterm_action_t action) { REQUIRE_RVAL(!SPIF_PTR_ISNULL(ev), FALSE); REQUIRE_RVAL(!SPIF_STR_ISNULL(action->parameter), FALSE); #ifdef ESCREEN if (TermWin.screen && TermWin.screen->backend) { # ifdef NS_HAVE_SCREEN /* translate escapes */ ns_parse_screen_interactive(TermWin.screen, SPIF_STR_STR(action->parameter)); # endif } else #endif tt_write(SPIF_STR_STR(action->parameter), spif_str_get_len(SPIF_STR(action->parameter))); return 1; }
static spif_bool_t action_handle_string(event_t *ev, spif_eterm_action_t action) { REQUIRE_RVAL(!SPIF_PTR_ISNULL(ev), FALSE); REQUIRE_RVAL(!SPIF_STR_ISNULL(action->parameter), FALSE); cmd_write(SPIF_STR_STR(action->parameter), spif_str_get_len(SPIF_STR(action->parameter))); return 1; }
static spif_bool_t action_handle_script(event_t *ev, spif_eterm_action_t action) { REQUIRE_RVAL(!SPIF_PTR_ISNULL(ev), FALSE); REQUIRE_RVAL(!SPIF_STR_ISNULL(action->parameter), FALSE); script_parse(SPIF_STR_STR(action->parameter)); return 1; }
static spif_ipsockaddr_t spif_url_get_ipaddr(spif_url_t self) { spif_uint8_t tries; spif_hostinfo_t hinfo; spif_ipsockaddr_t addr; spif_str_t hostname; ASSERT_RVAL(!SPIF_URL_ISNULL(self), (spif_ipsockaddr_t) NULL); /* We need a hostname of some type to connect to. */ hostname = SPIF_STR(spif_url_get_host(self)); REQUIRE_RVAL(!SPIF_STR_ISNULL(hostname), (spif_ipsockaddr_t) NULL); /* Try up to 3 times to resolve the hostname. */ h_errno = 0; tries = 0; do { tries++; hinfo = gethostbyname((char *) SPIF_STR_STR(hostname)); } while ((tries <= 3) && (!hinfo) && (h_errno == TRY_AGAIN)); if (!hinfo) { libast_print_error("Unable to resolve hostname \"%s\" -- %s\n", SPIF_STR_STR(hostname), hstrerror(h_errno)); return (spif_ipsockaddr_t) NULL; } if (!hinfo->h_addr_list) { libast_print_error("Invalid address list returned by gethostbyname()\n"); return (spif_ipsockaddr_t) NULL; } /* Grab the host IP address and port number, both in network byte order. */ addr = SPIF_ALLOC(ipsockaddr); addr->sin_family = AF_INET; addr->sin_port = htons(spif_url_get_portnum(self)); memcpy(&(addr->sin_addr), (void *) (hinfo->h_addr_list[0]), sizeof(addr->sin_addr)); D_OBJ(("Got address 0x%08x and port %d for name \"%s\"\n", (long) ntohl(*((int *) (&addr->sin_addr))), (int) ntohs(addr->sin_port), SPIF_STR_STR(hostname))); return addr; }
spif_bool_t spif_str_append(spif_str_t self, spif_str_t other) { ASSERT_RVAL(!SPIF_STR_ISNULL(self), FALSE); REQUIRE_RVAL(!SPIF_STR_ISNULL(other), FALSE); if (other->size && other->len) { self->size += other->size - 1; self->s = (spif_charptr_t) REALLOC(self->s, self->size); memcpy(self->s + self->len, SPIF_STR_STR(other), other->len + 1); self->len += other->len; } return TRUE; }
spif_str_t spif_str_dup(spif_str_t self) { spif_str_t tmp; ASSERT_RVAL(!SPIF_STR_ISNULL(self), (spif_str_t) NULL); tmp = SPIF_ALLOC(str); memcpy(tmp, self, SPIF_SIZEOF_TYPE(str)); tmp->s = (spif_charptr_t) STRDUP((const char *) SPIF_STR_STR(self)); tmp->len = self->len; tmp->size = self->size; return tmp; }
static spif_unixsockaddr_t spif_url_get_unixaddr(spif_url_t self) { spif_unixsockaddr_t addr; ASSERT_RVAL(!SPIF_URL_ISNULL(self), (spif_unixsockaddr_t) NULL); /* No address to look up, just a file path. */ addr = SPIF_ALLOC(unixsockaddr); addr->sun_family = AF_UNIX; addr->sun_path[0] = 0; strncat(addr->sun_path, (char *) SPIF_STR_STR(spif_url_get_path(self)), sizeof(addr->sun_path) - 1); return addr; }
spif_str_t spif_str_substr(spif_str_t self, spif_stridx_t idx, spif_stridx_t cnt) { ASSERT_RVAL(!SPIF_STR_ISNULL(self), (spif_str_t) NULL); if (idx < 0) { idx = self->len + idx; } REQUIRE_RVAL(idx >= 0, (spif_str_t) NULL); REQUIRE_RVAL(idx < self->len, (spif_str_t) NULL); if (cnt <= 0) { cnt = self->len - idx + cnt; } REQUIRE_RVAL(cnt >= 0, (spif_str_t) NULL); UPPER_BOUND(cnt, self->len - idx); return spif_str_new_from_buff(SPIF_STR_STR(self) + idx, cnt); }
spif_bool_t spif_url_init_from_str(spif_url_t self, spif_str_t other) { ASSERT_RVAL(!SPIF_URL_ISNULL(self), FALSE); if (!spif_str_init_from_ptr(SPIF_STR(self), SPIF_STR_STR(other))) { return FALSE; } spif_obj_set_class(SPIF_OBJ(self), SPIF_CLASS_VAR(url)); self->proto = (spif_str_t) NULL; self->user = (spif_str_t) NULL; self->passwd = (spif_str_t) NULL; self->host = (spif_str_t) NULL; self->port = (spif_str_t) NULL; self->path = (spif_str_t) NULL; self->query = (spif_str_t) NULL; spif_url_parse(self); return TRUE; }
spif_charptr_t spif_str_substr_to_ptr(spif_str_t self, spif_stridx_t idx, spif_stridx_t cnt) { spif_charptr_t newstr; ASSERT_RVAL(!SPIF_STR_ISNULL(self), (spif_charptr_t) NULL); if (idx < 0) { idx = self->len + idx; } REQUIRE_RVAL(idx >= 0, (spif_charptr_t) NULL); REQUIRE_RVAL(idx < self->len, (spif_charptr_t) NULL); if (cnt <= 0) { cnt = self->len - idx + cnt; } REQUIRE_RVAL(cnt >= 0, (spif_charptr_t) NULL); UPPER_BOUND(cnt, self->len - idx); newstr = (spif_charptr_t) MALLOC(cnt + 1); memcpy(newstr, SPIF_STR_STR(self) + idx, cnt); newstr[cnt] = 0; return newstr; }
spif_bool_t spif_socket_open(spif_socket_t self) { ASSERT_RVAL(!SPIF_SOCKET_ISNULL(self), FALSE); if (!(self->addr)) { /* Set family, protocol, and type flags. */ spif_socket_get_proto(self); /* Get remote address, if we have one. */ if (SPIF_SOCKET_FLAGS_IS_SET(self, SPIF_SOCKET_FLAGS_FAMILY_INET)) { self->fam = AF_INET; if (!SPIF_URL_ISNULL(self->remote_url)) { self->addr = (spif_sockaddr_t) spif_url_get_ipaddr(self->remote_url); } else { self->addr = (spif_sockaddr_t) NULL; } if (self->addr == (spif_sockaddr_t) NULL) { self->len = 0; } else { self->len = SPIF_SIZEOF_TYPE(ipsockaddr); } } else if (SPIF_SOCKET_FLAGS_IS_SET(self, SPIF_SOCKET_FLAGS_FAMILY_UNIX)) { self->fam = AF_UNIX; if (!SPIF_URL_ISNULL(self->remote_url)) { self->addr = (spif_sockaddr_t) spif_url_get_unixaddr(self->remote_url); } else { self->addr = (spif_sockaddr_t) NULL; } if (self->addr == (spif_sockaddr_t) NULL) { self->len = 0; } else { self->len = SPIF_SIZEOF_TYPE(unixsockaddr); } } else { D_OBJ(("Unknown socket family 0x%08x!\n", SPIF_SOCKET_FLAGS_IS_SET(self, SPIF_SOCKET_FLAGS_FAMILY))); ASSERT_NOTREACHED_RVAL(FALSE); } } /* If the socket isn't open yet, open it and get a file descriptor. */ if (self->fd < 0) { if (SPIF_SOCKET_FLAGS_IS_SET(self, SPIF_SOCKET_FLAGS_TYPE_STREAM)) { self->type = SOCK_STREAM; } else if (SPIF_SOCKET_FLAGS_IS_SET(self, SPIF_SOCKET_FLAGS_TYPE_DGRAM)) { self->type = SOCK_DGRAM; } else if (SPIF_SOCKET_FLAGS_IS_SET(self, SPIF_SOCKET_FLAGS_TYPE_RAW)) { self->type = SOCK_RAW; } else { D_OBJ(("Unknown socket type 0x%08x!\n", SPIF_SOCKET_FLAGS_IS_SET(self, SPIF_SOCKET_FLAGS_TYPE))); ASSERT_NOTREACHED_RVAL(FALSE); } self->fd = (spif_sockfd_t) socket(self->fam, self->type, self->proto); if (self->fd < 0) { libast_print_error("Unable to create socket(%d, %d, %d) -- %s\n", (int) self->fam, (int) self->type, (int) self->proto, strerror(errno)); return FALSE; } /* If we have a local URL, bind it to the appropriate address and port. */ if (!SPIF_URL_ISNULL(self->local_url)) { if (SPIF_SOCKET_FLAGS_IS_SET(self, SPIF_SOCKET_FLAGS_FAMILY_INET)) { spif_ipsockaddr_t addr; addr = spif_url_get_ipaddr(self->local_url); D_OBJ(("Binding to port %d\n", ntohs(addr->sin_port))); if (bind(self->fd, (spif_sockaddr_t) addr, SPIF_SIZEOF_TYPE(ipsockaddr))) { libast_print_error("Unable to bind socket %d to %s -- %s\n", (int) self->fd, SPIF_STR_STR(self->local_url), strerror(errno)); FREE(addr); return FALSE; } FREE(addr); } else if (SPIF_SOCKET_FLAGS_IS_SET(self, SPIF_SOCKET_FLAGS_FAMILY_UNIX)) { spif_unixsockaddr_t addr; addr = spif_url_get_unixaddr(self->local_url); if (bind(self->fd, (spif_sockaddr_t) addr, SPIF_SIZEOF_TYPE(unixsockaddr))) { libast_print_error("Unable to bind socket %d to %s -- %s\n", (int) self->fd, SPIF_STR_STR(self->local_url), strerror(errno)); FREE(addr); return FALSE; } FREE(addr); } } SPIF_SOCKET_FLAGS_SET(self, SPIF_SOCKET_FLAGS_OPEN); } /* Connect if we have a destination. If not, open a listening socket. */ if (!SPIF_URL_ISNULL(self->remote_url)) { spif_socket_clear_nbio(self); if ((connect(self->fd, self->addr, self->len)) < 0) { libast_print_error("Unable to connect socket %d to %s -- %s\n", (int) self->fd, SPIF_STR_STR(self->remote_url), strerror(errno)); return FALSE; } SPIF_SOCKET_FLAGS_SET(self, SPIF_SOCKET_FLAGS_CONNECTED); } else if (!SPIF_URL_ISNULL(self->local_url)) { if ((listen(self->fd, 5)) < 0) { libast_print_error("Unable to listen at %s on socket %d -- %s\n", SPIF_STR_STR(self->local_url), (int) self->fd, strerror(errno)); return FALSE; } SPIF_SOCKET_FLAGS_SET(self, SPIF_SOCKET_FLAGS_LISTEN); } return TRUE; }
double spif_str_to_float(spif_str_t self) { ASSERT_RVAL(!SPIF_STR_ISNULL(self), (double) NAN); return (double) (strtod((const char *)SPIF_STR_STR(self), (char **) NULL)); }
size_t spif_str_to_num(spif_str_t self, int base) { ASSERT_RVAL(!SPIF_STR_ISNULL(self), ((size_t) -1)); return (size_t) (strtoul((const char *) SPIF_STR_STR(self), (char **) NULL, base)); }
static spif_bool_t spif_socket_get_proto(spif_socket_t self) { spif_url_t url; spif_protoinfo_t proto; spif_str_t proto_str; spif_servinfo_t serv; ASSERT_RVAL(!SPIF_URL_ISNULL(self), FALSE); /* If we have a remote URL, use it. Otherwise, use the local one. */ url = ((SPIF_URL_ISNULL(self->remote_url)) ? (self->local_url) : (self->remote_url)); REQUIRE_RVAL(!SPIF_URL_ISNULL(url), FALSE); proto_str = spif_url_get_proto(url); if (!SPIF_STR_ISNULL(proto_str)) { if (SPIF_CMP_IS_EQUAL(spif_str_cmp_with_ptr(proto_str, SPIF_CHARPTR("raw")))) { spif_str_t target; /* Raw socket. Could be raw UNIX or raw IP. */ SPIF_SOCKET_FLAGS_SET(self, SPIF_SOCKET_FLAGS_TYPE_RAW); /* If we have a hostname, it's IP. If we have a path only, it's UNIX. */ target = spif_url_get_host(url); if (SPIF_STR_ISNULL(target)) { target = spif_url_get_path(url); if (!SPIF_STR_ISNULL(target)) { SPIF_SOCKET_FLAGS_SET(self, SPIF_SOCKET_FLAGS_FAMILY_UNIX); } } else { SPIF_SOCKET_FLAGS_SET(self, SPIF_SOCKET_FLAGS_FAMILY_INET); } } else if (SPIF_CMP_IS_EQUAL(spif_str_cmp_with_ptr(proto_str, SPIF_CHARPTR("unix")))) { /* UNIX socket. Assume stream-based. */ SPIF_SOCKET_FLAGS_SET(self, SPIF_SOCKET_FLAGS_FAMILY_UNIX); SPIF_SOCKET_FLAGS_SET(self, SPIF_SOCKET_FLAGS_TYPE_STREAM); } else { /* IP socket. See if they gave us a protocol name. */ SPIF_SOCKET_FLAGS_SET(self, SPIF_SOCKET_FLAGS_FAMILY_INET); proto = getprotobyname((char *) SPIF_STR_STR(proto_str)); if (!proto) { /* If it's not a protocol, it's probably a service. */ serv = getservbyname((char *) SPIF_STR_STR(proto_str), "tcp"); if (!serv) { serv = getservbyname((char *) SPIF_STR_STR(proto_str), "udp"); } if (serv) { /* If we found one, get the protocol info too. */ proto = getprotobyname(serv->s_proto); REQUIRE_RVAL(proto != NULL, FALSE); } } if (proto) { /* Bingo. Set the flags appropriately. */ self->proto = proto->p_proto; if (!strcmp(proto->p_name, "tcp")) { SPIF_SOCKET_FLAGS_SET(self, SPIF_SOCKET_FLAGS_TYPE_STREAM); } else if (!strcmp(proto->p_name, "udp")) { SPIF_SOCKET_FLAGS_SET(self, SPIF_SOCKET_FLAGS_TYPE_DGRAM); } } } } else { /* No protocol? Assume a UNIX socket. */ SPIF_SOCKET_FLAGS_SET(self, SPIF_SOCKET_FLAGS_FAMILY_UNIX); SPIF_SOCKET_FLAGS_SET(self, SPIF_SOCKET_FLAGS_TYPE_STREAM); } return TRUE; }
spif_bool_t spif_tok_eval(spif_tok_t self) { const char *pstr, *delim = NULL; spif_str_t tmp; char quote; size_t len; ASSERT_RVAL(!SPIF_TOK_ISNULL(self), FALSE); REQUIRE_RVAL(!SPIF_STR_ISNULL(self->src), FALSE); pstr = (const char *) SPIF_STR_STR(SPIF_STR(self->src)); len = spif_str_get_len(SPIF_STR(self->src)); if (!SPIF_STR_ISNULL(self->sep)) { delim = (const char *) SPIF_STR_STR(SPIF_STR(self->sep)); } if (!SPIF_LIST_ISNULL(self->tokens)) { SPIF_LIST_DEL(self->tokens); } self->tokens = SPIF_LIST_NEW(dlinked_list); /* Before we do anything, skip leading "whitespace." */ for (; *pstr && IS_DELIM(*pstr); pstr++); /* The outermost for loop is where we traverse the string. Each new word brings us back to the top where we resize our string list. */ for (quote = 0; *pstr; ) { tmp = spif_str_new_from_buff(SPIF_CHARPTR(""), len); spif_str_clear(tmp, 0); /* This for loop is where we process each character. */ for (; *pstr && (quote || !IS_DELIM(*pstr));) { if (*pstr == self->dquote || *pstr == self->quote) { /* It's a quote character, so set or reset the quote variable. */ if (quote) { if (quote == *pstr) { quote = 0; } else { /* It's a single quote inside double quotes, or vice versa. Leave it alone. */ spif_str_append_char(tmp, *pstr); } } else { quote = *pstr; } pstr++; } else { /* Handle any backslashes that are escaping delimiters or quotes. */ if ((*pstr == self->escape) && (IS_DELIM(*(pstr + 1)) || IS_QUOTE(*(pstr + 1)))) { /* Incrementing pstr here moves us past the backslash so that the line below will copy the next character to the new token, no questions asked. */ pstr++; } spif_str_append_char(tmp, *pstr++); } } /* Reallocate the new string to be just the right size. */ spif_str_trim(tmp); len -= spif_str_get_len(tmp); /* Add it to the list */ SPIF_LIST_APPEND(self->tokens, tmp); /* Move past any trailing "whitespace." */ for (; *pstr && IS_DELIM(*pstr); pstr++); } return TRUE; }
/** * Parse the command line arguments for options. * * This function iterates through the command line arguments looking * for options which have been defined. Each option encountered is * handled according to its type. * * @param argc The number of arguments. * @param argv The array of argument strings. * * @see @link DOXGRP_OPT Command Line Option Parser @endlink * @ingroup DOXGRP_OPT */ void spifopt_parse(int argc, char *argv[]) { spif_int32_t i, j; spif_charptr_t opt; REQUIRE(argc > 1); REQUIRE(argv != NULL); /* Process each command line arg one-by-one. */ for (i = 1, opt = SPIF_CHARPTR(argv[1]); i < argc; ) { spif_charptr_t val_ptr = NULL; spif_char_t islong = 0, hasequal = 0; D_OPTIONS(("argv[%d] == \"%s\", opt == \"%s\"\n", i, argv[i], opt)); if (SPIF_PTR_ISNULL(opt)) { /* NEXT_ARG(); */ break; } else if (opt == SPIF_CHARPTR(argv[i])) { /* If it's not an option, skip it. */ if (*opt != '-') { NEXT_ARG(); } else { opt++; } } /* If the second character is also a hyphen, it's a long option. */ if (*opt == '-') { islong = 1; /* Skip the leading "--" */ opt++; D_OPTIONS(("Long option detected\n")); if ((j = find_long_option(opt)) == -1) { NEXT_ARG(); } } else { if ((j = find_short_option(*opt)) == -1) { NEXT_LETTER(); } } if (!SPIFOPT_FLAGS_IS_SET(SPIFOPT_SETTING_PREPARSE) && SPIFOPT_FLAGS_IS_SET(SPIFOPT_SETTING_REMOVE_ARGS)) { argv[i] = NULL; } /* If a value was passed to this option, set val_ptr to point to it. */ if (islong) { val_ptr = find_value_long(SPIF_CHARPTR(opt), SPIF_CHARPTR(argv[i + 1]), &hasequal); } else { val_ptr = find_value_short(opt, SPIF_CHARPTR(argv[i + 1])); } /* Boolean options may or may not have a value... */ if (val_ptr) { if (SPIFOPT_OPT_IS_BOOLEAN(j) && !is_boolean_value(val_ptr)) { val_ptr = NULL; } else if (SPIFOPT_OPT_IS_ABSTRACT(j) && is_valid_option(val_ptr)) { val_ptr = NULL; } } if (val_ptr) { if (val_ptr == SPIF_CHARPTR(argv[i + 1])) { i++; opt += strlen((char *) opt); } } /* If this option is deprecated, print a warning before continuing. */ if (SPIFOPT_OPT_IS_DEPRECATED(j)) { spif_str_t warn; warn = spif_str_new_from_buff(SPIF_CHARPTR("The "), 128); if (SPIFOPT_OPT_SHORT(j)) { spif_str_append_char(warn, '-'); spif_str_append_char(warn, SPIFOPT_OPT_SHORT(j)); spif_str_append_from_ptr(warn, SPIF_CHARPTR(" / --")); } else { spif_str_append_from_ptr(warn, SPIF_CHARPTR("--")); } spif_str_append_from_ptr(warn, SPIFOPT_OPT_LONG(j)); spif_str_append_from_ptr(warn, SPIF_CHARPTR(" option is deprecated and should not be used.\n")); libast_print_warning((char *) SPIF_STR_STR(warn)); spif_str_del(warn); } /* Make sure that options which require a parameter have them. */ if (SPIFOPT_OPT_NEEDS_VALUE(j)) { if (!val_ptr) { if (islong) { libast_print_error("long option --%s requires a%s value\n", SPIFOPT_OPT_LONG(j), (SPIFOPT_OPT_IS_INTEGER(j) ? ("n integer") : (SPIFOPT_OPT_IS_STRING(j) ? " string" : (SPIFOPT_OPT_IS_ARGLIST(j) ? "n argument list" : "")))); } else { libast_print_error("option -%c requires a%s value\n", SPIFOPT_OPT_SHORT(j), (SPIFOPT_OPT_IS_INTEGER(j) ? ("n integer") : (SPIFOPT_OPT_IS_STRING(j) ? " string" : (SPIFOPT_OPT_IS_ARGLIST(j) ? "n argument list" : "")))); } CHECK_BAD(); continue; } /* Also make sure we know what to do with the value. */ if (!SPIFOPT_OPT_VALUE(j)) { NEXT_LOOP(); } } else if (SPIFOPT_OPT_IS_ABSTRACT(j) && !SPIFOPT_OPT_VALUE(j)) { /* Also make sure that abstract options have a function pointer. */ NEXT_LOOP(); } if (SPIFOPT_OPT_IS_BOOLEAN(j)) { if (!handle_boolean(j, val_ptr, islong)) { i--; } } else if (SPIFOPT_OPT_IS_STRING(j)) { if (SHOULD_PARSE(j)) { handle_string(j, val_ptr); } } else if (SPIFOPT_OPT_IS_INTEGER(j)) { if (SHOULD_PARSE(j)) { handle_integer(j, val_ptr); } } else if (SPIFOPT_OPT_IS_ARGLIST(j)) { if (SHOULD_PARSE(j)) { handle_arglist(j, val_ptr, hasequal, i, argc, argv); } if (!hasequal) { break; } } else if (SPIFOPT_OPT_IS_ABSTRACT(j)) { if (SHOULD_PARSE(j)) { D_OPTIONS(("Abstract option detected\n")); ((spifopt_abstract_handler_t) SPIFOPT_OPT_VALUE(j))(val_ptr); } } if (!SPIFOPT_FLAGS_IS_SET(SPIFOPT_SETTING_PREPARSE) && SPIFOPT_FLAGS_IS_SET(SPIFOPT_SETTING_REMOVE_ARGS)) { argv[i] = NULL; } NEXT_LOOP(); } if (SPIFOPT_FLAGS_IS_SET(SPIFOPT_SETTING_PREPARSE)) { SPIFOPT_FLAGS_CLEAR(SPIFOPT_SETTING_PREPARSE); } else if (SPIFOPT_FLAGS_IS_SET(SPIFOPT_SETTING_REMOVE_ARGS)) { for (i = 1, j = 1; i < argc; i++) { if (argv[i]) { argv[j] = argv[i]; j++; } } if (j > 1) { argv[j] = NULL; } } }
static spif_bool_t spif_url_parse(spif_url_t self) { spif_charptr_t s = SPIF_STR_STR(SPIF_STR(self)); spif_charptr_t pstr, pend, ptmp; ASSERT_RVAL(!SPIF_URL_ISNULL(self), FALSE); pstr = s; /* Check for "proto:" at the beginning. */ pend = SPIF_CHARPTR(strchr((char *) s, ':')); if (pend) { for (; pstr < pend; pstr++) { if (!isalnum(*pstr)) { break; } } if (pstr == pend) { /* Got one. */ self->proto = spif_str_new_from_buff(s, pend - s); pstr++; } else { /* Nope, reset. */ pstr = s; } } if ((*pstr == '/') && (pstr[1] == '/')) { pstr += 2; } /* Knock out the path and query if they're there. */ pend = SPIF_CHARPTR(strchr((char *) pstr, '/')); if (pend) { spif_charptr_t tmp = SPIF_CHARPTR(strchr((char *) pend, '?')); if (tmp) { self->query = spif_str_new_from_ptr(tmp + 1); self->path = spif_str_new_from_buff(pend, tmp - pend); } else { self->path = spif_str_new_from_ptr(pend); } } else if ((pend = SPIF_CHARPTR(strchr((char *)pstr, '?')))) { self->query = spif_str_new_from_ptr(pend + 1); } else { for (pend = pstr; *pend; pend++); } /* At this point, pend *must* point to the end of the user/pass/host/port part. */ /* Check for an @ sign, which would mean we have auth info. */ ptmp = SPIF_CHARPTR(strchr((char *) pstr, '@')); if ((ptmp) && (ptmp < pend)) { spif_charptr_t tmp = SPIF_CHARPTR(strchr((char *) pstr, ':')); if ((tmp) && (tmp < ptmp)) { /* Both username and password. */ self->user = spif_str_new_from_buff(pstr, tmp - pstr); self->passwd = spif_str_new_from_buff((tmp + 1), ptmp - tmp - 1); } else { self->user = spif_str_new_from_buff(pstr, ptmp - pstr); } pstr = ptmp + 1; } /* All that remains now between pstr and pend is host and maybe port. */ ptmp = SPIF_CHARPTR(strchr((char *) pstr, ':')); if ((ptmp) && (ptmp < pend)) { self->host = spif_str_new_from_buff(pstr, ptmp - pstr); self->port = spif_str_new_from_buff((ptmp + 1), pend - ptmp - 1); } else if (pstr != pend) { self->host = spif_str_new_from_buff(pstr, pend - pstr); } /* If we have a proto but no port, see if we can resolve the port using the proto. */ if (SPIF_STR_ISNULL(self->port) && !SPIF_STR_ISNULL(self->proto)) { spif_protoinfo_t proto; spif_servinfo_t serv; proto = getprotobyname((char *) SPIF_STR_STR(self->proto)); if (!proto) { /* If it's not a protocol, it's probably a service. */ serv = getservbyname((char *) SPIF_STR_STR(self->proto), "tcp"); if (!serv) { serv = getservbyname((char *) SPIF_STR_STR(self->proto), "udp"); } if (serv) { proto = getprotobyname(serv->s_proto); REQUIRE_RVAL(proto != NULL, FALSE); } } if (proto) { spif_char_t buff[32]; snprintf((char *) buff, sizeof(buff), "%d", ntohs(serv->s_port)); self->port = spif_str_new_from_ptr(buff); } } return TRUE; }