am_status_t Properties::parseBuffer(char *buffer) { am_status_t status = AM_SUCCESS; char *nextLine; #if defined(_AMD64_) size_t len; #else int len; #endif try { for (buffer = skipWhitespaceAndComments(buffer); *buffer; buffer = skipWhitespaceAndComments(nextLine)) { char *start = buffer; nextLine = terminateLine(buffer); // XXX - Should handle backslash escapes in the key buffer = findSeparator(start); if (start == buffer) { break; } std::string key(start, buffer - start); buffer = skipWhitespace(buffer); if (*buffer && isSeparator(*buffer)) { buffer += 1; buffer = skipWhitespace(buffer); } len = strlen(buffer) -1; while ((len > 0) && (buffer[len] == ' ')) { buffer[len--] = '\0'; } // XXX - Should handle backslash escapes in the value set(key, buffer); } if (*buffer) { status = AM_FAILURE; } } catch (const std::bad_alloc&) { status = AM_NO_MEMORY; } return status; }
/* * return values: * < 0: error. * 0: success, connection still open. * 1: success, connection closed by server. * > 1: http response code if <200 or >300. */ static int processHTTPResponse( int sockfd, const char *contentType, PZ_BUF zBuf, FILE* fp) { int i, respCode, chunkLen, status = 0; char *te, *ct, *temp = NULL; // Receive the response from the server... // Get first line of header.. zBuf->length = 0; //ZError( DBG_MISC, "first recvNextLine..."); if (recvNextLine( sockfd, zBuf)<0) return -1; ZInfo4( DBG_MISC, "%s", zBuf->buf ); if (strncmp(zBuf->buf, "HTTP/", 5) ) { return(-1); } for (i=0; zBuf->buf[i] != ' '; i++) ; respCode = atoi(zBuf->buf + i); if (respCode < 200 || respCode >= 300) { ZError(DBG_MISC, "Received an invalid response code->%d", respCode); return(respCode); } //ZError( DBG_MISC, "second recvNextLine..."); // Get test of the header.. while (recvNextLine( sockfd, zBuf) > 2); ZInfo4(DBG_MISC, "HTTP Response Header->%s", zBuf->buf); if ((ct = searchHeader(zBuf->buf, "Content-Type: ", 14) )) { temp = strdup(ct); terminateLine(temp); } if (contentType) { if (temp) { char *cte = strchr(temp, ';'); if(cte) *cte = '\0'; if(matchContentType(temp, (char*)contentType) ) { ZError(DBG_MISC, "CONTENT-TYPE doesn't match. actual->%s, expected->%s", temp, contentType); free(temp); return(-1); } free(temp); } else { ZError(DBG_MISC, "CONTENT-TYPE doesn't match. actual->NULL, expected->%s", contentType); return(-1); } } status = searchHeader(zBuf->buf, "Connection: close", 17) || searchHeader(zBuf->buf, "Proxy-Connection: close", 23); if ((te = searchHeader(zBuf->buf, "Transfer-Encoding: ", 19)) ) terminateLine(te); if (te && !strcasecmp(te, "chunked")) { ZInfo4(DBG_MISC, "Processing chunked response"); zBuf->length = 0; // ZError( DBG_MISC, "first recvChunkedBody..."); recvChunkedBody( sockfd, zBuf, fp); } else { /* * if there is a Content-Length header field it will be in * decimal. */ if((te = searchHeader(zBuf->buf, "Content-Length: ", 16))) { ZInfo4(DBG_MISC, "Content-length present"); if( ! (chunkLen = strtol(te, 0, 10)) ) { ZError(DBG_MISC, "Unable to get chunkLen ->%s", te); return(-1); } // Reset length.. zBuf->length = 0; ZInfo4(DBG_MISC, "Processing receive with chunkLen->%d", chunkLen); recvChunk2( fp, sockfd, chunkLen); } else { /* * non-persistent connection, where close signals end * of data (i.e. 'Connection: close', * 'Proxy-Connection: close' or pre HTTP/1.1 server) */ // Reset length.. zBuf->length = 0; // ZError( DBG_MISC, "third recvChunk..."); while (recvChunk2( fp, sockfd, BUFSIZE) == BUFSIZE); status = 1; } } return status; }
OV_RESULT ov_readConfigFile(ov_options* opts, char* configFile){ char lineStr[256]; char* startRead = NULL; char* temp = NULL; char* temp2 = NULL; char* temp3 = NULL; FILE* cfFile; OV_UINT j; OV_UINT line = 0; /* * parse config file * some memory is allocated on the heap. these variables are used while the server is running * hence this is no memleak. they are freed by the operating system on termination of the server * * * options from the commandline are NOT overwritten * lines starting with # and empty lines are ignored * Space and tab serve as whitespaces * lines are parsed as a whole * lines may be 256 characters long * no multi-line entries * * lines have the pattern * KEY VALUE * e.g. SERVERNAME ov_server1 * * recognized options are: * DBFILE path to database file. set to '-' to use no database * SERVERNAME name of this ov_server * HEAPSIZE size of TLSF heap pool * ID Ticket Identification for server access * PORT server port number * LIBRARY Start server with library. one library per line * LOGFILE logfile name for runtimeserver, you may use stdout, stderr or (on NT-systems) ntlog * ACTIVITYLOCK Locks OV activities (scheduler and accessorfnc). No argument * OPTION text Appends the option text to the * cmdline_options variable in Vendortree * text is mandatory * NOSTARTUP Do not startup the database. No argument * EXIT Exit immediately (test if database loads). No argument * EXEC IDENTIFIER CLASS LIBRARY Executes the first event in the schedulers * queue that matches concerning IDENTIFIER * CLASS and LIBRARY before starting the server. * All parameters are mandatory. Use '/' as wildcard. * ALLOWEDJITTER number of microseconds the scheduler may jitter before incrementing numExceeds in vondortree (the latter documents the realtime behaviour of the system) * KSMAXSTRLENGTH maximum length of strings to process with ks * KSMAXVECLENGTH maximum length of vectors to process with ks * KSMAXITEMSPERREQ maximum number of items per ks-request * DBSIZE db size when need to create * DBUTILLOG logfile name for dbutil, you may use stdout, stderr or (on NT-systems) ntlog * DBNOMAP read database but do not map * DBFORCECREATE force creation of a new database * old database file is removed */ if(!configFile || !(*configFile)){ return EXIT_FAILURE; } cfFile = fopen(configFile, "r"); if(!cfFile) { fprintf(stderr, "Could not open config file"); return EXIT_FAILURE; } clearerr(cfFile); /* get base path from path part of configFile */ #if OV_SYSTEM_NT for(j = strlen(configFile); configFile[j] != '\\' && configFile[j] != '/' && (j>0); j--); #else for(j = strlen(configFile); (configFile[j] != '/') && (j>0); j--); #endif if((j>0)) { opts->configBasePath = malloc(j+2); if(!opts->configBasePath) { ov_logfile_error("Could not reserve memory for basePath. Aborting."); return EXIT_FAILURE; } strncpy(opts->configBasePath, configFile, j+1); opts->configBasePath[j+1] = '\0'; //ov_logfile_debug("BasePath: %s", configBasePath); } /* * loop over lines */ while(fgets(lineStr, sizeof(lineStr), cfFile)) { line++; /* check if line complete */ if(!strchr(lineStr, '\n') && !feof(cfFile)) { ov_logfile_error("Error reading config file: line %u too long", line); return EXIT_FAILURE; } if(isComment(lineStr)) { /* skip line if comment */ continue; } startRead = skipWhiteSpace(lineStr); if(*startRead == '\0') break; /* probably EOF */ if(*startRead == '\n' || *startRead == '\r') continue; /* empty line */ /* set terminating '\0' at occurrence of newline or '#' */ terminateLine(startRead); /********************************************************************************** * parse parameters *********************************************************************************/ /* DBFILE */ if(strstr(startRead, "DBFILE")==startRead) { opt_clear_string(&opts->dbFilename); opts->dbFilename = readValue(startRead); if(!opts->dbFilename || !*opts->dbFilename){ return EXIT_FAILURE; } } /* SERVERNAME */ else if(strstr(startRead, "SERVERNAME")==startRead) { opt_clear_string(&opts->servername); opts->servername = readValue(startRead); if(!opts->servername || !*opts->servername){ return EXIT_FAILURE; } if(!serverNameOk(opts->servername)) { ov_logfile_error("Error parsing SERVERNAME in line %u: only A-Z, a-z, 0-9 and _ allowed in server name.", line); return EXIT_FAILURE; } } /* HEAPSIZE */ else if(strstr(startRead, "HEAPSIZE")==startRead) { #if TLSF_HEAP //ov_logfile_info("TLSF is activated"); temp = readValue(startRead); if(!temp || !*temp) return EXIT_FAILURE; if(!opts->poolsize){ opts->poolsize = strtoul(temp, NULL, 0); } else{ return OV_ERR_HEAPOUTOFMEMORY; } free(temp); #endif } /* ID */ else if(strstr(startRead, "ID")==startRead) { opt_clear_string(&opts->password); opts->password = readValue(startRead); if(!opts->password || !*opts->password){ return EXIT_FAILURE; } } /* PORT */ else if(strstr(startRead, "PORT")==startRead) { temp = readValue(startRead); if(!temp || !*temp){ return EXIT_FAILURE; } opts->port = strtol(temp, &temp2, 0); if(*temp2) { ov_logfile_error("Error parsing line %u: too many arguments for PORT.", line); free(temp); return EXIT_FAILURE; } free(temp); } /* LIBRARY */ else if(strstr(startRead, "LIBRARY")==startRead) { if (opts->libcount<MAX_STARTUP_LIBRARIES) { opts->libraries[opts->libcount] = readValue(startRead); if(!opts->libraries[opts->libcount] || !*opts->libraries[opts->libcount]){ return EXIT_FAILURE; } opts->libcount++; } else ov_logfile_error("Too many libraries in start command and configfile.\n"); } /* LOGFILE */ else if((opts->ctx==ov_runtimeserver && strstr(startRead, "LOGFILE")==startRead )|| (opts->ctx==ov_dbutil && strstr(startRead, "DBUTILLOG")==startRead )) { temp = readValue(startRead); if(!temp || !*temp){ return EXIT_FAILURE; } set_logfile(opts, temp); free(temp); } /* ACTIVITYLOCK */ else if(strstr(startRead, "ACTIVITYLOCK")==startRead) { opts->activitylock = TRUE; if(*(startRead+12)) { ov_logfile_error("Error parsing line %u: ACTIVITYLOCK does not accept parameters.", line); return EXIT_FAILURE; } } /* OPTION */ else if(strstr(startRead, "OPTION")==startRead) { temp = readValue(startRead); if(!temp || !*temp){ return EXIT_FAILURE; } temp2 = temp; while((!isWhiteSpace(temp2)) && *temp2) temp2++; if(*temp2!='\0') { /* whitespaces at line end are stripped: nothing may follow here */ ov_logfile_error("Error parsing OPTION in line %u: no whitespaces allowed in options.", line); free(temp); return EXIT_FAILURE; } if(opts->commandline_options) { temp2 = realloc(opts->commandline_options, strlen(opts->commandline_options)+strlen(temp)+2); //oldlength + new option length + ' ' + '\0' if(temp2) { strcat(temp2, " "); strcat(temp2, temp); opts->commandline_options = temp2; } } else //first time commandline_options is a NULL-pointer --> strlen would crash { opts->commandline_options = malloc(strlen(temp)+1); if(opts->commandline_options) strcpy(opts->commandline_options, temp); } free(temp); } /* NOSTARTUP */ else if(strstr(startRead, "NOSTARTUP")==startRead) { opts->startup = FALSE; if(*(startRead+9)) { ov_logfile_error("Error parsing line %u: NOSTARTUP does not accept parameters.", line); return EXIT_FAILURE; } } /* EXIT */ else if(strstr(startRead, "EXIT")==startRead) { opts->exit = TRUE; if(*(startRead+4)) { ov_logfile_error("Error parsing line %u: EXIT does not accept parameters.", line); return EXIT_FAILURE; } } /* EXEC */ else if(strstr(startRead, "EXEC")==startRead) { if(!opts->exec) { temp = readValue(startRead); if(!temp || !*temp){ return EXIT_FAILURE; } temp2 = temp; while(!isWhiteSpace(temp2)){ if(!*temp2){ EXECFEWARGUMENTSERROR: ov_logfile_error("Error parsing line %u: not enough arguments to EXEC option.", line); free(temp); return EXIT_FAILURE; } temp2++; } *temp2 = '\0'; if(*temp!='/'){ opt_reassign_string(&opts->execIdent, temp); if(!opts->execIdent){ free(temp); return EXIT_FAILURE; } } else { opt_clear_string(&opts->execIdent); } temp3 = skipWhiteSpace(++temp2); temp2 = temp3; while(!isWhiteSpace(temp2)){ if(!temp2) goto EXECFEWARGUMENTSERROR; temp2++; } *temp2 = '\0'; if(*temp3!='/'){ opt_reassign_string(&opts->execClass, temp3); if(!opts->execClass){ free(temp); return EXIT_FAILURE; } } else { opt_clear_string(&opts->execClass); } temp3 = skipWhiteSpace(++temp2); temp2 = temp3; while(*temp2 && !isWhiteSpace(temp2)) temp2++; if(*temp2){ ov_logfile_error("Error parsing line %u: too many arguments to EXEC option.", line); free(temp); return EXIT_FAILURE; } if(*temp3!='/'){ opt_reassign_string(&opts->execLib, temp3); if(!opts->execLib){ free(temp); return EXIT_FAILURE; } } else { opt_clear_string(&opts->execLib); } opts->exec = TRUE; free(temp); } } /* ALLOWEDJITTER */ else if(strstr(startRead, "ALLOWEDJITTER")==startRead) { temp = readValue(startRead); if(!temp || !*temp){ return EXIT_FAILURE; } opts->maxAllowedJitter = strtoul(temp, &temp2, 0); if(*temp2) { ov_logfile_error("Error parsing line %u: too many arguments for ALLOWEDJITTER.", line); free(temp); return EXIT_FAILURE; } free(temp); } /* MAXSTRLENGTH */ else if(strstr(startRead, "MAXSTRLENGTH")==startRead) { temp = readValue(startRead); if(!temp || !*temp){ return EXIT_FAILURE; } opts->maxStringLength = strtoul(temp, &temp2, 0); if(*temp2) { ov_logfile_error("Error parsing line %u: too many arguments for MAXSTRLENGTH.", line); free(temp); return EXIT_FAILURE; } free(temp); } /* MAXVECLENGTH */ else if(strstr(startRead, "MAXVECLENGTH")==startRead) { temp = readValue(startRead); if(!temp || !*temp){ return EXIT_FAILURE; } opts->maxVectorLength = strtoul(temp, &temp2, 0); if(*temp2) { ov_logfile_error("Error parsing line %u: too many arguments for MAXVECLENGTH.", line); free(temp); return EXIT_FAILURE; } free(temp); } /* MAXNAMELENGTH */ else if(strstr(startRead, "MAXNAMELENGTH")==startRead) { temp = readValue(startRead); if(!temp || !*temp){ return EXIT_FAILURE; } opts->maxNameLength = strtoul(temp, &temp2, 0); if(*temp2) { ov_logfile_error("Error parsing line %u: too many arguments for MAXNAMELENGTH.", line); free(temp); return EXIT_FAILURE; } free(temp); } /* MAXHIERARCHYDEPTH */ else if(strstr(startRead, "MAXHIERARCHYDEPTH")==startRead) { temp = readValue(startRead); if(!temp || !*temp){ return EXIT_FAILURE; } opts->maxHierarchyDepth = strtoul(temp, &temp2, 0); if(*temp2) { ov_logfile_error("Error parsing line %u: too many arguments for MAXHIERARCHYDEPTH.", line); free(temp); return EXIT_FAILURE; } free(temp); } /* KSMAXITEMSPERREQ */ else if(strstr(startRead, "KSMAXITEMSPERREQ")==startRead) { temp = readValue(startRead); if(!temp || !*temp){ return EXIT_FAILURE; } opts->ks_maxItemsPerRequest = strtoul(temp, &temp2, 0); if(*temp2) { ov_logfile_error("Error parsing line %u: too many arguments for KSMAXITEMSPERREQ.", line); free(temp); return EXIT_FAILURE; } free(temp); } /* DBSIZE */ else if(strstr(startRead, "DBSIZE")==startRead) { temp = readValue(startRead); if(!temp || !*temp) return EXIT_FAILURE; opts->dbSize = strtoul(temp, NULL, 0); free(temp); } /* DBNOMAP */ else if(strstr(startRead, "DBNOMAP")==startRead) { opts->dbflags |= OV_DBOPT_NOMAP; } /* DBFORCECREATE */ else if(strstr(startRead, "DBFORCECREATE")==startRead) { opts->dbflags |= OV_DBOPT_FORCECREATE; } /* * default: option unknown */ else { ov_logfile_error("Error parsing line %u: unknown option", line); return EXIT_FAILURE; } } /* getline returns -1 on error or eof. eof is ok, error aborts program */ if(ferror(cfFile)) { fprintf(stderr, "Error reading config file"); fclose(cfFile); return EXIT_FAILURE; } fclose(cfFile); return OV_ERR_OK; }