static HTTPResponse *_errorResponse(WOAppReq *app, WOURLComponents *wc, HTTPRequest *req) { HTTPResponse *resp; const char *redirect_url = &app->redirect_url[0]; WOLog(WO_ERR,"Request handling error: %s",_errors[app->error]); if (app->redirect_url[0] == 0) redirect_url = adaptor_valueForKey(WOERRREDIR); /* * try to do the right thing... */ if (redirect_url != NULL) { resp = resp_redirectedResponse(redirect_url); } else if (app->error == err_notFound) { if (ac_authorizeAppListing(wc)) resp = WOAdaptorInfo(NULL, wc); else { resp = resp_errorResponse(NOT_FOUND_APP, HTTP_NOT_FOUND); if (resp->statusMsg) WOFREE(resp->statusMsg); resp->statusMsg = WOSTRDUP("File Not Found"); } } else resp = resp_errorResponse(_errors[app->error], HTTP_SERVER_ERROR); if (resp) { st_add(resp->headers, "Cache-Control", "no-cache, private, no-store, must-revalidate, max-age=0", 0); st_add(resp->headers, "Expires", "Thu, 01 Jan 1970 00:00:00 GMT", 0); st_add(resp->headers, "date", "Thu, 01 Jan 1970 00:00:00 GMT", 0); st_add(resp->headers, "pragma", "no-cache", 0); } return resp; }
/* * Make a new combine_diff_path from path/mode/sha1 * and append it to paths list tail. * * Memory for created elements could be reused: * * - if last->next == NULL, the memory is allocated; * * - if last->next != NULL, it is assumed that p=last->next was returned * earlier by this function, and p->next was *not* modified. * The memory is then reused from p. * * so for clients, * * - if you do need to keep the element * * p = path_appendnew(p, ...); * process(p); * p->next = NULL; * * - if you don't need to keep the element after processing * * pprev = p; * p = path_appendnew(p, ...); * process(p); * p = pprev; * ; don't forget to free tail->next in the end * * p->parent[] remains uninitialized. */ static struct combine_diff_path *path_appendnew(struct combine_diff_path *last, int nparent, const struct strbuf *base, const char *path, int pathlen, unsigned mode, const struct object_id *oid) { struct combine_diff_path *p; size_t len = st_add(base->len, pathlen); size_t alloclen = combine_diff_path_size(nparent, len); /* if last->next is !NULL - it is a pre-allocated memory, we can reuse */ p = last->next; if (p && (alloclen > (intptr_t)p->next)) { FREE_AND_NULL(p); } if (!p) { p = xmalloc(alloclen); /* * until we go to it next round, .next holds how many bytes we * allocated (for faster realloc - we don't need copying old data). */ p->next = (struct combine_diff_path *)(intptr_t)alloclen; } last->next = p; p->path = (char *)&(p->parent[nparent]); memcpy(p->path, base->buf, base->len); memcpy(p->path + base->len, path, pathlen); p->path[len] = 0; p->mode = mode; oidcpy(&p->oid, oid ? oid : &null_oid); return p; }
/* * Called during server init - * * the following keys can be specified in an Init line in the * obj.conf, like this: * * Init fn="WebObjects_init" config="path-to-config" \ * root="WebObjects-Doc-Root-Path" * * pb contains the "name=value" pairs from the Init line * sn = rq = NULL * */ NSAPI_PUBLIC int WebObjects_init(pblock *pb, Session *sn, Request *rq) { strtbl *dict; int i; WOLog_init(NULL, NULL, WOLogLevel[WO_DBG]); dump_pb(pb,"init.pb"); dict = st_new(10); /* * copy all the key/value pairs into our init table */ for (i=0; i < pb->hsize; i++) { struct pb_entry *entry = pb->ht[i]; while (entry != NULL) { pb_param *kvpair = entry->param; if (kvpair != NULL) { st_add(dict, kvpair->name, kvpair->value, STR_COPYKEY|STR_COPYVALUE); } entry = entry->next; } } adaptorEnabled = init_adaptor(dict)==0; if (adaptorEnabled) log_error(1,"WebObjects",NULL,NULL,"initialized"); return REQ_PROCEED; }
strtbl *st_newWithString(const char *s) { strtbl *st = NULL; char key[MAXSTR], value[MAXSTR]; if ((s == NULL) || (*s != LEFTCURLY)) return NULL; /* * repeat over key = value pairs */ s++; while (*s != RIGHTCURLY) { s = _getstr(s, key); while (*s && isspace((int)*s)) s++; if (*s == EQUAL) s = _getstr(s+1, value); if (*key && *value) { if (st == NULL) st = st_new(0); st_add(st, key, value, STR_COPYKEY|STR_COPYVALUE); } while (*s && (isspace((int)*s) || (*s == SEMI))) s++; } return st; }
/* * return a redirect response to 'path' */ HTTPResponse *resp_redirectedResponse(const char *path) { HTTPResponse *resp; resp = WOCALLOC(1,sizeof(HTTPResponse)); resp->status = 302; /* redirected */ resp->statusMsg = WOSTRDUP("OK Apple"); resp->headers = st_new(2); st_add(resp->headers, LOCATION, path, STR_COPYVALUE|STR_FREEVALUE); return resp; }
static const char *add_slash(const char *path) { size_t len = strlen(path); if (path[len - 1] != '/') { char *with_slash = xmalloc(st_add(len, 2)); memcpy(with_slash, path, len); with_slash[len++] = '/'; with_slash[len] = 0; return with_slash; } return path; }
void resp_addHeader(HTTPResponse *resp, String *rawhdr) { char *key, *value; /* keep track of the String */ resp_addStringToResponse(resp, rawhdr); /* * break into key/value, make key lowercase * Note that this walks over the String's buffer, but * at this point the response owns the String so that's ok. * The String buffer will get reclaimed when responseStrings * is freed, in resp_free(). */ for (key = rawhdr->text, value = key; *value != ':'; value++) { if(*value == '\0') // mstoll 13.10.2005 check added { WOLog(WO_ERR,"Header without ':': %s", rawhdr->text); break; } if (isupper((int)*value)) *value = tolower((int)*value); /* ... and change to lowercase. */ } if (*value == ':') { *value++ = '\0'; /* terminate key string */ while (*value && isspace((int)*value)) value++; } else { return; /* Zounds ! something wrong with header... */ } st_add(resp->headers, key, value, 0); /* * scan inline for content-length */ if ((resp->content_length == 0) && ((strcasecmp(CONTENT_LENGTH,key) == 0) || strcasecmp("content_length", key) == 0)) { // 2009/06/10: an explicit content-length value is available. // Update response flag information: resp->flags |= RESP_LENGTH_EXPLICIT; resp->content_length = atoi(value); WOLog(WO_INFO,"content-length was set expl.: %d", resp->content_length); } if (((strcasecmp(CONTENT_TYPE,key) == 0) || strcasecmp("content_type", key) == 0)) { // 2011/11/16: an explicit content-type value is available. // Update response flag information: resp->flags |= RESP_CONTENT_TYPE_SET; } return; }
static struct mp_block *mem_pool_alloc_block(struct mem_pool *mem_pool, size_t block_alloc) { struct mp_block *p; mem_pool->pool_alloc += sizeof(struct mp_block) + block_alloc; p = xmalloc(st_add(sizeof(struct mp_block), block_alloc)); p->next_block = mem_pool->mp_block; p->next_free = (char *)p->space; p->end = p->next_free + block_alloc; mem_pool->mp_block = p; return p; }
static strtbl *read_registry_config() { const regthing *info; strtbl *config; char value[MAX_VAL_LENGTH]; config = st_new(12); for (info=options; info->regKey != NULL; info++) { if (WOReadKeyFromConfiguration(info->regKey, value, MAX_VAL_LENGTH)) st_add(config,info->myKey,value,STR_COPYVALUE|STR_FREEVALUE); } return config; }
HTTPResponse *resp_errorResponse(const char *msg, int status) { HTTPResponse *resp; char buf[12]; String *html_msg; resp = WOCALLOC(1,sizeof(HTTPResponse)); resp->status = status; resp->statusMsg = WOSTRDUP("Error WebObjects"); resp->headers = st_new(2); st_add(resp->headers, CONTENT_TYPE, DEFAULT_CONTENT, 0); html_msg = str_create(errorRespTextBegin, sizeof(errorRespTextBegin) + sizeof(errorRespTextEnd) + strlen(msg)); str_append(html_msg, msg); str_append(html_msg, errorRespTextEnd); resp->content_length = resp->content_valid = resp->content_read = html_msg->length; resp->content = html_msg->text; resp_addStringToResponse(resp, html_msg); resp->flags |= RESP_DONT_FREE_CONTENT; sprintf(buf,"%d",resp->content_length); st_add(resp->headers, CONTENT_LENGTH, buf, STR_COPYVALUE|STR_FREEVALUE); return resp; }
static void queue_directory(const unsigned char *sha1, struct strbuf *base, const char *filename, unsigned mode, int stage, struct archiver_context *c) { struct directory *d; size_t len = st_add4(base->len, 1, strlen(filename), 1); d = xmalloc(st_add(sizeof(*d), len)); d->up = c->bottom; d->baselen = base->len; d->mode = mode; d->stage = stage; c->bottom = d; d->len = xsnprintf(d->path, len, "%.*s%s/", (int)base->len, base->buf, filename); hashcpy(d->oid.hash, sha1); }
static int add_submodule_odb(const char *path) { struct strbuf objects_directory = STRBUF_INIT; struct alternate_object_database *alt_odb; int ret = 0; size_t alloc; strbuf_git_path_submodule(&objects_directory, path, "objects/"); if (!is_directory(objects_directory.buf)) { ret = -1; goto done; } /* avoid adding it twice */ prepare_alt_odb(); for (alt_odb = alt_odb_list; alt_odb; alt_odb = alt_odb->next) if (alt_odb->name - alt_odb->base == objects_directory.len && !strncmp(alt_odb->base, objects_directory.buf, objects_directory.len)) goto done; alloc = st_add(objects_directory.len, 42); /* for "12/345..." sha1 */ alt_odb = xmalloc(st_add(sizeof(*alt_odb), alloc)); alt_odb->next = alt_odb_list; xsnprintf(alt_odb->base, alloc, "%s", objects_directory.buf); alt_odb->name = alt_odb->base + objects_directory.len; alt_odb->name[2] = '/'; alt_odb->name[40] = '\0'; alt_odb->name[41] = '\0'; alt_odb_list = alt_odb; /* add possible alternates from the submodule */ read_info_alternates(objects_directory.buf, 0); done: strbuf_release(&objects_directory); return ret; }
void req_addHeader(HTTPRequest *req,const char *key, const char *value, int flags) { const char *hdrkey; hdrkey = req_AddHeader_common(req, key, value); /* * we know that all interfaces (CGI, NSAPI,...) use statically allocated * header keys, always. *Most* of the time, the value is static too, * but there are cases where it might not be e.g. derived value, like * "server-port", or are always malloc'd. */ st_add((strtbl *)req->headers, hdrkey, value, flags); return; }
/* * Called from the xml parser to process a tag attribute. Just adds the key/value pair to the * current_element dictionary. */ static void createAttribute(XMLCDocument *document, const XMLCCharacter *name, const unsigned int nameLength, const XMLCCharacter *value, const unsigned int valueLength) { WOXMLEdits *config = (WOXMLEdits *)document; if (config->error != 0) /* would be nice to tell parser to stop */ return; config->errorLocation = &value[valueLength+1]; if (config->current_element) { /* Insert null terminators into the xml buffer. */ /* This is so we don't have to copy all the string values. They are stored by reference */ /* until the parse completes, then they are copied into the "live" configuration. The */ /* buffer containing the xml is not freed until after this completes. */ ((char *)name)[nameLength] = 0; ((char *)value)[valueLength] = 0; st_add(config->current_element, name, value, 0); } else WOLog(WO_WARN, "createAttribute() called with NULL current_element."); return; }
/* * Pretend as if the user told us to merge with the remote-tracking * branch we have for the upstream of the current branch */ static int setup_with_upstream(const char ***argv) { struct branch *branch = branch_get(NULL); int i; const char **args; if (!branch) die(_("No current branch.")); if (!branch->remote_name) die(_("No remote for the current branch.")); if (!branch->merge_nr) die(_("No default upstream defined for the current branch.")); args = xcalloc(st_add(branch->merge_nr, 1), sizeof(char *)); for (i = 0; i < branch->merge_nr; i++) { if (!branch->merge[i]->dst) die(_("No remote-tracking branch for %s from %s"), branch->merge[i]->src, branch->remote_name); args[i] = branch->merge[i]->dst; } args[i] = NULL; *argv = args; return i; }
void st_setValueForKey(strtbl *st, const char *key, const char *value, int flags) { int index; strtblelem *el; index = st_findKey(st, key); if (index == -1) { st_add(st, key, value, flags); } else { el = &st->head[index]; if (el->flags & STR_FREEVALUE) WOFREE((void *)el->value); /* keep the old key flags, but take the new value flags */ el->flags = (el->flags & (STR_COPYKEY|STR_FREEKEY)) | (flags & (STR_COPYVALUE | STR_FREEVALUE)); if (flags & STR_COPYVALUE) { el->value = WOSTRDUP(value); el->flags |= STR_FREEVALUE; } else el->value = value; } return; }
// Per-CPU process scheduler. // Each CPU calls scheduler() after setting itself up. // Scheduler never returns. It loops, doing: // - choose a process to run // - swtch to start running that process // - eventually that process transfers control // via swtch back to the scheduler. void scheduler(void) { struct proc *p; struct cpu *c; int i; #ifdef STRACE st_init(); #endif c = &cpus[cpu()]; for(;;){ // Enable interrupts on this processor. sti(); acquire(&proc_table_lock); //hold lottery #ifdef LOTTERY if (tickets == 0) { release(&proc_table_lock); continue; } //cprintf("tickets: %d\n", tickets); int winner = rand() / (32767 / tickets + 1); int sum = 0; //cprintf("winner: %d\n", winner); #endif // Loop over process table looking for process to run. for(i = 0; i < NPROC; i++){ p = &proc[i]; if(p->state != RUNNABLE) continue; #ifdef LOTTERY sum += p->tickets; if (sum <= winner) continue; #endif // Switch to chosen process. It is the process's job // to release proc_table_lock and then reacquire it // before jumping back to us. c->curproc = p; setupsegs(p); setstate(p, RUNNING); #ifdef STRACE st_add(p); #endif swtch(&c->context, &p->context); // Process is done running for now. // It should have changed its p->state before coming back. c->curproc = 0; setupsegs(0); #ifdef LOTTERY break; #endif } release(&proc_table_lock); } }
char *shorten_unambiguous_ref(const char *refname, int strict) { int i; static char **scanf_fmts; static int nr_rules; char *short_name; if (!nr_rules) { /* * Pre-generate scanf formats from ref_rev_parse_rules[]. * Generate a format suitable for scanf from a * ref_rev_parse_rules rule by interpolating "%s" at the * location of the "%.*s". */ size_t total_len = 0; size_t offset = 0; /* the rule list is NULL terminated, count them first */ for (nr_rules = 0; ref_rev_parse_rules[nr_rules]; nr_rules++) /* -2 for strlen("%.*s") - strlen("%s"); +1 for NUL */ total_len += strlen(ref_rev_parse_rules[nr_rules]) - 2 + 1; scanf_fmts = xmalloc(st_add(st_mult(sizeof(char *), nr_rules), total_len)); offset = 0; for (i = 0; i < nr_rules; i++) { assert(offset < total_len); scanf_fmts[i] = (char *)&scanf_fmts[nr_rules] + offset; offset += snprintf(scanf_fmts[i], total_len - offset, ref_rev_parse_rules[i], 2, "%s") + 1; } } /* bail out if there are no rules */ if (!nr_rules) return xstrdup(refname); /* buffer for scanf result, at most refname must fit */ short_name = xstrdup(refname); /* skip first rule, it will always match */ for (i = nr_rules - 1; i > 0 ; --i) { int j; int rules_to_fail = i; int short_name_len; if (1 != sscanf(refname, scanf_fmts[i], short_name)) continue; short_name_len = strlen(short_name); /* * in strict mode, all (except the matched one) rules * must fail to resolve to a valid non-ambiguous ref */ if (strict) rules_to_fail = nr_rules; /* * check if the short name resolves to a valid ref, * but use only rules prior to the matched one */ for (j = 0; j < rules_to_fail; j++) { const char *rule = ref_rev_parse_rules[j]; char refname[PATH_MAX]; /* skip matched rule */ if (i == j) continue; /* * the short name is ambiguous, if it resolves * (with this previous rule) to a valid ref * read_ref() returns 0 on success */ mksnpath(refname, sizeof(refname), rule, short_name_len, short_name); if (ref_exists(refname)) break; } /* * short name is non-ambiguous if all previous rules * haven't resolved to a valid ref */ if (j == rules_to_fail) return short_name; } free(short_name); return xstrdup(refname); }
int main() { #ifdef PROFILE int i; #endif const char *config_url, *username, *password, *config_options; strtbl *options = NULL; int exit_status = 0; // install SIGUSR1, SIGPIPE, SIGTERM handler signal(SIGTERM, sig_handler); signal(SIGUSR1, sig_handler); signal(SIGPIPE, sig_handler); /* Provide a hook via an environment variable to define the config URL */ config_url = getenv(WO_CONFIG_URL); if (!config_url) { /* Flat file URL */ /* config_url = "file:///Local/Library/WebObjects/Configuration/WOConfig.xml"; */ /* Local wotaskd */ /* config_url = "http://localhost:1085"; */ /* Multicast URL */ config_url = CONFIG_URL; /* Actually "webobjects://239.128.14.2:1085"; */ } WOLog(WO_INFO,"<FastCGI> config url is %s", config_url); options = st_new(8); st_add(options, WOCONFIG, config_url, 0); /* * If your webserver is configured to pass these environment variables, we use them to * protect WOAdaptorInfo output. */ username = getenv(WO_ADAPTOR_INFO_USERNAME); if (username && strlen(username) != 0) { st_add(options, WOUSERNAME, username, 0); password = getenv(WO_ADAPTOR_INFO_PASSWORD); if(password && strlen(password) != 0) { st_add(options, WOPASSWORD, password, 0); } } config_options = getenv(WO_CONFIG_OPTIONS); if (config_options) st_add(options, WOOPTIONS, config_options, 0); /* * SECURITY ALERT * * To disable WOAdaptorInfo, uncomment the next line. * st_add(options, WOUSERNAME, "disabled", 0); * * To specify an WOAdaptorInfo username and password, uncomment the next two lines. * st_add(options, WOUSERNAME, "joe", 0); * st_add(options, WOPASSWORD, "secret", 0); * */ if (init_adaptor(options)) { WOLog( WO_ERR, "<FastCGI> Adaptor initialization failed."); exit(-1); } WOLog( WO_INFO,"<FastCGI> process started" ); while (!should_terminate) { HTTPRequest *req; HTTPResponse *resp = NULL; WOURLComponents wc = WOURLComponents_Initializer; const char *qs; unsigned int qs_len; char *url; const char *script_name, *path_info; const char *reqerr; WOURLError urlerr; FCGX_ParamArray hdrp_org; exit_status = FCGX_Accept(&in, &out, &err, &hdrp ); if ( exit_status < 0 ) { break; } #ifdef PROFILE for (i=0; i < 50000; i++) { #endif WOLog( WO_INFO,"<FastCGI> request accepted" ); #ifdef WIN32 _setmode(_fileno(stdout), _O_BINARY); _setmode(_fileno(stdin), _O_BINAR1Y); #endif script_name = FCGX_GetParam( CGI_SCRIPT_NAME, hdrp); path_info = FCGX_GetParam( CGI_PATH_INFO, hdrp); WOLog( WO_INFO,"<FastCGI> CGI_SCRIPT_NAME = %s", script_name ); WOLog( WO_INFO,"<FastCGI> CGI_PATH_INFO = %s", path_info ); if (script_name == NULL) { prepareAndSendErrorResponse(INV_SCRIPT, HTTP_NOT_FOUND); break; } else if (path_info == NULL) { path_info = "/"; } /* * extract WebObjects application name from URI */ url = WOMALLOC(strlen(path_info) + strlen(script_name) + 1); strcpy(url, script_name); strcat(url, path_info); WOLog(WO_INFO,"<FastCGI> new request: %s",url); urlerr = WOParseApplicationName(&wc, url); if (urlerr != WOURLOK) { const char *_urlerr; _urlerr = WOURLstrerror(urlerr); WOLog(WO_INFO,"<FastCGI> URL Parsing Error: %s", _urlerr); if (urlerr == WOURLInvalidApplicationName) { if (ac_authorizeAppListing(&wc)) { resp = WOAdaptorInfo(NULL, &wc); sendErrorResponse(resp); } else { prepareAndSendErrorResponse(_urlerr, HTTP_NOT_FOUND); } WOFREE(url); break; } prepareAndSendErrorResponse(_urlerr, HTTP_BAD_REQUEST); WOFREE(url); break; } /* * build the request... */ req = req_new( FCGX_GetParam("REQUEST_METHOD", hdrp), NULL); /* * validate the method */ reqerr = req_validateMethod(req); if (reqerr) { prepareAndSendErrorResponse(reqerr, HTTP_BAD_REQUEST); WOFREE(url); break; } /* * copy the headers. This looks wierd... all we're doing is copying * *every* environment variable into our headers. It may be beyond * the spec, but more information probably won't hurt. */ hdrp_org=hdrp; while (hdrp && *hdrp) { char *key, *value; /* copy env. line. */ key = WOSTRDUP(*hdrp); for (value = key; *value && !isspace((int)*value) && (*value != '='); value++) {} if (*value) { *value++ = '\0'; /* null terminate 'key' */ } while (*value && (isspace((int)*value) || (*value == '='))) { value++; } /* BEGIN Support for getting the client's certificate. */ if (strcmp((const char *)key, "SSL_CLIENT_CERTIFICATE") == 0 || strcmp((const char *)key, "SSL_SERVER_CERTIFICATE") == 0 ) { value = 0; WOLog(WO_INFO,"<FastCGI> DROPPING ENV VAR (DUPLICATE) = %s", key); } if (strcmp((const char *)key, "SSL_CLIENT_CERT") == 0 || strcmp((const char *)key, "SSL_SERVER_CERT") == 0) { value = make_cert_one_line(value); //WOLog(WO_INFO,"<FastCGI> PASSING %s = %s", key, value); } /* END Support for getting the client's certificate */ if (key && *key && value && *value) { /* must specify copy key and value because key translation might replace this key, and value lives in the same buffer */ req_addHeader(req, key, value, STR_COPYKEY|STR_COPYVALUE); } /* BEGIN Support for getting the client's certificate */ if (freeValueNeeded ) { free(value); freeValueNeeded=0; } /* END Support for getting the client's certificate */ WOFREE(key); hdrp++; /* next env variable */ } hdrp=hdrp_org; /* * get form data if any * assume that POSTs with content length will be reformatted to GETs later */ WOLog ( WO_INFO, "Getting request data, length: %d",req->content_length ); if (req->content_length > 0) { req_allocateContent(req, req->content_length, 1); req->getMoreContent = (req_getMoreContentCallback)readContentData; WOLog ( WO_INFO, "content_buffer_size: %d",req->content_buffer_size ); if (req->content_buffer_size == 0) { prepareAndSendErrorResponse(ALLOCATION_FAILURE, HTTP_SERVER_ERROR); WOFREE(url); break; } if (readContentData(req, req->content, req->content_buffer_size, 1) == -1) { prepareAndSendErrorResponse(WOURLstrerror(WOURLInvalidPostData), HTTP_BAD_REQUEST); WOFREE(url); break; } } /* Always get the query string */ qs = FCGX_GetParam("QUERY_STRING", hdrp); if (qs) { qs_len = strlen(qs); } else { qs_len = 0; } if (qs_len > 0) { wc.queryString.start = qs; wc.queryString.length = qs_len; WOLog(WO_INFO,"<FastCGI> new request with Query String: %s", qs); } /* * message the application & collect the response */ resp = tr_handleRequest(req, url, &wc, FCGX_GetParam(CGI_SERVER_PROTOCOL, hdrp), documentRoot()); if (resp != NULL) { sendResponse(resp); resp_free(resp); /* dump the response */ } WOFREE(url); req_free(req); #if defined(FINDLEAKS) showleaks(); #endif } #ifdef PROFILE } #endif st_free(options); WOLog( WO_INFO,"<FastCGI> process exiting" ); return exit_status; }