static AP_Result tcl_eval0(AP_World *w, AP_Obj interp_name, AP_Obj command, AP_Obj result, EvalOption option) { Tcl_Interp *interp; Tcl_Obj *tcl_command, *eval_string; int r; interp = GetInterp(w, interp_name); if (!interp) return AP_EXCEPTION; tcl_command = PrologToTclObj(w, command, interp); Tcl_IncrRefCount(tcl_command); if (option == arg_list) { eval_string = Tcl_NewStringObj((char *)"eval", -1); if (!tcl_command || !eval_string) { return AP_SetStandardError(w, AP_RESOURCE_ERROR, AP_NewSymbolFromStr(w, "tcl_memory")); } Tcl_ListObjReplace(interp, tcl_command, 0, 0, 1, &eval_string); } r = Tcl_EvalObj(interp, tcl_command); Tcl_DecrRefCount(tcl_command); /* Hack to refresh result */ PI_getan(&result.p, &result.t, 3); return TclToPrologResult(w, &result, interp, r); }
static LDAP_SetErrorCode(LDAPTCL *ldaptcl, int code, Tcl_Interp *interp) { char shortbuf[16]; char *errp; int lderrno; if (code == -1) code = ldap_get_lderrno(ldaptcl->ldap); if ((ldaptcl->flags & LDAPTCL_INTERRCODES) || code > LDAPTCL_MAXERR || ldaptclerrorcode[code] == NULL) { sprintf(shortbuf, "0x%03x", code); errp = shortbuf; } else errp = ldaptclerrorcode[code]; Tcl_SetErrorCode(interp, errp, NULL); if (ldaptcl->trapCmdObj) { int *i; Tcl_Obj *cmdObj; if (ldaptcl->traplist != NULL) { for (i = ldaptcl->traplist; *i && *i != code; i++) ; if (*i == 0) return; } (void) Tcl_EvalObj(interp, ldaptcl->trapCmdObj); } }
/************************************************************************* * FUNCTION : RPMTransaction_Set::RPM_callback * * ARGUMENTS : none * * RETURNS : TCL_OK or TCL_ERROR * * EXCEPTIONS : none * * PURPOSE : Set or get problem mask flags * *************************************************************************/ void *RPMTransaction_Set::RPM_callback( const void * h, const rpmCallbackType what, const unsigned long amount, const unsigned long total, fnpyKey key ) { // Build up the list of call back bits Tcl_Obj *bitstring = Tcl_NewObj(); for (unsigned i = 0; i < sizeof(bits)/sizeof(bits[0]); ++i) { if (what & bits[i].bit) { Tcl_ListObjAppendElement(_interp,bitstring,Tcl_NewStringObj(bits[i].msg,-1)); } } RPMHeader_Obj *hdr = (RPMHeader_Obj *)key; Tcl_Obj *cmd[] = { Tcl_NewStringObj("::RPM::Callback",-1), bitstring, Tcl_NewLongObj(amount), Tcl_NewLongObj(total), hdr?hdr->Get_obj():Tcl_NewObj() }; Tcl_Obj *script = Tcl_NewListObj(sizeof(cmd)/sizeof(cmd[0]),cmd); Tcl_IncrRefCount(script); Tcl_EvalObj(_interp,script); Tcl_DecrRefCount(script); // Now, handle any special operations here if (what & RPMCALLBACK_INST_OPEN_FILE) { assert(hdr); FD_t fd = hdr->Open(); if (!fd || Ferror(fd)) { if (fd) { Fclose(fd); fd = 0; } } return (void *)fd; } if (what & RPMCALLBACK_INST_CLOSE_FILE) { assert(hdr); hdr->Close(); return 0; } return 0; }
/************************************************************************* * FUNCTION : RPMTransaction_Set::Solve * * ARGUMENTS : transaction set, key, this in disguise * * RETURNS : -1 (retry), 0 (ignore), 1 (not found) * * EXCEPTIONS : none * * PURPOSE : Solve an install problem * *************************************************************************/ int RPMTransaction_Set::Solve(rpmds key) { // Throw the key over to TCL. Tcl_Obj *cmd[] = { Tcl_NewStringObj("::RPM::Solve",-1), Tcl_NewStringObj(Tcl_GetCommandName(_interp, me),-1), RPMDependency_Obj::Create_from_ds(key) }; Tcl_Obj *script = Tcl_NewListObj(sizeof(cmd)/sizeof(cmd[0]),cmd); Tcl_IncrRefCount(script); Tcl_EvalObj(_interp,script); Tcl_DecrRefCount(script); // Now get the return value Tcl_Obj *result = Tcl_GetObjResult(_interp); int rv = 0; Tcl_GetIntFromObj(_interp,result,&rv); return rv; }
/* ** Called for each row of the result. ** ** This version is used when either of the following is true: ** ** (1) This version of TCL uses UTF-8 and the data in the ** SQLite database is already in the UTF-8 format. ** ** (2) This version of TCL uses ISO8859 and the data in the ** SQLite database is already in the ISO8859 format. */ static int DbEvalCallback( void *clientData, /* An instance of CallbackData */ int nCol, /* Number of columns in the result */ char ** azCol, /* Data for each column */ char ** azN /* Name for each column */ ){ CallbackData *cbData = (CallbackData*)clientData; int i, rc; if( azCol==0 || (cbData->once && cbData->zArray[0]) ){ Tcl_SetVar2(cbData->interp, cbData->zArray, "*", "", 0); for(i=0; i<nCol; i++){ Tcl_SetVar2(cbData->interp, cbData->zArray, "*", azN[i], TCL_LIST_ELEMENT|TCL_APPEND_VALUE); if( azN[nCol] ){ char *z = sqlite_mprintf("typeof:%s", azN[i]); Tcl_SetVar2(cbData->interp, cbData->zArray, z, azN[i+nCol], TCL_LIST_ELEMENT|TCL_APPEND_VALUE); sqlite_freemem(z); } } cbData->once = 0; } if( azCol!=0 ){ if( cbData->zArray[0] ){ for(i=0; i<nCol; i++){ char *z = azCol[i]; if( z==0 ) z = ""; Tcl_SetVar2(cbData->interp, cbData->zArray, azN[i], z, 0); } }else{ for(i=0; i<nCol; i++){ char *z = azCol[i]; if( z==0 ) z = ""; Tcl_SetVar(cbData->interp, azN[i], z, 0); } } } rc = Tcl_EvalObj(cbData->interp, cbData->pCode); if( rc==TCL_CONTINUE ) rc = TCL_OK; cbData->tcl_rc = rc; return rc!=TCL_OK; }
/* ** Called for each row of the result. ** ** This version is used when TCL expects UTF-8 data but the database ** uses the ISO8859 format. A translation must occur from ISO8859 into ** UTF-8. */ static int DbEvalCallback( void *clientData, /* An instance of CallbackData */ int nCol, /* Number of columns in the result */ char ** azCol, /* Data for each column */ char ** azN /* Name for each column */ ){ CallbackData *cbData = (CallbackData*)clientData; int i, rc; Tcl_DString dCol; Tcl_DStringInit(&dCol); if( cbData->azColName==0 ){ assert( cbData->once ); cbData->once = 0; if( cbData->zArray[0] ){ Tcl_SetVar2(cbData->interp, cbData->zArray, "*", "", 0); } cbData->azColName = malloc( nCol*sizeof(char*) ); if( cbData->azColName==0 ){ return 1; } cbData->nColName = nCol; for(i=0; i<nCol; i++){ Tcl_ExternalToUtfDString(NULL, azN[i], -1, &dCol); cbData->azColName[i] = malloc( Tcl_DStringLength(&dCol) + 1 ); if( cbData->azColName[i] ){ strcpy(cbData->azColName[i], Tcl_DStringValue(&dCol)); }else{ return 1; } if( cbData->zArray[0] ){ Tcl_SetVar2(cbData->interp, cbData->zArray, "*", Tcl_DStringValue(&dCol), TCL_LIST_ELEMENT|TCL_APPEND_VALUE); if( azN[nCol]!=0 ){ Tcl_DString dType; Tcl_DStringInit(&dType); Tcl_DStringAppend(&dType, "typeof:", -1); Tcl_DStringAppend(&dType, Tcl_DStringValue(&dCol), -1); Tcl_DStringFree(&dCol); Tcl_ExternalToUtfDString(NULL, azN[i+nCol], -1, &dCol); Tcl_SetVar2(cbData->interp, cbData->zArray, Tcl_DStringValue(&dType), Tcl_DStringValue(&dCol), TCL_LIST_ELEMENT|TCL_APPEND_VALUE); Tcl_DStringFree(&dType); } } Tcl_DStringFree(&dCol); } } if( azCol!=0 ){ if( cbData->zArray[0] ){ for(i=0; i<nCol; i++){ char *z = azCol[i]; if( z==0 ) z = ""; Tcl_DStringInit(&dCol); Tcl_ExternalToUtfDString(NULL, z, -1, &dCol); Tcl_SetVar2(cbData->interp, cbData->zArray, cbData->azColName[i], Tcl_DStringValue(&dCol), 0); Tcl_DStringFree(&dCol); } }else{ for(i=0; i<nCol; i++){ char *z = azCol[i]; if( z==0 ) z = ""; Tcl_DStringInit(&dCol); Tcl_ExternalToUtfDString(NULL, z, -1, &dCol); Tcl_SetVar(cbData->interp, cbData->azColName[i], Tcl_DStringValue(&dCol), 0); Tcl_DStringFree(&dCol); } } } rc = Tcl_EvalObj(cbData->interp, cbData->pCode); if( rc==TCL_CONTINUE ) rc = TCL_OK; cbData->tcl_rc = rc; return rc!=TCL_OK; }
void start_tcl(void) { char *id = "start_tcl"; char buf[BUFSIZ]; int fd; int tot, len; interp = Tcl_CreateInterp(); if (Tcl_Init(interp) == TCL_ERROR) { sprintf(log_buffer, "Tcl_Init error: %s", Tcl_GetStringResult(interp)); log_err(-1, id, log_buffer); die(0); } #if TCLX #if TCL_MINOR_VERSION < 5 && TCL_MAJOR_VERSION < 8 if (TclX_Init(interp) == TCL_ERROR) { #else if (Tclx_Init(interp) == TCL_ERROR) { #endif sprintf(log_buffer, "Tclx_Init error: %s", Tcl_GetStringResult(interp)); log_err(-1, id, log_buffer); die(0); } #endif add_cmds(interp); if (initfil) { int code; code = Tcl_EvalFile(interp, initfil); if (code != TCL_OK) { char *trace; trace = (char *)Tcl_GetVar(interp, "errorInfo", 0); if (trace == NULL) trace = (char *)Tcl_GetStringResult(interp); fprintf(stderr, "%s: TCL error @ line %d: %s\n", initfil, interp->errorLine, trace); sprintf(log_buffer, "%s: TCL error @ line %d: %s", initfil, interp->errorLine, Tcl_GetStringResult(interp)); log_err(-1, id, log_buffer); die(0); } sprintf(log_buffer, "init file %s", initfil); log_record(PBSEVENT_SYSTEM, PBS_EVENTCLASS_SERVER, id, log_buffer); } if ((fd = open(bodyfil, O_RDONLY)) == -1) { log_err(errno, id, bodyfil); die(0); } sprintf(log_buffer, "body file: %s", bodyfil); log_record(PBSEVENT_SYSTEM, PBS_EVENTCLASS_SERVER, id, log_buffer); if (body) free(body); if ((body = malloc(BUFSIZ)) == NULL) { log_err(errno, id, "malloc"); die(0); } for (tot = 0; (len = read(fd, buf, sizeof(buf))) > 0; tot += len) { if ((body = realloc(body, tot + len + 1)) == NULL) { log_err(errno, id, "realloc"); die(0); } memcpy(&body[tot], buf, len); } if (len == -1) { log_err(errno, id, bodyfil); die(0); } body[tot] = '\0'; close(fd); #if TCL_MAJOR_VERSION >= 8 if (body_obj == NULL) { body_obj = Tcl_NewStringObj(body, tot); Tcl_IncrRefCount(body_obj); } else { Tcl_SetStringObj(body_obj, body, tot); } #endif } int addclient(name) char *name; { static char id[] = "addclient"; struct hostent *host, *gethostbyname(); struct in_addr saddr; if ((host = gethostbyname(name)) == NULL) { sprintf(log_buffer, "host %s not found", name); log_err(-1, id, log_buffer); return -1; } if (numclients >= START_CLIENTS) { pbs_net_t *newclients; newclients = realloc(okclients, sizeof(pbs_net_t) * (numclients + 1)); if (newclients == NULL) return -1; okclients = newclients; } memcpy((char *)&saddr, host->h_addr, host->h_length); okclients[numclients++] = saddr.s_addr; return 0; } /* * read_config - read and process the configuration file (see -c option) * * Currently, the only statement is $clienthost to specify which systems * can contact the scheduler. */ #define CONF_LINE_LEN 120 static int read_config(file) char *file; { static char *id = "read_config"; FILE *conf; int i; char line[CONF_LINE_LEN]; char *token; struct specialconfig { char *name; int (*handler)(); } special[] = { {"clienthost", addclient }, { NULL, NULL } }; #if !defined(DEBUG) && !defined(NO_SECURITY_CHECK) if (chk_file_sec(file, 0, 0, S_IWGRP | S_IWOTH, 1, 0)) return (-1); #endif if ((conf = fopen(file, "r")) == NULL) { log_err(errno, id, "cannot open config file"); return (-1); } while (fgets(line, CONF_LINE_LEN, conf)) { if ((line[0] == '#') || (line[0] == '\n')) continue; /* ignore comment & null line */ else if (line[0] == '$') /* special */ { if ((token = strtok(line, " \t")) == NULL) token = ""; for (i = 0; special[i].name; i++) { if (strcmp(token + 1, special[i].name) == 0) break; } if (special[i].name == NULL) { sprintf(log_buffer, "config name %s not known", token); log_record(PBSEVENT_ERROR, PBS_EVENTCLASS_SERVER, msg_daemonname, log_buffer); return (-1); } token = strtok(NULL, " \t"); if (*(token + strlen(token) - 1) == '\n') *(token + strlen(token) - 1) = '\0'; if (special[i].handler(token)) { fclose(conf); return (-1); } } else { log_record(PBSEVENT_ERROR, PBS_EVENTCLASS_SERVER, msg_daemonname, "invalid line in config file"); fclose(conf); return (-1); } } fclose(conf); return (0); } void restart(sig) int sig; { char *id = "restart"; if (sig) { sprintf(log_buffer, "restart on signal %d", sig); log_close(1); log_open(logfile, path_log); } else { sprintf(log_buffer, "restart command"); } log_record(PBSEVENT_SYSTEM, PBS_EVENTCLASS_SERVER, id, log_buffer); Tcl_DeleteInterp(interp); if (configfile) { if (read_config(configfile) != 0) die(0); } start_tcl(); } void badconn(msg) char *msg; { static char id[] = "badconn"; struct in_addr addr; char buf[5*sizeof(addr) + 100]; struct hostent *phe; addr = saddr.sin_addr; phe = gethostbyaddr((void *) & addr, sizeof(addr), AF_INET); if (phe == NULL) { char hold[6]; int i; union { struct in_addr aa; u_char bb[sizeof(addr)]; } uu; uu.aa = addr; sprintf(buf, "%u", uu.bb[0]); for (i = 1; i < (int)sizeof(addr); i++) { sprintf(hold, ".%u", uu.bb[i]); strcat(buf, hold); } } else { strncpy(buf, phe->h_name, sizeof(buf)); buf[sizeof(buf)-1] = '\0'; } sprintf(log_buffer, "%s on port %u %s", buf, ntohs(saddr.sin_port), msg); log_err(-1, id, log_buffer); return; } unsigned int server_command() { static char id[] = "server_command"; int new_socket; int i; torque_socklen_t slen; unsigned int cmd; pbs_net_t addr; slen = sizeof(saddr); new_socket = accept(server_sock, (struct sockaddr *) & saddr, &slen); if (new_socket == -1) { log_err(errno, id, "accept"); return SCH_ERROR; } if (ntohs(saddr.sin_port) >= IPPORT_RESERVED) { badconn("non-reserved port"); close(new_socket); return SCH_ERROR; } addr = (pbs_net_t)saddr.sin_addr.s_addr; for (i = 0; i < numclients; i++) { if (addr == okclients[i]) break; } if (i == numclients) { badconn("unauthorized host"); close(new_socket); return SCH_ERROR; } if ((connector = socket_to_conn(new_socket)) < 0) { log_err(errno, id, "socket_to_conn"); return SCH_ERROR; } if (get_4byte(new_socket, &cmd) != 1) { log_err(errno, id, "get4bytes"); return SCH_ERROR; } return cmd; } /* * lock_out - lock out other daemons from this directory. */ static void lock_out(fds, op) int fds; int op; /* F_WRLCK or F_UNLCK */ { struct flock flock; flock.l_type = op; flock.l_whence = SEEK_SET; flock.l_start = 0; flock.l_len = 0; /* whole file */ if (fcntl(fds, F_SETLK, &flock) < 0) { (void)strcpy(log_buffer, "pbs_sched: another scheduler running\n"); log_err(errno, msg_daemonname, log_buffer); fprintf(stderr, log_buffer); exit(1); } } int main(argc, argv) int argc; char *argv[]; { char *id = "main"; int code; struct hostent *hp; int go, c, errflg = 0; int lockfds; int t = 1; char *ptr; pid_t pid; char *cp, host[100]; char *homedir = PBS_SERVER_HOME; unsigned int port; char path_priv[_POSIX_PATH_MAX]; char *dbfile = "sched_out"; int alarm_time = 180; struct sigaction act; caddr_t curr_brk = 0, next_brk; extern char *optarg; extern int optind, opterr; fd_set fdset; #ifndef DEBUG if (IamRoot() == 0) { return (1); } #endif /* DEBUG */ glob_argv = argv; if ((cp = strrchr(argv[0], '/')) == NULL) cp = argv[0]; else cp++; msg_daemonname = strdup(cp); port = get_svrport(PBS_SCHEDULER_SERVICE_NAME, "tcp", PBS_SCHEDULER_SERVICE_PORT); while ((c = getopt(argc, argv, "L:S:d:i:b:t:p:a:vc:")) != EOF) { switch (c) { case 'L': logfile = optarg; break; case 'S': port = (unsigned int)atoi(optarg); if (port == 0) { fprintf(stderr, "%s: illegal port\n", optarg); errflg = 1; } break; case 'd': homedir = optarg; break; case 'i': /* initialize */ initfil = optarg; break; case 'b': bodyfil = optarg; break; case 't': termfil = optarg; break; case 'p': dbfile = optarg; break; case 'a': alarm_time = strtol(optarg, &ptr, 10); if (alarm_time <= 0 || *ptr != '\0') { fprintf(stderr, "%s: bad alarm time\n", optarg); errflg = 1; } break; case 'c': configfile = optarg; break; case 'v': verbose = 1; break; case '?': errflg = 1; break; } } if (errflg || optind != argc) { static char *options[] = { "[-L logfile]", "[-S port]", "[-d home]", "[-i init]", "[-b body]", "[-t term]", "[-p output]", "[-a alarm]", "[-c configfile]", "[-v]", NULL }; int i; fprintf(stderr, "usage: %s\n", argv[0]); for (i = 0; options[i]; i++) fprintf(stderr, "\t%s\n", options[i]); exit(1); } /* Save the original working directory for "restart" */ if ((oldpath = getcwd((char *)NULL, MAXPATHLEN)) == NULL) { fprintf(stderr, "cannot get current working directory\n"); exit(1); } (void)sprintf(path_priv, "%s/sched_priv", homedir); #if !defined(DEBUG) && !defined(NO_SECURITY_CHECK) c = chk_file_sec(path_priv, 1, 0, S_IWGRP | S_IWOTH, 1, 0); c |= chk_file_sec(PBS_ENVIRON, 0, 0, S_IWGRP | S_IWOTH, 0, 0); if (c != 0) exit(1); #endif /* not DEBUG and not NO_SECURITY_CHECK */ if (chdir(path_priv) == -1) { perror(path_priv); exit(1); } (void)sprintf(path_log, "%s/sched_logs", homedir); (void)strcpy(pbs_current_user, "Scheduler"); /* The following is code to reduce security risks */ /* start out with standard umask, system resource limit infinite */ umask(022); if (setup_env(PBS_ENVIRON) == -1) exit(1); c = getgid(); (void)setgroups(1, (gid_t *)&c); /* secure suppl. group ids */ c = sysconf(_SC_OPEN_MAX); while (--c > 2) (void)close(c); /* close any file desc left open by parent */ #ifndef DEBUG #ifdef _CRAY (void)limit(C_JOB, 0, L_CPROC, 0); (void)limit(C_JOB, 0, L_CPU, 0); (void)limit(C_JOBPROCS, 0, L_CPU, 0); (void)limit(C_PROC, 0, L_FD, 255); (void)limit(C_JOB, 0, L_FSBLK, 0); (void)limit(C_JOBPROCS, 0, L_FSBLK, 0); (void)limit(C_JOB, 0, L_MEM , 0); (void)limit(C_JOBPROCS, 0, L_MEM , 0); #else /* not _CRAY */ { struct rlimit rlimit; rlimit.rlim_cur = RLIM_INFINITY; rlimit.rlim_max = RLIM_INFINITY; (void)setrlimit(RLIMIT_CPU, &rlimit); (void)setrlimit(RLIMIT_FSIZE, &rlimit); (void)setrlimit(RLIMIT_DATA, &rlimit); (void)setrlimit(RLIMIT_STACK, &rlimit); #ifdef RLIMIT_RSS (void)setrlimit(RLIMIT_RSS , &rlimit); #endif /* RLIMIT_RSS */ #ifdef RLIMIT_VMEM (void)setrlimit(RLIMIT_VMEM , &rlimit); #endif /* RLIMIT_VMEM */ } #endif /* not _CRAY */ #if !defined(NO_SECURITY_CHECK) c = 0; if (initfil) { if (*initfil != '/') { (void)sprintf(log_buffer, "%s/%s", path_priv, initfil); c |= chk_file_sec(log_buffer, 0, 0, S_IWGRP | S_IWOTH, 1, 0); } else { c |= chk_file_sec(initfil, 0, 0, S_IWGRP | S_IWOTH, 1, 0); } } if (bodyfil) { if (*bodyfil != '/') { (void)sprintf(log_buffer, "%s/%s", path_priv, bodyfil); c |= chk_file_sec(log_buffer, 0, 0, S_IWGRP | S_IWOTH, 1, 0); } else { c |= chk_file_sec(bodyfil, 0, 0, S_IWGRP | S_IWOTH, 1, 0); } } if (termfil) { if (*termfil != '/') { (void)sprintf(log_buffer, "%s/%s", path_priv, termfil); c |= chk_file_sec(log_buffer, 0, 0, S_IWGRP | S_IWOTH, 1, 0); } else { c |= chk_file_sec(termfil, 0, 0, S_IWGRP | S_IWOTH, 1, 0); } } if (c) exit(1); #endif /* not NO_SECURITY_CHECK */ #endif /* not DEBUG */ if (log_open(logfile, path_log) == -1) { fprintf(stderr, "%s: logfile could not be opened\n", argv[0]); exit(1); } if (gethostname(host, sizeof(host)) == -1) { char *prob = "gethostname"; log_err(errno, id, prob); perror(prob); die(0); } if ((hp = gethostbyname(host)) == NULL) { char *prob = "gethostbyname"; log_err(errno, id, prob); perror(prob); die(0); } if ((server_sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { char *prob = "socket"; log_err(errno, id, prob); perror(prob); die(0); } if (setsockopt(server_sock, SOL_SOCKET, SO_REUSEADDR, (char *)&t, sizeof(t)) == -1) { char *prob = "setsockopt"; log_err(errno, id, prob); perror(prob); die(0); } saddr.sin_family = AF_INET; saddr.sin_port = htons((unsigned short)port); memcpy(&saddr.sin_addr, hp->h_addr, hp->h_length); if (bind(server_sock, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) { char *prob = "bind"; log_err(errno, id, prob); perror(prob); die(0); } if (listen(server_sock, 5) < 0) { char *prob = "listen"; log_err(errno, id, prob); perror(prob); die(0); } okclients = (pbs_net_t *)calloc(START_CLIENTS, sizeof(pbs_net_t)); addclient("localhost"); /* who has permission to call MOM */ addclient(host); if (configfile) { if (read_config(configfile) != 0) die(0); } lockfds = open("sched.lock", O_CREAT | O_TRUNC | O_WRONLY, 0644); if (lockfds < 0) { char *prob = "lock file"; log_err(errno, id, prob); perror(prob); die(0); } lock_out(lockfds, F_WRLCK); #ifndef DEBUG lock_out(lockfds, F_UNLCK); if ((pid = fork()) == -1) /* error on fork */ { char *prob = "fork"; log_err(errno, id, prob); perror(prob); die(0); } else if (pid > 0) /* parent exits */ exit(0); if ((pid = setsid()) == -1) { log_err(errno, id, "setsid"); die(0); } lock_out(lockfds, F_WRLCK); freopen(dbfile, "a", stdout); setvbuf(stdout, NULL, _IOLBF, 0); dup2(fileno(stdout), fileno(stderr)); #else pid = getpid(); setvbuf(stdout, NULL, _IOLBF, 0); setvbuf(stderr, NULL, _IOLBF, 0); #endif freopen("/dev/null", "r", stdin); /* write schedulers pid into lockfile */ (void)sprintf(log_buffer, "%d\n", pid); (void)write(lockfds, log_buffer, strlen(log_buffer) + 1); #if (PLOCK_DAEMONS & 2) (void)plock(PROCLOCK); /* lock daemon into memory */ #endif sprintf(log_buffer, "%s startup pid %d", argv[0], pid); log_record(PBSEVENT_SYSTEM, PBS_EVENTCLASS_SERVER, id, log_buffer); sprintf(log_buffer, "%s using TCL %s (%s)", argv[0], TCL_VERSION, TCL_PATCH_LEVEL); fprintf(stderr, "%s\n", log_buffer); log_record(PBSEVENT_SYSTEM, PBS_EVENTCLASS_SERVER, id, log_buffer); fullresp(0); sigemptyset(&allsigs); act.sa_flags = 0; sigaddset(&allsigs, SIGHUP); /* remember to block these */ sigaddset(&allsigs, SIGINT); /* during critical sections */ sigaddset(&allsigs, SIGTERM); /* so we don't get confused */ act.sa_mask = allsigs; act.sa_handler = restart; /* do a restart on SIGHUP */ sigaction(SIGHUP, &act, NULL); act.sa_handler = toolong; /* handle an alarm call */ sigaction(SIGALRM, &act, NULL); act.sa_handler = die; /* bite the biscuit for all following */ sigaction(SIGINT, &act, NULL); sigaction(SIGTERM, &act, NULL); start_tcl(); FD_ZERO(&fdset); for (go = 1; go;) { unsigned int cmd; FD_SET(server_sock, &fdset); if (select(FD_SETSIZE, &fdset, NULL, NULL, NULL) == -1) { if (errno != EINTR) log_err(errno, id, "select"); continue; } if (!FD_ISSET(server_sock, &fdset)) continue; cmd = server_command(); if (cmd == (unsigned)SCH_ERROR || cmd == (unsigned)SCH_SCHEDULE_NULL) continue; if (sigprocmask(SIG_BLOCK, &allsigs, &oldsigs) == -1) log_err(errno, id, "sigprocmaskSIG_BLOCK)"); if (verbose) { sprintf(log_buffer, "command %d", cmd); log_record(PBSEVENT_SYSTEM, PBS_EVENTCLASS_SERVER, id, log_buffer); } switch (cmd) { case SCH_SCHEDULE_NEW: case SCH_SCHEDULE_TERM: case SCH_SCHEDULE_TIME: case SCH_SCHEDULE_RECYC: case SCH_SCHEDULE_CMD: case SCH_SCHEDULE_FIRST: alarm(alarm_time); #if TCL_MAJOR_VERSION >= 8 /* execute compiled body code for TCL-8 */ code = Tcl_EvalObj(interp, body_obj); #else code = Tcl_Eval(interp, body); #endif alarm(0); switch (code) { case TCL_OK: case TCL_RETURN: break; default: { char *trace; char codename[20]; switch (code) { case TCL_BREAK: strcpy(codename, "break"); break; case TCL_CONTINUE: strcpy(codename, "continue"); break; default: strcpy(codename, "<unknown>"); break; } trace = (char *)Tcl_GetVar(interp, "errorInfo", 0); if (trace == NULL) trace = (char *)Tcl_GetStringResult(interp); fprintf(stderr, "%s: TCL interpreter return code %d (%s) @ line %d: %s\n", bodyfil, code, codename, interp->errorLine, trace); sprintf(log_buffer, "%s: TCL error @ line %d: %s", bodyfil, interp->errorLine, Tcl_GetStringResult(interp)); log_err(-1, id, log_buffer); die(0); } } break; case SCH_CONFIGURE: case SCH_RULESET: restart(0); break; case SCH_QUIT: go = 0; break; default: log_err(-1, id, "unknown command"); break; } if (connector >= 0 && server_disconnect(connector)) { log_err(errno, id, "server_disconnect"); die(0); } connector = -1; if (verbose) { next_brk = (caddr_t)sbrk(0); if (next_brk > curr_brk) { sprintf(log_buffer, "brk point %p", next_brk); log_record(PBSEVENT_SYSTEM, PBS_EVENTCLASS_SERVER, id, log_buffer); curr_brk = next_brk; } } if (sigprocmask(SIG_SETMASK, &oldsigs, NULL) == -1) log_err(errno, id, "sigprocmask(SIG_SETMASK)"); } if (termfil) { code = Tcl_EvalFile(interp, termfil); if (code != TCL_OK) { char *trace; trace = (char *)Tcl_GetVar(interp, "errorInfo", 0); if (trace == NULL) trace = (char *)Tcl_GetStringResult(interp); fprintf(stderr, "%s: TCL error @ line %d: %s\n", termfil, interp->errorLine, trace); sprintf(log_buffer, "%s: TCL error @ line %d: %s", termfil, interp->errorLine, Tcl_GetStringResult(interp)); log_err(-1, id, log_buffer); die(0); } sprintf(log_buffer, "term file: %s", termfil); log_record(PBSEVENT_SYSTEM, PBS_EVENTCLASS_SERVER, id, log_buffer); } sprintf(log_buffer, "%s normal finish pid %d", argv[0], pid); log_record(PBSEVENT_SYSTEM, PBS_EVENTCLASS_SERVER, id, log_buffer); (void)close(server_sock); exit(0); }
int Extension::foreachCmd ( ClientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { if (objc != 4) { Tcl_WrongNumArgs( interp, 1, objv, "varList collectionHandle script"); return TCL_ERROR; } Tcl_Obj *pVarList = objv[1]; Tcl_Obj *pBody = objv[3]; Reference *pCollection = referenceHandles.find(interp, objv[2]); if (pCollection == 0) { const char *arg = Tcl_GetStringFromObj(objv[2], 0); Tcl_AppendResult( interp, "invalid interface pointer handle ", arg, 0); return TCL_ERROR; } // Collections should implement a _NewEnum method which returns an object // that enumerates the elements. HRESULT hr; PositionalArguments arguments; _variant_t varResult; hr = pCollection->invoke( DISPID_NEWENUM, DISPATCH_METHOD | DISPATCH_PROPERTYGET, arguments, &varResult); if (FAILED(hr) || V_VT(&varResult) != VT_UNKNOWN) { Tcl_AppendResult(interp, "object is not a collection", NULL); return TCL_ERROR; } IUnknownPtr pUnk(V_UNKNOWN(&varResult)); // Get a specific kind of enumeration. IEnumVARIANTPtr pEnumVARIANT; IEnumUnknownPtr pEnumUnknown; enum EnumKind { ENUM_VARIANT, ENUM_UNKNOWN }; EnumKind enumKind; hr = pUnk->QueryInterface( IID_IEnumVARIANT, reinterpret_cast<void **>(&pEnumVARIANT)); if (SUCCEEDED(hr)) { enumKind = ENUM_VARIANT; } else { hr = pUnk->QueryInterface( IID_IEnumUnknown, reinterpret_cast<void **>(&pEnumUnknown)); if (SUCCEEDED(hr)) { enumKind = ENUM_UNKNOWN; } } if (FAILED(hr)) { Tcl_AppendResult(interp, "Unknown enumerator type: not IEnumVARIANT or IEnumUnknown", NULL); return TCL_ERROR; } int completionCode; int varc; // number of loop variables completionCode = Tcl_ListObjLength(interp, pVarList, &varc); if (completionCode != TCL_OK) { return TCL_ERROR; } if (varc < 1) { Tcl_AppendResult(interp, "foreach varlist is empty", NULL); return TCL_ERROR; } while (true) { // If the variable list has been converted to another kind of Tcl // object, convert it back to a list and refetch the pointer to its // element array. Tcl_Obj **varv; completionCode = Tcl_ListObjGetElements(interp, pVarList, &varc, &varv); if (completionCode != TCL_OK) { return TCL_ERROR; } // Assign values to all loop variables. int v = 0; for (; v < varc; ++v) { TclObject value; ULONG count; switch (enumKind) { case ENUM_VARIANT: { _variant_t elementVar; hr = pEnumVARIANT->Next(1, &elementVar, &count); if (hr == S_OK && count > 0) { value = TclObject(&elementVar, Type::variant(), interp, 0); } } break; case ENUM_UNKNOWN: { IUnknown *pElement; hr = pEnumUnknown->Next(1, &pElement, &count); if (hr == S_OK && count > 0) { value = referenceHandles.newObj( interp, Reference::newReference(pElement)); } } break; } if (FAILED(hr)) { _com_issue_error(hr); } if (hr != S_OK || count == 0) { break; } Tcl_Obj *varValuePtr = Tcl_ObjSetVar2( interp, varv[v], NULL, value, TCL_LEAVE_ERR_MSG); if (varValuePtr == NULL) { return TCL_ERROR; } } if (v == 0) { completionCode = TCL_OK; break; } if (v < varc) { TclObject empty; for (; v < varc; ++v) { Tcl_Obj *varValuePtr = Tcl_ObjSetVar2( interp, varv[v], NULL, empty, TCL_LEAVE_ERR_MSG); if (varValuePtr == NULL) { return TCL_ERROR; } } } // Execute the script body. completionCode = #if TCL_MINOR_VERSION >= 1 Tcl_EvalObjEx(interp, pBody, 0); #else Tcl_EvalObj(interp, pBody); #endif if (completionCode == TCL_CONTINUE) { // do nothing } else if (completionCode == TCL_BREAK) { completionCode = TCL_OK; break; } else if (completionCode == TCL_ERROR) { std::ostringstream oss; oss << "\n (\"foreach\" body line %d)" << interp->errorLine; Tcl_AddObjErrorInfo( interp, const_cast<char *>(oss.str().c_str()), -1); break; } else if (completionCode != TCL_OK) { break; } } if (completionCode == TCL_OK) { Tcl_ResetResult(interp); } return completionCode; }