Changeset 6571


Ignore:
Timestamp:
Nov 6, 2016 8:04:26 PM (7 years ago)
Author:
ldelgass
Message:

Separate out config file parser, add default simple text parser, make Tcl parser
optional.

Location:
nanoscale/trunk
Files:
4 added
6 edited

Legend:

Unmodified
Added
Removed
  • nanoscale/trunk/Makefile.in

    r4585 r6571  
     1USE_TCL_CONFIG  = #yes
    12
    23CC              = @CC@
     
    2526
    2627SERVER_OBJS     = server.o
     28ifdef USE_TCL_CONFIG
     29SERVER_OBJS    += tclparser.o
     30else
     31SERVER_OBJS    += configparser.o
     32endif
    2733CLIENT_OBJS     = client.o clientlib.o
    2834
     
    3339SVN_VERSION     = $(shell svnversion $(srcdir) | sed 's/Unversioned directory/unknown/')
    3440
    35 DEFINES         = -DSERVERSFILE=\"$(libdir)/renderservers.tcl\" \
     41ifdef USE_TCL_CONFIG
     42CONFIGFILE      = renderservers.tcl
     43DEFINES         = -DTCL_CONFIG
     44else
     45CONFIGFILE      = renderservers.cfg
     46DEFINES         =
     47endif
     48DEFINES         += -DSERVERSFILE=\"$(libdir)/$(CONFIGFILE)\" \
    3649                -DSVN_VERSION=\"$(SVN_VERSION)\" \
    3750                -DLOGDIR=\"$(LOGDIR)\"
    38 INCLUDES        = -I. $(TCL_INC_SPEC)
    39 LIBS            = $(TCL_LIB_SPEC) \
    40                 -Wl,-rpath,$(LD_RUN_PATH)
     51INCLUDES        = -I.
     52ifdef USE_TCL_CONFIG
     53INCLUDES       += $(TCL_INC_SPEC)
     54endif
     55ifdef USE_TCL_CONFIG
     56LIBS            = $(TCL_LIB_SPEC) -Wl,-rpath,$(LD_RUN_PATH)
     57else
     58LIBS            =
     59endif
    4160
    4261.PHONY: all install clean distclean
     
    4968        $(CC) $(CC_SWITCHES) -o $@ $^ $(LIBS)
    5069
    51 install: nanoscale renderservers.tcl start_nanoscale.sh
     70install: nanoscale $(CONFIGFILE) start_nanoscale.sh
    5271        $(INSTALL_PROGRAM) -D nanoscale $(bindir)/nanoscale
    5372        $(INSTALL_PROGRAM) start_nanoscale.sh $(bindir)/start_nanoscale.sh
    54         $(INSTALL_SCRIPT) renderservers.tcl $(libdir)
     73        $(INSTALL_DATA) $(CONFIGFILE) $(libdir)
    5574
    5675client: $(CLIENT_OBJS)
     
    6079
    6180clean:
    62         $(RM) -r a.out $(SERVER_OBJS) *~ core* $(TARGETS) *.log *.tmp logfile* .deps/*.d
     81        $(RM) -r a.out *.o *~ core* $(TARGETS) *.log *.tmp logfile* .deps/*.d
    6382
    6483distclean: clean
    6584        $(RM) -r autom4te.cache
    66         $(RM) Makefile config.cache config.log config.status config.h renderservers.tcl start_nanoscale.sh
     85        $(RM) Makefile config.cache config.log config.status config.h $(CONFIGFILE) start_nanoscale.sh
    6786
     87server.o: server.h
     88configparser.o: server.h
     89tclparser.o: server.h
  • nanoscale/trunk/configure

    r4584 r6571  
    76767676
    76777677
    7678 ac_config_files="$ac_config_files Makefile renderservers.tcl start_nanoscale.sh"
     7678ac_config_files="$ac_config_files Makefile renderservers.cfg renderservers.tcl start_nanoscale.sh"
    76797679
    76807680cat >confcache <<\_ACEOF
     
    83728372    "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
    83738373    "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
     8374    "renderservers.cfg") CONFIG_FILES="$CONFIG_FILES renderservers.cfg" ;;
    83748375    "renderservers.tcl") CONFIG_FILES="$CONFIG_FILES renderservers.tcl" ;;
    83758376    "start_nanoscale.sh") CONFIG_FILES="$CONFIG_FILES start_nanoscale.sh" ;;
  • nanoscale/trunk/configure.ac

    r6200 r6571  
    118118AC_OUTPUT([
    119119   Makefile \
     120   renderservers.cfg \
    120121   renderservers.tcl \
    121122   start_nanoscale.sh])
  • nanoscale/trunk/renderservers.tcl.in

    r6504 r6571  
    134134    MSMSSERVER ${libdir}/vmd/msms
    135135    STRIDE_BIN ${libdir}/vmd/stride
    136     LD_LIBRARY_PATH ""
    137136    __GL_SYNC_TO_VBLANK 0
    138137}
  • nanoscale/trunk/server.c

    r6506 r6571  
    11/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
    22/* ======================================================================
    3  *  Copyright (c) 2004-2014  HUBzero Foundation, LLC
     3 *  Copyright (c) 2004-2016  HUBzero Foundation, LLC
    44 * ----------------------------------------------------------------------
    55 *  See the file "license.terms" for information on usage and
     
    2020#include <sys/stat.h>
    2121#include <sys/file.h>
    22 #include <syslog.h>
    2322#include <unistd.h>
    2423#include <fcntl.h>
    2524
     25#ifdef TCL_CONFIG
    2626#include <tcl.h>
     27#endif
    2728
    2829#include "config.h"
    29 
    30 #define TRUE    1
    31 #define FALSE   0
    32 
    33 #ifndef SERVERSFILE
    34 #define SERVERSFILE  "/opt/hubzero/rappture/render/lib/renderservers.tcl"
    35 #endif
    36 
    37 #ifndef LOGDIR
    38 #define LOGDIR          "/tmp"
    39 #endif
    40 
    41 #define ERROR(...)      SysLog(LOG_ERR, __FILE__, __LINE__, __VA_ARGS__)
    42 #define TRACE(...)      SysLog(LOG_DEBUG, __FILE__, __LINE__, __VA_ARGS__)
    43 #define WARN(...)       SysLog(LOG_WARNING, __FILE__, __LINE__, __VA_ARGS__)
    44 #define INFO(...)       SysLog(LOG_INFO, __FILE__, __LINE__, __VA_ARGS__)
     30#include "server.h"
    4531
    4632static const char *syslogLevels[] = {
     
    5541};
    5642
    57 /* RenderServer --
    58  *
    59  *      Contains information to describe/execute a render server.
    60  */
    61 typedef struct {
    62     const char *name;                   /* Name of server. */
    63     int port;                           /* Port to listen to. */
    64     int numCmdArgs;                     /* # of args in command.  */
    65     int numEnvArgs;                     /* # of args in environment.  */
    66     char *const *cmdArgs;               /* Command to execute for
    67                                          * server. */
    68     char *const *envArgs;               /* Environment strings to set. */
    69     int listenerFd;                     /* Descriptor of the listener
    70                                            socket. */
    71     int inputFd;                        /* Descriptor to dup input side of
    72                                          * server socket. */
    73     int outputFd;                       /* Descriptor to dup output side of
    74                                          * server socket. */
    75     int logStdout;                      /* Redirect server stdout to a
    76                                            file. */
    77     int logStderr;                      /* Redirect server stderr to a
    78                                            file. */
    79     int combineLogs;                    /* Combine server stdout/stderr in
    80                                          * same file. */
    81 } RenderServer;
    82 
    83 static Tcl_HashTable serverTable;       /* Table of render servers
    84                                          * representing services available to
    85                                          * clients.  A new instance is forked
    86                                          * and executed each time a new
    87                                          * request is accepted. */
     43static int numServers = 0;
     44/* Table of render servers representing services available to
     45 * clients.  A new instance is forked and executed each time a
     46 * new request is accepted. */
     47static RenderServer *serverTable[MAX_SERVERS];
     48
    8849static int debug = FALSE;
    8950static pid_t serverPid;
    9051
    9152static void
     53Help(const char *program)
     54{
     55    fprintf(stderr,
     56        "Syntax: %s [-d] [-f serversFile] [-x numVideoCards]\n", program);
     57    exit(1);
     58}
     59
     60static void
     61InitLog()
     62{
     63    //openlog("nanoscale", LOG_CONS | LOG_PID,  LOG_USER);
     64    openlog("nanoscale", LOG_PID,  LOG_USER);
     65}
     66
     67void
    9268SysLog(int priority, const char *path, int lineNum, const char* fmt, ...)
    9369{
     
    10581        s++;
    10682    }
    107     length = snprintf(message, MSG_LEN, "nanoscale (%d %d) %s: %s:%d ",
    108         serverPid, getpid(), syslogLevels[priority],  s, lineNum);
     83    if (serverPid != getpid()) {
     84        length = snprintf(message, MSG_LEN, "(%d) %s: %s:%d ",
     85                          serverPid, syslogLevels[priority],  s, lineNum);
     86    } else {
     87        length = snprintf(message, MSG_LEN, "%s: %s:%d ",
     88                          syslogLevels[priority],  s, lineNum);
     89    }
    10990    length += vsnprintf(message + length, MSG_LEN - length, fmt, lst);
    11091    message[MSG_LEN] = '\0';
     
    11697}
    11798
    118 static void
    119 Help(const char *program)
    120 {
    121     fprintf(stderr,
    122         "Syntax: %s [-d] [-f serversFile] [-x numVideoCards]\n", program);
    123     exit(1);
    124 }
    125 
    126 static RenderServer *
    127 NewServer(Tcl_Interp *interp, const char *name)
     99RenderServer *
     100NewServer(const char *name)
    128101{
    129102    RenderServer *serverPtr;
     
    132105    memset(serverPtr, 0, sizeof(RenderServer));
    133106    if (serverPtr == NULL) {
    134         Tcl_AppendResult(interp, "can't allocate structure for \"",
    135                 name, "\": ", Tcl_PosixError(interp), (char *)NULL);
     107        ERROR("can't allocate structure: %s", strerror(errno));
    136108        return NULL;
    137109    }
    138     serverPtr->name = strdup(name);
     110    if (name != NULL) {
     111        serverPtr->name = strdup(name);
     112    }
    139113    serverPtr->outputFd = STDOUT_FILENO;
    140114    serverPtr->inputFd = STDIN_FILENO;
     
    145119}
    146120
    147 static int
    148 ParseSwitches(Tcl_Interp *interp, RenderServer *serverPtr, int *objcPtr,
    149               Tcl_Obj ***objvPtr)
    150 {
    151     int i, objc;
    152     Tcl_Obj **objv;
    153 
    154     objc = *objcPtr;
    155     objv = *objvPtr;
    156     for (i = 3; i < objc; i += 2) {
    157         const char *string;
    158         char c;
    159 
    160         string = Tcl_GetString(objv[i]);
    161         if (string[0] != '-') {
    162             break;
    163         }
    164         c = string[1];
    165         if ((c == 'i') && (strcmp(string, "-input") == 0)) {
    166             int f;
    167 
    168             if (Tcl_GetIntFromObj(interp, objv[i+1], &f) != TCL_OK) {
    169                 return TCL_ERROR;
    170             }
    171             serverPtr->inputFd = f;
    172         } else if ((c == 'o') && (strcmp(string, "-output") == 0)) {
    173             int f;
    174 
    175             if (Tcl_GetIntFromObj(interp, objv[i+1], &f) != TCL_OK) {
    176                 return TCL_ERROR;
    177             }
    178             serverPtr->outputFd = f;
    179         } else if ((c == 'l') && (strcmp(string, "-logstdout") == 0)) {
    180             int state;
    181 
    182             if (Tcl_GetBooleanFromObj(interp, objv[i+1], &state) != TCL_OK) {
    183                 return TCL_ERROR;
    184             }
    185             serverPtr->logStdout = state;
    186         } else if ((c == 'l') && (strcmp(string, "-logstderr") == 0)) {
    187             int state;
    188 
    189             if (Tcl_GetBooleanFromObj(interp, objv[i+1], &state) != TCL_OK) {
    190                 return TCL_ERROR;
    191             }
    192             serverPtr->logStderr = state;
    193         } else if ((c == 'c') && (strcmp(string, "-combinelogs") == 0)) {
    194             int state;
    195 
    196             if (Tcl_GetBooleanFromObj(interp, objv[i+1], &state) != TCL_OK) {
    197                 return TCL_ERROR;
    198             }
    199             serverPtr->combineLogs = state;
    200         } else {
    201             Tcl_AppendResult(interp, "unknown switch \"", string, "\"",
    202                              (char *)NULL);
    203             return TCL_ERROR;
    204         }
    205     }
    206     *objcPtr = objc - (i - 3);
    207     *objvPtr = objv + (i - 3);
    208     return TCL_OK;
    209 }
    210 
    211 /*
    212  * RegisterServerCmd --
    213  *
    214  *      Registers a render server to be run when a client connects
    215  *      on the designated port. The form of the commands is
    216  *
    217  *          register_server <name> <port> <cmd> <environ>
    218  *
    219  *      where
    220  *
    221  *          name        Token for the render server.
    222  *          port        Port to listen to accept connections.
    223  *          cmd         Command to be run to start the render server.
    224  *          environ     Name-value pairs of representing environment
    225  *                      variables.
    226  *
    227  *      Note that "cmd" and "environ" are variable and backslash
    228  *      substituted.  A listener socket automatically is established on
    229  *      the given port to accept client requests.
    230  *
    231  *      Example:
    232  *
    233  *          register_server myServer 12345 ?switches? {
    234  *               /path/to/myserver arg arg
    235  *          } {
    236  *               LD_LIBRARY_PATH $libdir/myServer
    237  *          }
    238  *
    239  */
    240 static int
    241 RegisterServerCmd(ClientData clientData, Tcl_Interp *interp, int objc,
    242                   Tcl_Obj *const *objv)
    243 {
    244     Tcl_Obj *objPtr;
    245     const char *serverName;
    246     int bool, isNew;
    247     int f;
    248     int port;
    249     int numCmdArgs, numEnvArgs;
    250     char *const *cmdArgs;
    251     char *const *envArgs;
    252     struct sockaddr_in addr;
    253     RenderServer *serverPtr;
    254     Tcl_HashEntry *hPtr;
    255 
    256     if (objc < 4) {
    257         Tcl_AppendResult(interp, "wrong # args: should be \"",
    258                 Tcl_GetString(objv[0]), " serverName port ?flags? cmd ?environ?",
    259                 (char *)NULL);
    260         return TCL_ERROR;
    261     }
    262     serverName = Tcl_GetString(objv[1]);
    263     if (Tcl_GetIntFromObj(interp, objv[2], &port) != TCL_OK) {
    264         return TCL_ERROR;
    265     }
    266     hPtr = Tcl_CreateHashEntry(&serverTable, (char *)((long)port), &isNew);
    267     if (!isNew) {
    268         Tcl_AppendResult(interp, "a server is already listening on port ",
    269                 Tcl_GetString(objv[2]), (char *)NULL);
    270         return TCL_ERROR;
    271     }
    272     serverPtr = NewServer(interp, serverName);
    273     if (serverPtr == NULL) {
    274         return TCL_ERROR;
    275     }
    276     Tcl_SetHashValue(hPtr, serverPtr);
    277     if (ParseSwitches(interp, serverPtr, &objc, (Tcl_Obj ***)&objv) != TCL_OK) {
    278         goto error;
    279     }
    280     objPtr = Tcl_SubstObj(interp, objv[3],
    281                           TCL_SUBST_VARIABLES | TCL_SUBST_BACKSLASHES);
    282     if (Tcl_SplitList(interp, Tcl_GetString(objPtr), &numCmdArgs,
    283         (const char ***)&cmdArgs) != TCL_OK) {
    284         goto error;
    285     }
    286     serverPtr->cmdArgs = cmdArgs;
    287     serverPtr->numCmdArgs = numCmdArgs;
    288 
    289     numEnvArgs = 0;
    290     envArgs = NULL;
    291     if (objc == 5) {
    292         objPtr = Tcl_SubstObj(interp, objv[4],
    293                 TCL_SUBST_VARIABLES | TCL_SUBST_BACKSLASHES);
    294         if (Tcl_SplitList(interp, Tcl_GetString(objPtr), &numEnvArgs,
    295                 (const char ***)&envArgs) != TCL_OK) {
    296             goto error;
    297         }
    298         if (numEnvArgs & 0x1) {
    299             Tcl_AppendResult(interp, "odd # elements in enviroment list",
    300                              (char *)NULL);
    301             goto error;
    302         }
    303     }
    304     serverPtr->envArgs = envArgs;
    305     serverPtr->numEnvArgs = numEnvArgs;
    306 
    307     /* Create a socket for listening. */
    308     f = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    309     if (f < 0) {
    310         Tcl_AppendResult(interp, "can't create listener socket for \"",
    311                 serverPtr->name, "\": ", Tcl_PosixError(interp), (char *)NULL);
    312         goto error;
    313     }
    314 
    315     /* If the render server instance should be killed, drop the socket address
    316      * reservation immediately, don't linger. */
    317     bool = TRUE;
    318     if (setsockopt(f, SOL_SOCKET, SO_REUSEADDR, &bool, sizeof(bool)) < 0) {
    319         Tcl_AppendResult(interp, "can't create set socket option for \"",
    320                 serverPtr->name, "\": ", Tcl_PosixError(interp), (char *)NULL);
    321         goto error;
    322     }
    323 
    324     /* Bind this address to the socket. */
    325     addr.sin_family = AF_INET;
    326     addr.sin_port = htons(port);
    327     addr.sin_addr.s_addr = htonl(INADDR_ANY);
    328     if (bind(f, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
    329         Tcl_AppendResult(interp, "can't bind to socket for \"",
    330                 serverPtr->name, "\": ", Tcl_PosixError(interp), (char *)NULL);
    331         goto error;
    332     }
    333     /* Listen on the specified port. */
    334     if (listen(f, 5) < 0) {
    335         Tcl_AppendResult(interp, "can't listen to socket for \"",
    336                 serverPtr->name, "\": ", Tcl_PosixError(interp), (char *)NULL);
    337         return TCL_ERROR;
    338     }
    339     serverPtr->listenerFd = f;
    340 
    341     return TCL_OK;
    342  error:
    343     free(serverPtr);
    344     return TCL_ERROR;
    345 }
    346 
    347 static int
    348 ParseServersFile(const char *fileName)
    349 {
    350     Tcl_Interp *interp;
    351 
    352     interp = Tcl_CreateInterp();
    353     Tcl_MakeSafe(interp);
    354     Tcl_CreateObjCommand(interp, "register_server", RegisterServerCmd, NULL,
    355                          NULL);
    356     if (Tcl_EvalFile(interp, fileName) != TCL_OK) {
    357         ERROR("Can't add server: %s", Tcl_GetString(Tcl_GetObjResult(interp)));
    358         return FALSE;
    359     }
    360     Tcl_DeleteInterp(interp);
    361     return TRUE;
     121static void
     122InitServerTable()
     123{
     124    memset(serverTable, 0, sizeof(serverTable));
    362125}
    363126
     
    365128main(int argc, char **argv)
    366129{
     130    int si;
    367131#ifdef SA_NOCLDWAIT
    368132    struct sigaction action;
     
    377141                                         * screen.  */
    378142    int screenNum;                      /* Current X screen number. */
    379     Tcl_HashEntry *hPtr;
    380     Tcl_HashSearch iter;
    381143    const char *fileName;               /* Path to servers file. */
    382144
     
    388150
    389151    strcpy(display, ":0.0");
    390     Tcl_InitHashTable(&serverTable, TCL_ONE_WORD_KEYS);
     152    InitLog();
     153    InitServerTable();
    391154
    392155    /* Process command line switches. */
     
    437200    }
    438201    serverPid = getpid();
    439     if (!ParseServersFile(fileName)) {
     202    if (!ParseServersFile(fileName, &numServers, serverTable)) {
     203        ERROR("Exiting on invalid configuration");
    440204        exit(1);
    441205    }
    442206
    443     if (serverTable.numEntries == 0) {
     207    /* Create listening sockets */
     208    for (si = 0; si < numServers; si++) {
     209        int fd, bool;
     210        struct sockaddr_in addr;
     211        RenderServer *serverPtr;
     212
     213        serverPtr = serverTable[si];
     214
     215        /* Create a socket for listening. */
     216        fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
     217        if (fd < 0) {
     218            ERROR("can't create listener socket for \"%s\": %s",
     219                  serverPtr->name, strerror(errno));
     220            exit(1);
     221        }
     222        /* If the render server instance should be killed, drop the socket
     223           address reservation immediately, don't linger. */
     224        bool = TRUE;
     225        if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &bool, sizeof(bool)) < 0) {
     226            ERROR("can't create set socket option for \"%s\": %s",
     227                  serverPtr->name, strerror(errno));
     228            exit(1);
     229        }
     230        /* Bind this address to the socket. */
     231        addr.sin_family = AF_INET;
     232        addr.sin_port = htons(serverPtr->port);
     233        addr.sin_addr.s_addr = htonl(INADDR_ANY);
     234        if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
     235            ERROR("can't bind to socket for \"%s\": %s",
     236                  serverPtr->name, strerror(errno));
     237            exit(1);
     238        }
     239        /* Listen on the specified port. */
     240        if (listen(fd, 5) < 0) {
     241            ERROR("can't listen to socket for \"%s\": %s",
     242                  serverPtr->name, strerror(errno));
     243            exit(1);
     244        }
     245        serverPtr->listenerFd = fd;
     246        INFO("%s listening on %d", serverPtr->name, serverPtr->port);
     247    }
     248
     249    if (numServers == 0) {
    444250        ERROR("No servers designated.");
    445251        exit(1);
     
    457263    FD_ZERO(&serverFds);
    458264    maxFd = -1;
    459     for (hPtr = Tcl_FirstHashEntry(&serverTable, &iter); hPtr != NULL;
    460          hPtr = Tcl_NextHashEntry(&iter)) {
     265    for (si = 0; si < numServers; si++) {
    461266        RenderServer *serverPtr;
    462267
    463         serverPtr = Tcl_GetHashValue(hPtr);
     268        serverPtr = serverTable[si];
     269
    464270        FD_SET(serverPtr->listenerFd, &serverFds);
    465271        if (serverPtr->listenerFd > maxFd) {
     
    477283            break;                      /* Error on select. */
    478284        }
    479         for (hPtr = Tcl_FirstHashEntry(&serverTable, &iter); hPtr != NULL;
    480              hPtr = Tcl_NextHashEntry(&iter)) {
     285        for (si = 0; si < numServers; si++) {
    481286            RenderServer *serverPtr;
    482287            pid_t child;
     
    485290            struct sockaddr_in newaddr;
    486291
    487             serverPtr = Tcl_GetHashValue(hPtr);
     292            serverPtr = serverTable[si];
    488293            if (!FD_ISSET(serverPtr->listenerFd, &readFds)) {
    489294                continue;
     
    645450                /* Set the configured environment */
    646451                for (i = 0; i < serverPtr->numEnvArgs; i += 2) {
     452                    INFO("Env: %s=%s", serverPtr->envArgs[i],
     453                         serverPtr->envArgs[i+1]);
    647454                    setenv(serverPtr->envArgs[i], serverPtr->envArgs[i+1], 1);
    648455                }
    649                 { 
     456                {
    650457                    char *cmd;
    651458
    652                     cmd = Tcl_Merge(serverPtr->numCmdArgs,
    653                                     (const char *const *)serverPtr->cmdArgs);
     459                    cmd = MergeArgs(serverPtr->numCmdArgs, serverPtr->cmdArgs);
    654460                    INFO("Executing %s: client=%s, \"%s\" in=%d out=%d on DISPLAY=%s",
    655461                         serverPtr->name, inet_ntoa(newaddr.sin_addr),
    656462                         cmd, serverPtr->inputFd, serverPtr->outputFd, display);
     463                    FreeArgs(cmd);
     464                    //closelog();
    657465                    /* Replace the current process with the render server. */
    658466                    execvp(serverPtr->cmdArgs[0], serverPtr->cmdArgs);
    659                     ERROR("Can't execute \"%s\": %s", cmd, strerror(errno));
    660                     Tcl_Free(cmd);
     467                    ERROR("Can't execute \"%s\": %s", serverPtr->cmdArgs[0],
     468                          strerror(errno));
    661469                    exit(1);
    662470                }
  • nanoscale/trunk/start_nanoscale.sh.in

    r6267 r6571  
    2929
    3030# Start a window manager so geovis doesn't crash
    31 pgrep -u rappture -x twm > /dev/null || twm -display :0 &
     31#pgrep -u rappture -x twm > /dev/null || twm -display :0 &
    3232
    3333exec ${bindir}/nanoscale -x ${numVideo}
Note: See TracChangeset for help on using the changeset viewer.