int main(int argc, char *argv[]) { int i,j,k; mapObj *map=NULL; imageObj *image = NULL; char **layers=NULL; int num_layers=0; int layer_found=0; char *outfile=NULL; /* no -o sends image to STDOUT */ int iterations = 1; int draws = 0; for(i=1;i<argc;i++) { if (strcmp(argv[i],"-c") == 0) { /* user specified number of draws */ iterations = atoi(argv[i+1]); printf("We will draw %d times...\n", iterations); continue; } if(strcmp(argv[i], "-all_debug") == 0 && i < argc-1 ) /* global debug */ { int debug_level = atoi(argv[++i]); msSetGlobalDebugLevel(debug_level); /* Send output to stderr by default */ if (msGetErrorFile() == NULL) msSetErrorFile("stderr", NULL); continue; } } for(draws=0; draws<iterations; draws++) { struct mstimeval requeststarttime, requestendtime; if(msGetGlobalDebugLevel() >= MS_DEBUGLEVEL_TUNING) msGettimeofday(&requeststarttime, NULL); if(argc > 1 && strcmp(argv[1], "-v") == 0) { printf("%s\n", msGetVersion()); exit(0); } /* ---- check the number of arguments, return syntax if not correct ---- */ if( argc < 3 ) { fprintf(stdout, "\nPurpose: convert a mapfile to an image\n\n"); fprintf(stdout, "Syntax: shp2img -m mapfile [-o image] [-e minx miny maxx maxy] [-s sizex sizey]\n" " [-l \"layer1 [layers2...]\"] [-i format]\n" " [-all_debug n] [-map_debug n] [-layer_debug n] [-p n] [-c n] [-d layername datavalue]\n"); fprintf(stdout," -m mapfile: Map file to operate on - required\n" ); fprintf(stdout," -i format: Override the IMAGETYPE value to pick output format\n" ); fprintf(stdout," -o image: output filename (stdout if not provided)\n"); fprintf(stdout," -e minx miny maxx maxy: extents to render\n"); fprintf(stdout," -s sizex sizey: output image size\n"); fprintf(stdout," -l layers: layers / groups to enable - make sure they are quoted and space seperated if more than one listed\n" ); fprintf(stdout," -all_debug n: Set debug level for map and all layers\n" ); fprintf(stdout," -map_debug n: Set map debug level\n" ); fprintf(stdout," -layer_debug layer_name n: Set layer debug level\n" ); fprintf(stdout," -c n: draw map n number of times\n" ); fprintf(stdout," -p n: pause for n seconds after reading the map\n" ); fprintf(stdout," -d layername datavalue: change DATA value for layer\n" ); exit(0); } if ( msSetup() != MS_SUCCESS ) { msWriteError(stderr); exit(1); } /* Use MS_ERRORFILE and MS_DEBUGLEVEL env vars if set */ if ( msDebugInitFromEnv() != MS_SUCCESS ) { msWriteError(stderr); msCleanup(0); exit(1); } for(i=1;i<argc;i++) { /* Step though the user arguments, 1st to find map file */ if(strcmp(argv[i],"-m") == 0) { map = msLoadMap(argv[i+1], NULL); if(!map) { msWriteError(stderr); msCleanup(0); exit(1); } msApplyDefaultSubstitutions(map); } } if(!map) { fprintf(stderr, "Mapfile (-m) option not specified.\n"); msCleanup(0); exit(1); } for(i=1;i<argc;i++) { /* Step though the user arguments */ if(strcmp(argv[i],"-m") == 0) { /* skip it */ i+=1; } if(strcmp(argv[i],"-p") == 0) { int pause_length = atoi(argv[i+1]); time_t start_time = time(NULL); printf( "Start pause of %d seconds.\n", pause_length ); while( time(NULL) < start_time + pause_length ) {} printf( "Done pause.\n" ); i+=1; } if(strcmp(argv[i],"-o") == 0) { /* load the output image filename */ outfile = argv[i+1]; i+=1; } if(strcmp(argv[i],"-i") == 0) { outputFormatObj *format; format = msSelectOutputFormat( map, argv[i+1] ); if( format == NULL ) printf( "No such OUTPUTFORMAT as %s.\n", argv[i+1] ); else { msFree( (char *) map->imagetype ); map->imagetype = msStrdup( argv[i+1] ); msApplyOutputFormat( &(map->outputformat), format, map->transparent, map->interlace, map->imagequality ); } i+=1; } if(strcmp(argv[i],"-d") == 0) { /* swap layer data */ for(j=0; j<map->numlayers; j++) { if(strcmp(GET_LAYER(map, j)->name, argv[i+1]) == 0) { free(GET_LAYER(map, j)->data); GET_LAYER(map, j)->data = msStrdup(argv[i+2]); break; } } i+=2; } if(strcmp(argv[i], "-all_debug") == 0 && i < argc-1 ) /* global debug */ { int debug_level = atoi(argv[++i]); /* msSetGlobalDebugLevel() already called. Just need to force debug * level in map and all layers */ map->debug = debug_level; for(j=0; j<map->numlayers; j++) { GET_LAYER(map, j)->debug = debug_level; } } if(strcmp(argv[i], "-map_debug") == 0 && i < argc-1 ) /* debug */ { map->debug = atoi(argv[++i]); /* Send output to stderr by default */ if (msGetErrorFile() == NULL) msSetErrorFile("stderr", NULL); } if(strcmp(argv[i], "-layer_debug") == 0 && i < argc-1 ) /* debug */ { const char *layer_name = argv[++i]; int debug_level = atoi(argv[++i]); int got_layer = 0; for(j=0; j<map->numlayers; j++) { if(strcmp(GET_LAYER(map, j)->name,layer_name) == 0 ) { GET_LAYER(map, j)->debug = debug_level; got_layer = 1; } } if( !got_layer ) fprintf( stderr, " Did not find layer '%s' from -layer_debug switch.\n", layer_name ); /* Send output to stderr by default */ if (msGetErrorFile() == NULL) msSetErrorFile("stderr", NULL); } if(strcmp(argv[i],"-e") == 0) { /* change extent */ if( argc <= i+4 ) { fprintf( stderr, "Argument -e needs 4 space separated numbers as argument.\n" ); msCleanup(0); exit(1); } map->extent.minx = atof(argv[i+1]); map->extent.miny = atof(argv[i+2]); map->extent.maxx = atof(argv[i+3]); map->extent.maxy = atof(argv[i+4]); i+=4; } if (strcmp(argv[i], "-s") == 0) { msMapSetSize(map, atoi(argv[i+1]), atoi(argv[i+2])); i+=2; } if(strcmp(argv[i],"-l") == 0) { /* load layer list */ layers = msStringSplit(argv[i+1], ' ', &(num_layers)); for(j=0; j<num_layers; j++) { /* loop over -l */ layer_found=0; for(k=0; k<map->numlayers; k++) { if((GET_LAYER(map, k)->name && strcasecmp(GET_LAYER(map, k)->name, layers[j]) == 0) || (GET_LAYER(map, k)->group && strcasecmp(GET_LAYER(map, k)->group, layers[j]) == 0)) { layer_found = 1; break; } } if (layer_found==0) { fprintf(stderr, "Layer (-l) \"%s\" not found\n", layers[j]); msCleanup(0); exit(1); } } for(j=0; j<map->numlayers; j++) { if(GET_LAYER(map, j)->status == MS_DEFAULT) continue; else { GET_LAYER(map, j)->status = MS_OFF; for(k=0; k<num_layers; k++) { if((GET_LAYER(map, j)->name && strcasecmp(GET_LAYER(map, j)->name, layers[k]) == 0) || (GET_LAYER(map, j)->group && strcasecmp(GET_LAYER(map, j)->group, layers[k]) == 0)) { GET_LAYER(map, j)->status = MS_ON; break; } } } } msFreeCharArray(layers, num_layers); i+=1; } } image = msDrawMap(map, MS_FALSE); if(!image) { msWriteError(stderr); msFreeMap(map); msCleanup(0); exit(1); } if( msSaveImage(map, image, outfile) != MS_SUCCESS ) { msWriteError(stderr); } msFreeImage(image); msFreeMap(map); if(msGetGlobalDebugLevel() >= MS_DEBUGLEVEL_TUNING) { msGettimeofday(&requestendtime, NULL); msDebug("shp2img total time: %.3fs\n", (requestendtime.tv_sec+requestendtime.tv_usec/1.0e6)- (requeststarttime.tv_sec+requeststarttime.tv_usec/1.0e6) ); } msCleanup(0); } /* for(draws=0; draws<iterations; draws++) { */ return(0); } /* ---- END Main Routine ---- */
/** * @details This is called by `MapservAsync` and runs in a different thread to * that function. It performs the actual work of interacting with * mapserver. The code is based on the logic found in the `mapserv` program but * the output is instead buffered using the mapserver output buffering * functionality: it can then be captured and passed back to the client. * * @param req The asynchronous libuv request. */ void Map::MapservWork(uv_work_t *req) { /* No HandleScope! This is run in a separate thread: *No* contact should be made with the Node/V8 world here. */ MapBaton *baton = static_cast<MapBaton*>(req->data); mapservObj* mapserv = NULL; bool reportError = false; // flag an error as worthy of reporting if (msDebugInitFromEnv() != MS_SUCCESS) { reportError = true; goto handle_error; } mapserv = msAllocMapServObj(); msIO_installStdinFromBuffer(); // required to catch POSTS without data msIO_installStdoutToBuffer(); // required to capture mapserver output // load the CGI parameters from the environment object mapserv->request->NumParams = wrap_loadParams(mapserv->request, GetEnv, const_cast<char *>(baton->body.c_str()), baton->body.length(), static_cast<void *>(&(baton->env))); if( mapserv->request->NumParams == -1 ) { // no errors are generated by default but messages are output instead msSetError( MS_MISCERR, "No request parameters loaded", "Map::MapservWork" ); reportError = true; goto get_output; } // Copy the map into the mapservObj for this request if(!LoadMap(mapserv, baton->map)) { reportError = true; goto get_output; } // Execute the request if(msCGIDispatchRequest(mapserv) != MS_SUCCESS) { reportError = true; goto get_output; } get_output: // Get the content type. If headers other than content-type need to be // retrieved it may be best to use something along the lines of // <https://github.com/joyent/http-parser>. baton->content_type = msIO_stripStdoutBufferContentType(); msIO_stripStdoutBufferContentHeaders(); // Get the buffered output baton->buffer = msIO_getStdoutBufferBytes(); handle_error: // handle any unhandled errors errorObj *error = msGetErrorObj(); if (error && error->code != MS_NOERR) { // report the error if requested if (reportError) { baton->error = new MapserverError(error); } msResetErrorList(); // clear all handled errors } // clean up msFreeMapServObj(mapserv); msIO_resetHandlers(); msDebugCleanup(); return; }
int main(int argc, char *argv[]) { int iArg; int sendheaders = MS_TRUE; struct mstimeval execstarttime, execendtime; struct mstimeval requeststarttime, requestendtime; mapservObj* mapserv = NULL; exitSignal = 0; msSetup(); /* Use MS_ERRORFILE and MS_DEBUGLEVEL env vars if set */ if( msDebugInitFromEnv() != MS_SUCCESS ) { msCGIWriteError(mapserv); msCleanup(); exit(0); } if(msGetGlobalDebugLevel() >= MS_DEBUGLEVEL_TUNING) msGettimeofday(&execstarttime, NULL); /* -------------------------------------------------------------------- */ /* Process arguments. In normal use as a cgi-bin there are no */ /* commandline switches, but we provide a few for test/debug */ /* purposes, and to query the version info. */ /* -------------------------------------------------------------------- */ for( iArg = 1; iArg < argc; iArg++ ) { /* Keep only "-v", "-nh" and "QUERY_STRING=..." enabled by default. * The others will require an explicit -DMS_ENABLE_CGI_CL_DEBUG_ARGS * at compile time. */ if( strcmp(argv[iArg],"-v") == 0 ) { printf("%s\n", msGetVersion()); fflush(stdout); exit(0); } else if(strcmp(argv[iArg], "-nh") == 0) { sendheaders = MS_FALSE; } else if( strncmp(argv[iArg], "QUERY_STRING=", 13) == 0 ) { /* Debugging hook... pass "QUERY_STRING=..." on the command-line */ putenv( "REQUEST_METHOD=GET" ); putenv( argv[iArg] ); } #ifdef MS_ENABLE_CGI_CL_DEBUG_ARGS else if( iArg < argc-1 && strcmp(argv[iArg], "-tmpbase") == 0) { msForceTmpFileBase( argv[++iArg] ); } else if( iArg < argc-1 && strcmp(argv[iArg], "-t") == 0) { char **tokens; int numtokens=0; if((tokens=msTokenizeMap(argv[iArg+1], &numtokens)) != NULL) { int i; for(i=0; i<numtokens; i++) printf("%s\n", tokens[i]); msFreeCharArray(tokens, numtokens); } else { msCGIWriteError(mapserv); } exit(0); } else if( strncmp(argv[iArg], "MS_ERRORFILE=", 13) == 0 ) { msSetErrorFile( argv[iArg] + 13, NULL ); } else if( strncmp(argv[iArg], "MS_DEBUGLEVEL=", 14) == 0) { msSetGlobalDebugLevel( atoi(argv[iArg] + 14) ); } #endif /* MS_ENABLE_CGI_CL_DEBUG_ARGS */ else { /* we don't produce a usage message as some web servers pass junk arguments */ } } /* -------------------------------------------------------------------- */ /* Setup cleanup magic, mainly for FastCGI case. */ /* -------------------------------------------------------------------- */ #ifndef WIN32 signal( SIGUSR1, msCleanupOnSignal ); signal( SIGTERM, msCleanupOnSignal ); #endif #ifdef USE_FASTCGI msIO_installFastCGIRedirect(); #ifdef WIN32 atexit( msCleanupOnExit ); #endif /* In FastCGI case we loop accepting multiple requests. In normal CGI */ /* use we only accept and process one request. */ while( !exitSignal && FCGI_Accept() >= 0 ) { #endif /* def USE_FASTCGI */ /* -------------------------------------------------------------------- */ /* Process a request. */ /* -------------------------------------------------------------------- */ mapserv = msAllocMapServObj(); mapserv->sendheaders = sendheaders; /* override the default if necessary (via command line -nh switch) */ mapserv->request->NumParams = loadParams(mapserv->request, NULL, NULL, 0, NULL); if( mapserv->request->NumParams == -1 ) { msCGIWriteError(mapserv); goto end_request; } mapserv->map = msCGILoadMap(mapserv); if(!mapserv->map) { msCGIWriteError(mapserv); goto end_request; } if( mapserv->map->debug >= MS_DEBUGLEVEL_TUNING) msGettimeofday(&requeststarttime, NULL); #ifdef USE_FASTCGI if( mapserv->map->debug ) { static int nRequestCounter = 1; msDebug( "CGI Request %d on process %d\n", nRequestCounter, getpid() ); nRequestCounter++; } #endif if(msCGIDispatchRequest(mapserv) != MS_SUCCESS) { msCGIWriteError(mapserv); goto end_request; } end_request: if(mapserv) { if(mapserv->map && mapserv->map->debug >= MS_DEBUGLEVEL_TUNING) { msGettimeofday(&requestendtime, NULL); msDebug("mapserv request processing time (msLoadMap not incl.): %.3fs\n", (requestendtime.tv_sec+requestendtime.tv_usec/1.0e6)- (requeststarttime.tv_sec+requeststarttime.tv_usec/1.0e6) ); } msCGIWriteLog(mapserv,MS_FALSE); msFreeMapServObj(mapserv); } #ifdef USE_FASTCGI /* FCGI_ --- return to top of loop */ msResetErrorList(); continue; } /* end fastcgi loop */ #endif /* normal case, processing is complete */ if(msGetGlobalDebugLevel() >= MS_DEBUGLEVEL_TUNING) { msGettimeofday(&execendtime, NULL); msDebug("mapserv total execution time: %.3fs\n", (execendtime.tv_sec+execendtime.tv_usec/1.0e6)- (execstarttime.tv_sec+execstarttime.tv_usec/1.0e6) ); } msCleanup(); exit( 0 ); }