source: branches/PublicaMundi_David-devel/zoo-project/zoo-kernel/zoo_loader.c @ 553

Last change on this file since 553 was 553, checked in by david, 9 years ago
  • change user privileges
  • add new parameters in main.cfg
  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc
File size: 23.4 KB
Line 
1/**
2 * Author : Gérald FENOY
3 *
4 *  Copyright 2008-2011 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
25#define MALLOC_CHECK_ 0
26#define MALLOC_CHECK 0
27
28/**
29 * Specific includes
30 */
31#ifndef WIN32
32/*
33#include "fcgio.h"
34#include "fcgi_config.h"
35#include "fcgi_stdio.h"
36*/
37#include <unistd.h>
38#include <fcgiapp.h>
39#endif
40#include <sys/wait.h>
41#include <pthread.h>
42#include <sys/types.h>
43#include <unistd.h>
44#include "service_internal.h"
45#ifdef WIN32
46#include "windows.h"
47#define strtok_r strtok_s
48#endif
49
50extern "C"
51{
52#include "cgic.h"
53#include <libxml/tree.h>
54#include <libxml/xmlmemory.h>
55#include <libxml/parser.h>
56#include <libxml/xpath.h>
57#include <libxml/xpathInternals.h>
58
59#include <string.h>
60#include <stdio.h>
61#include <stdlib.h>
62#include <glib.h>
63#include <sys/stat.h>
64#include <ctype.h>
65
66}
67
68#include "service_zcfg.h"
69//#include "service_internal.h"
70
71xmlXPathObjectPtr extractFromDoc (xmlDocPtr, const char *);
72int runRequest (map **,struct cgi_env **,FCGX_Request *);
73
74using namespace std;
75
76#ifndef TRUE
77#define TRUE 1
78#endif
79#ifndef FALSE
80#define FALSE -1
81#endif
82
83
84static void PrintEnv(FCGX_Stream *out, char *label, char **envp)
85{
86    FCGX_FPrintF(out, "%s:<br>\n<pre>\n", label);
87    for( ; *envp != NULL; envp++) {
88        FCGX_FPrintF(out, "%s\n", *envp);
89    }
90    FCGX_FPrintF(out, "</pre><p>\n");
91}
92
93#define PATH_SOCKET "/tmp/zoo.sock"
94#define THREAD_COUNT 50
95static int counts[THREAD_COUNT];
96
97
98int process(FCGX_Request *request){
99
100      int pid = getpid();
101      struct cgi_env *cgi;
102      //PrintEnv(request.err, "Request environment", request.envp);
103      cgi = (struct cgi_env*)malloc(sizeof(struct cgi_env));
104      cgiMain_init (NULL, NULL,&cgi,request);
105      char *strQuery = NULL;
106      if (cgi->cgiQueryString != NULL)
107        strQuery = zStrdup (cgi->cgiQueryString);
108      map *tmpMap = NULL;
109
110      if (strncmp (cgi->cgiContentType, "text/xml", 8) == 0 ||
111          strncasecmp (cgi->cgiRequestMethod, "post", 4) == 0)
112        {
113          if (cgi->cgiContentLength == 0)
114            {
115              char *post_data = NULL;
116              int i = 0;
117              int ch = FCGX_GetChar(request->in);
118              while (ch != -1){
119                {
120                  i++;
121                  if (post_data == NULL)
122                    {
123                    post_data=(char*)malloc(sizeof(char));
124                    post_data[i-1] = (char) ch;
125                    }
126                  else
127                    {
128                    post_data=(char*)realloc(post_data,i*sizeof(char));
129                    post_data[i-1] = (char) ch;
130                    }
131                  ch = FCGX_GetChar(request->in);
132                  if (ch == -1 ){
133                    post_data=(char*)realloc(post_data,(i + 1)*sizeof(char));
134                    post_data[i] = '\0';
135                    }
136                }
137                cgi->cgiContentLength = i;
138              if (post_data == NULL && (strQuery == NULL || strlen (strQuery) == 0))
139                {
140                  return errorException (NULL,
141                                         "ZOO-Kernel failed to process your request cause the request was emtpty.",
142                                         "InternalError", NULL,request->out);
143                }
144              else
145                {
146                  if (strQuery == NULL || strlen (strQuery) == 0)
147                    tmpMap = createMap ("request", post_data);
148                }
149              if (post_data != NULL)
150                free (post_data);
151                }
152            }
153          else
154            {
155              char *post_data = new char[cgi->cgiContentLength + 1];
156              int r = FCGX_GetStr(post_data,cgi->cgiContentLength,request->in);
157              if ( r > 0)
158                {
159                  post_data[r] = '\0';
160                  cgi->cgiContentLength = r;
161                  tmpMap = createMap ("request", post_data);
162                }
163              else
164                {
165                  post_data[0] = '\0';
166                  char **array, **arrayStep;
167                  if (cgiFormEntries (&array,&cgi) != cgiFormSuccess)
168                    {
169                      return 1;
170                    }
171                  arrayStep = array;
172                  while (*arrayStep)
173                    {
174                      char *ivalue = new char[cgi->cgiContentLength];
175                      cgiFormStringNoNewlines (*arrayStep, ivalue,
176                                               cgi->cgiContentLength,&cgi);
177                      char *tmpValueFinal =
178                        (char *)
179                        malloc ((strlen (*arrayStep) + strlen (ivalue) +
180                                 1) * sizeof (char));
181                      sprintf (tmpValueFinal, "%s=%s", *arrayStep, ivalue);
182                      if (strlen (post_data) == 0)
183                        {
184                          sprintf (post_data, "%s", tmpValueFinal);
185                        }
186                      else
187                        {
188                          char *tmp = zStrdup (post_data);
189                          sprintf (post_data, "%s&%s", tmp, tmpValueFinal);
190                          free (tmp);
191                        }
192                      free (tmpValueFinal);
193#ifdef DEBUG
194                      fprintf (stderr, "(( \n %s \n %s \n ))", *arrayStep,
195                               ivalue);
196#endif
197                      delete[]ivalue;
198                      arrayStep++;
199                    }
200                  if (tmpMap != NULL)
201                    addToMap (tmpMap, "request", post_data);
202                  else
203                    tmpMap = createMap ("request", post_data);
204                }
205              delete[]post_data;
206            }
207        }
208      else
209        {
210#ifdef DEBUG
211          dumpMap (tmpMap);
212#endif
213       
214       char **array, **arrayStep;
215          if (cgiFormEntries (&array,&cgi) != cgiFormSuccess)
216            {
217              return 1;
218            }
219          arrayStep = array;
220          while (*arrayStep)
221            {
222              char *value = new char[cgi->cgiContentLength];
223              cgiFormStringNoNewlines (*arrayStep, value, cgi->cgiContentLength,&cgi);
224#ifdef DEBUG
225              fprintf (stderr, "(( \n %s \n %s \n ))", *arrayStep, value);
226#endif
227              if (tmpMap != NULL)
228                addToMap (tmpMap, *arrayStep, value);
229              else
230                tmpMap = createMap (*arrayStep, value);
231              arrayStep++;
232              delete[]value;
233            }
234          cgiStringArrayFree (array);
235        }
236
237#ifdef WIN32
238      map *tmpReq = getMap (tmpMap, "rfile");
239      if (tmpReq != NULL)
240        {
241          FILE *lf = fopen (tmpReq->value, "r");
242          fseek (lf, 0, SEEK_END);
243          long flen = ftell (lf);
244          fseek (lf, 0, SEEK_SET);
245          char *buffer = (char *) malloc ((flen + 1) * sizeof (char));
246          fread (buffer, flen, 1, lf);
247          fclose (lf);
248          addToMap (tmpMap, "request", buffer);
249          free (buffer);
250          cgiContentLength = flen + 9;
251        }
252#endif
253  /**
254   * In case that the POST method was used, then check if params came in XML
255   * format else try to use the attribute "request" which should be the only
256   * one.
257   */
258      if (strncasecmp (cgi->cgiRequestMethod, "post", 4) == 0 ||
259          (count (tmpMap) == 1 && strncmp (tmpMap->value, "<", 1) == 0)
260#ifdef WIN32
261          || tmpReq != NULL
262#endif
263        )
264        {
265    /**
266     * Store the original XML request in xrequest map
267     */
268          map *t1 = getMap (tmpMap, "request");
269          if (t1 != NULL && strncasecmp (t1->value, "<", 1) == 0)
270            {
271              addToMap (tmpMap, "xrequest", t1->value);
272              xmlInitParser ();
273              xmlDocPtr doc = xmlParseMemory (t1->value, cgi->cgiContentLength);
274              {
275                xmlXPathObjectPtr reqptr = extractFromDoc (doc,
276                                                           "/*[local-name()='Envelope']/*[local-name()='Body']/*");
277                if (reqptr != NULL)
278                  {
279                    xmlNodeSet *req = reqptr->nodesetval;
280                    if (req != NULL && req->nodeNr == 1)
281                      {
282                        addToMap (tmpMap, "soap", "true");
283                        for (int k = 0; k < req->nodeNr; k++)
284                          {
285                            //xmlNsPtr ns=xmlNewNs(req->nodeTab[k],BAD_CAST "http://www.w3.org/2001/XMLSchema-instance",BAD_CAST "xsi");
286                            xmlDocSetRootElement (doc, req->nodeTab[k]);
287                            xmlChar *xmlbuff;
288                            int buffersize;
289                            xmlDocDumpFormatMemoryEnc (doc, &xmlbuff,
290                                                       &buffersize, "utf-8",
291                                                       1);
292                            addToMap (tmpMap, "xrequest", (char *) xmlbuff);
293                            xmlFree (xmlbuff);
294                          }
295                      }
296                    xmlXPathFreeObject (reqptr);
297                  }
298              }
299
300              xmlNodePtr cur = xmlDocGetRootElement (doc);
301              char *tval;
302              tval = NULL;
303              tval = (char *) xmlGetProp (cur, BAD_CAST "service");
304              if (tval != NULL)
305                {
306                  addToMap (tmpMap, "service", tval);
307                  xmlFree (tval);
308                }
309              tval = NULL;
310              tval = (char *) xmlGetProp (cur, BAD_CAST "language");
311              if (tval != NULL)
312                {
313                  addToMap (tmpMap, "language", tval);
314                  xmlFree (tval);
315                }
316              const char *requests[3] =
317                { "GetCapabilities", "DescribeProcess", "Execute" };
318              for (int j = 0; j < 3; j++)
319                {
320                  char tt[128];
321                  sprintf (tt, "/*[local-name()='%s']", requests[j]);
322                  xmlXPathObjectPtr reqptr = extractFromDoc (doc, tt);
323                  if (reqptr != NULL)
324                    {
325                      xmlNodeSet *req = reqptr->nodesetval;
326#ifdef DEBUG
327                      fprintf (stderr, "%i", req->nodeNr);
328#endif
329                      if (req != NULL && req->nodeNr == 1)
330                        {
331                          if (t1->value != NULL)
332                            free (t1->value);
333                          t1->value = zStrdup (requests[j]);
334                          j = 2;
335                        }
336                      xmlXPathFreeObject (reqptr);
337                    }
338                }
339              if (strncasecmp (t1->value, "GetCapabilities", 15) == 0)
340                {
341                  xmlXPathObjectPtr versptr =
342                    extractFromDoc (doc, "/*/*/*[local-name()='Version']");
343                  xmlNodeSet *vers = versptr->nodesetval;
344                  xmlChar *content = xmlNodeListGetString (doc,
345                                                           vers->
346                                                           nodeTab
347                                                           [0]->xmlChildrenNode,
348                                                           1);
349                  addToMap (tmpMap, "version", (char *) content);
350                  xmlXPathFreeObject (versptr);
351                  xmlFree (content);
352                }
353              else
354                {
355                  tval = NULL;
356                  tval = (char *) xmlGetProp (cur, BAD_CAST "version");
357                  if (tval != NULL)
358                    {
359                      addToMap (tmpMap, "version", tval);
360                      xmlFree (tval);
361                    }
362                  tval = (char *) xmlGetProp (cur, BAD_CAST "language");
363                  if (tval != NULL)
364                    {
365                      addToMap (tmpMap, "language", tval);
366                      xmlFree (tval);
367                    }
368                  xmlXPathObjectPtr idptr =
369                    extractFromDoc (doc, "/*/*[local-name()='Identifier']");
370                  if (idptr != NULL)
371                    {
372                      xmlNodeSet *id = idptr->nodesetval;
373                      if (id != NULL)
374                        {
375                          char *identifiers = NULL;
376                          identifiers =
377                            (char *) calloc (cgi->cgiContentLength, sizeof (char));
378                          identifiers[0] = 0;
379                          for (int k = 0; k < id->nodeNr; k++)
380                            {
381                              xmlChar *content = xmlNodeListGetString (doc,
382                                                                       id->nodeTab
383                                                                       [k]->
384                                                                       xmlChildrenNode,
385                                                                       1);
386                              if (strlen (identifiers) > 0)
387                                {
388                                  char *tmp = zStrdup (identifiers);
389                                  snprintf (identifiers,
390                                            strlen (tmp) +
391                                            xmlStrlen (content) + 2, "%s,%s",
392                                            tmp, content);
393                                  free (tmp);
394                                }
395                              else
396                                {
397                                  snprintf (identifiers,
398                                            xmlStrlen (content) + 1, "%s",
399                                            content);
400                                }
401                              xmlFree (content);
402                            }
403                          xmlXPathFreeObject (idptr);
404                          addToMap (tmpMap, "Identifier", identifiers);
405                          free (identifiers);
406                        }
407                    }
408                }
409              xmlFreeDoc (doc);
410              xmlCleanupParser ();
411            }
412          else
413            {
414              freeMap (&tmpMap);
415              free (tmpMap);
416              tmpMap = createMap ("not_valid", "true");
417            }
418
419          char *token, *saveptr;
420          token = strtok_r (cgi->cgiQueryString, "&", &saveptr);
421          while (token != NULL)
422            {
423              char *token1, *saveptr1;
424              char *name = NULL;
425              char *value = NULL;
426              token1 = strtok_r (token, "=", &saveptr1);
427              while (token1 != NULL)
428                {
429                  if (name == NULL)
430                    name = zStrdup (token1);
431                  else
432                    value = zStrdup (token1);
433                  token1 = strtok_r (NULL, "=", &saveptr1);
434                }
435              addToMap (tmpMap, name, value);
436              free (name);
437              free (value);
438              name = NULL;
439              value = NULL;
440              token = strtok_r (NULL, "&", &saveptr);
441            }
442
443        }
444
445      if (strncasecmp (cgi->cgiContentType, "multipart/form-data", 19) == 0)
446        {
447          map *tmp = getMap (tmpMap, "dataInputs");
448          if (tmp != NULL)
449            {
450              addToMap (tmpMap, "dataInputs",
451                        strstr (strQuery, "dataInputs=") + 11);
452            }
453        }
454
455      if (strQuery != NULL)
456        free (strQuery);
457
458      runRequest (&tmpMap,&cgi,request);
459
460  /**
461   * Required but can't be made after executing a process using POST requests.
462   */
463      if ( /*strncasecmp(cgiRequestMethod,"post",4)!=0 && count(tmpMap)!=1 && */ tmpMap != NULL)
464        {
465          freeMap (&tmpMap);
466          free (tmpMap);
467        }
468        // a verifier fait planter
469      cgiFreeResources (&cgi);
470
471      FCGX_Finish_r(request);
472      return 0;
473}
474
475
476
477int
478main (int argc, char *argv[])
479{
480
481
482 int debug_flag = 0;
483 int background_flag = 0;
484 char *file_value = NULL;
485 int index;
486 int c;
487
488 opterr = 0;
489 while ((c = getopt (argc, argv, "dbhf:")) != -1)
490      switch (c)
491      {
492      case 'd':
493        debug_flag = 1;
494        break;
495      case 'b':
496        background_flag = 1;
497        break;
498      case 'h':
499        fprintf(stderr,"TODO: need to print help\n");
500        fflush(stderr);
501        return 0;
502      case 'f':
503        file_value = optarg;
504        break;
505      case '?':
506        if (optopt == 'f')
507          fprintf (stderr, "Option -%c requires an argument.\n", optopt);
508        else if (isprint (optopt))
509          fprintf (stderr, "Unknown option `-%c'.\n", optopt);
510        else
511          fprintf (stderr,"Unknown option character `\\x%x'.\n",optopt);
512        return 1;
513      default:
514        abort ();
515      }
516
517
518  maps *conf;
519  conf = (maps *) malloc (MAPS_SIZE);
520 
521  int ret = conf_read (file_value, conf);
522  if ( ret == 2){
523    //a verifier mais conf_read ne renvoie jamais 0
524    fprintf(stderr,"Erreur lors de la lecture de %s\n",file_value);
525    return 1;
526  }
527
528  char *rootDir;
529  map *m_rootDir = getMapFromMaps (conf, "server", "rootDir");
530  if (m_rootDir == NULL){
531    fprintf(stderr,"Configuration error: rootDir");
532    return 2;
533  }
534  else {
535   rootDir = (char*)malloc((strlen(m_rootDir->value) +1)*sizeof(char*));
536   strncpy(rootDir,m_rootDir->value,strlen(m_rootDir->value));
537   rootDir[strlen(m_rootDir->value)] = '\0';
538   //freeMap(&m_rootDir);
539  }
540
541  int req_worker;
542  map *m_req_worker = getMapFromMaps (conf, "server", "req_worker");
543  if (m_req_worker == NULL){
544    fprintf(stderr,"Configuration error: req_worker not found");
545    return 2;
546  }
547  else {
548    req_worker=atoi(m_req_worker->value);
549    //freeMap(&m_req_worker);
550    if (req_worker == 0){
551        fprintf(stderr,"Configuration error: req_worker");
552        return 2;
553    }
554  }
555 
556  int async_worker;
557  map *m_async_worker = getMapFromMaps (conf, "server", "async_worker"); 
558  if (m_async_worker == NULL){
559    fprintf(stderr,"Configuration error: async_worker not found");
560    return 2;
561  }
562  else {
563    async_worker = atoi(m_async_worker->value);
564    //freeMap(&m_async_worker);
565    if (async_worker == 0){
566        fprintf(stderr,"Configuration error: req_worker");
567        return 2;
568    }
569  }
570
571  int max_requests;
572  map *m_max_requests = getMapFromMaps (conf, "server", "max_requests");
573  if (m_max_requests == NULL){
574    fprintf(stderr,"Configuration error: max_requests");
575    return 2;
576  }
577  else {
578    max_requests = atoi(m_max_requests->value);
579    //freeMap(&m_max_requests);
580    if (max_requests == 0){
581        fprintf(stderr,"Configuration error: max_requests");
582        return 2;
583    }
584  }
585
586  map *m_listen = getMapFromMaps (conf, "server", "listen");
587  char *listen;
588  if (m_listen == NULL){
589    fprintf(stderr,"Configuration error: listen not found");
590    return 2;
591  }
592  else {
593    listen = (char *)malloc((strlen(m_listen->value) +1)*sizeof(char*));
594    strncpy(listen,m_listen->value,strlen(m_listen->value));
595    listen[strlen(m_listen->value)] = '\0';
596    //freeMap(&m_listen);
597  }
598  int listen_owner;
599  map *m_listen_owner = getMapFromMaps (conf, "server", "listen_owner");
600  if (m_listen_owner == NULL){
601    fprintf(stderr,"Configuration error: listen_owner");
602    return 2;
603  }
604  else {
605    listen_owner = atoi(m_listen_owner->value);
606    //freeMap(&m_listen_owner);
607    if (listen_owner == 0){
608        fprintf(stderr,"Configuration error: listen_owner");
609        return 2;
610    }
611  }
612
613  int listen_group;
614  map *m_listen_group = getMapFromMaps (conf, "server", "listen_group");
615  if (m_listen_group == NULL){
616    fprintf(stderr,"Configuration error: listen_group");
617    return 2;
618  }
619  else {
620    listen_group = atoi(m_listen_group->value);
621    //freeMap(&m_listen_group);
622    if (listen_group == 0){
623        fprintf(stderr,"Configuration error: listen_group");
624        return 2;
625    }
626  }
627
628  char * listen_mode;
629  map *m_listen_mode = getMapFromMaps (conf, "server", "listen_mode");
630  if (m_listen_mode == NULL){
631    fprintf(stderr,"Configuration error: listen_mode");
632    return 2;
633  }
634  else {
635    listen_mode = (char *)malloc((strlen(m_listen_mode->value) +1)*sizeof(char*));
636    strncpy(listen_mode,m_listen_mode->value,strlen(m_listen_mode->value));
637    listen_mode[strlen(m_listen_mode->value)] = '\0';
638    //freeMap(&m_listen_mode);
639  }
640
641  int listen_queue;
642  map *m_listen_queue = getMapFromMaps (conf, "server", "listen_queue");
643  if (m_listen_queue == NULL){
644    fprintf(stderr,"Configuration error: listen_queue");
645    return 2;
646  }
647  else {
648    listen_queue = atoi(m_listen_queue->value);
649    //freeMap(&m_listen_queue);
650    if (listen_queue == 0){
651        fprintf(stderr,"Configuration error: listen_queue");
652        return 2;
653    }
654  }
655
656  int id_user;
657  map *m_user = getMapFromMaps (conf, "server", "uid");
658  if (m_user == NULL){
659    fprintf(stderr,"Configuration error: id_user");
660    return 2;
661  }
662  else {
663    id_user = atoi(m_user->value);
664    //freeMap(&m_user);
665    if (id_user == 0){
666        fprintf(stderr,"Configuration error: id_user");
667        return 2;
668    }
669  }
670
671
672  int id_group;
673  map *m_group = getMapFromMaps (conf, "server", "gid");
674  if (m_group == NULL){
675    fprintf(stderr,"Configuration error: gid");
676    return 2;
677  }
678  else {
679    id_group = atoi(m_group->value);
680    //freeMap(&m_group);
681    if (id_group == 0){
682        fprintf(stderr,"Configuration error: id_group");
683        return 2;
684    }
685  }
686
687  int sock = FCGX_OpenSocket(listen, listen_queue); 
688  init_services_conf (rootDir);
689 
690  ret = chown(listen, listen_owner, listen_group); 
691  if (ret != 0){
692    fprintf(stderr,"Change owner error on : %s\n",listen);
693    return 3;
694  }
695 
696  ret = setgid(id_group);
697  if (ret != 0){
698    fprintf(stderr,"Change gid error\n");
699    return 3;
700  }
701
702  ret = setuid(id_user);
703  if (ret != 0){
704    fprintf(stderr,"Change uid error\n");
705    return 3;
706  }
707 
708  int fork_status = fork();
709  if (fork_status == 0){
710    //child
711    int forker_pid = getpid();
712    FCGX_Init();
713    FCGX_Request request;
714    FCGX_InitRequest(&request, sock, 0);
715    int i;
716    int count_request = 0;
717    for (i = 0; i< req_worker; i++){
718        fork_status = fork();
719        if (fork_status == 0){
720            fprintf(stderr,"child %d \n",i);
721            fflush(stderr);
722            break;
723        }
724    }
725    while(1){
726        if (forker_pid != getpid()){
727            while(FCGX_Accept_r(&request) == 0){
728                process(&request);
729                count_request ++;
730                if (count_request >= max_requests){
731                    fprintf(stderr,"Max request stop process\n");
732                    fflush(stderr);
733                    exit(0);
734                }
735            }
736        }
737        else {
738            wait(0);
739            fprintf(stderr,"new child\n");
740            fflush(stderr);
741            fork();
742        }
743    }
744  }
745  else {
746 
747  while(1);
748
749  }
750 
751  return 0;
752}
753 
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