/* * command is called with argc==0 when checking for -V or -v option * In this case return 0 when -v or -V or unknown option, otherwise * the shift count to the command is returned */ int b_command(register int argc,char *argv[],Shbltin_t *context) { register int n, flags=0; register Shell_t *shp = context->shp; opt_info.index = opt_info.offset = 0; while((n = optget(argv,sh_optcommand))) switch(n) { case 'p': if(sh_isoption(SH_RESTRICTED)) errormsg(SH_DICT,ERROR_exit(1),e_restricted,"-p"); sh_onstate(SH_DEFPATH); break; case 'v': flags |= X_FLAG; break; case 'V': flags |= V_FLAG; break; case 'x': shp->xargexit = 1; break; case ':': if(argc==0) return(0); errormsg(SH_DICT,2, "%s", opt_info.arg); break; case '?': if(argc==0) return(0); errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg); break; } if(argc==0) return(flags?0:opt_info.index); argv += opt_info.index; if(error_info.errors || !*argv) errormsg(SH_DICT,ERROR_usage(2),"%s", optusage((char*)0)); return(whence(shp,argv, flags)); }
/* * for the whence command */ int b_whence(int argc,char *argv[],Shbltin_t *context) { register int flags=0, n; register Shell_t *shp = context->shp; NOT_USED(argc); if(*argv[0]=='t') flags = V_FLAG; while((n = optget(argv,sh_optwhence))) switch(n) { case 'a': flags |= A_FLAG; /* FALL THRU */ case 'v': flags |= V_FLAG; break; case 'f': flags |= F_FLAG; break; case 'p': flags |= P_FLAG; flags &= ~V_FLAG; break; case 'q': flags |= Q_FLAG; break; case ':': errormsg(SH_DICT,2, "%s", opt_info.arg); break; case '?': errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg); break; } argv += opt_info.index; if(error_info.errors || !*argv) errormsg(SH_DICT,ERROR_usage(2),optusage((char*)0)); return(whence(shp, argv, flags)); }
/*virtual */void HTTPDataHandler::onDataReady(boost::shared_ptr< Connection > connection) { // get any pending data from the connection std::vector< char > buffer; std::size_t bytes_read; int reason; boost::tie( bytes_read, reason ) = connection->read(buffer); buffer.resize(bytes_read); /* Regardless of whether we have all the data pending on the * connection or not, we may have enough to get a request. In any * case, buffer now contains anything we have. */ /* If the connection has an attribute, it's the request with any data * that was left over from the last time. */ boost::any & connection_attribute(connection->getAttribute(attribute_index__)); boost::shared_ptr< Details::Request > request; std::vector< char >::iterator where; bool end_of_headers_found(false); after_connection_attributes_are_got: do { if (connection_attribute.empty() /* no existing attribute */) { // parse the request, as it is new boost::tie(request, where) = extractRequestHeader< Connection, Details::Request, Exceptions::HTTP::UnknownMethod, Exceptions::HTTP::UnsupportedProtocol >(connection, supported_methods__, buffer.begin(), buffer.end()); if (!request && where == buffer.begin()) { /* the extraction errored out because the first line was incomplete. * If this is the case, we will store whatever we got in the connection * attributes and return. */ break; } else { /* all is well */ } assert(request || where == buffer.end()); } else { std::vector< char > temp_buffer; boost::tie( request, temp_buffer, end_of_headers_found ) = boost::any_cast< boost::tuple< boost::shared_ptr< Details::Request >, std::vector< char >, bool > >(connection_attribute); buffer.insert(buffer.begin(), temp_buffer.begin(), temp_buffer.end()); /* connection_attribute.clear(); ==> */ boost::any a; connection_attribute.swap(a); where = buffer.begin(); } } while(!(request || where == buffer.end())); /* from here on, white space is important as we need to count the number of * carriage returns (13) or newlines (10). If we find two of them before * finding a non-whitespace character (that is: two newlines or two carriage * returns), the requests consists of only the header. If we find only one, * there is a header before the end of the request, and there might be a * body. */ bool end_of_buffer_found(false); if (request) do { std::vector< char >::iterator whence(where); whence = advanceThroughIgnorableWhiteSpace(whence, buffer.end()); if (moreHeaders(where, whence)) { where = whence; whence = findHeaderEnd(where, buffer.end()); if (where != whence) { Details::Header header; boost::tie(header.name_, header.value_) = splitHeader< Exceptions::HTTP::InvalidHeader >(where, whence); request->header_fields_.push_back(header); where = whence; } else { /* we're at the end of the current buffer, but more headers are still * to come. We'll break out of the loop (by setting end_of_buffer_found, * in some corner-cases, where will not be at buffer.end() but we will * still have found the end of the buffer) and store what we currently know * about the request in the connection attributes (the end of the headers * will not have been found, so this will happen automatically) */ end_of_buffer_found = true; } } else // we have all of the header { where = whence; end_of_headers_found = true; } } while (!end_of_headers_found && where != buffer.end() && !end_of_buffer_found); if (end_of_headers_found) { /* When we get here, we don't know whether the request has a body. * If it does, there is a Content-Length header among the headers * that will contain the size of the body. */ Details::HeaderFields::const_iterator curr(request->header_fields_.begin()); Details::HeaderFields::const_iterator end(request->header_fields_.end()); while (curr != end && curr->name_ != "Content-Length") ++curr; bool complete_body_found(false); if (curr != end) { std::size_t body_size(boost::lexical_cast< std::size_t >(curr->value_)); std::vector< char >::iterator whence(where); /* When we get here, the "where" and "whence" iterators should both be * at the start of the body. We will advance "whence" to the end of the * body - which should be within the bounds of the buffer. */ if (std::size_t(std::distance(whence, buffer.end())) < body_size) { connection_attribute = boost::make_tuple(request, std::vector< char >(where, buffer.end()), end_of_headers_found); } else { std::advance(whence, body_size); assert(request->body_.empty()); request->body_.insert(request->body_.end(), where, whence); where = whence; complete_body_found = true; } } else { /* request does not have a body */ complete_body_found = true; } if (complete_body_found) { request_handler_.handle(request); /* Now, if whence is not at the end of the buffer, more requests may be * in the buffer. We need to handle those. */ if (where != buffer.end()) { connection_attribute = boost::make_tuple(boost::shared_ptr< Details::Request >(), std::vector< char >(where, buffer.end()), false); buffer.clear(); goto after_connection_attributes_are_got; } else { /* done */ } } } else { connection_attribute = boost::make_tuple(request, std::vector< char >(where, buffer.end()), end_of_headers_found); } }