Changeset 4114 for trunk/packages


Ignore:
Timestamp:
Jan 14, 2014, 7:53:10 AM (11 years ago)
Author:
ldelgass
Message:

Check if input and output fds are different before duping socket second time.
Also whitespace cleanup.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/packages/vizservers/nanoscale/server.c

    r4113 r4114  
     1/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
     2/* ======================================================================
     3 *  Copyright (c) 2006-2014  HUBzero Foundation, LLC
     4 * ----------------------------------------------------------------------
     5 *  See the file "license.terms" for information on usage and
     6 *  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
     7 * ======================================================================
     8 */
    19
    210#define _GNU_SOURCE
     
    98106        s++;
    99107    }
    100     length = snprintf(message, MSG_LEN, "nanoscale (%d %d) %s: %s:%d ", 
    101         serverPid, getpid(), syslogLevels[priority],  s, lineNum);
     108    length = snprintf(message, MSG_LEN, "nanoscale (%d %d) %s: %s:%d ",
     109        serverPid, getpid(), syslogLevels[priority],  s, lineNum);
    102110    length += vsnprintf(message + length, MSG_LEN - length, fmt, lst);
    103111    message[MSG_LEN] = '\0';
    104112    if (debug) {
    105         fprintf(stderr, "%s\n", message);
     113        fprintf(stderr, "%s\n", message);
    106114    } else {
    107         syslog(priority, message, length);
     115        syslog(priority, message, length);
    108116    }
    109117}
    110118
    111 static void 
     119static void
    112120Help(const char *program)
    113121{
    114122    fprintf(stderr,
    115         "Syntax: %s [-d] [-f serversFile] [-x numVideoCards]\n", program);
     123        "Syntax: %s [-d] [-f serversFile] [-x numVideoCards]\n", program);
    116124    exit(1);
    117125}
     
    125133    memset(serverPtr, 0, sizeof(RenderServer));
    126134    if (serverPtr == NULL) {
    127         Tcl_AppendResult(interp, "can't allocate structure for \"",
    128                 name, "\": ", Tcl_PosixError(interp), (char *)NULL);
    129         return NULL;
     135        Tcl_AppendResult(interp, "can't allocate structure for \"",
     136                name, "\": ", Tcl_PosixError(interp), (char *)NULL);
     137        return NULL;
    130138    }
    131139    serverPtr->name = strdup(name);
     
    139147
    140148static int
    141 ParseSwitches(Tcl_Interp *interp, RenderServer *serverPtr, int *objcPtr, 
    142               Tcl_Obj ***objvPtr)
     149ParseSwitches(Tcl_Interp *interp, RenderServer *serverPtr, int *objcPtr,
     150              Tcl_Obj ***objvPtr)
    143151{
    144152    int i, objc;
     
    148156    objv = *objvPtr;
    149157    for (i = 3; i < objc; i += 2) {
    150         const char *string;
    151         char c;
    152 
    153         string = Tcl_GetString(objv[i]);
    154         if (string[0] != '-') {
    155             break;
    156         }
    157         c = string[1];
    158         if ((c == 'i') && (strcmp(string, "-input") == 0)) {
    159             int f;
    160 
    161             if (Tcl_GetIntFromObj(interp, objv[i+1], &f) != TCL_OK) {
    162                 return TCL_ERROR;
    163             }
    164             serverPtr->inputFd = 1;
    165         } else if ((c == 'o') && (strcmp(string, "-output") == 0)) {
    166             int f;
    167 
    168             if (Tcl_GetIntFromObj(interp, objv[i+1], &f) != TCL_OK) {
    169                 return TCL_ERROR;
    170             }
    171             serverPtr->outputFd = 1;
    172         } else if ((c == 'l') && (strcmp(string, "-logstdout") == 0)) {
    173             int state;
    174 
    175             if (Tcl_GetBooleanFromObj(interp, objv[i+1], &state) != TCL_OK) {
    176                 return TCL_ERROR;
    177             }
    178             serverPtr->logStdout = state;
    179         } else if ((c == 'l') && (strcmp(string, "-logstderr") == 0)) {
    180             int state;
    181 
    182             if (Tcl_GetBooleanFromObj(interp, objv[i+1], &state) != TCL_OK) {
    183                 return TCL_ERROR;
    184             }
    185             serverPtr->logStderr = state;
    186         } else if ((c == 'c') && (strcmp(string, "-combinelogs") == 0)) {
    187             int state;
    188 
    189             if (Tcl_GetBooleanFromObj(interp, objv[i+1], &state) != TCL_OK) {
    190                 return TCL_ERROR;
    191             }
    192             serverPtr->combineLogs = state;
    193         } else {
    194             Tcl_AppendResult(interp, "unknown switch \"", string, "\"",
    195                              (char *)NULL);
    196             return TCL_ERROR;
    197         }
     158        const char *string;
     159        char c;
     160
     161        string = Tcl_GetString(objv[i]);
     162        if (string[0] != '-') {
     163            break;
     164        }
     165        c = string[1];
     166        if ((c == 'i') && (strcmp(string, "-input") == 0)) {
     167            int f;
     168
     169            if (Tcl_GetIntFromObj(interp, objv[i+1], &f) != TCL_OK) {
     170                return TCL_ERROR;
     171            }
     172            serverPtr->inputFd = 1;
     173        } else if ((c == 'o') && (strcmp(string, "-output") == 0)) {
     174            int f;
     175
     176            if (Tcl_GetIntFromObj(interp, objv[i+1], &f) != TCL_OK) {
     177                return TCL_ERROR;
     178            }
     179            serverPtr->outputFd = 1;
     180        } else if ((c == 'l') && (strcmp(string, "-logstdout") == 0)) {
     181            int state;
     182
     183            if (Tcl_GetBooleanFromObj(interp, objv[i+1], &state) != TCL_OK) {
     184                return TCL_ERROR;
     185            }
     186            serverPtr->logStdout = state;
     187        } else if ((c == 'l') && (strcmp(string, "-logstderr") == 0)) {
     188            int state;
     189
     190            if (Tcl_GetBooleanFromObj(interp, objv[i+1], &state) != TCL_OK) {
     191                return TCL_ERROR;
     192            }
     193            serverPtr->logStderr = state;
     194        } else if ((c == 'c') && (strcmp(string, "-combinelogs") == 0)) {
     195            int state;
     196
     197            if (Tcl_GetBooleanFromObj(interp, objv[i+1], &state) != TCL_OK) {
     198                return TCL_ERROR;
     199            }
     200            serverPtr->combineLogs = state;
     201        } else {
     202            Tcl_AppendResult(interp, "unknown switch \"", string, "\"",
     203                             (char *)NULL);
     204            return TCL_ERROR;
     205        }
    198206    }
    199207    *objcPtr = objc - (i - 3);
     
    233241static int
    234242RegisterServerCmd(ClientData clientData, Tcl_Interp *interp, int objc,
    235                   Tcl_Obj *const *objv)
     243                  Tcl_Obj *const *objv)
    236244{
    237245    Tcl_Obj *objPtr;
     
    248256
    249257    if (objc < 4) {
    250         Tcl_AppendResult(interp, "wrong # args: should be \"",
    251                 Tcl_GetString(objv[0]), " serverName port ?flags? cmd ?environ?",
    252                 (char *)NULL);
    253         return TCL_ERROR;
     258        Tcl_AppendResult(interp, "wrong # args: should be \"",
     259                Tcl_GetString(objv[0]), " serverName port ?flags? cmd ?environ?",
     260                (char *)NULL);
     261        return TCL_ERROR;
    254262    }
    255263    serverName = Tcl_GetString(objv[1]);
    256264    if (Tcl_GetIntFromObj(interp, objv[2], &port) != TCL_OK) {
    257         return TCL_ERROR;
     265        return TCL_ERROR;
    258266    }
    259267    hPtr = Tcl_CreateHashEntry(&serverTable, (char *)((long)port), &isNew);
    260268    if (!isNew) {
    261         Tcl_AppendResult(interp, "a server is already listening on port ",
    262                 Tcl_GetString(objv[2]), (char *)NULL);
    263         return TCL_ERROR;
     269        Tcl_AppendResult(interp, "a server is already listening on port ",
     270                Tcl_GetString(objv[2]), (char *)NULL);
     271        return TCL_ERROR;
    264272    }
    265273    serverPtr = NewServer(interp, serverName);
    266274    if (serverPtr == NULL) {
    267         return TCL_ERROR;
     275        return TCL_ERROR;
    268276    }
    269277    Tcl_SetHashValue(hPtr, serverPtr);
    270278    if (ParseSwitches(interp, serverPtr, &objc, (Tcl_Obj ***)&objv) != TCL_OK) {
    271         goto error;
    272     }
    273     objPtr = Tcl_SubstObj(interp, objv[3], 
    274                           TCL_SUBST_VARIABLES | TCL_SUBST_BACKSLASHES);
    275     if (Tcl_SplitList(interp, Tcl_GetString(objPtr), &numCmdArgs, 
    276         (const char ***)&cmdArgs) != TCL_OK) {
    277         goto error;
     279        goto error;
     280    }
     281    objPtr = Tcl_SubstObj(interp, objv[3],
     282                          TCL_SUBST_VARIABLES | TCL_SUBST_BACKSLASHES);
     283    if (Tcl_SplitList(interp, Tcl_GetString(objPtr), &numCmdArgs,
     284        (const char ***)&cmdArgs) != TCL_OK) {
     285        goto error;
    278286    }
    279287    serverPtr->cmdArgs = cmdArgs;
    280288    serverPtr->numCmdArgs = numCmdArgs;
    281    
     289
    282290    numEnvArgs = 0;
    283291    envArgs = NULL;
    284292    if (objc == 5) {
    285         objPtr = Tcl_SubstObj(interp, objv[4],
    286                 TCL_SUBST_VARIABLES | TCL_SUBST_BACKSLASHES);
    287         if (Tcl_SplitList(interp, Tcl_GetString(objPtr), &numEnvArgs,
    288                 (const char ***)&envArgs) != TCL_OK) {
    289             goto error;
    290         }
    291         if (numEnvArgs & 0x1) {
    292             Tcl_AppendResult(interp, "odd # elements in enviroment list",
    293                              (char *)NULL);
    294             goto error;
    295         }
     293        objPtr = Tcl_SubstObj(interp, objv[4],
     294                TCL_SUBST_VARIABLES | TCL_SUBST_BACKSLASHES);
     295        if (Tcl_SplitList(interp, Tcl_GetString(objPtr), &numEnvArgs,
     296                (const char ***)&envArgs) != TCL_OK) {
     297            goto error;
     298        }
     299        if (numEnvArgs & 0x1) {
     300            Tcl_AppendResult(interp, "odd # elements in enviroment list",
     301                             (char *)NULL);
     302            goto error;
     303        }
    296304    }
    297305    serverPtr->envArgs = envArgs;
     
    301309    f = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    302310    if (f < 0) {
    303         Tcl_AppendResult(interp, "can't create listerner socket for \"",
    304                 serverPtr->name, "\": ", Tcl_PosixError(interp), (char *)NULL);
    305         goto error;
     311        Tcl_AppendResult(interp, "can't create listerner socket for \"",
     312                serverPtr->name, "\": ", Tcl_PosixError(interp), (char *)NULL);
     313        goto error;
    306314    }
    307315 
     
    310318    bool = TRUE;
    311319    if (setsockopt(f, SOL_SOCKET, SO_REUSEADDR, &bool, sizeof(bool)) < 0) {
    312         Tcl_AppendResult(interp, "can't create set socket option for \"",
    313                 serverPtr->name, "\": ", Tcl_PosixError(interp), (char *)NULL);
    314         goto error;
     320        Tcl_AppendResult(interp, "can't create set socket option for \"",
     321                serverPtr->name, "\": ", Tcl_PosixError(interp), (char *)NULL);
     322        goto error;
    315323    }
    316324
     
    320328    addr.sin_addr.s_addr = htonl(INADDR_ANY);
    321329    if (bind(f, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
    322         Tcl_AppendResult(interp, "can't bind to socket for \"",
    323                 serverPtr->name, "\": ", Tcl_PosixError(interp), (char *)NULL);
    324         goto error;
     330        Tcl_AppendResult(interp, "can't bind to socket for \"",
     331                serverPtr->name, "\": ", Tcl_PosixError(interp), (char *)NULL);
     332        goto error;
    325333    }
    326334    /* Listen on the specified port. */
    327335    if (listen(f, 5) < 0) {
    328         Tcl_AppendResult(interp, "can't listen to socket for \"",
    329                 serverPtr->name, "\": ", Tcl_PosixError(interp), (char *)NULL);
    330         return TCL_ERROR;
     336        Tcl_AppendResult(interp, "can't listen to socket for \"",
     337                serverPtr->name, "\": ", Tcl_PosixError(interp), (char *)NULL);
     338        return TCL_ERROR;
    331339    }
    332340    serverPtr->listenerFd = f;
     
    338346}
    339347
    340 static int 
     348static int
    341349ParseServersFile(const char *fileName)
    342350{
     
    345353    interp = Tcl_CreateInterp();
    346354    Tcl_MakeSafe(interp);
    347     Tcl_CreateObjCommand(interp, "register_server", RegisterServerCmd, NULL, 
    348                         NULL);
     355    Tcl_CreateObjCommand(interp, "register_server", RegisterServerCmd, NULL,
     356                        NULL);
    349357    if (Tcl_EvalFile(interp, fileName) != TCL_OK) {
    350         ERROR("Can't add server: %s", Tcl_GetString(Tcl_GetObjResult(interp)));
    351         return FALSE;
     358        ERROR("Can't add server: %s", Tcl_GetString(Tcl_GetObjResult(interp)));
     359        return FALSE;
    352360    }
    353361    Tcl_DeleteInterp(interp);
     
    355363}
    356364
    357 int 
     365int
    358366main(int argc, char **argv)
    359367{
     
    385393    /* Process command line switches. */
    386394    for (;;) {
    387         int c;
    388         int option_index = 0;
    389         struct option long_options[] = {
    390             // name, has_arg, flag, val
    391             { 0,0,0,0 },
    392         };
    393 
    394         c = getopt_long(argc, argv, "x:f:d", long_options, &option_index);
    395         if (c == -1) {
    396             break;
    397         }
    398 
    399         switch(c) {
    400         case 'x':                       /* Number of video cards */
    401             maxCards = strtoul(optarg, 0, 0);
    402             if ((maxCards < 1) || (maxCards > 10)) {
    403                 fprintf(stderr, "Bad number of max videocards specified\n");
    404                 return 1;
    405             }
    406             break;
    407         case 'd':                       /* Debug  */
    408             debug = TRUE;
    409             break;
    410 
    411         case 'f':                       /* Server file path. */
    412             fileName = strdup(optarg);
    413             break;
    414 
    415         default:
    416             fprintf(stderr,"Don't know what option '%c'.\n", c);
    417             Help(argv[0]);
    418             exit(1);
    419         }
     395        int c;
     396        int option_index = 0;
     397        struct option long_options[] = {
     398            // name, has_arg, flag, val
     399            { 0,0,0,0 },
     400        };
     401
     402        c = getopt_long(argc, argv, "x:f:d", long_options, &option_index);
     403        if (c == -1) {
     404            break;
     405        }
     406
     407        switch(c) {
     408        case 'x':                       /* Number of video cards */
     409            maxCards = strtoul(optarg, 0, 0);
     410            if ((maxCards < 1) || (maxCards > 10)) {
     411                fprintf(stderr, "Bad number of max videocards specified\n");
     412                return 1;
     413            }
     414            break;
     415        case 'd':                       /* Debug  */
     416            debug = TRUE;
     417            break;
     418
     419        case 'f':                       /* Server file path. */
     420            fileName = strdup(optarg);
     421            break;
     422
     423        default:
     424            fprintf(stderr,"Don't know what option '%c'.\n", c);
     425            Help(argv[0]);
     426            exit(1);
     427        }
    420428    }
    421429
    422430    if (!debug) {
    423         /* Detach this process from the controlling terminal process. The
    424         * current directory becomes /tmp and redirect stdin/stdout/stderr to
    425         * /dev/null. */
    426         if (daemon(0,0) < 0) {
    427             ERROR("Can't daemonize nanoscale: %s", strerror(errno));
    428             exit(1);
    429         }
     431        /* Detach this process from the controlling terminal process. The
     432        * current directory becomes /tmp and redirect stdin/stdout/stderr to
     433        * /dev/null. */
     434        if (daemon(0,0) < 0) {
     435            ERROR("Can't daemonize nanoscale: %s", strerror(errno));
     436            exit(1);
     437        }
    430438    }
    431439    serverPid = getpid();
    432440    if (!ParseServersFile(fileName)) {
    433         exit(1);
    434     }   
     441        exit(1);
     442    }
    435443
    436444    if (serverTable.numEntries == 0) {
    437         ERROR("No servers designated.");
    438         exit(1);
     445        ERROR("No servers designated.");
     446        exit(1);
    439447    }
    440448    signal(SIGPIPE, SIG_IGN);
     
    451459    maxFd = -1;
    452460    for (hPtr = Tcl_FirstHashEntry(&serverTable, &iter); hPtr != NULL;
    453         hPtr = Tcl_NextHashEntry(&iter)) {
    454         RenderServer *serverPtr;
    455        
    456         serverPtr = Tcl_GetHashValue(hPtr);
    457         FD_SET(serverPtr->listenerFd, &serverFds);
    458         if (serverPtr->listenerFd > maxFd) {
    459             maxFd = serverPtr->listenerFd;
    460         }
     461        hPtr = Tcl_NextHashEntry(&iter)) {
     462        RenderServer *serverPtr;
     463
     464        serverPtr = Tcl_GetHashValue(hPtr);
     465        FD_SET(serverPtr->listenerFd, &serverFds);
     466        if (serverPtr->listenerFd > maxFd) {
     467            maxFd = serverPtr->listenerFd;
     468        }
    461469    }
    462470
    463471    for (;;) {
    464         fd_set readFds;
    465 
    466         /* Reset using the array of server file descriptors. */
    467         memcpy(&readFds, &serverFds, sizeof(serverFds));
    468         if (select(maxFd+1, &readFds, NULL, NULL, 0) <= 0) {
    469             ERROR("Select failed: %s", strerror(errno));
    470             break;                      /* Error on select. */
    471         }
    472         for (hPtr = Tcl_FirstHashEntry(&serverTable, &iter); hPtr != NULL;
    473              hPtr = Tcl_NextHashEntry(&iter)) {
    474             RenderServer *serverPtr;
    475             pid_t child;
    476             int sock;
    477             socklen_t length;
    478             struct sockaddr_in newaddr;
    479 
    480             serverPtr = Tcl_GetHashValue(hPtr);
    481             if (!FD_ISSET(serverPtr->listenerFd, &readFds)) {
    482                 continue;               
    483             }
    484             /* Rotate the display's screen number.  If we have multiple video
    485              * cards, try to spread the jobs out among them.  */
    486             screenNum++;
    487             if (screenNum >= maxCards) {
    488                 screenNum = 0;
    489             }
    490             /* Accept the new connection. */
    491             length = sizeof(newaddr);
     472        fd_set readFds;
     473
     474        /* Reset using the array of server file descriptors. */
     475        memcpy(&readFds, &serverFds, sizeof(serverFds));
     476        if (select(maxFd+1, &readFds, NULL, NULL, 0) <= 0) {
     477            ERROR("Select failed: %s", strerror(errno));
     478            break;                      /* Error on select. */
     479        }
     480        for (hPtr = Tcl_FirstHashEntry(&serverTable, &iter); hPtr != NULL;
     481             hPtr = Tcl_NextHashEntry(&iter)) {
     482            RenderServer *serverPtr;
     483            pid_t child;
     484            int sock;
     485            socklen_t length;
     486            struct sockaddr_in newaddr;
     487
     488            serverPtr = Tcl_GetHashValue(hPtr);
     489            if (!FD_ISSET(serverPtr->listenerFd, &readFds)) {
     490                continue;
     491            }
     492            /* Rotate the display's screen number.  If we have multiple video
     493             * cards, try to spread the jobs out among them.  */
     494            screenNum++;
     495            if (screenNum >= maxCards) {
     496                screenNum = 0;
     497            }
     498            /* Accept the new connection. */
     499            length = sizeof(newaddr);
    492500#ifdef HAVE_ACCEPT4
    493             sock = accept4(serverPtr->listenerFd, (struct sockaddr *)&newaddr,
    494                         &length, SOCK_CLOEXEC);
     501            sock = accept4(serverPtr->listenerFd, (struct sockaddr *)&newaddr,
     502                        &length, SOCK_CLOEXEC);
    495503#else
    496             sock = accept(serverPtr->listenerFd, (struct sockaddr *)&newaddr,
    497                        &length);
     504            sock = accept(serverPtr->listenerFd, (struct sockaddr *)&newaddr,
     505                       &length);
    498506#endif
    499             if (sock < 0) {
    500                 ERROR("Can't accept server \"%s\": %s", serverPtr->name,
    501                       strerror(errno));
    502                 exit(1);
    503             }
     507            if (sock < 0) {
     508                ERROR("Can't accept server \"%s\": %s", serverPtr->name,
     509                      strerror(errno));
     510                exit(1);
     511            }
    504512#ifndef HAVE_ACCEPT4
    505             int flags = fcntl(sock, F_GETFD);
    506             flags |= FD_CLOEXEC;
    507             if (fcntl(sock, F_SETFD, flags) < 0) {
    508                 ERROR("Can't set FD_CLOEXEC on socket \"%s\": %s",
    509                         serverPtr->name, strerror(errno));
    510                 exit(1);
    511             }
     513            int flags = fcntl(sock, F_GETFD);
     514            flags |= FD_CLOEXEC;
     515            if (fcntl(sock, F_SETFD, flags) < 0) {
     516                ERROR("Can't set FD_CLOEXEC on socket \"%s\": %s",
     517                        serverPtr->name, strerror(errno));
     518                exit(1);
     519            }
    512520#endif
    513             INFO("Connecting \"%s\" to %s\n", serverPtr->name,
    514                  inet_ntoa(newaddr.sin_addr));
    515 
    516             /* Fork the new process.  Connect I/O to the new socket. */
    517             child = fork();
    518             if (child < 0) {
    519                 ERROR("Can't fork \"%s\": %s", serverPtr->name,
    520                       strerror(errno));
    521                 continue;
    522             }
    523             if (child == 0) {           /* Child process. */
    524                 int i;
    525 
    526                 umask(0);
    527                 if ((!debug) && (setsid() < 0)) {
    528                     ERROR("Can't setsid \"%s\": %s", serverPtr->name,
    529                           strerror(errno));
    530                     exit(1);
    531                 }
    532                 if ((!debug) && ((chdir("/")) < 0)) {
    533                     ERROR("Can't change to root directory for \"%s\": %s",
    534                           serverPtr->name, strerror(errno));
    535                     exit(1);
    536                 }
    537                 if (serverPtr->combineLogs) {
    538                     char path[BUFSIZ];
    539                     int newFd;
    540 
    541                     sprintf(path, "%s/%s-%d.log", LOGDIR,
    542                         serverPtr->name, getpid());
    543                     if (serverPtr->logStdout) {
    544                         newFd = open(path, O_WRONLY | O_CREAT| O_TRUNC, 0600);
    545                     } else {
    546                         newFd = open("/dev/null", O_WRONLY, 0600);
    547                     }
    548                     if (newFd < 0) {
    549                         ERROR("%s: can't open \"%s\": %s", serverPtr->name,
    550                               path, strerror(errno));
    551                         exit(1);
    552                     }
    553                     if (dup2(newFd, 1) < 0) {
    554                         ERROR("%s: can't dup stdout to \"%s\": %s",
    555                               serverPtr->name, path, strerror(errno));
    556                         exit(1);
    557                     }
    558                     if (dup2(newFd, 2) < 0) {
    559                         ERROR("%s: can't dup stderr to \"%s\": %s",
    560                               serverPtr->name, path, strerror(errno));
    561                         exit(1);
    562                     }
    563                 } else {
    564                     char path[BUFSIZ];
    565                     int newFd;
    566 
    567                     sprintf(path, "%s/%s-%d.stdout", LOGDIR,
    568                         serverPtr->name, getpid());
    569                     if (serverPtr->logStdout) {
    570                         newFd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0600);
    571                     } else {
    572                         newFd = open("/dev/null", O_WRONLY, 0600);
    573                     }
    574                     if (newFd < 0) {
    575                         ERROR("%s: can't open \"%s\": %s", serverPtr->name,
    576                               path, strerror(errno));
    577                         exit(1);
    578                     }
    579                     if (dup2(newFd, 1) < 0) {
    580                         ERROR("%s: can't dup stdout to \"%s\": %s",
    581                               serverPtr->name, path, strerror(errno));
    582                         exit(1);
    583                     }
    584                     sprintf(path, "%s/%s-%d.stderr", LOGDIR,
    585                         serverPtr->name, getpid());
    586                     if (serverPtr->logStderr) {
    587                         newFd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0600);
    588                     } else {
    589                         newFd = open("/dev/null", O_WRONLY, 0600);
    590                     }
    591                     if (newFd < 0) {
    592                         ERROR("%s: can't open \"%s\": %s", serverPtr->name,
    593                               path, strerror(errno));
    594                         exit(1);
    595                     }
    596                     if (dup2(newFd, 1) < 0) {
    597                         ERROR("%s: can't dup stderr to \"%s\": %s",
    598                               serverPtr->name, path, strerror(errno));
    599                         exit(1);
    600                     }
    601                 }
    602                 /* Dup the socket to descriptors, normally 3 and 4 */
    603                 if (dup2(sock, serverPtr->inputFd) < 0)  { /* Stdin */
    604                     ERROR("%s: can't dup stdin: %s", serverPtr->name,
    605                         strerror(errno));
    606                     exit(1);
    607                 }
    608                 if (dup2(sock, serverPtr->outputFd) < 0) { /* Stdout */
    609                     ERROR("%s: can't dup stdout: %s", serverPtr->name,
    610                           strerror(errno));
    611                     exit(1);
    612                 }
    613                 for(i = serverPtr->outputFd + 1; i <= FD_SETSIZE; i++) {
    614                     close(i);           /* Close all the other descriptors. */
    615                 }
    616 
    617                 /* Set the screen number in the DISPLAY variable. */
    618                 display[3] = screenNum + '0';
    619                 setenv("DISPLAY", display, 1);
    620                 /* Set the enviroment, if necessary. */
    621                 for (i = 0; i < serverPtr->numEnvArgs; i += 2) {
    622                     setenv(serverPtr->envArgs[i], serverPtr->envArgs[i+1], 1);
    623                 }
    624                 INFO("Executing %s: client %s, %s on DISPLAY=%s",
    625                         serverPtr->name, inet_ntoa(newaddr.sin_addr),
    626                         serverPtr->cmdArgs[0], display);
    627                 /* Replace the current process with the render server. */
    628                 execvp(serverPtr->cmdArgs[0], serverPtr->cmdArgs);
    629                 ERROR("Can't execute \"%s\": %s", serverPtr->cmdArgs[0],
    630                       strerror(errno));
    631                 exit(1);
    632             } else {
    633                 close(sock);
    634             }
    635         }
     521            INFO("Connecting \"%s\" to %s\n", serverPtr->name,
     522                 inet_ntoa(newaddr.sin_addr));
     523
     524            /* Fork the new process.  Connect I/O to the new socket. */
     525            child = fork();
     526            if (child < 0) {
     527                ERROR("Can't fork \"%s\": %s", serverPtr->name,
     528                      strerror(errno));
     529                continue;
     530            }
     531            if (child == 0) {           /* Child process. */
     532                int i;
     533
     534                umask(0);
     535                if ((!debug) && (setsid() < 0)) {
     536                    ERROR("Can't setsid \"%s\": %s", serverPtr->name,
     537                          strerror(errno));
     538                    exit(1);
     539                }
     540                if ((!debug) && ((chdir("/")) < 0)) {
     541                    ERROR("Can't change to root directory for \"%s\": %s",
     542                          serverPtr->name, strerror(errno));
     543                    exit(1);
     544                }
     545                if (serverPtr->combineLogs) {
     546                    char path[BUFSIZ];
     547                    int newFd;
     548
     549                    sprintf(path, "%s/%s-%d.log", LOGDIR,
     550                        serverPtr->name, getpid());
     551                    if (serverPtr->logStdout) {
     552                        newFd = open(path, O_WRONLY | O_CREAT| O_TRUNC, 0600);
     553                    } else {
     554                        newFd = open("/dev/null", O_WRONLY, 0600);
     555                    }
     556                    if (newFd < 0) {
     557                        ERROR("%s: can't open \"%s\": %s", serverPtr->name,
     558                              path, strerror(errno));
     559                        exit(1);
     560                    }
     561                    if (dup2(newFd, 1) < 0) {
     562                        ERROR("%s: can't dup stdout to \"%s\": %s",
     563                              serverPtr->name, path, strerror(errno));
     564                        exit(1);
     565                    }
     566                    if (dup2(newFd, 2) < 0) {
     567                        ERROR("%s: can't dup stderr to \"%s\": %s",
     568                              serverPtr->name, path, strerror(errno));
     569                        exit(1);
     570                    }
     571                } else {
     572                    char path[BUFSIZ];
     573                    int newFd;
     574
     575                    sprintf(path, "%s/%s-%d.stdout", LOGDIR,
     576                        serverPtr->name, getpid());
     577                    if (serverPtr->logStdout) {
     578                        newFd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0600);
     579                    } else {
     580                        newFd = open("/dev/null", O_WRONLY, 0600);
     581                    }
     582                    if (newFd < 0) {
     583                        ERROR("%s: can't open \"%s\": %s", serverPtr->name,
     584                              path, strerror(errno));
     585                        exit(1);
     586                    }
     587                    if (dup2(newFd, 1) < 0) {
     588                        ERROR("%s: can't dup stdout to \"%s\": %s",
     589                              serverPtr->name, path, strerror(errno));
     590                        exit(1);
     591                    }
     592                    sprintf(path, "%s/%s-%d.stderr", LOGDIR,
     593                        serverPtr->name, getpid());
     594                    if (serverPtr->logStderr) {
     595                        newFd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0600);
     596                    } else {
     597                        newFd = open("/dev/null", O_WRONLY, 0600);
     598                    }
     599                    if (newFd < 0) {
     600                        ERROR("%s: can't open \"%s\": %s", serverPtr->name,
     601                              path, strerror(errno));
     602                        exit(1);
     603                    }
     604                    if (dup2(newFd, 1) < 0) {
     605                        ERROR("%s: can't dup stderr to \"%s\": %s",
     606                              serverPtr->name, path, strerror(errno));
     607                        exit(1);
     608                    }
     609                }
     610                /* Dup the socket to descriptors, normally 3 and 4 */
     611                if (dup2(sock, serverPtr->inputFd) < 0)  { /* input */
     612                    ERROR("%s: can't dup socket to fd %d: %s",
     613                          serverPtr->name, serverPtr->inputFd,
     614                          strerror(errno));
     615                    exit(1);
     616                }
     617                if (serverPtr->inputFd != serverPtr->outputFd) {
     618                    if (dup2(sock, serverPtr->outputFd) < 0) { /* output */
     619                        ERROR("%s: can't dup socket to fd %d: %s",
     620                              serverPtr->name, serverPtr->outputFd,
     621                              strerror(errno));
     622                        exit(1);
     623                    }
     624                }
     625                for (i = serverPtr->outputFd + 1; i <= FD_SETSIZE; i++) {
     626                    close(i);           /* Close all the other descriptors. */
     627                }
     628
     629                /* Set the screen number in the DISPLAY variable. */
     630                display[3] = screenNum + '0';
     631                setenv("DISPLAY", display, 1);
     632                /* Set the enviroment, if necessary. */
     633                for (i = 0; i < serverPtr->numEnvArgs; i += 2) {
     634                    setenv(serverPtr->envArgs[i], serverPtr->envArgs[i+1], 1);
     635                }
     636                INFO("Executing %s: client %s, %s on DISPLAY=%s",
     637                        serverPtr->name, inet_ntoa(newaddr.sin_addr),
     638                        serverPtr->cmdArgs[0], display);
     639                /* Replace the current process with the render server. */
     640                execvp(serverPtr->cmdArgs[0], serverPtr->cmdArgs);
     641                ERROR("Can't execute \"%s\": %s", serverPtr->cmdArgs[0],
     642                      strerror(errno));
     643                exit(1);
     644            } else {
     645                close(sock);
     646            }
     647        }
    636648    }
    637649    exit(1);
Note: See TracChangeset for help on using the changeset viewer.