• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

geographika / mapserver / 17823520225

18 Sep 2025 08:57AM UTC coverage: 41.442% (-0.02%) from 41.466%
17823520225

push

github

geographika
Use full path for CONFIG test

62112 of 149877 relevant lines covered (41.44%)

25354.57 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

77.95
/src/apps/mapserv.c
1
/******************************************************************************
2
 * $id: mapserv.c 9470 2009-10-16 16:09:31Z sdlime $
3
 *
4
 * Project:  MapServer
5
 * Purpose:  MapServer CGI mainline.
6
 * Author:   Steve Lime and the MapServer team.
7
 *
8
 ******************************************************************************
9
 * Copyright (c) 1996-2005 Regents of the University of Minnesota.
10
 *
11
 * Permission is hereby granted, free of charge, to any person obtaining a
12
 * copy of this software and associated documentation files (the "Software"),
13
 * to deal in the Software without restriction, including without limitation
14
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15
 * and/or sell copies of the Software, and to permit persons to whom the
16
 * Software is furnished to do so, subject to the following conditions:
17
 *
18
 * The above copyright notice and this permission notice shall be included in
19
 * all copies of this Software or works derived from this Software.
20
 *
21
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27
 * DEALINGS IN THE SOFTWARE.
28
 ****************************************************************************/
29

30
#ifndef _XOPEN_SOURCE
31
#define _XOPEN_SOURCE 500 // for putenv
32
#endif
33

34
#include "mapserver-config.h"
35
#include <stdbool.h>
36
#include <stdlib.h>
37

38
#ifdef USE_FASTCGI
39
#define NO_FCGI_DEFINES
40
#include "fcgi_stdio.h"
41
#endif
42

43
#include "mapserv.h"
44
#include "../mapio.h"
45
#include "../maptime.h"
46

47
#include "cpl_conv.h"
48

49
#ifndef _WIN32
50
#include <signal.h>
51
#endif
52

53
/************************************************************************/
54
/*                      FastCGI cleanup functions.                      */
55
/************************************************************************/
56

57
static int finish_process = 0;
58

59
#ifndef _WIN32
60
static void msCleanupOnSignal(int nInData) {
×
61
  (void)nInData;
62
  finish_process = 1;
×
63
}
×
64
#endif
65

66
#ifdef _WIN32
67
static void msCleanupOnExit(void) { finish_process = 1; }
68
#endif
69

70
#ifdef USE_FASTCGI
71

72
/************************************************************************/
73
/*                           msIO_fcgiRead()                            */
74
/*                                                                      */
75
/*      This is the default implementation via stdio.                   */
76
/************************************************************************/
77

78
static int msIO_fcgiRead(void *cbData, void *data, int byteCount)
159✔
79

80
{
81
  return (int)FCGI_fread(data, 1, byteCount, (FCGI_FILE *)cbData);
159✔
82
}
83

84
/************************************************************************/
85
/*                           msIO_fcgiWrite()                           */
86
/*                                                                      */
87
/*      This is the default implementation via stdio.                   */
88
/************************************************************************/
89

90
static int msIO_fcgiWrite(void *cbData, void *data, int byteCount)
194,000✔
91

92
{
93
  return (int)FCGI_fwrite(data, 1, byteCount, (FCGI_FILE *)cbData);
194,000✔
94
}
95

96
/************************************************************************/
97
/*                    msIO_installFastCGIRedirect()                     */
98
/************************************************************************/
99
static int msIO_installFastCGIRedirect()
1,991✔
100

101
{
102
  msIOContext stdin_ctx, stdout_ctx, stderr_ctx;
103

104
  stdin_ctx.label = "fcgi";
1,991✔
105
  stdin_ctx.write_channel = MS_FALSE;
1,991✔
106
  stdin_ctx.readWriteFunc = msIO_fcgiRead;
1,991✔
107
  stdin_ctx.cbData = (void *)FCGI_stdin;
1,991✔
108

109
  stdout_ctx.label = "fcgi";
1,991✔
110
  stdout_ctx.write_channel = MS_TRUE;
1,991✔
111
  stdout_ctx.readWriteFunc = msIO_fcgiWrite;
1,991✔
112
  stdout_ctx.cbData = (void *)FCGI_stdout;
1,991✔
113

114
  stderr_ctx.label = "fcgi";
1,991✔
115
  stderr_ctx.write_channel = MS_TRUE;
1,991✔
116
  stderr_ctx.readWriteFunc = msIO_fcgiWrite;
1,991✔
117
  stderr_ctx.cbData = (void *)FCGI_stderr;
1,991✔
118

119
  msIO_installHandlers(&stdin_ctx, &stdout_ctx, &stderr_ctx);
1,991✔
120

121
  return MS_TRUE;
1,991✔
122
}
123

