Пример #1
0
/*!
    \brief Returns a string based on the format provided.

    This function is Renesas specific and is based on the Renesas provided
    vsprintf function.
    
    \Note vsnprintf is not thread safe
    
    \param[out] out_str Location to store the resulting string.
    \param[in] SIZE The size in bytes of the location to receive the resulting
      string.
    \param[in] FMT The format string used to create the resulting string
    \param[in] ap variable length argument list to use with the placeholders in
      FMT.

    \return The number of bytes that would have been copied.  
*/
int vsnprintf(char * out_str, const size_t SIZE,
  const char * FMT, va_list ap)
{
    if(!out_str || !SIZE || !FMT)
    {
        return -1;
    } // if any of the parameters are invalid //

    result_str = out_str;
    result_len = 0;

    // -1 to save 1 byte for NULL termination.
    max_result_len = SIZE - 1;

    while(FMT && *FMT)
    {
        if(*FMT == '%')
        {
            FMT++;
			if(*FMT == '%')
            {
                append_ch(*FMT);
                FMT++;
			} // if a '%' should be added //
            else
            {
                int bytes_added;
                
                FMT = _local_print(append_ch, FMT, (int **)&ap, &bytes_added);
            } // else fill in the place holder //
        } // if a '%' //
        else
        {
            append_ch(*FMT++);
		} // else it's not '%' //
	} // while characters remain //

	*result_str = '\0';
    result_str = 0;                 // no longer operating on that data location
    max_result_len = 0;
	return result_len;
} // vsnprintf //
Пример #2
0
 static void append_uint( FILE *file, char **beg, char *end, uintmax_t value )
 {
     if( value != 0 ) {
         int cnt = 0;
         for( uintmax_t tmp = value; tmp; tmp >>= 4, ++cnt ) {
         }
         for( ; cnt; --cnt ) {
             char ch = "0123456789ABCDEF"[( value >> ( cnt * 4 - 4 ) ) & 0xF];
             append_ch( file, beg, end, ch );
         }
     } else {
Пример #3
0
void http_open(struct url_info *url, int flags, struct inode *inode,
	       const char **redir)
{
    struct pxe_pvt_inode *socket = PVT(inode);
    int header_bytes;
    const char *next;
    char field_name[20];
    char field_value[1024];
    size_t field_name_len, field_value_len;
    enum state {
	st_httpver,
	st_stcode,
	st_skipline,
	st_fieldfirst,
	st_fieldname,
	st_fieldvalue,
	st_skip_fieldname,
	st_skip_fieldvalue,
	st_eoh,
    } state;
    static char location[FILENAME_MAX];
    uint32_t content_length; /* same as inode->size */
    size_t response_size;
    int status;
    int pos;
    int err;

    (void)flags;

    if (!header_buf)
	return;			/* http is broken... */

    /* This is a straightforward TCP connection after headers */
    socket->ops = &http_conn_ops;

    /* Reset all of the variables */
    inode->size = content_length = -1;

    /* Start the http connection */
    err = core_tcp_open(socket);
    if (err)
        return;

    if (!url->port)
	url->port = HTTP_PORT;

    err = core_tcp_connect(socket, url->ip, url->port);
    if (err)
	goto fail;

    strcpy(header_buf, "GET /");
    header_bytes = 5;
    header_bytes += url_escape_unsafe(header_buf+5, url->path,
				      header_len - 5);
    if (header_bytes >= header_len)
	goto fail;		/* Buffer overflow */
    header_bytes += snprintf(header_buf + header_bytes,
			     header_len - header_bytes,
			     " HTTP/1.0\r\n"
			     "Host: %s\r\n"
			     "User-Agent: Syslinux/" VERSION_STR "\r\n"
			     "Connection: close\r\n"
			     "%s"
			     "\r\n",
			     url->host, cookie_buf ? cookie_buf : "");
    if (header_bytes >= header_len)
	goto fail;		/* Buffer overflow */

    err = core_tcp_write(socket, header_buf, header_bytes, false);
    if (err)
	goto fail;

    /* Parse the HTTP header */
    state = st_httpver;
    pos = 0;
    status = 0;
    response_size = 0;
    field_value_len = 0;
    field_name_len = 0;

    while (state != st_eoh) {
	int ch = pxe_getc(inode);
	/* Eof before I finish paring the header */
	if (ch == -1)
	    goto fail;
#if 0
        printf("%c", ch);
#endif
	response_size++;
	if (ch == '\r' || ch == '\0')
	    continue;
	switch (state) {
	case st_httpver:
	    if (ch == ' ') {
		state = st_stcode;
		pos = 0;
	    }
	    break;

	case st_stcode:
	    if (ch < '0' || ch > '9')
	       goto fail;
	    status = (status*10) + (ch - '0');
	    if (++pos == 3)
		state = st_skipline;
	    break;

	case st_skipline:
	    if (ch == '\n')
		state = st_fieldfirst;
	    break;

	case st_fieldfirst:
	    if (ch == '\n')
		state = st_eoh;
	    else if (isspace(ch)) {
		/* A continuation line */
		state = st_fieldvalue;
		goto fieldvalue;
	    }
	    else if (is_token(ch)) {
		/* Process the previous field before starting on the next one */
		if (strcasecmp(field_name, "Content-Length") == 0) {
		    next = field_value;
		    /* Skip leading whitespace */
		    while (isspace(*next))
			next++;
		    content_length = 0;
		    for (;(*next >= '0' && *next <= '9'); next++) {
			if ((content_length * 10) < content_length)
			    break;
			content_length = (content_length * 10) + (*next - '0');
		    }
		    /* In the case of overflow or other error ignore
		     * Content-Length.
		     */
		    if (*next)
			content_length = -1;
		}
		else if (strcasecmp(field_name, "Location") == 0) {
		    next = field_value;
		    /* Skip leading whitespace */
		    while (isspace(*next))
			next++;
		    strlcpy(location, next, sizeof location);
		}
		/* Start the field name and field value afress */
		field_name_len = 1;
		field_name[0] = ch;
		field_name[1] = '\0';
		field_value_len = 0;
		field_value[0] = '\0';
		state = st_fieldname;
	    }
	    else /* Bogus try to recover */
		state = st_skipline;
	    break;

	case st_fieldname:
	    if (ch == ':' ) {
		state = st_fieldvalue;
	    }
	    else if (is_token(ch)) {
		if (!append_ch(field_name, sizeof field_name, &field_name_len, ch))
		    state = st_skip_fieldname;
	    }
	    /* Bogus cases try to recover */
	    else if (ch == '\n')
		state = st_fieldfirst;
	    else
		state = st_skipline;
	    break;

	 case st_fieldvalue:
	    if (ch == '\n')
		state = st_fieldfirst;
	    else {
	    fieldvalue:
		if (!append_ch(field_value, sizeof field_value, &field_value_len, ch))
		    state = st_skip_fieldvalue;
	    }
	    break;

	/* For valid fields whose names are longer than I choose to support. */
	case st_skip_fieldname:
	    if (ch == ':')
		state = st_skip_fieldvalue;
	    else if (is_token(ch))
		state = st_skip_fieldname;
	    /* Bogus cases try to recover */
	    else if (ch == '\n')
		state = st_fieldfirst;
	    else
		state = st_skipline;
	    break;

	/* For valid fields whose bodies are longer than I choose to support. */
	case st_skip_fieldvalue:
	    if (ch == '\n')
		state = st_fieldfirst;
	    break;

	case st_eoh:
	   break; /* Should never happen */
	}
    }

    if (state != st_eoh)
	status = 0;

    switch (status) {
    case 200:
	/*
	 * All OK, need to mark header data consumed and set up a file
	 * structure...
	 */
	/* Treat the remainder of the bytes as data */
	socket->tftp_filepos -= response_size;
	break;
    case 301:
    case 302:
    case 303:
    case 307:
	/* A redirect */
	if (!location[0])
	    goto fail;
	*redir = location;
	goto fail;
    default:
	goto fail;
	break;
    }
    return;
fail:
    inode->size = 0;
    core_tcp_close_file(inode);
    return;
}