예제 #1
0
파일: socket.c 프로젝트: mej/libast
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;
}
예제 #2
0
파일: str.c 프로젝트: mej/libast
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);
}
예제 #3
0
파일: str.c 프로젝트: mej/libast
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);
}
예제 #4
0
파일: str.c 프로젝트: mej/libast
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);
    }
}
예제 #5
0
파일: str.c 프로젝트: mej/libast
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);
    }
}
예제 #6
0
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;
}
예제 #7
0
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;
}
예제 #8
0
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;
}
예제 #9
0
파일: socket.c 프로젝트: mej/libast
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;
}
예제 #10
0
파일: str.c 프로젝트: mej/libast
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;
}
예제 #11
0
파일: str.c 프로젝트: mej/libast
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;
}
예제 #12
0
파일: socket.c 프로젝트: mej/libast
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;
}
예제 #13
0
파일: str.c 프로젝트: mej/libast
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);
}
예제 #14
0
파일: url.c 프로젝트: Limsik/e17
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;
}
예제 #15
0
파일: str.c 프로젝트: mej/libast
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;
}
예제 #16
0
파일: socket.c 프로젝트: mej/libast
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;
}
예제 #17
0
파일: str.c 프로젝트: mej/libast
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));
}
예제 #18
0
파일: str.c 프로젝트: mej/libast
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));
}
예제 #19
0
파일: socket.c 프로젝트: mej/libast
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;
}
예제 #20
0
파일: tok.c 프로젝트: Limsik/e17
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;
}
예제 #21
0
파일: options.c 프로젝트: mej/libast
/**
 * 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;
        }
    }
}
예제 #22
0
파일: url.c 프로젝트: Limsik/e17
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;
}