124
#endif
125
/************************************************************************/
126
/*                                main()                                */
127
/************************************************************************/
128
int main(int argc, char *argv[]) {
1,991✔
129
  int sendheaders = MS_TRUE;
130
  struct mstimeval execstarttime, execendtime;
131
  struct mstimeval requeststarttime, requestendtime;
132
  mapservObj *mapserv = NULL;
133
  configObj *config = NULL;
134

135
  /*
136
  ** Process -v and -h command line arguments  first end exit. We want to avoid
137
  *any error messages
138
  ** associated with msLoadConfig() or msSetup().
139
  */
140
  const char *config_filename = NULL;
141
  const bool use_command_line_options = getenv("QUERY_STRING") == NULL;
1,991✔
142
  if (use_command_line_options) {
1,991✔
143
    /* WARNING:
144
     * Do not parse command line arguments (especially those that could have
145
     * dangerous consequences if controlled through a web request), without
146
     * checking that the QUERY_STRING environment variable is *not* set, because
147
     * in a CGI context, command line arguments can be generated from the
148
     * content of the QUERY_STRING, and thus cause a security problem. For ex,
149
     * "http://example.com/mapserv.cgi?-conf+bar would result in "mapserv.cgi
150
     * -conf bar" being invoked. See
151
     * https://github.com/MapServer/MapServer/pull/6429#issuecomment-952533589
152
     * and https://datatracker.ietf.org/doc/html/rfc3875#section-4.4
153
     */
154
    for (int iArg = 1; iArg < argc; iArg++) {
3,921✔
155
      if (strcmp(argv[iArg], "-v") == 0) {
1,930✔
156
        printf("%s\n", msGetVersion());
×
157
        fflush(stdout);
×
158
        exit(0);
×
159
      } else if (strcmp(argv[iArg], "-h") == 0 ||
1,930✔
160
                 strcmp(argv[iArg], "--help") == 0) {
1,930✔
161
        printf("Usage: mapserv [--help] [-v] [-nh] [QUERY_STRING=value] "
162
               "[PATH_INFO=value]\n");
163
        printf("                [-conf filename]\n");
164
        printf("\n");
165
        printf("Options :\n");
166
        printf("  -h, --help              Display this help message.\n");
167
        printf("  -v                      Display version and exit.\n");
168
        printf(
169
            "  -nh                     Suppress HTTP headers in CGI mode.\n");
170
        printf("  -conf filename          Filename of the MapServer "
171
               "configuration file.\n");
172
        printf("  QUERY_STRING=value      Set the QUERY_STRING in GET request "
173
               "mode.\n");
174
        printf("  PATH_INFO=value         Set the PATH_INFO for an API "
175
               "request.\n");
176
        fflush(stdout);
×
177
        exit(0);
×
178
      } else if (iArg < argc - 1 && strcmp(argv[iArg], "-conf") == 0) {
1,930✔
179
        config_filename = argv[iArg + 1];
17✔
180
        ++iArg;
17✔
181
      }
182
    }
183
  }
184

185
  config = msLoadConfig(config_filename); // first thing
1,991✔
186
  if (config == NULL) {
1,991✔
187
#ifdef USE_FASTCGI
188
    msIO_installFastCGIRedirect(); // FastCGI setup for error handling here
4✔
189
    FCGI_Accept();
4✔
190
#endif
191
    msCGIWriteError(mapserv);
4✔
192
    exit(0);
4✔
193
  }
194

195
  /* -------------------------------------------------------------------- */
196
  /*      Initialize mapserver.  This sets up threads, GD and GEOS as     */
197
  /*      well as using MS_ERRORFILE and MS_DEBUGLEVEL env vars if set.   */
198
  /* -------------------------------------------------------------------- */
199
  if (msSetup() != MS_SUCCESS) {
1,987✔
200
#ifdef USE_FASTCGI
201
    msIO_installFastCGIRedirect(); // FastCGI setup for error handling here
×
202
    FCGI_Accept();
×
203
#endif
204
    msCGIWriteError(mapserv);
×
205
    msCleanup();
×
206
    msFreeConfig(config);
×
207
    exit(0);
×
208
  }
209

210
  if (msGetGlobalDebugLevel() >= MS_DEBUGLEVEL_TUNING)
1,987✔
211
    msGettimeofday(&execstarttime, NULL);
×
212

213
  /* -------------------------------------------------------------------- */
214
  /*      Process arguments. In normal use as a cgi-bin there are no      */
215
  /*      commandline switches, but we provide a few for test/debug       */
216
  /*      purposes.                                                       */
217
  /* -------------------------------------------------------------------- */
218
  if (use_command_line_options) {
1,987✔
219
    for (int iArg = 1; iArg < argc; iArg++) {
3,922✔
220
      if (strcmp(argv[iArg], "-nh") == 0) {
1,935✔
221
        sendheaders = MS_FALSE;
222
        msIO_setHeaderEnabled(MS_FALSE);
×
223
      } else if (strncmp(argv[iArg], "QUERY_STRING=", 13) == 0) {
1,935✔
224
        /* Debugging hook... pass "QUERY_STRING=..." on the command-line */
225
        putenv("REQUEST_METHOD=GET");
1,827✔
226
        /* coverity[tainted_string] */
227
        putenv(argv[iArg]);
1,827✔
228
      } else if (strncmp(argv[iArg], "PATH_INFO=", 10) == 0) {
108✔
229
        /* Debugging hook for APIs... pass "PATH_INFO=..." on the command-line
230
         */
231
        putenv("REQUEST_METHOD=GET");
39✔
232
        /* coverity[tainted_string] */
233
        putenv(argv[iArg]);
39✔
234
      }
235
    }
236
  }
237

238
  /* -------------------------------------------------------------------- */
239
  /*      Setup cleanup magic, mainly for FastCGI case.                   */
240
  /* -------------------------------------------------------------------- */
241
#ifndef _WIN32
242
  signal(SIGUSR1, msCleanupOnSignal);
1,987✔
243
  signal(SIGTERM, msCleanupOnSignal);
1,987✔
244
#endif
245

246
#ifdef USE_FASTCGI
247
  msIO_installFastCGIRedirect();
1,987✔
248

249
  /* In FastCGI case we loop accepting multiple requests.  In normal CGI */
250
  /* use we only accept and process one request.  */
251
  while (!finish_process && FCGI_Accept() >= 0) {
3,974✔
252
#endif /* def USE_FASTCGI */
253

254
    /* -------------------------------------------------------------------- */
255
    /*      Process a request.                                              */
256
    /* -------------------------------------------------------------------- */
257
    mapserv = msAllocMapServObj();
1,987✔
258
    mapserv->sendheaders = sendheaders; /* override the default if necessary
1,987✔
259
                                           (via command line -nh switch) */
260

261
    mapserv->request->NumParams =
1,987✔
262
        loadParams(mapserv->request, NULL, NULL, 0, NULL);
1,987✔
263

264
    const char *path_info = getenv("PATH_INFO");
1,987✔
265
    if (path_info != NULL && strcmp(path_info, "/") == 0) {
1,987✔
266
      if (msConfigGetEnv(config, "MS_INDEX_TEMPLATE_DIRECTORY") != NULL) {
1✔
267
        // return the landing page if MS_INDEX_TEMPLATE_DIRECTORY is set
268
        msCGIDispatchIndexRequest(mapserv, config);
1✔
269
        goto end_request;
1✔
270
      }
271
    }
272

273
    if (msCGIIsAPIRequest(mapserv) == MS_FALSE &&
1,986✔
274
        mapserv->request->NumParams == -1) { /* no QUERY_STRING or PATH_INFO */
1,948✔
275
      msCGIWriteError(mapserv);
1✔
276
      goto end_request;
1✔
277
    }
278

279
    mapserv->map = msCGILoadMap(mapserv, config);
1,985✔
280
    if (!mapserv->map) {
1,985✔
281
      msCGIWriteError(mapserv);
13✔
282
      goto end_request;
13✔
283
    }
284

285
    if (mapserv->map->debug >= MS_DEBUGLEVEL_TUNING)
1,972✔
286
      msGettimeofday(&requeststarttime, NULL);
3✔
287

288
#ifdef USE_FASTCGI
289
    if (mapserv->map->debug) {
1,972✔
290
      static int nRequestCounter = 1;
291

292
      msDebug("CGI Request %d on process %d\n", nRequestCounter, getpid());
39✔
293
      nRequestCounter++;
39✔
294
    }
295
#endif
296

297
    if (mapserv->request->api_path != NULL) {
1,972✔
298
      switch (mapserv->request->api_path_length) {
37✔
299
      case 0: // just in case, treat as normal
×
300
        if (msCGIDispatchRequest(mapserv) != MS_SUCCESS) {
×
301
          msCGIWriteError(mapserv);
×
302
          goto end_request;
×
303
        }
304
        break;
305

306
      case 1:
4✔
307
        if (msConfigGetEnv(config, "MS_INDEX_TEMPLATE_DIRECTORY") != NULL) {
4✔
308
          // Try normal dispatch first
309
          if (msCGIDispatchRequest(mapserv) != MS_SUCCESS) {
×
310
            // Fallback to landing page
311
            if (msCGIDispatchMapIndexRequest(mapserv, config) != MS_SUCCESS) {
×
312
              msCGIWriteError(mapserv);
×
313
              goto end_request;
×
314
            }
315
          }
316
        } else {
317
          if (msCGIDispatchRequest(mapserv) != MS_SUCCESS) {
4✔
318
            msCGIWriteError(mapserv);
2✔
319
            goto end_request;
2✔
320
          }
321
        }
322
        break;
323

324
      default: // length > 1
33✔
325
        if (msCGIDispatchAPIRequest(mapserv) != MS_SUCCESS) {
33✔
326
          msCGIWriteError(mapserv);
2✔
327
          goto end_request;
2✔
328
        }
329
        break;
330
      }
331
    } else {
332
      // api_path == NULL
333
      if (msCGIDispatchRequest(mapserv) != MS_SUCCESS) {
1,935✔
334
        msCGIWriteError(mapserv);
268✔
335
        goto end_request;
268✔
336
      }
337
    }
338

339
  end_request:
1,667✔
340
    if (mapserv->map && mapserv->map->debug >= MS_DEBUGLEVEL_TUNING) {
1,987✔
341
      msGettimeofday(&requestendtime, NULL);
3✔
342
      msDebug("mapserv request processing time (msLoadMap not incl.): %.3fs\n",
3✔
343
              (requestendtime.tv_sec + requestendtime.tv_usec / 1.0e6) -
3✔
344
                  (requeststarttime.tv_sec + requeststarttime.tv_usec / 1.0e6));
3✔
345
    }
346
    msFreeMapServObj(mapserv);
1,987✔
347
#ifdef USE_FASTCGI
348
    /* FCGI_ --- return to top of loop */
349
    msResetErrorList();
1,987✔
350
    continue;
1,987✔
351
  } /* end fastcgi loop */
352
#endif
353

354
  /* normal case, processing is complete */
355
  if (msGetGlobalDebugLevel() >= MS_DEBUGLEVEL_TUNING) {
1,987✔
356
    msGettimeofday(&execendtime, NULL);
×
357
    msDebug("mapserv total execution time: %.3fs\n",
×
358
            (execendtime.tv_sec + execendtime.tv_usec / 1.0e6) -
×
359
                (execstarttime.tv_sec + execstarttime.tv_usec / 1.0e6));
×
360
  }
361
  msCleanup();
1,987✔
362
  msFreeConfig(config);
1,987✔
363

364
#ifdef _WIN32
365
  /* flush pending writes to stdout */
366
  fflush(stdout);
367
#endif
368

369
  exit(0);
1,987✔
370
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc