コード例 #1
0
ファイル: vector.c プロジェクト: romkazor/sngrep
void
vector_clear(vector_t *vector)
{
    // Remove all items in the vector
    while (vector_first(vector))
        vector_remove(vector, vector_first(vector));
}
コード例 #2
0
ファイル: sip_msg.c プロジェクト: cukupupas/sngrep
const char *
msg_get_attribute(sip_msg_t *msg, int id, char *value)
{
    sdp_media_t *media;
    char *ar;

    switch (id) {
        case SIP_ATTR_SRC:
            sprintf(value, "%s:%u", msg->packet->ip_src, msg->packet->sport);
            break;
        case SIP_ATTR_DST:
            sprintf(value, "%s:%u", msg->packet->ip_dst, msg->packet->dport);
            break;
        case SIP_ATTR_METHOD:
            if (sip_method_str(msg->reqresp)) {
                sprintf(value, "%s", sip_method_str(msg->reqresp));
            } else {
                sip_get_response_str(msg, value);
            }
            break;
        case SIP_ATTR_SIPFROM:
            sprintf(value, "%s", msg->sip_from);
            break;
        case SIP_ATTR_SIPTO:
            sprintf(value, "%s", msg->sip_to);
            break;
        case SIP_ATTR_SIPFROMUSER:
            sprintf(value, "%s", msg->sip_from);
            if ((ar = strchr(value, '@')))
                *ar = '\0';
            break;
        case SIP_ATTR_SIPTOUSER:
            sprintf(value, "%s", msg->sip_to);
            if ((ar = strchr(value, '@')))
                *ar = '\0';
            break;
        case SIP_ATTR_DATE:
            timeval_to_date(msg_get_time(msg), value);
            break;
        case SIP_ATTR_TIME:
            timeval_to_time(msg_get_time(msg), value);
            break;
        case SIP_ATTR_SDP_ADDRESS:
            if ((media = vector_first(msg->medias)))
                sprintf(value, "%s", media_get_address(media));
            break;
        case SIP_ATTR_SDP_PORT:
            if ((media = vector_first(msg->medias)))
                sprintf(value, "%d", media_get_port(media));
            break;
        default:
            fprintf(stderr, "Unhandled attribute %s (%d)\n", sip_attr_get_name(id), id); abort();
        break;
    }

    return strlen(value) ? value : NULL;

}
コード例 #3
0
ファイル: sip_msg.c プロジェクト: cukupupas/sngrep
struct timeval
msg_get_time(sip_msg_t *msg) {
    struct timeval t = { };
    capture_frame_t *frame;

    if (msg && (frame = vector_first(msg->packet->frames)))
        return frame->header->ts;
    return t;
}
コード例 #4
0
ファイル: sip_call.c プロジェクト: digitainc/sngrep
int
call_is_invite(sip_call_t *call)
{
    sip_msg_t *first;
    if ((first = vector_first(call->msgs)))
        return (first->reqresp == SIP_METHOD_INVITE);

    return 0;
}
コード例 #5
0
ファイル: sip_call.c プロジェクト: digitainc/sngrep
const char *
call_get_attribute(sip_call_t *call, enum sip_attr_id id, char *value)
{
    sip_msg_t *first, *last;

    if (!call)
        return NULL;

    switch (id) {
        case SIP_ATTR_CALLINDEX:
            sprintf(value, "%d", call->index);
            break;
        case SIP_ATTR_CALLID:
            sprintf(value, "%s", call->callid);
            break;
        case SIP_ATTR_XCALLID:
            sprintf(value, "%s", call->xcallid);
            break;
        case SIP_ATTR_MSGCNT:
            sprintf(value, "%d", vector_count(call->msgs));
            break;
        case SIP_ATTR_CALLSTATE:
            sprintf(value, "%s", call_state_to_str(call->state));
            break;
        case SIP_ATTR_TRANSPORT:
            first = vector_first(call->msgs);
            sprintf(value, "%s", sip_transport_str(first->packet->type));
            break;
        case SIP_ATTR_CONVDUR:
            timeval_to_duration(msg_get_time(call->cstart_msg), msg_get_time(call->cend_msg), value);
            break;
        case SIP_ATTR_TOTALDUR:
            first = vector_first(call->msgs);
            last = vector_last(call->msgs);
            timeval_to_duration(msg_get_time(first), msg_get_time(last), value);
            break;
        default:
            return msg_get_attribute(vector_first(call->msgs), id, value);
            break;
    }

    return strlen(value) ? value : NULL;
}
コード例 #6
0
ファイル: capture.c プロジェクト: cruzccl/sngrep
pcap_dumper_t *
dump_open(const char *dumpfile)
{
    capture_info_t *capinfo;

    if (vector_count(capture_cfg.sources) == 1) {
        capinfo = vector_first(capture_cfg.sources);
        return pcap_dump_open(capinfo->handle, dumpfile);
    }
    return NULL;
}
コード例 #7
0
ファイル: capture.c プロジェクト: linuxmaniac/sngrep
const char *
capture_device()
{
    capture_info_t *capinfo;

    if (vector_count(capture_cfg.sources) == 1) {
        capinfo = vector_first(capture_cfg.sources);
        return capinfo->device;
    }
    return NULL;
}
コード例 #8
0
ファイル: capture.c プロジェクト: cruzccl/sngrep
char *
capture_last_error()
{
    capture_info_t *capinfo;
    if (vector_count(capture_cfg.sources) == 1) {
        capinfo = vector_first(capture_cfg.sources);
        return pcap_geterr(capinfo->handle);
    }
    return NULL;

}
コード例 #9
0
ファイル: sip.c プロジェクト: digitainc/sngrep
void
sip_calls_rotate()
{
    sip_call_t *call = vector_first(calls.list);

    // Remove from callids hash
    htable_remove(calls.callids, call->callid);
    // Remove first call from active and call lists
    vector_remove(calls.active, call);
    vector_remove(calls.list, call);

}
コード例 #10
0
ファイル: thread.c プロジェクト: mtmiron/toi
VALUE
thread_s_main()
{
	VALUE thr;

	return (VALUE)vector_first(thr_stk);

	for (thr = cur_thr; TEST(thr); thr = THREAD(thr)->up)
		if (! TEST(THREAD(thr)->up) )
			return thr;
	return thr;
}
コード例 #11
0
ファイル: group.c プロジェクト: romkazor/sngrep
sip_call_t *
call_group_get_next(sip_call_group_t *group, sip_call_t *call)
{
    sip_msg_t *next, *first;
    sip_call_t *c;
    int i;

    if (!group)
        return NULL;

    // Get call of the first message in group
    if (!call) {
        if ((next = call_group_get_next_msg(group, NULL))) {
            return next->call;
        }
        return NULL;
    }

    // Initialize candidate
    next = NULL;

    // Get the call with the next chronological message
    for (i = 0; i < vector_count(group->calls); i++) {
        if ((c = vector_item(group->calls, i)) == call)
            continue;

        // Get first message
        first = vector_first(c->msgs);

        // Is first message of this call older?
        if (msg_is_older(first, vector_first(call->msgs))
            && (!next || !msg_is_older(first, next))) {
            next = first;
            break;
        }
    }

    return (next) ? next->call : NULL;
}
コード例 #12
0
ファイル: sip_call.c プロジェクト: digitainc/sngrep
void
call_update_state(sip_call_t *call, sip_msg_t *msg)
{
    int reqresp;
    sip_msg_t *first;

    if (!call_is_invite(call))
        return;

    // Get the first message in the call
    first = vector_first(call->msgs);

    // Get current message Method / Response Code
    reqresp = msg->reqresp;

    // If this message is actually a call, get its current state
    if (call->state) {
        if (call->state == SIP_CALLSTATE_CALLSETUP) {
            if (reqresp == SIP_METHOD_ACK && call->invitecseq == msg->cseq) {
                // Alice and Bob are talking
                call->state = SIP_CALLSTATE_INCALL;
                call->cstart_msg = msg;
            } else if (reqresp == SIP_METHOD_CANCEL) {
                // Alice is not in the mood
                call->state = SIP_CALLSTATE_CANCELLED;
            } else if (reqresp > 400 && call->invitecseq == msg->cseq) {
                // Bob is not in the mood
                call->state = SIP_CALLSTATE_REJECTED;
            }
        } else if (call->state == SIP_CALLSTATE_INCALL) {
            if (reqresp == SIP_METHOD_BYE) {
                // Thanks for all the fish!
                call->state = SIP_CALLSTATE_COMPLETED;
                call->cend_msg = msg;
            }
        } else if (reqresp == SIP_METHOD_INVITE && call->state !=  SIP_CALLSTATE_INCALL) {
            // Call is being setup (after proper authentication)
            call->invitecseq = msg->cseq;
            call->state = SIP_CALLSTATE_CALLSETUP;
        }
    } else {
        // This is actually a call
        if (reqresp == SIP_METHOD_INVITE) {
            call->invitecseq = msg->cseq;
            call->state = SIP_CALLSTATE_CALLSETUP;
        }
    }
}
コード例 #13
0
ファイル: capture.c プロジェクト: linuxmaniac/sngrep
const char*
capture_input_file()
{
    capture_info_t *capinfo;

    if (vector_count(capture_cfg.sources) == 1) {
        capinfo = vector_first(capture_cfg.sources);
        if (capinfo->infile) {
            return sng_basename(capinfo->infile);
        } else {
            return NULL;
        }
    } else {
        return "Multiple files";
    }
}
コード例 #14
0
ファイル: sip_call.c プロジェクト: jungle-boogie/sngrep
const char *
call_get_attribute(sip_call_t *call, enum sip_attr_id id)
{
    if (!call)
        return NULL;

    switch (id) {
        case SIP_ATTR_CALLINDEX:
        case SIP_ATTR_CALLID:
        case SIP_ATTR_MSGCNT:
        case SIP_ATTR_CALLSTATE:
        case SIP_ATTR_CONVDUR:
        case SIP_ATTR_TOTALDUR:
            return sip_attr_get_value(call->attrs, id);
        default:
            return msg_get_attribute(vector_first(call->msgs), id);
    }

    return NULL;
}
コード例 #15
0
ch8 *
fixed_gap_arena_text(FixedGapArena *arena, memi offset, memi size, ch8 *out)
{
    hale_assert(offset <= arena->size);
    hale_assert(size <= arena->size);
    hale_assert(offset + size <= arena->size);
    if (size == 0) {
        return out;
    }

    Buf *it = &vector_first(&arena->buffers);
    Buf *end = it + vector_count(arena->buffers);
    it = find_buf_GT(arena, &offset, it, end);

#if HALE_DEBUG
    ch8 *out_end = out + size;
#endif

    // Protected by asserts above.
    hale_assert_requirement(it != end);

    memi s = buf_length(it);
    s = hale_minimum(size, s - offset);
    out = buf_text(it, offset, s, out);
    hale_assert_debug(out <= out_end);
    size -= s;

    while (size)
    {
        ++it;
        s = hale_minimum(size, buf_length(it));
        out = buf_text(it, 0, s, out);
        hale_assert_debug(out <= out_end);
        size -= s;
    }

    return out;
}
コード例 #16
0
ファイル: sip_call.c プロジェクト: jungle-boogie/sngrep
void
call_update_state(sip_call_t *call, sip_msg_t *msg)
{
    const char *callstate;
    char dur[20];
    int reqresp;
    sip_msg_t *first;

    if (!call_is_invite(call))
        return;

    // Get the first message in the call
    first = vector_first(call->msgs);

    // Get current message Method / Response Code
    reqresp = msg->reqresp;

    // If this message is actually a call, get its current state
    if ((callstate = call_get_attribute(call, SIP_ATTR_CALLSTATE))) {
        if (!strcmp(callstate, SIP_CALLSTATE_CALLSETUP)) {
            if (reqresp == 200) {
                // Alice and Bob are talking
                call_set_attribute(call, SIP_ATTR_CALLSTATE, SIP_CALLSTATE_INCALL);
                // Store the timestap where call has started
                call->active = 1;
                call->cstart_msg = msg;
            } else if (reqresp == SIP_METHOD_CANCEL) {
                // Alice is not in the mood
                call_set_attribute(call, SIP_ATTR_CALLSTATE, SIP_CALLSTATE_CANCELLED);
                // Store total call duration
                call_set_attribute(call, SIP_ATTR_TOTALDUR, timeval_to_duration(msg_get_time(first), msg_get_time(msg), dur));
                call->active = 0;
            } else if (reqresp > 400) {
                // Bob is not in the mood
                call_set_attribute(call, SIP_ATTR_CALLSTATE, SIP_CALLSTATE_REJECTED);
                // Store total call duration
                call_set_attribute(call, SIP_ATTR_TOTALDUR, timeval_to_duration(msg_get_time(first), msg_get_time(msg), dur));
                call->active = 0;
            }
        } else if (!strcmp(callstate, SIP_CALLSTATE_INCALL)) {
            if (reqresp == SIP_METHOD_BYE) {
                // Thanks for all the fish!
                call_set_attribute(call, SIP_ATTR_CALLSTATE, SIP_CALLSTATE_COMPLETED);
                // Store Conversation duration
                call_set_attribute(call, SIP_ATTR_CONVDUR,
                                   timeval_to_duration(msg_get_time(call->cstart_msg), msg_get_time(msg), dur));
                call->active = 0;
            }
        } else if (reqresp == SIP_METHOD_INVITE && strcmp(callstate, SIP_CALLSTATE_INCALL)) {
            // Call is being setup (after proper authentication)
            call_set_attribute(call, SIP_ATTR_CALLSTATE, SIP_CALLSTATE_CALLSETUP);
            call->active = 1;
        } else {
            // Store total call duration
            call_set_attribute(call, SIP_ATTR_TOTALDUR, timeval_to_duration(msg_get_time(first), msg_get_time(msg), dur));
        }
    } else {
        // This is actually a call
        if (reqresp == SIP_METHOD_INVITE) {
            call_set_attribute(call, SIP_ATTR_CALLSTATE, SIP_CALLSTATE_CALLSETUP);
            call->active = 1;
        }
    }
}
コード例 #17
0
ファイル: capture_eep.c プロジェクト: erhuabushuo/sngrep
int
capture_eep_send_v3(capture_packet_t *pkt)
{
    struct hep_generic *hg = NULL;
    void* buffer;
    unsigned int buflen = 0, iplen = 0, tlen = 0;
    hep_chunk_ip4_t src_ip4, dst_ip4;
#ifdef USE_IPV6
    hep_chunk_ip6_t src_ip6, dst_ip6;
#endif
    hep_chunk_t payload_chunk;
    hep_chunk_t authkey_chunk;
    capture_frame_t *frame = vector_first(pkt->frames);
    unsigned char *data = capture_packet_get_payload(pkt);
    unsigned int len = capture_packet_get_payload_len(pkt);

    hg = sng_malloc(sizeof(struct hep_generic));

    /* header set "HEP3" */
    memcpy(hg->header.id, "\x48\x45\x50\x33", 4);

    /* IP proto */
    hg->ip_family.chunk.vendor_id = htons(0x0000);
    hg->ip_family.chunk.type_id = htons(0x0001);
    hg->ip_family.data = pkt->ip_version == 4 ? AF_INET : AF_INET6;
    hg->ip_family.chunk.length = htons(sizeof(hg->ip_family));

    /* Proto ID */
    hg->ip_proto.chunk.vendor_id = htons(0x0000);
    hg->ip_proto.chunk.type_id = htons(0x0002);
    hg->ip_proto.data = pkt->proto;
    hg->ip_proto.chunk.length = htons(sizeof(hg->ip_proto));

    /* IPv4 */
    if (pkt->ip_version == 4) {
        /* SRC IP */
        src_ip4.chunk.vendor_id = htons(0x0000);
        src_ip4.chunk.type_id = htons(0x0003);
        inet_pton(AF_INET, pkt->ip_src, &src_ip4.data);
        src_ip4.chunk.length = htons(sizeof(src_ip4));

        /* DST IP */
        dst_ip4.chunk.vendor_id = htons(0x0000);
        dst_ip4.chunk.type_id = htons(0x0004);
        inet_pton(AF_INET, pkt->ip_dst, &dst_ip4.data);
        dst_ip4.chunk.length = htons(sizeof(dst_ip4));

        iplen = sizeof(dst_ip4) + sizeof(src_ip4);
    }

#ifdef USE_IPV6
    /* IPv6 */
    else if(pkt->ip_version == 6) {
        /* SRC IPv6 */
        src_ip6.chunk.vendor_id = htons(0x0000);
        src_ip6.chunk.type_id = htons(0x0005);
        inet_pton(AF_INET6, pkt->ip_src, &src_ip6.data);
        src_ip6.chunk.length = htonl(sizeof(src_ip6));

        /* DST IPv6 */
        dst_ip6.chunk.vendor_id = htons(0x0000);
        dst_ip6.chunk.type_id = htons(0x0006);
        inet_pton(AF_INET6, pkt->ip_dst, &dst_ip6.data);
        dst_ip6.chunk.length = htonl(sizeof(dst_ip6));

        iplen = sizeof(dst_ip6) + sizeof(src_ip6);
    }
#endif

    /* SRC PORT */
    hg->src_port.chunk.vendor_id = htons(0x0000);
    hg->src_port.chunk.type_id = htons(0x0007);
    hg->src_port.data = htons(pkt->sport);
    hg->src_port.chunk.length = htons(sizeof(hg->src_port));

    /* DST PORT */
    hg->dst_port.chunk.vendor_id = htons(0x0000);
    hg->dst_port.chunk.type_id = htons(0x0008);
    hg->dst_port.data = htons(pkt->dport);
    hg->dst_port.chunk.length = htons(sizeof(hg->dst_port));

    /* TIMESTAMP SEC */
    hg->time_sec.chunk.vendor_id = htons(0x0000);
    hg->time_sec.chunk.type_id = htons(0x0009);
    hg->time_sec.data = htonl(frame->header->ts.tv_sec);
    hg->time_sec.chunk.length = htons(sizeof(hg->time_sec));

    /* TIMESTAMP USEC */
    hg->time_usec.chunk.vendor_id = htons(0x0000);
    hg->time_usec.chunk.type_id = htons(0x000a);
    hg->time_usec.data = htonl(frame->header->ts.tv_usec);
    hg->time_usec.chunk.length = htons(sizeof(hg->time_usec));

    /* Protocol TYPE */
    hg->proto_t.chunk.vendor_id = htons(0x0000);
    hg->proto_t.chunk.type_id = htons(0x000b);
    hg->proto_t.data = 1;
    hg->proto_t.chunk.length = htons(sizeof(hg->proto_t));

    /* Capture ID */
    hg->capt_id.chunk.vendor_id = htons(0x0000);
    hg->capt_id.chunk.type_id = htons(0x000c);
    hg->capt_id.data = htons(eep_cfg.capt_id);
    hg->capt_id.chunk.length = htons(sizeof(hg->capt_id));

    /* Payload */
    payload_chunk.vendor_id = htons(0x0000);
    payload_chunk.type_id = htons(0x000f);
    payload_chunk.length = htons(sizeof(payload_chunk) + len);

    tlen = sizeof(struct hep_generic) + len + iplen + sizeof(hep_chunk_t);

    /* auth key */
    if (eep_cfg.capt_password != NULL) {

        tlen += sizeof(hep_chunk_t);
        /* Auth key */
        authkey_chunk.vendor_id = htons(0x0000);
        authkey_chunk.type_id = htons(0x000e);
        authkey_chunk.length = htons(sizeof(authkey_chunk) + strlen(eep_cfg.capt_password));
        tlen += strlen(eep_cfg.capt_password);
    }

    /* total */
    hg->header.length = htons(tlen);

    if (!(buffer = sng_malloc(tlen))) {
        sng_free(hg);
        return 1;
    }
    memcpy((void*) buffer, hg, sizeof(struct hep_generic));
    buflen = sizeof(struct hep_generic);

    /* IPv4 */
    if (pkt->ip_version == 4) {
        /* SRC IP */
        memcpy((void*) buffer + buflen, &src_ip4, sizeof(struct hep_chunk_ip4));
        buflen += sizeof(struct hep_chunk_ip4);

        memcpy((void*) buffer + buflen, &dst_ip4, sizeof(struct hep_chunk_ip4));
        buflen += sizeof(struct hep_chunk_ip4);
    }

#ifdef USE_IPV6
    /* IPv6 */
    else if(pkt->ip_version == 6) {
        /* SRC IPv6 */
        memcpy((void*) buffer+buflen, &src_ip4, sizeof(struct hep_chunk_ip6));
        buflen += sizeof(struct hep_chunk_ip6);

        memcpy((void*) buffer+buflen, &dst_ip6, sizeof(struct hep_chunk_ip6));
        buflen += sizeof(struct hep_chunk_ip6);
    }
#endif

    /* AUTH KEY CHUNK */
    if (eep_cfg.capt_password != NULL) {

        memcpy((void*) buffer + buflen, &authkey_chunk, sizeof(struct hep_chunk));
        buflen += sizeof(struct hep_chunk);

        /* Now copying payload self */
        memcpy((void*) buffer + buflen, eep_cfg.capt_password, strlen(eep_cfg.capt_password));
        buflen += strlen(eep_cfg.capt_password);
    }

    /* PAYLOAD CHUNK */
    memcpy((void*) buffer + buflen, &payload_chunk, sizeof(struct hep_chunk));
    buflen += sizeof(struct hep_chunk);

    /* Now copying payload itself */
    memcpy((void*) buffer + buflen, data, len);
    buflen += len;

    if (send(eep_cfg.client_sock, buffer, buflen, 0) == -1) {
        return 1;
    }

    /* FREE */
    sng_free(buffer);
    sng_free(hg);
    return 0;
}
コード例 #18
0
ファイル: capture_eep.c プロジェクト: erhuabushuo/sngrep
int
capture_eep_send_v2(capture_packet_t *pkt)
{
    void* buffer;
    unsigned int buflen = 0, tlen = 0;
    struct hep_hdr hdr;
    struct hep_timehdr hep_time;
    struct hep_iphdr hep_ipheader;
#ifdef USE_IPV6
    struct hep_ip6hdr hep_ip6header;
#endif
    unsigned char *data = capture_packet_get_payload(pkt);
    unsigned int len = capture_packet_get_payload_len(pkt);
    capture_frame_t *frame = vector_first(pkt->frames);

    /* Version && proto */
    hdr.hp_v = 2;
    hdr.hp_f = pkt->ip_version == 4 ? AF_INET : AF_INET6;
    hdr.hp_p = pkt->proto;
    hdr.hp_sport = htons(pkt->sport);
    hdr.hp_dport = htons(pkt->dport);

    /* Timestamp */
    hep_time.tv_sec = frame->header->ts.tv_sec;
    hep_time.tv_usec = frame->header->ts.tv_usec;
    hep_time.captid = eep_cfg.capt_id;

    /* Calculate initial HEP packet size */
    tlen = sizeof(struct hep_hdr) + sizeof(struct hep_timehdr);

    /* IPv4 */
    if (pkt->ip_version == 4) {
        inet_pton(AF_INET, pkt->ip_src, &hep_ipheader.hp_src);
        inet_pton(AF_INET, pkt->ip_dst, &hep_ipheader.hp_dst);
        tlen += sizeof(struct hep_iphdr);
        hdr.hp_l += sizeof(struct hep_iphdr);
    }

#ifdef USE_IPV6
    /* IPv6 */
    else if(pkt->ip_version == 6) {
        inet_pton(AF_INET6, pkt->ip_src, &hep_ip6header.hp6_src);
        inet_pton(AF_INET6, pkt->ip_dst, &hep_ip6header.hp6_dst);
        tlen += sizeof(struct hep_ip6hdr);
        hdr.hp_l += sizeof(struct hep_ip6hdr);
    }
#endif

    // Add payload size to the final size of HEP packet
    tlen += len;
    hdr.hp_l = htons(tlen);

    // Allocate memory for HEPv2 packet
    if (!(buffer = sng_malloc(tlen)))
        return 1;

    // Copy basic headers
    buflen = 0;
    memcpy((void*) buffer + buflen, &hdr, sizeof(struct hep_hdr));
    buflen += sizeof(struct hep_hdr);

    // Copy IP header
    if (pkt->ip_version == 4) {
        memcpy((void*) buffer + buflen, &hep_ipheader, sizeof(struct hep_iphdr));
        buflen += sizeof(struct hep_iphdr);
    }
#ifdef USE_IPV6
    else if(pkt->ip_version == 6) {
        memcpy((void*) buffer + buflen, &hep_ip6header, sizeof(struct hep_ip6hdr));
        buflen += sizeof(struct hep_ip6hdr);
    }
#endif

    // Copy TImestamp header
    memcpy((void*) buffer + buflen, &hep_time, sizeof(struct hep_timehdr));
    buflen += sizeof(struct hep_timehdr);

    // Now copy payload itself
    memcpy((void*) buffer + buflen, data, len);
    buflen += len;

    if (send(eep_cfg.client_sock, buffer, buflen, 0) == -1) {
        return 1;
    }

    /* FREE */
    sng_free(buffer);

    return 1;
}
コード例 #19
0
ファイル: cparse.c プロジェクト: AkiraSuu/lagopus
/* Parse the line. */
enum cparse_result
cparse(char *line, struct cnode *top, struct cparam *param, int exec) {
  uint32_t i;
  uint32_t j;
  char *arg;
  struct cnode *cnode;
  enum match_type current;

  struct vector *args;
  struct vector *matched;
  struct vector *candidate;
  struct vector *argv;

  /* Arguments, matched and candidate. */
  args = param->args;
  matched = param->matched;
  candidate = param->candidate;
  argv = param->argv;

  /* Lexical analysis. */
  clex(line, args);

  /* Set top candidate. */
  vector_reset(candidate);
  vector_append(candidate, top->v);

  /* Empty line. */
  if (vector_max(args) == 0) {
    return CPARSE_EMPTY_LINE;
  }

  /* Parse user input arguments. */
  for (i = 0; i < vector_max(args); i++) {
    /* Set current word to arg. */
    arg = vector_slot(args, i);

    /* Empty tail space. */
    if (strcmp(arg, "") == 0) {
      if (param->index > 0) {
        param->index--;
      }
      if (args->max > 0) {
        args->max--;
      }
      param->tail = 1;
      break;
    }

    /* Remember index. */
    param->index = i;

    /* Starting from no match. */
    current = NONE_MATCH;

    /* Rest matched vector. */
    vector_reset(matched);

    /* Match with schema. */
    for (j = 0; j < vector_max(candidate); j++) {
      enum match_type match = NONE_MATCH;

      cnode = vector_slot(candidate, j);

      if (exec == CPARSE_EXEC_MODE || exec == CPARSE_CONFIG_EXEC_MODE) {
        cnode_schema_match(cnode, arg, &match);
      }

      if (exec == CPARSE_CONFIG_MODE ||
          (exec == CPARSE_CONFIG_EXEC_MODE && match == NONE_MATCH)) {
        if (strcmp(arg, cnode->name) == 0) {
          match = KEYWORD_MATCH;
        }
      }

      if (match == NONE_MATCH) {
        continue;
      }

      if (match > current) {
        vector_reset(matched);
        current = match;
        vector_set(matched, cnode);
      } else if (match == current) {
        vector_set(matched, cnode);
      }

      if (CHECK_FLAG(cnode->flags, CNODE_FLAG_SET_NODE)) {
        SET32_FLAG(param->flags, CNODE_FLAG_SET_NODE);
      }

      if (CHECK_FLAG(cnode->flags, CNODE_FLAG_DELETE_NODE)) {
        SET32_FLAG(param->flags, CNODE_FLAG_DELETE_NODE);
      }
    }

    /* There is no match. */
    if (vector_max(matched) == 0) {
      break;
    }

    /* Update next level schema. */
    vector_reset(candidate);
    for (j = 0; j < vector_max(matched); j++) {
      cnode = vector_slot(matched, j);
      vector_append(candidate, cnode->v);
    }
  }

  /* Match result check. */
  if (vector_max(matched) == 0) {
    return CPARSE_NO_MATCH;
  } else if (vector_max(matched) > 1) {
    return CPARSE_AMBIGUOUS;
  }

  /* Parse success, set matched node. */
  param->exec = vector_first(matched);

  /* Return incomplete if the node is not leaf. */
  if (!cnode_is_leaf(param->exec)) {
    return CPARSE_INCOMPLETE;
  }

  /* Here we can build argc/argv.  This is only possible at this stage
   * since during parsing, we can't determine which node is actually
   * matched.  We allow user to abbreviate input so there could be
   * multiple candidate node during parsing.  */
  if (exec) {
    build_argv(param->exec, args, vector_max(args) - 1, argv);
  }

  /* Success. */
  return CPARSE_SUCCESS;
}