source: trunk/zoo-project/zoo-kernel/zoo_service_loader.c @ 675

Last change on this file since 675 was 673, checked in by djay, 9 years ago

Fixes in configure.ac. Fix in registry creation. Fixes for Data node for WPS version 2.0.0.

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc
File size: 65.0 KB
Line 
1/*
2 * Author : Gérald FENOY
3 *
4 *  Copyright 2008-2013 GeoLabs SARL. All rights reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24
25extern "C" int yylex ();
26extern "C" int crlex ();
27
28#ifdef USE_OTB
29#include "service_internal_otb.h"
30#else
31#define length(x) (sizeof(x) / sizeof(x[0]))
32#endif
33
34#include "cgic.h"
35
36extern "C"
37{
38#include <libxml/tree.h>
39#include <libxml/xmlmemory.h>
40#include <libxml/parser.h>
41#include <libxml/xpath.h>
42#include <libxml/xpathInternals.h>
43}
44
45#include "ulinet.h"
46
47#include <libintl.h>
48#include <locale.h>
49#include <string.h>
50
51#include "service.h"
52
53#include "service_internal.h"
54#include "server_internal.h"
55#include "response_print.h"
56#include "request_parser.h"
57#include "sqlapi.h"
58
59#ifdef USE_PYTHON
60#include "service_internal_python.h"
61#endif
62
63#ifdef USE_SAGA
64#include "service_internal_saga.h"
65#endif
66
67#ifdef USE_JAVA
68#include "service_internal_java.h"
69#endif
70
71#ifdef USE_PHP
72#include "service_internal_php.h"
73#endif
74
75#ifdef USE_JS
76#include "service_internal_js.h"
77#endif
78
79#ifdef USE_RUBY
80#include "service_internal_ruby.h"
81#endif
82
83#ifdef USE_PERL
84#include "service_internal_perl.h"
85#endif
86
87#include <dirent.h>
88#include <signal.h>
89#include <unistd.h>
90#ifndef WIN32
91#include <dlfcn.h>
92#include <libgen.h>
93#else
94#include <windows.h>
95#include <direct.h>
96#include <sys/types.h>
97#include <sys/stat.h>
98#include <unistd.h>
99#define pid_t int;
100#endif
101#include <fcntl.h>
102#include <time.h>
103#include <stdarg.h>
104
105#ifdef WIN32
106extern "C"
107{
108  __declspec (dllexport) char *strcasestr (char const *a, char const *b)
109#ifndef USE_MS
110  {
111    char *x = zStrdup (a);
112    char *y = zStrdup (b);
113
114      x = _strlwr (x);
115      y = _strlwr (y);
116    char *pos = strstr (x, y);
117    char *ret = pos == NULL ? NULL : (char *) (a + (pos - x));
118      free (x);
119      free (y);
120      return ret;
121  };
122#else
123   ;
124#endif
125}
126#endif
127
128/**
129 * Translation function for zoo-kernel
130 */
131#define _(String) dgettext ("zoo-kernel",String)
132/**
133 * Translation function for zoo-service
134 */
135#define __(String) dgettext ("zoo-service",String)
136
137#ifdef WIN32
138  #ifndef PROGRAMNAME
139    #define PROGRAMNAME "zoo_loader.cgi"
140  #endif
141#endif
142
143extern int getServiceFromFile (maps *, const char *, service **);
144
145/**
146 * Parse the service file using getServiceFromFile or use getServiceFromYAML
147 * if YAML support was activated.
148 *
149 * @param conf the conf maps containing the main.cfg settings
150 * @param file the file name to parse
151 * @param service the service to update witht the file content
152 * @param name the service name
153 * @return true if the file can be parsed or false
154 * @see getServiceFromFile, getServiceFromYAML
155 */
156int
157readServiceFile (maps * conf, char *file, service ** service, char *name)
158{
159  int t = getServiceFromFile (conf, file, service);
160#ifdef YAML
161  if (t < 0)
162    {
163      t = getServiceFromYAML (conf, file, service, name);
164    }
165#endif
166  return t;
167}
168
169/**
170 * Replace a char by another one in a string
171 *
172 * @param str the string to update
173 * @param toReplace the char to replace
174 * @param toReplaceBy the char that will be used
175 */
176void
177translateChar (char *str, char toReplace, char toReplaceBy)
178{
179  int i = 0, len = strlen (str);
180  for (i = 0; i < len; i++)
181    {
182      if (str[i] == toReplace)
183        str[i] = toReplaceBy;
184    }
185}
186
187
188/**
189 * Create the profile registry.
190 *
191 * The profile registry is optional (created only if the registry key is
192 * available in the [main] section of the main.cfg file) and can be used to
193 * store the profiles hierarchy. The registry is a directory which should
194 * contain the following sub-directories:
195 *  * concept: direcotry containing .html files describing concept
196 *  * generic: directory containing .zcfg files for wps:GenericProcess
197 *  * implementation: directory containing .zcfg files for wps:Process
198 *
199 * @param m the conf maps containing the main.cfg settings
200 * @param r the registry to update
201 * @param reg_dir the resgitry
202 * @param saved_stdout the saved stdout identifier
203 * @return 0 if the resgitry is null or was correctly updated, -1 on failure
204 */
205int
206createRegistry (maps* m,registry ** r, char *reg_dir, int saved_stdout)
207{
208  char registryKeys[3][15]={
209    "concept",
210    "generic",
211    "implementation"
212  };
213  int scount = 0,i=0;
214  if (reg_dir == NULL)
215    return 0;
216  for(i=0;i<3;i++){
217    char * tmpName =
218      (char *) malloc ((strlen (reg_dir) + strlen (registryKeys[i]) + 2) *
219                       sizeof (char));
220    sprintf (tmpName, "%s/%s", reg_dir, registryKeys[i]);
221   
222    DIR *dirp1 = opendir (tmpName);
223    struct dirent *dp1;
224    while ((dp1 = readdir (dirp1)) != NULL){
225      char* extn = strstr(dp1->d_name, ".zcfg");
226      if(dp1->d_name[0] != '.' && extn != NULL && strlen(extn) == 5)
227        {
228          int t;
229          char *tmps1=
230            (char *) malloc ((strlen (tmpName) + strlen (dp1->d_name) + 2) *
231                             sizeof (char));
232          sprintf (tmps1, "%s/%s", tmpName, dp1->d_name);
233          char *tmpsn = zStrdup (dp1->d_name);
234          tmpsn[strlen (tmpsn) - 5] = 0;
235          service* s1 = (service *) malloc (SERVICE_SIZE);
236          if (s1 == NULL)
237            {
238              dup2 (saved_stdout, fileno (stdout));
239              errorException (m, _("Unable to allocate memory."),
240                              "InternalError", NULL);
241              return -1;
242            }
243          t = readServiceFile (m, tmps1, &s1, tmpsn);
244          free (tmpsn);
245          if (t < 0)
246            {
247              map *tmp00 = getMapFromMaps (m, "lenv", "message");
248              char tmp01[1024];
249              if (tmp00 != NULL)
250                sprintf (tmp01, _("Unable to parse the ZCFG file: %s (%s)"),
251                         dp1->d_name, tmp00->value);
252              else
253                sprintf (tmp01, _("Unable to parse the ZCFG file: %s."),
254                         dp1->d_name);
255              dup2 (saved_stdout, fileno (stdout));
256              errorException (m, tmp01, "InternalError", NULL);
257              return -1;
258            }
259#ifdef DEBUG
260          dumpService (s1);
261          fflush (stdout);
262          fflush (stderr);
263#endif
264          if(strncasecmp(registryKeys[i],"implementation",14)==0){
265            inheritance(*r,&s1);
266          }
267          addServiceToRegistry(r,registryKeys[i],s1);
268          freeService (&s1);
269          free (s1);
270          scount++;
271        }
272    }
273    (void) closedir (dirp1);
274  }
275  return 0;
276}
277
278/**
279 * Recursivelly parse zcfg starting from the ZOO-Kernel cwd.
280 * Call the func function given in arguments after parsing the ZCFG file.
281 *
282 * @param m the conf maps containing the main.cfg settings
283 * @param r the registry containing profiles hierarchy
284 * @param n the root XML Node to add the sub-elements
285 * @param conf_dir the location of the main.cfg file (basically cwd)
286 * @param prefix the current prefix if any, or NULL
287 * @param saved_stdout the saved stdout identifier
288 * @param level the current level (number of sub-directories to reach the
289 * current path)
290 * @see inheritance, readServiceFile
291 */
292int
293recursReaddirF (maps * m, registry *r, xmlNodePtr n, char *conf_dir, char *prefix,
294                int saved_stdout, int level, void (func) (maps *, xmlNodePtr,
295                                                          service *))
296{
297  struct dirent *dp;
298  int scount = 0;
299
300  if (conf_dir == NULL)
301    return 1;
302  DIR *dirp = opendir (conf_dir);
303  if (dirp == NULL)
304    {
305      if (level > 0)
306        return 1;
307      else
308        return -1;
309    }
310  char tmp1[25];
311  sprintf (tmp1, "sprefix_%d", level);
312  char levels[17];
313  sprintf (levels, "%d", level);
314  setMapInMaps (m, "lenv", "level", levels);
315  while ((dp = readdir (dirp)) != NULL)
316    if ((dp->d_type == DT_DIR || dp->d_type == DT_LNK) && dp->d_name[0] != '.'
317        && strstr (dp->d_name, ".") == NULL)
318      {
319
320        char *tmp =
321          (char *) malloc ((strlen (conf_dir) + strlen (dp->d_name) + 2) *
322                           sizeof (char));
323        sprintf (tmp, "%s/%s", conf_dir, dp->d_name);
324
325        if (prefix != NULL)
326          {
327            prefix = NULL;
328          }
329        prefix = (char *) malloc ((strlen (dp->d_name) + 2) * sizeof (char));
330        sprintf (prefix, "%s.", dp->d_name);
331
332        //map* tmpMap=getMapFromMaps(m,"lenv",tmp1);
333
334        int res;
335        if (prefix != NULL)
336          {
337            setMapInMaps (m, "lenv", tmp1, prefix);
338            char levels1[17];
339            sprintf (levels1, "%d", level + 1);
340            setMapInMaps (m, "lenv", "level", levels1);
341            res =
342              recursReaddirF (m, r, n, tmp, prefix, saved_stdout, level + 1,
343                              func);
344            sprintf (levels1, "%d", level);
345            setMapInMaps (m, "lenv", "level", levels1);
346            free (prefix);
347            prefix = NULL;
348          }
349        else
350          res = -1;
351        free (tmp);
352        if (res < 0)
353          {
354            return res;
355          }
356      }
357    else
358      {
359        char* extn = strstr(dp->d_name, ".zcfg");
360        if(dp->d_name[0] != '.' && extn != NULL && strlen(extn) == 5)
361          {
362            int t;
363            char tmps1[1024];
364            memset (tmps1, 0, 1024);
365            snprintf (tmps1, 1024, "%s/%s", conf_dir, dp->d_name);
366            service *s1 = (service *) malloc (SERVICE_SIZE);
367            if (s1 == NULL)
368              {
369                dup2 (saved_stdout, fileno (stdout));
370                errorException (m, _("Unable to allocate memory."),
371                                "InternalError", NULL);
372                return -1;
373              }
374#ifdef DEBUG
375            fprintf (stderr, "#################\n%s\n#################\n",
376                     tmps1);
377#endif
378            char *tmpsn = zStrdup (dp->d_name);
379            tmpsn[strlen (tmpsn) - 5] = 0;
380            t = readServiceFile (m, tmps1, &s1, tmpsn);
381            free (tmpsn);
382            if (t < 0)
383              {
384                map *tmp00 = getMapFromMaps (m, "lenv", "message");
385                char tmp01[1024];
386                if (tmp00 != NULL)
387                  sprintf (tmp01, _("Unable to parse the ZCFG file: %s (%s)"),
388                           dp->d_name, tmp00->value);
389                else
390                  sprintf (tmp01, _("Unable to parse the ZCFG file: %s."),
391                           dp->d_name);
392                dup2 (saved_stdout, fileno (stdout));
393                errorException (m, tmp01, "InternalError", NULL);
394                return -1;
395              }
396#ifdef DEBUG
397            dumpService (s1);
398            fflush (stdout);
399            fflush (stderr);
400#endif
401            inheritance(r,&s1);
402            func (m, n, s1);
403            freeService (&s1);
404            free (s1);
405            scount++;
406          }
407      }
408  (void) closedir (dirp);
409  return 1;
410}
411
412/**
413 * Signal handling function which simply call exit(0).
414 *
415 * @param sig the signal number
416 */
417void
418donothing (int sig)
419{
420#ifdef DEBUG
421  fprintf (stderr, "Signal %d after the ZOO-Kernel returned result!\n", sig);
422#endif
423  exit (0);
424}
425
426/**
427 * Signal handling function which create an ExceptionReport node containing the
428 * information message corresponding to the signal number.
429 *
430 * @param sig the signal number
431 */
432void
433sig_handler (int sig)
434{
435  char tmp[100];
436  const char *ssig;
437  switch (sig)
438    {
439    case SIGSEGV:
440      ssig = "SIGSEGV";
441      break;
442    case SIGTERM:
443      ssig = "SIGTERM";
444      break;
445    case SIGINT:
446      ssig = "SIGINT";
447      break;
448    case SIGILL:
449      ssig = "SIGILL";
450      break;
451    case SIGFPE:
452      ssig = "SIGFPE";
453      break;
454    case SIGABRT:
455      ssig = "SIGABRT";
456      break;
457    default:
458      ssig = "UNKNOWN";
459      break;
460    }
461  sprintf (tmp,
462           _
463           ("ZOO Kernel failed to process your request, receiving signal %d = %s"),
464           sig, ssig);
465  errorException (NULL, tmp, "InternalError", NULL);
466#ifdef DEBUG
467  fprintf (stderr, "Not this time!\n");
468#endif
469  exit (0);
470}
471
472/**
473 * Load a service provider and run the service function.
474 *
475 * @param myMap the conf maps containing the main.cfg settings
476 * @param s1 the service structure
477 * @param request_inputs map storing all the request parameters
478 * @param inputs the inputs maps
479 * @param ioutputs the outputs maps
480 * @param eres the result returned by the service execution
481 */
482void
483loadServiceAndRun (maps ** myMap, service * s1, map * request_inputs,
484                   maps ** inputs, maps ** ioutputs, int *eres)
485{
486  char tmps1[1024];
487  char ntmp[1024];
488  maps *m = *myMap;
489  maps *request_output_real_format = *ioutputs;
490  maps *request_input_real_format = *inputs;
491  /**
492   * Extract serviceType to know what kind of service should be loaded
493   */
494  map *r_inputs = NULL;
495#ifndef WIN32
496  getcwd (ntmp, 1024);
497#else
498  _getcwd (ntmp, 1024);
499#endif
500  r_inputs = getMap (s1->content, "serviceType");
501#ifdef DEBUG
502  fprintf (stderr, "LOAD A %s SERVICE PROVIDER \n", r_inputs->value);
503  fflush (stderr);
504#endif
505
506  map* libp = getMapFromMaps(m, "main", "libPath");
507 
508  if (strlen (r_inputs->value) == 1
509      && strncasecmp (r_inputs->value, "C", 1) == 0)
510  {
511     if (libp != NULL && libp->value != NULL) {
512            r_inputs = getMap (s1->content, "ServiceProvider");
513                sprintf (tmps1, "%s/%s", libp->value, r_inputs->value);
514         }
515     else {     
516        r_inputs = getMap (request_inputs, "metapath");
517        if (r_inputs != NULL)
518          sprintf (tmps1, "%s/%s", ntmp, r_inputs->value);
519        else
520          sprintf (tmps1, "%s/", ntmp);
521         
522        char *altPath = zStrdup (tmps1);
523        r_inputs = getMap (s1->content, "ServiceProvider");
524        sprintf (tmps1, "%s/%s", altPath, r_inputs->value);
525        free (altPath);
526         }
527#ifdef DEBUG
528      fprintf (stderr, "Trying to load %s\n", tmps1);
529#endif
530#ifdef WIN32
531      HINSTANCE so =
532        LoadLibraryEx (tmps1, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
533#else
534      void *so = dlopen (tmps1, RTLD_LAZY);
535#endif
536#ifdef WIN32
537      char* errstr = getLastErrorMessage();
538#else
539      char *errstr;
540      errstr = dlerror ();
541#endif
542#ifdef DEBUG
543          fprintf (stderr, "%s loaded (%s) \n", tmps1, errstr);
544#endif
545      if (so != NULL)
546        {
547#ifdef DEBUG
548          fprintf (stderr, "Library loaded %s \n", errstr);
549          fprintf (stderr, "Service Shared Object = %s\n", r_inputs->value);
550#endif
551          r_inputs = getMap (s1->content, "serviceType");
552#ifdef DEBUG
553          dumpMap (r_inputs);
554          fprintf (stderr, "%s\n", r_inputs->value);
555          fflush (stderr);
556#endif
557          if (strncasecmp (r_inputs->value, "C-FORTRAN", 9) == 0)
558            {
559              r_inputs = getMap (request_inputs, "Identifier");
560              char fname[1024];
561              sprintf (fname, "%s_", r_inputs->value);
562#ifdef DEBUG
563              fprintf (stderr, "Try to load function %s\n", fname);
564#endif
565#ifdef WIN32
566              typedef int (CALLBACK * execute_t) (char ***, char ***,
567                                                  char ***);
568              execute_t execute = (execute_t) GetProcAddress (so, fname);
569#else
570              typedef int (*execute_t) (char ***, char ***, char ***);
571              execute_t execute = (execute_t) dlsym (so, fname);
572#endif
573#ifdef DEBUG
574#ifdef WIN32
575                          errstr = getLastErrorMessage();
576#else
577              errstr = dlerror ();
578#endif
579              fprintf (stderr, "Function loaded %s\n", errstr);
580#endif
581
582              char main_conf[10][30][1024];
583              char inputs[10][30][1024];
584              char outputs[10][30][1024];
585              for (int i = 0; i < 10; i++)
586                {
587                  for (int j = 0; j < 30; j++)
588                    {
589                      memset (main_conf[i][j], 0, 1024);
590                      memset (inputs[i][j], 0, 1024);
591                      memset (outputs[i][j], 0, 1024);
592                    }
593                }
594              mapsToCharXXX (m, (char ***) main_conf);
595              mapsToCharXXX (request_input_real_format, (char ***) inputs);
596              mapsToCharXXX (request_output_real_format, (char ***) outputs);
597              *eres =
598                execute ((char ***) &main_conf[0], (char ***) &inputs[0],
599                         (char ***) &outputs[0]);
600#ifdef DEBUG
601              fprintf (stderr, "Function run successfully \n");
602#endif
603              charxxxToMaps ((char ***) &outputs[0],
604                             &request_output_real_format);
605            }
606          else
607            {
608#ifdef DEBUG
609#ifdef WIN32
610                          errstr = getLastErrorMessage();
611              fprintf (stderr, "Function %s failed to load because of %s\n",
612                       r_inputs->value, errstr);
613#endif
614#endif
615              r_inputs = getMapFromMaps (m, "lenv", "Identifier");
616#ifdef DEBUG
617              fprintf (stderr, "Try to load function %s\n", r_inputs->value);
618#endif
619              typedef int (*execute_t) (maps **, maps **, maps **);
620#ifdef WIN32
621              execute_t execute =
622                (execute_t) GetProcAddress (so, r_inputs->value);
623#else
624              execute_t execute = (execute_t) dlsym (so, r_inputs->value);
625#endif
626
627              if (execute == NULL)
628                {
629#ifdef WIN32
630                                  errstr = getLastErrorMessage();
631#else
632                  errstr = dlerror ();
633#endif
634                  char *tmpMsg =
635                    (char *) malloc (2048 + strlen (r_inputs->value));
636                  sprintf (tmpMsg,
637                           _
638                           ("Error occured while running the %s function: %s"),
639                           r_inputs->value, errstr);
640                  errorException (m, tmpMsg, "InternalError", NULL);
641                  free (tmpMsg);
642#ifdef DEBUG
643                  fprintf (stderr, "Function %s error %s\n", r_inputs->value,
644                           errstr);
645#endif
646                  *eres = -1;
647                  return;
648                }
649
650#ifdef DEBUG
651#ifdef WIN32
652                          errstr = getLastErrorMessage();
653#else
654              errstr = dlerror ();
655#endif
656              fprintf (stderr, "Function loaded %s\n", errstr);
657#endif
658
659#ifdef DEBUG
660              fprintf (stderr, "Now run the function \n");
661              fflush (stderr);
662#endif
663              *eres =
664                execute (&m, &request_input_real_format,
665                         &request_output_real_format);
666#ifdef DEBUG
667              fprintf (stderr, "Function loaded and returned %d\n", eres);
668              fflush (stderr);
669#endif
670            }
671#ifdef WIN32
672          *ioutputs = dupMaps (&request_output_real_format);
673          FreeLibrary (so);
674#else
675          dlclose (so);
676#endif
677        }
678      else
679        {
680      /**
681       * Unable to load the specified shared library
682       */
683          char tmps[1024];
684#ifdef WIN32
685                  errstr = getLastErrorMessage();
686#else
687              errstr = dlerror ();
688#endif
689          sprintf (tmps, _("Unable to load C Library %s"), errstr);
690          errorException(m,tmps,"InternalError",NULL);
691          *eres = -1;
692        }
693    }
694  else
695
696#ifdef USE_SAGA
697  if (strncasecmp (r_inputs->value, "SAGA", 6) == 0)
698    {
699      *eres =
700        zoo_saga_support (&m, request_inputs, s1,
701                            &request_input_real_format,
702                            &request_output_real_format);
703    }
704  else
705#endif
706
707#ifdef USE_OTB
708  if (strncasecmp (r_inputs->value, "OTB", 6) == 0)
709    {
710      *eres =
711        zoo_otb_support (&m, request_inputs, s1,
712                            &request_input_real_format,
713                            &request_output_real_format);
714    }
715  else
716#endif
717
718#ifdef USE_PYTHON
719  if (strncasecmp (r_inputs->value, "PYTHON", 6) == 0)
720    {
721      *eres =
722        zoo_python_support (&m, request_inputs, s1,
723                            &request_input_real_format,
724                            &request_output_real_format);
725    }
726  else
727#endif
728
729#ifdef USE_JAVA
730  if (strncasecmp (r_inputs->value, "JAVA", 4) == 0)
731    {
732      *eres =
733        zoo_java_support (&m, request_inputs, s1, &request_input_real_format,
734                          &request_output_real_format);
735    }
736  else
737#endif
738
739#ifdef USE_PHP
740  if (strncasecmp (r_inputs->value, "PHP", 3) == 0)
741    {
742      *eres =
743        zoo_php_support (&m, request_inputs, s1, &request_input_real_format,
744                         &request_output_real_format);
745    }
746  else
747#endif
748
749
750#ifdef USE_PERL
751  if (strncasecmp (r_inputs->value, "PERL", 4) == 0)
752    {
753      *eres =
754        zoo_perl_support (&m, request_inputs, s1, &request_input_real_format,
755                          &request_output_real_format);
756    }
757  else
758#endif
759
760#ifdef USE_JS
761  if (strncasecmp (r_inputs->value, "JS", 2) == 0)
762    {
763      *eres =
764        zoo_js_support (&m, request_inputs, s1, &request_input_real_format,
765                        &request_output_real_format);
766    }
767  else
768#endif
769
770#ifdef USE_RUBY
771  if (strncasecmp (r_inputs->value, "Ruby", 4) == 0)
772    {
773      *eres =
774        zoo_ruby_support (&m, request_inputs, s1, &request_input_real_format,
775                          &request_output_real_format);
776    }
777  else
778#endif
779
780    {
781      char tmpv[1024];
782      sprintf (tmpv,
783               _
784               ("Programming Language (%s) set in ZCFG file is not currently supported by ZOO Kernel.\n"),
785               r_inputs->value);
786      errorException (m, tmpv, "InternalError", NULL);
787      *eres = -1;
788    }
789  *myMap = m;
790  *ioutputs = request_output_real_format;
791}
792
793
794#ifdef WIN32
795/**
796 * createProcess function: create a new process after setting some env variables
797 */
798void
799createProcess (maps * m, map * request_inputs, service * s1, char *opts,
800               int cpid, maps * inputs, maps * outputs)
801{
802  STARTUPINFO si;
803  PROCESS_INFORMATION pi;
804  ZeroMemory (&si, sizeof (si));
805  si.cb = sizeof (si);
806  ZeroMemory (&pi, sizeof (pi));
807  char *tmp = (char *) malloc ((1024 + cgiContentLength) * sizeof (char));
808  char *tmpq = (char *) malloc ((1024 + cgiContentLength) * sizeof (char));
809  map *req = getMap (request_inputs, "request");
810  map *id = getMap (request_inputs, "identifier");
811  map *di = getMap (request_inputs, "DataInputs");
812
813  // The required size for the dataInputsKVP and dataOutputsKVP buffers
814  // may exceed cgiContentLength, hence a 2 kb extension. However, a
815  // better solution would be to have getMapsAsKVP() determine the required
816  // buffer size before allocating memory.     
817  char *dataInputsKVP = getMapsAsKVP (inputs, cgiContentLength + 2048, 0);
818  char *dataOutputsKVP = getMapsAsKVP (outputs, cgiContentLength + 2048, 1);
819#ifdef DEBUG
820  fprintf (stderr, "DATAINPUTSKVP %s\n", dataInputsKVP);
821  fprintf (stderr, "DATAOUTPUTSKVP %s\n", dataOutputsKVP);
822#endif
823  map *sid = getMapFromMaps (m, "lenv", "sid");
824  map *r_inputs = getMapFromMaps (m, "main", "tmpPath");
825  map *r_inputs1 = getMap (request_inputs, "metapath");
826 
827  int hasIn = -1;
828  if (r_inputs1 == NULL)
829    {
830      r_inputs1 = createMap ("metapath", "");
831      hasIn = 1;
832    }
833  map *r_inputs2 = getMap (request_inputs, "ResponseDocument");
834  if (r_inputs2 == NULL)
835    r_inputs2 = getMap (request_inputs, "RawDataOutput");
836  map *tmpPath = getMapFromMaps (m, "lenv", "cwd");
837
838  map *tmpReq = getMap (request_inputs, "xrequest");
839 
840  if(r_inputs2 != NULL && tmpReq != NULL) {
841        const char key[] = "rfile=";
842        char* kvp = (char*) malloc((FILENAME_MAX + strlen(key))*sizeof(char));
843        char* filepath = kvp + strlen(key);
844        strncpy(kvp, key, strlen(key));
845        addToCache(m, tmpReq->value, tmpReq->value, "text/xml", strlen(tmpReq->value), 
846                   filepath, FILENAME_MAX);                               
847    if (filepath == NULL) {
848        errorException( m, _("Unable to cache HTTP POST Execute request."), "InternalError", NULL); 
849                return;
850    }   
851        sprintf(tmp,"\"metapath=%s&%s&cgiSid=%s",
852                r_inputs1->value,kvp,sid->value);
853    sprintf(tmpq,"metapath=%s&%s",
854                r_inputs1->value,kvp);
855        free(kvp);             
856  }
857  else if (r_inputs2 != NULL)
858    {
859      sprintf (tmp,
860               "\"metapath=%s&request=%s&service=WPS&version=1.0.0&Identifier=%s&DataInputs=%s&%s=%s&cgiSid=%s",
861               r_inputs1->value, req->value, id->value, dataInputsKVP,
862               r_inputs2->name, dataOutputsKVP, sid->value);
863      sprintf (tmpq,
864               "metapath=%s&request=%s&service=WPS&version=1.0.0&Identifier=%s&DataInputs=%s&%s=%s",
865               r_inputs1->value, req->value, id->value, dataInputsKVP,
866               r_inputs2->name, dataOutputsKVP);                   
867    }
868  else
869    {
870      sprintf (tmp,
871               "\"metapath=%s&request=%s&service=WPS&version=1.0.0&Identifier=%s&DataInputs=%s&cgiSid=%s",
872               r_inputs1->value, req->value, id->value, dataInputsKVP,
873               sid->value);
874      sprintf (tmpq,
875               "metapath=%s&request=%s&service=WPS&version=1.0.0&Identifier=%s&DataInputs=%s",
876               r_inputs1->value, req->value, id->value, dataInputsKVP,
877               sid->value);   
878    }
879
880  if (hasIn > 0)
881    {
882      freeMap (&r_inputs1);
883      free (r_inputs1);
884    }
885  char *tmp1 = zStrdup (tmp);
886  sprintf (tmp, "\"%s\" %s \"%s\"", PROGRAMNAME, tmp1, sid->value); 
887  free (dataInputsKVP);
888  free (dataOutputsKVP);
889#ifdef DEBUG
890  fprintf (stderr, "REQUEST IS : %s \n", tmp);
891#endif
892
893  map* usid = getMapFromMaps (m, "lenv", "usid");
894  if (usid != NULL && usid->value != NULL) {
895    SetEnvironmentVariable("USID", TEXT (usid->value));
896  }
897
898  SetEnvironmentVariable ("CGISID", TEXT (sid->value));
899  SetEnvironmentVariable ("QUERY_STRING", TEXT (tmpq));
900  // knut: Prevent REQUEST_METHOD=POST in background process call to cgic:main (process hangs when reading cgiIn):
901  SetEnvironmentVariable("REQUEST_METHOD", "GET");
902 
903  char clen[1000];
904  sprintf (clen, "%d", strlen (tmpq));
905  SetEnvironmentVariable ("CONTENT_LENGTH", TEXT (clen));
906
907  if (!CreateProcess (NULL,     // No module name (use command line)
908                      TEXT (tmp),       // Command line
909                      NULL,     // Process handle not inheritable
910                      NULL,     // Thread handle not inheritable
911                      FALSE,    // Set handle inheritance to FALSE
912                      CREATE_NO_WINDOW, // Apache won't wait until the end
913                      NULL,     // Use parent's environment block
914                      NULL,     // Use parent's starting directory
915                      &si,      // Pointer to STARTUPINFO struct
916                      &pi)      // Pointer to PROCESS_INFORMATION struct
917    )
918    {
919#ifdef DEBUG
920      fprintf (stderr, "CreateProcess failed (%d).\n", GetLastError ());
921#endif
922      if (tmp != NULL) {
923        free(tmp);
924      }
925      if (tmpq != NULL) {
926        free(tmpq);
927      }         
928      return;
929    }
930  else
931    {
932#ifdef DEBUG
933      fprintf (stderr, "CreateProcess successful (%d).\n\n\n\n",
934               GetLastError ());
935#endif
936    }
937  CloseHandle (pi.hProcess);
938  CloseHandle (pi.hThread);
939 
940  if (tmp != NULL) {
941    free(tmp);
942  }
943  if (tmpq != NULL) {
944    free(tmpq);
945  }
946 
947#ifdef DEBUG
948  fprintf (stderr, "CreateProcess finished !\n");
949#endif
950}
951#endif
952
953/**
954 * Process the request.
955 *
956 * @param inputs the request parameters map
957 * @return 0 on sucess, other value on failure
958 * @see conf_read,recursReaddirF
959 */
960int
961runRequest (map ** inputs)
962{
963
964#ifndef USE_GDB
965#ifndef WIN32
966  signal (SIGCHLD, SIG_IGN);
967#endif 
968  signal (SIGSEGV, sig_handler);
969  signal (SIGTERM, sig_handler);
970  signal (SIGINT, sig_handler);
971  signal (SIGILL, sig_handler);
972  signal (SIGFPE, sig_handler);
973  signal (SIGABRT, sig_handler);
974#endif
975
976  map *r_inputs = NULL;
977  map *request_inputs = *inputs;
978#ifdef IGNORE_METAPATH
979  addToMap(request_inputs, "metapath", "");
980#endif 
981  maps *m = NULL;
982  char *REQUEST = NULL;
983  /**
984   * Parsing service specfic configuration file
985   */
986  m = (maps *) malloc (MAPS_SIZE);
987  if (m == NULL)
988    {
989      return errorException (m, _("Unable to allocate memory."),
990                             "InternalError", NULL);
991    }
992  char ntmp[1024];
993#ifndef WIN32
994  getcwd (ntmp, 1024);
995#else
996  _getcwd (ntmp, 1024);
997#endif
998  r_inputs = getMapOrFill (&request_inputs, "metapath", "");
999
1000  char conf_file[10240];
1001  snprintf (conf_file, 10240, "%s/%s/main.cfg", ntmp, r_inputs->value);
1002  if (conf_read (conf_file, m) == 2)
1003    {
1004      errorException (NULL, _("Unable to load the main.cfg file."),
1005                      "InternalError", NULL);
1006      free (m);
1007      return 1;
1008    }
1009#ifdef DEBUG
1010  fprintf (stderr, "***** BEGIN MAPS\n");
1011  dumpMaps (m);
1012  fprintf (stderr, "***** END MAPS\n");
1013#endif
1014
1015  map *getPath = getMapFromMaps (m, "main", "gettextPath");
1016  if (getPath != NULL)
1017    {
1018      bindtextdomain ("zoo-kernel", getPath->value);
1019      bindtextdomain ("zoo-services", getPath->value);
1020    }
1021  else
1022    {
1023      bindtextdomain ("zoo-kernel", "/usr/share/locale/");
1024      bindtextdomain ("zoo-services", "/usr/share/locale/");
1025    }
1026
1027
1028  /**
1029   * Manage our own error log file (usefull to separate standard apache debug
1030   * messages from the ZOO-Kernel ones but also for IIS users to avoid wrong
1031   * headers messages returned by the CGI due to wrong redirection of stderr)
1032   */
1033  FILE *fstde = NULL;
1034  map *fstdem = getMapFromMaps (m, "main", "logPath");
1035  if (fstdem != NULL)
1036    fstde = freopen (fstdem->value, "a+", stderr);
1037
1038  r_inputs = getMap (request_inputs, "language");
1039  if (r_inputs == NULL)
1040    r_inputs = getMap (request_inputs, "AcceptLanguages");
1041  if (r_inputs == NULL)
1042    r_inputs = getMapFromMaps (m, "main", "language");
1043  if (r_inputs != NULL)
1044    {
1045      if (isValidLang (m, r_inputs->value) < 0)
1046        {
1047          char tmp[1024];
1048          sprintf (tmp,
1049                   _
1050                   ("The value %s is not supported for the <language> parameter"),
1051                   r_inputs->value);
1052          errorException (m, tmp, "InvalidParameterValue", "language");
1053          freeMaps (&m);
1054          free (m);
1055          free (REQUEST);
1056          return 1;
1057
1058        }
1059      char *tmp = zStrdup (r_inputs->value);
1060      setMapInMaps (m, "main", "language", tmp);
1061#ifdef DEB
1062      char tmp2[12];
1063      sprintf (tmp2, "%s.utf-8", tmp);
1064      translateChar (tmp2, '-', '_');
1065      setlocale (LC_ALL, tmp2);
1066#else
1067      translateChar (tmp, '-', '_');
1068      setlocale (LC_ALL, tmp);
1069#endif
1070#ifndef WIN32
1071      setenv ("LC_ALL", tmp, 1);
1072#else
1073      char tmp1[12];
1074      sprintf (tmp1, "LC_ALL=%s", tmp);
1075      putenv (tmp1);
1076#endif
1077      free (tmp);
1078    }
1079  else
1080    {
1081      setlocale (LC_ALL, "en_US");
1082#ifndef WIN32
1083      setenv ("LC_ALL", "en_US", 1);
1084#else
1085      char tmp1[12];
1086      sprintf (tmp1, "LC_ALL=en_US");
1087      putenv (tmp1);
1088#endif
1089      setMapInMaps (m, "main", "language", "en-US");
1090    }
1091  setlocale (LC_NUMERIC, "en_US");
1092  bind_textdomain_codeset ("zoo-kernel", "UTF-8");
1093  textdomain ("zoo-kernel");
1094  bind_textdomain_codeset ("zoo-services", "UTF-8");
1095  textdomain ("zoo-services");
1096
1097  map *lsoap = getMap (request_inputs, "soap");
1098  if (lsoap != NULL && strcasecmp (lsoap->value, "true") == 0)
1099    setMapInMaps (m, "main", "isSoap", "true");
1100  else
1101    setMapInMaps (m, "main", "isSoap", "false");
1102
1103  if(strlen(cgiServerName)>0)
1104    {
1105      char tmpUrl[1024];
1106       
1107      if ( getenv("HTTPS") != NULL && strncmp(getenv("HTTPS"), "on", 2) == 0 ) { // Knut: check if non-empty instead of "on"?           
1108        if ( strncmp(cgiServerPort, "443", 3) == 0 ) { 
1109          sprintf(tmpUrl, "https://%s%s", cgiServerName, cgiScriptName);
1110        }
1111        else {
1112          sprintf(tmpUrl, "https://%s:%s%s", cgiServerName, cgiServerPort, cgiScriptName);
1113        }
1114      }
1115      else {
1116        if ( strncmp(cgiServerPort, "80", 2) == 0 ) { 
1117          sprintf(tmpUrl, "http://%s%s", cgiServerName, cgiScriptName);
1118        }
1119        else {
1120          sprintf(tmpUrl, "http://%s:%s%s", cgiServerName, cgiServerPort, cgiScriptName);
1121        }
1122      }
1123#ifdef DEBUG
1124      fprintf(stderr,"*** %s ***\n",tmpUrl);
1125#endif
1126      setMapInMaps(m,"main","serverAddress",tmpUrl);
1127    }
1128
1129  //Check for minimum inputs
1130  map* version=getMap(request_inputs,"version");
1131  if(version==NULL)
1132    version=getMapFromMaps(m,"main","version");
1133  setMapInMaps(m,"main","rversion",version->value);
1134  int vid=getVersionId(version->value);
1135  if(vid<0)
1136    vid=0;
1137  map* err=NULL;
1138  const char **vvr=(const char**)requests[vid];
1139  checkValidValue(request_inputs,&err,"request",vvr,1);
1140  const char *vvs[]={
1141    "WPS",
1142    NULL
1143  };
1144  if(err!=NULL){
1145    checkValidValue(request_inputs,&err,"service",(const char**)vvs,1);
1146    printExceptionReportResponse (m, err);
1147    freeMap(&err);
1148    free(err);
1149    if (count (request_inputs) == 1)
1150      {
1151        freeMap (&request_inputs);
1152        free (request_inputs);
1153      }
1154    freeMaps (&m);
1155    free (m);
1156    return 1;
1157  }
1158  checkValidValue(request_inputs,&err,"service",(const char**)vvs,1);
1159
1160  const char *vvv[]={
1161    "1.0.0",
1162    "2.0.0",
1163    NULL
1164  };
1165  r_inputs = getMap (request_inputs, "Request");
1166  REQUEST = zStrdup (r_inputs->value);
1167  int reqId=-1;
1168  if (strncasecmp (REQUEST, "GetCapabilities", 15) != 0){
1169    checkValidValue(request_inputs,&err,"version",(const char**)vvv,1);
1170    int j=0;
1171    for(j=0;j<nbSupportedRequests;j++){
1172      if(requests[vid][j]!=NULL && requests[vid][j+1]!=NULL){
1173        if(j<nbReqIdentifier && strncasecmp(REQUEST,requests[vid][j+1],strlen(REQUEST))==0){
1174          checkValidValue(request_inputs,&err,"identifier",NULL,1);
1175          reqId=j+1;
1176          break;
1177        }
1178        else
1179          if(j>=nbReqIdentifier && j<nbReqIdentifier+nbReqJob && 
1180             strncasecmp(REQUEST,requests[vid][j+1],strlen(REQUEST))==0){
1181            checkValidValue(request_inputs,&err,"jobid",NULL,1);
1182            reqId=j+1;
1183            break;
1184          }
1185      }else
1186        break;
1187    }
1188  }else{
1189    checkValidValue(request_inputs,&err,"AcceptVersions",(const char**)vvv,-1);
1190    map* version1=getMap(request_inputs,"AcceptVersions");
1191    if(version1!=NULL){
1192      if(strstr(version1->value,schemas[1][0])!=NULL)
1193        addToMap(request_inputs,"version",schemas[1][0]);
1194      else
1195        addToMap(request_inputs,"version",version1->value);
1196      version=getMap(request_inputs,"version");
1197      setMapInMaps(m,"main","rversion",version->value);
1198      vid=getVersionId(version->value);
1199    }
1200  }
1201  if(err!=NULL){
1202    printExceptionReportResponse (m, err);
1203    freeMap(&err);
1204    free(err);
1205    if (count (request_inputs) == 1)
1206      {
1207        freeMap (&request_inputs);
1208        free (request_inputs);
1209      }
1210    free(REQUEST);
1211    freeMaps (&m);
1212    free (m);
1213    return 1;
1214  }
1215
1216  r_inputs = getMap (request_inputs, "serviceprovider");
1217  if (r_inputs == NULL)
1218    {
1219      addToMap (request_inputs, "serviceprovider", "");
1220    }
1221
1222  maps *request_output_real_format = NULL;
1223  map *tmpm = getMapFromMaps (m, "main", "serverAddress");
1224  if (tmpm != NULL)
1225    SERVICE_URL = zStrdup (tmpm->value);
1226  else
1227    SERVICE_URL = zStrdup (DEFAULT_SERVICE_URL);
1228
1229
1230
1231  service *s1;
1232  int scount = 0;
1233#ifdef DEBUG
1234  dumpMap (r_inputs);
1235#endif
1236  char conf_dir[1024];
1237  int t;
1238  char tmps1[1024];
1239
1240  r_inputs = NULL;
1241  r_inputs = getMap (request_inputs, "metapath");
1242 
1243  if (r_inputs != NULL)
1244    snprintf (conf_dir, 1024, "%s/%s", ntmp, r_inputs->value);
1245  else
1246    snprintf (conf_dir, 1024, "%s", ntmp);
1247
1248  map* reg = getMapFromMaps (m, "main", "registry");
1249  registry* zooRegistry=NULL;
1250  if(reg!=NULL){
1251    int saved_stdout = dup (fileno (stdout));
1252    dup2 (fileno (stderr), fileno (stdout));
1253    createRegistry (m,&zooRegistry,reg->value,saved_stdout);
1254    dup2 (saved_stdout, fileno (stdout));
1255  }
1256
1257  if (strncasecmp (REQUEST, "GetCapabilities", 15) == 0)
1258    {
1259#ifdef DEBUG
1260      dumpMap (r_inputs);
1261#endif
1262      xmlDocPtr doc = xmlNewDoc (BAD_CAST "1.0");
1263      xmlNodePtr n=printGetCapabilitiesHeader(doc,m,(version!=NULL?version->value:"1.0.0"));
1264      /**
1265       * Here we need to close stdout to ensure that unsupported chars
1266       * has been found in the zcfg and then printed on stdout
1267       */
1268      int saved_stdout = dup (fileno (stdout));
1269      dup2 (fileno (stderr), fileno (stdout));
1270      if (int res =               
1271          recursReaddirF (m, zooRegistry, n, conf_dir, NULL, saved_stdout, 0,
1272                          printGetCapabilitiesForProcess) < 0)
1273        {
1274          freeMaps (&m);
1275          free (m);
1276          if(zooRegistry!=NULL){
1277            freeRegistry(&zooRegistry);
1278            free(zooRegistry);
1279          }
1280          free (REQUEST);
1281          free (SERVICE_URL);
1282          fflush (stdout);
1283          return res;
1284        }
1285      fflush (stdout);
1286      dup2 (saved_stdout, fileno (stdout));
1287      printDocument (m, doc, getpid ());
1288      freeMaps (&m);
1289      free (m);
1290      if(zooRegistry!=NULL){
1291        freeRegistry(&zooRegistry);
1292        free(zooRegistry);
1293      }
1294      free (REQUEST);
1295      free (SERVICE_URL);
1296      fflush (stdout);
1297      return 0;
1298    }
1299  else
1300    {
1301      r_inputs = getMap (request_inputs, "JobId");
1302      if(reqId>nbReqIdentifier){
1303        if (strncasecmp (REQUEST, "GetStatus", strlen(REQUEST)) == 0 ||
1304            strncasecmp (REQUEST, "GetResult", strlen(REQUEST)) == 0){
1305          runGetStatus(m,r_inputs->value,REQUEST);
1306          freeMaps (&m);
1307          free (m);
1308          if(zooRegistry!=NULL){
1309            freeRegistry(&zooRegistry);
1310            free(zooRegistry);
1311          }
1312          free (REQUEST);
1313          free (SERVICE_URL);
1314          return 0;
1315        }
1316        else
1317          if (strncasecmp (REQUEST, "Dismiss", strlen(REQUEST)) == 0){
1318            runDismiss(m,r_inputs->value);
1319            freeMaps (&m);
1320            free (m);
1321            if(zooRegistry!=NULL){
1322              freeRegistry(&zooRegistry);
1323              free(zooRegistry);
1324            }
1325            free (REQUEST);
1326            free (SERVICE_URL);
1327            return 0;
1328           
1329          }
1330        return 0;
1331      }
1332      if(reqId<=nbReqIdentifier){
1333        r_inputs = getMap (request_inputs, "Identifier");
1334
1335        struct dirent *dp;
1336        DIR *dirp = opendir (conf_dir);
1337        if (dirp == NULL)
1338          {
1339            errorException (m, _("The specified path path does not exist."),
1340                            "InvalidParameterValue", conf_dir);
1341            freeMaps (&m);
1342            free (m);
1343            if(zooRegistry!=NULL){
1344              freeRegistry(&zooRegistry);
1345              free(zooRegistry);
1346            }
1347            free (REQUEST);
1348            free (SERVICE_URL);
1349            return 0;
1350          }
1351        if (strncasecmp (REQUEST, "DescribeProcess", 15) == 0)
1352          {
1353            /**
1354             * Loop over Identifier list
1355             */
1356            xmlDocPtr doc = xmlNewDoc (BAD_CAST "1.0");
1357            r_inputs = NULL;
1358            r_inputs = getMap (request_inputs, "version");
1359            xmlNodePtr n = printWPSHeader(doc,m,"DescribeProcess",
1360                                          root_nodes[vid][1],(version!=NULL?version->value:"1.0.0"),1);
1361
1362            r_inputs = getMap (request_inputs, "Identifier");
1363
1364            char *orig = zStrdup (r_inputs->value);
1365
1366            int saved_stdout = dup (fileno (stdout));
1367            dup2 (fileno (stderr), fileno (stdout));
1368            if (strcasecmp ("all", orig) == 0)
1369              {
1370                if (int res =
1371                    recursReaddirF (m, zooRegistry, n, conf_dir, NULL, saved_stdout, 0,
1372                                    printDescribeProcessForProcess) < 0)
1373                  return res;
1374              }
1375            else
1376              {
1377                char *saveptr;
1378                char *tmps = strtok_r (orig, ",", &saveptr);
1379
1380                char buff[256];
1381                char buff1[1024];
1382                while (tmps != NULL)
1383                  {
1384                    int hasVal = -1;
1385                    char *corig = zStrdup (tmps);
1386                    if (strstr (corig, ".") != NULL)
1387                      {
1388
1389                        parseIdentifier (m, conf_dir, corig, buff1);
1390                        map *tmpMap = getMapFromMaps (m, "lenv", "metapath");
1391                        if (tmpMap != NULL)
1392                          addToMap (request_inputs, "metapath", tmpMap->value);
1393                        map *tmpMapI = getMapFromMaps (m, "lenv", "Identifier");
1394
1395                        s1 = (service *) malloc (SERVICE_SIZE);
1396                        t = readServiceFile (m, buff1, &s1, tmpMapI->value);
1397                        if (t < 0)
1398                          {
1399                            map *tmp00 = getMapFromMaps (m, "lenv", "message");
1400                            char tmp01[1024];
1401                            if (tmp00 != NULL)
1402                              sprintf (tmp01,
1403                                       _
1404                                       ("Unable to parse the ZCFG file for the following ZOO-Service: %s. Message: %s"),
1405                                       tmps, tmp00->value);
1406                            else
1407                              sprintf (tmp01,
1408                                       _
1409                                       ("Unable to parse the ZCFG file for the following ZOO-Service: %s."),
1410                                       tmps);
1411                            dup2 (saved_stdout, fileno (stdout));
1412                            errorException (m, tmp01, "InvalidParameterValue",
1413                                            "identifier");
1414                            freeMaps (&m);
1415                            free (m);
1416                            if(zooRegistry!=NULL){
1417                              freeRegistry(&zooRegistry);
1418                              free(zooRegistry);
1419                            }
1420                            free (REQUEST);
1421                            free (corig);
1422                            free (orig);
1423                            free (SERVICE_URL);
1424                            free (s1);
1425                            closedir (dirp);
1426                            xmlFreeDoc (doc);
1427                            xmlCleanupParser ();
1428                            zooXmlCleanupNs ();
1429                            return 1;
1430                          }
1431#ifdef DEBUG
1432                        dumpService (s1);
1433#endif
1434                        inheritance(zooRegistry,&s1);
1435                        printDescribeProcessForProcess (m, n, s1);
1436                        freeService (&s1);
1437                        free (s1);
1438                        s1 = NULL;
1439                        scount++;
1440                        hasVal = 1;
1441                        setMapInMaps (m, "lenv", "level", "0");
1442                      }
1443                    else
1444                      {
1445                        memset (buff, 0, 256);
1446                        snprintf (buff, 256, "%s.zcfg", corig);
1447                        memset (buff1, 0, 1024);
1448#ifdef DEBUG
1449                        printf ("\n#######%s\n########\n", buff);
1450#endif
1451                        while ((dp = readdir (dirp)) != NULL)
1452                          {
1453                            if (strcasecmp (dp->d_name, buff) == 0)
1454                              {
1455                                memset (buff1, 0, 1024);
1456                                snprintf (buff1, 1024, "%s/%s", conf_dir,
1457                                          dp->d_name);
1458                                s1 = (service *) malloc (SERVICE_SIZE);
1459                                if (s1 == NULL)
1460                                  {
1461                                    dup2 (saved_stdout, fileno (stdout));
1462                                    return errorException (m,
1463                                                           _
1464                                                           ("Unable to allocate memory."),
1465                                                           "InternalError",
1466                                                           NULL);
1467                                  }
1468#ifdef DEBUG
1469                                printf
1470                                  ("#################\n(%s) %s\n#################\n",
1471                                   r_inputs->value, buff1);
1472#endif
1473                                char *tmp0 = zStrdup (dp->d_name);
1474                                tmp0[strlen (tmp0) - 5] = 0;
1475                                t = readServiceFile (m, buff1, &s1, tmp0);
1476                                free (tmp0);
1477                                if (t < 0)
1478                                  {
1479                                    map *tmp00 =
1480                                      getMapFromMaps (m, "lenv", "message");
1481                                    char tmp01[1024];
1482                                    if (tmp00 != NULL)
1483                                      sprintf (tmp01,
1484                                               _
1485                                               ("Unable to parse the ZCFG file: %s (%s)"),
1486                                               dp->d_name, tmp00->value);
1487                                    else
1488                                      sprintf (tmp01,
1489                                               _
1490                                               ("Unable to parse the ZCFG file: %s."),
1491                                               dp->d_name);
1492                                    dup2 (saved_stdout, fileno (stdout));
1493                                    errorException (m, tmp01, "InternalError",
1494                                                    NULL);
1495                                    freeMaps (&m);
1496                                    free (m);
1497                                    if(zooRegistry!=NULL){
1498                                      freeRegistry(&zooRegistry);
1499                                      free(zooRegistry);
1500                                    }
1501                                    free (orig);
1502                                    free (REQUEST);
1503                                    closedir (dirp);
1504                                    xmlFreeDoc (doc);
1505                                    xmlCleanupParser ();
1506                                    zooXmlCleanupNs ();
1507                                    return 1;
1508                                  }
1509#ifdef DEBUG
1510                                dumpService (s1);
1511#endif
1512                                inheritance(zooRegistry,&s1);
1513                                printDescribeProcessForProcess (m, n, s1);
1514                                freeService (&s1);
1515                                free (s1);
1516                                s1 = NULL;
1517                                scount++;
1518                                hasVal = 1;
1519                              }
1520                          }
1521                      }
1522                    if (hasVal < 0)
1523                      {
1524                        map *tmp00 = getMapFromMaps (m, "lenv", "message");
1525                        char tmp01[1024];
1526                        if (tmp00 != NULL)
1527                          sprintf (tmp01,
1528                                   _("Unable to parse the ZCFG file: %s (%s)"),
1529                                   buff, tmp00->value);
1530                        else
1531                          sprintf (tmp01,
1532                                   _("Unable to parse the ZCFG file: %s."),
1533                                   buff);
1534                        dup2 (saved_stdout, fileno (stdout));
1535                        errorException (m, tmp01, "InvalidParameterValue",
1536                                        "Identifier");
1537                        freeMaps (&m);
1538                        free (m);
1539                        if(zooRegistry!=NULL){
1540                          freeRegistry(&zooRegistry);
1541                          free(zooRegistry);
1542                        }
1543                        free (orig);
1544                        free (REQUEST);
1545                        closedir (dirp);
1546                        xmlFreeDoc (doc);
1547                        xmlCleanupParser ();
1548                        zooXmlCleanupNs ();
1549                        return 1;
1550                      }
1551                    rewinddir (dirp);
1552                    tmps = strtok_r (NULL, ",", &saveptr);
1553                    if (corig != NULL)
1554                      free (corig);
1555                  }
1556              }
1557            closedir (dirp);
1558            fflush (stdout);
1559            dup2 (saved_stdout, fileno (stdout));
1560            free (orig);
1561            printDocument (m, doc, getpid ());
1562            freeMaps (&m);
1563            free (m);
1564            if(zooRegistry!=NULL){
1565              freeRegistry(&zooRegistry);
1566              free(zooRegistry);
1567            }
1568            free (REQUEST);
1569            free (SERVICE_URL);
1570            fflush (stdout);
1571            return 0;
1572          }
1573        else if (strncasecmp (REQUEST, "Execute", strlen (REQUEST)) != 0)
1574          {
1575            map* version=getMapFromMaps(m,"main","rversion");
1576            int vid=getVersionId(version->value);
1577            int len,j=0;
1578            for(j=0;j<nbSupportedRequests;j++){
1579              if(requests[vid][j]!=NULL)
1580                len+=strlen(requests[vid][j])+2;
1581              else{
1582                len+=4;
1583                break;
1584              }
1585            }
1586            char *tmpStr=(char*)malloc(len*sizeof(char));
1587            int it=0;
1588            for(j=0;j<nbSupportedRequests;j++){
1589              if(requests[vid][j]!=NULL){
1590                if(it==0){
1591                  sprintf(tmpStr,"%s",requests[vid][j]);
1592                  it++;
1593                }else{
1594                  char *tmpS=zStrdup(tmpStr);
1595                  if(j+1<nbSupportedRequests && requests[vid][j+1]==NULL){
1596                    sprintf(tmpStr,"%s and %s",tmpS,requests[vid][j]);
1597                  }else{
1598                    sprintf(tmpStr,"%s, %s",tmpS,requests[vid][j]);
1599                 
1600                  }
1601                  free(tmpS);
1602                }
1603              }
1604              else{
1605                len+=4;
1606                break;
1607              }
1608            }
1609            char* message=(char*)malloc((61+len)*sizeof(char));
1610            sprintf(message,"The <request> value was not recognized. Allowed values are %s.",tmpStr);
1611            errorException (m,_(message),"InvalidParameterValue", "request");
1612#ifdef DEBUG
1613            fprintf (stderr, "No request found %s", REQUEST);
1614#endif
1615            closedir (dirp);
1616            freeMaps (&m);
1617            free (m);
1618            if(zooRegistry!=NULL){
1619              freeRegistry(&zooRegistry);
1620              free(zooRegistry);
1621            }
1622            free (REQUEST);
1623            free (SERVICE_URL);
1624            fflush (stdout);
1625            return 0;
1626          }
1627        closedir (dirp);
1628      }
1629    }
1630
1631  map *postRequest = NULL;
1632  postRequest = getMap (request_inputs, "xrequest");
1633
1634  if(vid==1 && postRequest==NULL){
1635    errorException (m,_("Unable to run Execute request using the GET HTTP method"),"InvalidParameterValue", "request"); 
1636    freeMaps (&m);
1637    free (m);
1638    if(zooRegistry!=NULL){
1639      freeRegistry(&zooRegistry);
1640      free(zooRegistry);
1641    }
1642    free (REQUEST);
1643    free (SERVICE_URL);
1644    fflush (stdout);
1645    return 0;
1646  }
1647 
1648  s1 = NULL;
1649  s1 = (service *) malloc (SERVICE_SIZE);
1650  if (s1 == NULL)
1651    {
1652      freeMaps (&m);
1653      free (m);
1654      if(zooRegistry!=NULL){
1655        freeRegistry(&zooRegistry);
1656        free(zooRegistry);
1657      }
1658      free (REQUEST);
1659      free (SERVICE_URL);
1660      return errorException (m, _("Unable to allocate memory."),
1661                             "InternalError", NULL);
1662    }
1663
1664  r_inputs = getMap (request_inputs, "MetaPath");
1665  if (r_inputs != NULL)
1666    snprintf (tmps1, 1024, "%s/%s", ntmp, r_inputs->value);
1667  else
1668    snprintf (tmps1, 1024, "%s/", ntmp);
1669  r_inputs = getMap (request_inputs, "Identifier");
1670  char *ttmp = zStrdup (tmps1);
1671  snprintf (tmps1, 1024, "%s/%s.zcfg", ttmp, r_inputs->value);
1672  free (ttmp);
1673#ifdef DEBUG
1674  fprintf (stderr, "Trying to load %s\n", tmps1);
1675#endif
1676  if (strstr (r_inputs->value, ".") != NULL)
1677    {
1678      char *identifier = zStrdup (r_inputs->value);
1679      parseIdentifier (m, conf_dir, identifier, tmps1);
1680      map *tmpMap = getMapFromMaps (m, "lenv", "metapath");
1681      if (tmpMap != NULL)
1682        addToMap (request_inputs, "metapath", tmpMap->value);
1683      free (identifier);
1684    }
1685  else
1686    {
1687      setMapInMaps (m, "lenv", "Identifier", r_inputs->value);
1688      setMapInMaps (m, "lenv", "oIdentifier", r_inputs->value);
1689    }
1690
1691  r_inputs = getMapFromMaps (m, "lenv", "Identifier");
1692  int saved_stdout = dup (fileno (stdout));
1693  dup2 (fileno (stderr), fileno (stdout));
1694  t = readServiceFile (m, tmps1, &s1, r_inputs->value);
1695  inheritance(zooRegistry,&s1);
1696  if(zooRegistry!=NULL){
1697    freeRegistry(&zooRegistry);
1698    free(zooRegistry);
1699  }
1700  fflush (stdout);
1701  dup2 (saved_stdout, fileno (stdout));
1702  if (t < 0)
1703    {
1704      char *tmpMsg = (char *) malloc (2048 + strlen (r_inputs->value));
1705      sprintf (tmpMsg,
1706               _
1707               ("The value for <identifier> seems to be wrong (%s). Please specify one of the processes in the list returned by a GetCapabilities request."),
1708               r_inputs->value);
1709      errorException (m, tmpMsg, "InvalidParameterValue", "identifier");
1710      free (tmpMsg);
1711      free (s1);
1712      freeMaps (&m);
1713      free (m);
1714      free (REQUEST);
1715      free (SERVICE_URL);
1716      return 0;
1717    }
1718  close (saved_stdout);
1719
1720#ifdef DEBUG
1721  dumpService (s1);
1722#endif
1723  int j;
1724
1725
1726  /**
1727   * Create the input and output maps data structure
1728   */
1729  int i = 0;
1730  HINTERNET hInternet;
1731  HINTERNET res;
1732  hInternet = InternetOpen (
1733#ifndef WIN32
1734                            (LPCTSTR)
1735#endif
1736                            "ZooWPSClient\0",
1737                            INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
1738
1739#ifndef WIN32
1740  if (!CHECK_INET_HANDLE (hInternet))
1741    fprintf (stderr, "WARNING : hInternet handle failed to initialize");
1742#endif
1743  maps *request_input_real_format = NULL;
1744  maps *tmpmaps = request_input_real_format;
1745
1746
1747  if(parseRequest(&m,&request_inputs,s1,&request_input_real_format,&request_output_real_format,&hInternet)<0){
1748    freeMaps (&m);
1749    free (m);
1750    free (REQUEST);
1751    free (SERVICE_URL);
1752    InternetCloseHandle (&hInternet);
1753    freeService (&s1);
1754    free (s1);
1755    return 0;
1756  }
1757
1758
1759  // Define each env variable in runing environment
1760  maps *curs = getMaps (m, "env");
1761  if (curs != NULL)
1762    {
1763      map *mapcs = curs->content;
1764      while (mapcs != NULLMAP)
1765        {
1766#ifndef WIN32
1767          setenv (mapcs->name, mapcs->value, 1);
1768#else
1769#ifdef DEBUG
1770          fprintf (stderr, "[ZOO: setenv (%s=%s)]\n", mapcs->name,
1771                   mapcs->value);
1772#endif
1773          if (mapcs->value[strlen (mapcs->value) - 2] == '\r')
1774            {
1775#ifdef DEBUG
1776              fprintf (stderr, "[ZOO: Env var finish with \r]\n");
1777#endif
1778              mapcs->value[strlen (mapcs->value) - 1] = 0;
1779            }
1780#ifdef DEBUG
1781          if (SetEnvironmentVariable (mapcs->name, mapcs->value) == 0)
1782            {
1783              fflush (stderr);
1784              fprintf (stderr, "setting variable... %s\n", "OK");
1785            }
1786          else
1787            {
1788              fflush (stderr);
1789              fprintf (stderr, "setting variable... %s\n", "OK");
1790            }
1791#else
1792
1793
1794          SetEnvironmentVariable (mapcs->name, mapcs->value);
1795#endif
1796          char *toto =
1797            (char *)
1798            malloc ((strlen (mapcs->name) + strlen (mapcs->value) +
1799                     2) * sizeof (char));
1800          sprintf (toto, "%s=%s", mapcs->name, mapcs->value);
1801          putenv (toto);
1802#ifdef DEBUG
1803          fflush (stderr);
1804#endif
1805#endif
1806#ifdef DEBUG
1807          fprintf (stderr, "[ZOO: setenv (%s=%s)]\n", mapcs->name,
1808                   mapcs->value);
1809          fflush (stderr);
1810#endif
1811          mapcs = mapcs->next;
1812        }
1813    }
1814
1815#ifdef DEBUG
1816  dumpMap (request_inputs);
1817#endif
1818
1819  map *status = getMap (request_inputs, "status");
1820  if(vid==0){
1821    // Need to check if we need to fork to load a status enabled
1822    r_inputs = NULL;
1823    map *store = getMap (request_inputs, "storeExecuteResponse");
1824    /**
1825     * 05-007r7 WPS 1.0.0 page 57 :
1826     * 'If status="true" and storeExecuteResponse is "false" then the service
1827     * shall raise an exception.'
1828     */
1829    if (status != NULL && strcmp (status->value, "true") == 0 &&
1830        store != NULL && strcmp (store->value, "false") == 0)
1831      {
1832        errorException (m,
1833                        _
1834                        ("The status parameter cannot be set to true if storeExecuteResponse is set to false. Please modify your request parameters."),
1835                        "InvalidParameterValue", "storeExecuteResponse");
1836        freeService (&s1);
1837        free (s1);
1838        freeMaps (&m);
1839        free (m);
1840       
1841        freeMaps (&request_input_real_format);
1842        free (request_input_real_format);
1843       
1844        freeMaps (&request_output_real_format);
1845        free (request_output_real_format);
1846
1847        free (REQUEST);
1848        free (SERVICE_URL);
1849        return 1;
1850      }
1851    r_inputs = getMap (request_inputs, "storeExecuteResponse");
1852  }else{
1853    // Define status depending on the WPS 2.0.0 mode attribute
1854    status = getMap (request_inputs, "mode");
1855    map* mode=getMap(s1->content,"mode");
1856    if(strcasecmp(status->value,"async")==0){
1857      if(mode!=NULL && strcasecmp(mode->value,"async")==0)
1858        addToMap(request_inputs,"status","true");
1859      else{
1860        if(mode!=NULL){
1861          // see ref. http://docs.opengeospatial.org/is/14-065/14-065.html#61
1862          errorException (m,_("The process does not permit the desired execution mode."),"NoSuchMode", mode->value); 
1863          fflush (stdout);
1864          freeMaps (&m);
1865          free (m);
1866          if(zooRegistry!=NULL){
1867            freeRegistry(&zooRegistry);
1868            free(zooRegistry);
1869          }
1870          freeMaps (&request_input_real_format);
1871          free (request_input_real_format);
1872          freeMaps (&request_output_real_format);
1873          free (request_output_real_format);
1874          free (REQUEST);
1875          free (SERVICE_URL);
1876          return 0;
1877        }else
1878          addToMap(request_inputs,"status","true");
1879      }
1880    }
1881    else{
1882      if(strcasecmp(status->value,"auto")==0){
1883        if(mode!=NULL){
1884          if(strcasecmp(mode->value,"async")==0)
1885            addToMap(request_inputs,"status","false");
1886          else
1887            addToMap(request_inputs,"status","true");
1888        }
1889        else
1890          addToMap(request_inputs,"status","false");
1891      }else
1892        addToMap(request_inputs,"status","false");
1893    }
1894    status = getMap (request_inputs, "status");
1895  }
1896
1897  int eres = SERVICE_STARTED;
1898  int cpid = getpid ();
1899
1900  /**
1901   * Initialize the specific [lenv] section which contains runtime variables:
1902   *
1903   *  - usid : it is an unique identification number
1904   *  - sid : it is the process idenfitication number (OS)
1905   *  - uusid : it is an universally unique identification number
1906   *  - status : value between 0 and 100 to express the  completude of
1907   * the operations of the running service
1908   *  - message : is a string where you can store error messages, in case
1909   * service is failing, or o provide details on the ongoing operation.
1910   *  - cwd : is the current working directory
1911   *  - soap : is a boolean value, true if the request was contained in a SOAP
1912   * Envelop
1913   *  - sessid : string storing the session identifier (only when cookie is
1914   * used)
1915   *  - cgiSid : only defined on Window platforms (for being able to identify
1916   * the created process)
1917   *
1918   */
1919  maps *_tmpMaps = (maps *) malloc (MAPS_SIZE);
1920  _tmpMaps->name = zStrdup ("lenv");
1921  char tmpBuff[100];
1922  struct ztimeval tp;
1923  if (zGettimeofday (&tp, NULL) == 0)
1924    sprintf (tmpBuff, "%i", (cpid + ((int) tp.tv_sec + (int) tp.tv_usec)));
1925  else
1926    sprintf (tmpBuff, "%i", (cpid + (int) time (NULL)));
1927  _tmpMaps->content = createMap ("osid", tmpBuff);
1928  _tmpMaps->next = NULL;
1929  sprintf (tmpBuff, "%i", cpid);
1930  addToMap (_tmpMaps->content, "sid", tmpBuff);
1931  char* tmpUuid=get_uuid();
1932  addToMap (_tmpMaps->content, "uusid", tmpUuid);
1933  addToMap (_tmpMaps->content, "usid", tmpUuid);
1934  free(tmpUuid);
1935  addToMap (_tmpMaps->content, "status", "0");
1936  addToMap (_tmpMaps->content, "cwd", ntmp);
1937  addToMap (_tmpMaps->content, "message", _("No message provided"));
1938  map *ltmp = getMap (request_inputs, "soap");
1939  if (ltmp != NULL)
1940    addToMap (_tmpMaps->content, "soap", ltmp->value);
1941  else
1942    addToMap (_tmpMaps->content, "soap", "false");
1943
1944  // Parse the session file and add it to the main maps
1945  if (cgiCookie != NULL && strlen (cgiCookie) > 0)
1946    {
1947      int hasValidCookie = -1;
1948      char *tcook = zStrdup (cgiCookie);
1949      char *tmp = NULL;
1950      map *testing = getMapFromMaps (m, "main", "cookiePrefix");
1951      if (testing == NULL)
1952        {
1953          tmp = zStrdup ("ID=");
1954        }
1955      else
1956        {
1957          tmp =
1958            (char *) malloc ((strlen (testing->value) + 2) * sizeof (char));
1959          sprintf (tmp, "%s=", testing->value);
1960        }
1961      if (strstr (cgiCookie, ";") != NULL)
1962        {
1963          char *token, *saveptr;
1964          token = strtok_r (cgiCookie, ";", &saveptr);
1965          while (token != NULL)
1966            {
1967              if (strcasestr (token, tmp) != NULL)
1968                {
1969                  if (tcook != NULL)
1970                    free (tcook);
1971                  tcook = zStrdup (token);
1972                  hasValidCookie = 1;
1973                }
1974              token = strtok_r (NULL, ";", &saveptr);
1975            }
1976        }
1977      else
1978        {
1979          if (strstr (cgiCookie, "=") != NULL
1980              && strcasestr (cgiCookie, tmp) != NULL)
1981            {
1982              tcook = zStrdup (cgiCookie);
1983              hasValidCookie = 1;
1984            }
1985          if (tmp != NULL)
1986            {
1987              free (tmp);
1988            }
1989        }
1990      if (hasValidCookie > 0)
1991        {
1992          addToMap (_tmpMaps->content, "sessid", strstr (tcook, "=") + 1);
1993          char session_file_path[1024];
1994          map *tmpPath = getMapFromMaps (m, "main", "sessPath");
1995          if (tmpPath == NULL)
1996            tmpPath = getMapFromMaps (m, "main", "tmpPath");
1997          char *tmp1 = strtok (tcook, ";");
1998          if (tmp1 != NULL)
1999            sprintf (session_file_path, "%s/sess_%s.cfg", tmpPath->value,
2000                     strstr (tmp1, "=") + 1);
2001          else
2002            sprintf (session_file_path, "%s/sess_%s.cfg", tmpPath->value,
2003                     strstr (cgiCookie, "=") + 1);
2004          free (tcook);
2005          maps *tmpSess = (maps *) malloc (MAPS_SIZE);
2006          struct stat file_status;
2007          int istat = stat (session_file_path, &file_status);
2008          if (istat == 0 && file_status.st_size > 0)
2009            {
2010              conf_read (session_file_path, tmpSess);
2011              addMapsToMaps (&m, tmpSess);
2012              freeMaps (&tmpSess);
2013              free (tmpSess);
2014            }
2015        }
2016    }
2017  addMapsToMaps (&m, _tmpMaps);
2018  freeMaps (&_tmpMaps);
2019  free (_tmpMaps);
2020  maps* bmap=NULL;
2021#ifdef DEBUG
2022  dumpMap (request_inputs);
2023#endif
2024#ifdef WIN32
2025  char *cgiSidL = NULL;
2026  if (getenv ("CGISID") != NULL)
2027    addToMap (request_inputs, "cgiSid", getenv ("CGISID"));
2028
2029  char* usidp;
2030  if ( (usidp = getenv("USID")) != NULL ) {
2031    setMapInMaps (m, "lenv", "usid", usidp);
2032  }
2033
2034  map *test1 = getMap (request_inputs, "cgiSid");
2035  if (test1 != NULL)
2036    {
2037      cgiSid = test1->value;
2038      addToMap (request_inputs, "storeExecuteResponse", "true");
2039      addToMap (request_inputs, "status", "true");
2040      setMapInMaps (m, "lenv", "sid", test1->value);
2041      status = getMap (request_inputs, "status");
2042    }
2043#endif
2044  char *fbkp, *fbkpid, *fbkpres, *fbkp1, *flog;
2045  FILE *f0, *f1;
2046  if (status != NULL)
2047    if (strcasecmp (status->value, "false") == 0)
2048      status = NULLMAP;
2049  if (status == NULLMAP)
2050    {
2051      if(validateRequest(&m,s1,request_inputs, &request_input_real_format,&request_output_real_format,&hInternet)<0){
2052        freeService (&s1);
2053        free (s1);
2054        freeMaps (&m);
2055        free (m);
2056        free (REQUEST);
2057        free (SERVICE_URL);
2058        freeMaps (&request_input_real_format);
2059        free (request_input_real_format);
2060        freeMaps (&request_output_real_format);
2061        free (request_output_real_format);
2062        freeMaps (&tmpmaps);
2063        free (tmpmaps);
2064        return -1;
2065      }
2066
2067      loadServiceAndRun (&m, s1, request_inputs, &request_input_real_format,
2068                         &request_output_real_format, &eres);
2069    }
2070  else
2071    {
2072      int pid;
2073#ifdef DEBUG
2074      fprintf (stderr, "\nPID : %d\n", cpid);
2075#endif
2076
2077#ifndef WIN32
2078      pid = fork ();
2079#else
2080      if (cgiSid == NULL)
2081        {
2082          createProcess (m, request_inputs, s1, NULL, cpid,
2083                         request_input_real_format,
2084                         request_output_real_format);
2085          pid = cpid;
2086        }
2087      else
2088        {
2089          pid = 0;
2090          cpid = atoi (cgiSid);
2091        }
2092#endif
2093      if (pid > 0)
2094        {
2095          /**
2096           * dady :
2097           * set status to SERVICE_ACCEPTED
2098           */
2099#ifdef DEBUG
2100          fprintf (stderr, "father pid continue (origin %d) %d ...\n", cpid,
2101                   getpid ());
2102#endif
2103          eres = SERVICE_ACCEPTED;
2104        }
2105      else if (pid == 0)
2106        {
2107          /**
2108           * son : have to close the stdout, stdin and stderr to let the parent
2109           * process answer to http client.
2110           */
2111          map* usid = getMapFromMaps (m, "lenv", "uusid");
2112          map* tmpm = getMapFromMaps (m, "lenv", "osid");
2113          int cpid = atoi (tmpm->value);
2114          r_inputs = getMapFromMaps (m, "main", "tmpPath");
2115          map* r_inputs1 = createMap("ServiceName", s1->name);
2116
2117          // Create the filename for the result file (.res)
2118          fbkpres =
2119            (char *)
2120            malloc ((strlen (r_inputs->value) +
2121                     strlen (usid->value) + 7) * sizeof (char));
2122          sprintf (fbkpres, "%s/%s.res", r_inputs->value, usid->value);
2123          bmap = (maps *) malloc (MAPS_SIZE);
2124          bmap->name=zStrdup("status");
2125          bmap->content=createMap("usid",usid->value);
2126          bmap->next=NULL;
2127          addToMap(bmap->content,"sid",tmpm->value);
2128          addIntToMap(bmap->content,"pid",getpid());
2129         
2130          // Create PID file referencing the OS process identifier
2131          fbkpid =
2132            (char *)
2133            malloc ((strlen (r_inputs->value) +
2134                     strlen (usid->value) + 7) * sizeof (char));
2135          sprintf (fbkpid, "%s/%s.pid", r_inputs->value, usid->value);
2136
2137          f0 = freopen (fbkpid, "w+", stdout);
2138          fprintf(stdout,"%d",getpid());
2139          fflush(stdout);
2140
2141          // Create SID file referencing the semaphore name
2142          fbkp =
2143            (char *)
2144            malloc ((strlen (r_inputs->value) + strlen (r_inputs1->value) +
2145                     strlen (usid->value) + 7) * sizeof (char));
2146          sprintf (fbkp, "%s/%s.sid", r_inputs->value, usid->value);
2147
2148          FILE* f2 = fopen (fbkp, "w+");
2149          fprintf(f2,"%s",tmpm->value);
2150          fflush(f2);
2151          fclose(f2);
2152          free(fbkp);
2153
2154          fbkp =
2155            (char *)
2156            malloc ((strlen (r_inputs->value) + strlen (r_inputs1->value) +
2157                     strlen (usid->value) + 7) * sizeof (char));
2158          sprintf (fbkp, "%s/%s_%s.xml", r_inputs->value, r_inputs1->value,
2159                   usid->value);
2160          flog =
2161            (char *)
2162            malloc ((strlen (r_inputs->value) + strlen (r_inputs1->value) +
2163                     strlen (usid->value) + 13) * sizeof (char));
2164          sprintf (flog, "%s/%s_%s_error.log", r_inputs->value,
2165                   r_inputs1->value, usid->value);
2166#ifdef DEBUG
2167          fprintf (stderr, "RUN IN BACKGROUND MODE \n");
2168          fprintf (stderr, "son pid continue (origin %d) %d ...\n", cpid,
2169                   getpid ());
2170          fprintf (stderr, "\nFILE TO STORE DATA %s\n", r_inputs->value);
2171#endif
2172          freopen (flog, "w+", stderr);
2173          fflush (stderr);
2174          f0 = freopen (fbkp, "w+", stdout);
2175          rewind (stdout);
2176#ifndef WIN32
2177          fclose (stdin);
2178#endif
2179
2180#ifdef RELY_ON_DB
2181          init_sql(m);
2182          recordServiceStatus(m);
2183#endif
2184          if(vid==0){
2185            /**
2186             * set status to SERVICE_STARTED and flush stdout to ensure full
2187             * content was outputed (the file used to store the ResponseDocument).
2188             * The rewind stdout to restart writing from the bgining of the file,
2189             * this way the data will be updated at the end of the process run.
2190             */
2191            printProcessResponse (m, request_inputs, cpid, s1, r_inputs1->value,
2192                                  SERVICE_STARTED, request_input_real_format,
2193                                  request_output_real_format);
2194            fflush (stdout);
2195#ifdef RELY_ON_DB
2196            recordResponse(m,fbkp);
2197#endif
2198          }
2199
2200          fflush (stderr);
2201
2202          fbkp1 =
2203            (char *)
2204            malloc ((strlen (r_inputs->value) + strlen (r_inputs1->value) +
2205                     strlen (usid->value) + 13) * sizeof (char));
2206          sprintf (fbkp1, "%s/%s_final_%s.xml", r_inputs->value,
2207                   r_inputs1->value, usid->value);
2208
2209          f1 = freopen (fbkp1, "w+", stdout);
2210
2211          if(validateRequest(&m,s1,request_inputs, &request_input_real_format,&request_output_real_format,&hInternet)<0){
2212            freeService (&s1);
2213            free (s1);
2214            freeMaps (&m);
2215            free (m);
2216            free (REQUEST);
2217            free (SERVICE_URL);
2218            freeMaps (&request_input_real_format);
2219            free (request_input_real_format);
2220            freeMaps (&request_output_real_format);
2221            free (request_output_real_format);
2222            freeMaps (&tmpmaps);
2223            free (tmpmaps);
2224            fflush (stdout);
2225            fflush (stderr);
2226            unhandleStatus (m);
2227            return -1;
2228          }
2229          loadServiceAndRun (&m, s1, request_inputs,
2230                             &request_input_real_format,
2231                             &request_output_real_format, &eres);
2232
2233        }
2234      else
2235        {
2236          /**
2237           * error server don't accept the process need to output a valid
2238           * error response here !!!
2239           */
2240          eres = -1;
2241          errorException (m, _("Unable to run the child process properly"),
2242                          "InternalError", NULL);
2243        }
2244    }
2245
2246#ifdef DEBUG
2247  dumpMaps (request_output_real_format);
2248#endif
2249  if (eres != -1)
2250    outputResponse (s1, request_input_real_format,
2251                    request_output_real_format, request_inputs,
2252                    cpid, m, eres);
2253  fflush (stdout);
2254 
2255  /**
2256   * Ensure that if error occurs when freeing memory, no signal will return
2257   * an ExceptionReport document as the result was already returned to the
2258   * client.
2259   */
2260#ifndef USE_GDB
2261  signal (SIGSEGV, donothing);
2262  signal (SIGTERM, donothing);
2263  signal (SIGINT, donothing);
2264  signal (SIGILL, donothing);
2265  signal (SIGFPE, donothing);
2266  signal (SIGABRT, donothing);
2267#endif
2268  if (((int) getpid ()) != cpid || cgiSid != NULL)
2269    {
2270      fclose (stdout);
2271      //fclose (stderr);
2272      /**
2273       * Dump back the final file fbkp1 to fbkp
2274       */
2275      fclose (f0);
2276      fclose (f1);
2277
2278      FILE *f2 = fopen (fbkp1, "rb");
2279#ifndef RELY_ON_DB
2280      semid lid = getShmLockId (m, 1);
2281      if (lid < 0)
2282        return -1;
2283      lockShm (lid);
2284#endif
2285      fclose(f0);
2286      FILE *f3 = fopen (fbkp, "wb+");
2287      free (fbkp);
2288      fseek (f2, 0, SEEK_END);
2289      long flen = ftell (f2);
2290      fseek (f2, 0, SEEK_SET);
2291      char *tmps1 = (char *) malloc ((flen + 1) * sizeof (char));
2292      fread (tmps1, flen, 1, f2);
2293      fwrite (tmps1, 1, flen, f3);
2294      fclose (f2);
2295      fclose (f3);
2296      unlink (fbkpid);
2297      switch(eres){
2298      default:
2299      case SERVICE_FAILED:
2300        setMapInMaps(bmap,"status","status",wpsStatus[1]);
2301        setMapInMaps(m,"lenv","fstate",wpsStatus[1]);
2302        break;
2303      case SERVICE_SUCCEEDED:
2304        setMapInMaps(bmap,"status","status",wpsStatus[0]);
2305        setMapInMaps(m,"lenv","fstate",wpsStatus[0]);
2306        break;
2307      }
2308#ifndef RELY_ON_DB
2309      dumpMapsToFile(bmap,fbkpres);
2310      removeShmLock (m, 1);
2311#else
2312      recordResponse(m,fbkp1);
2313#endif
2314      freeMaps(&bmap);
2315      free(bmap);
2316      unlink (fbkp1);
2317      unlink (flog);
2318      unhandleStatus (m);
2319      free(fbkpid);
2320      free(fbkpres);
2321      free (flog);
2322      free (fbkp1);
2323      free (tmps1);
2324    }
2325
2326  freeService (&s1);
2327  free (s1);
2328  freeMaps (&m);
2329  free (m);
2330
2331  freeMaps (&request_input_real_format);
2332  free (request_input_real_format);
2333
2334  freeMaps (&request_output_real_format);
2335  free (request_output_real_format);
2336
2337  free (REQUEST);
2338  free (SERVICE_URL);
2339#ifdef DEBUG
2340  fprintf (stderr, "Processed response \n");
2341  fflush (stdout);
2342  fflush (stderr);
2343#endif
2344
2345  if (((int) getpid ()) != cpid || cgiSid != NULL)
2346    {
2347      exit (0);
2348    }
2349
2350  return 0;
2351}
Note: See TracBrowser for help on using the repository browser.

Search

ZOO Sponsors

http://www.zoo-project.org/trac/chrome/site/img/geolabs-logo.pnghttp://www.zoo-project.org/trac/chrome/site/img/neogeo-logo.png http://www.zoo-project.org/trac/chrome/site/img/apptech-logo.png http://www.zoo-project.org/trac/chrome/site/img/3liz-logo.png http://www.zoo-project.org/trac/chrome/site/img/gateway-logo.png

Become a sponsor !

Knowledge partners

http://www.zoo-project.org/trac/chrome/site/img/ocu-logo.png http://www.zoo-project.org/trac/chrome/site/img/gucas-logo.png http://www.zoo-project.org/trac/chrome/site/img/polimi-logo.png http://www.zoo-project.org/trac/chrome/site/img/fem-logo.png http://www.zoo-project.org/trac/chrome/site/img/supsi-logo.png http://www.zoo-project.org/trac/chrome/site/img/cumtb-logo.png

Become a knowledge partner

Related links

http://zoo-project.org/img/ogclogo.png http://zoo-project.org/img/osgeologo.png