int main(int argc, char* argv[]) { int rcErrors = 0; /* * Initialize the runtime. */ RTR3InitExe(argc, &argv, RTR3INIT_FLAGS_SUPLIB); #ifndef AUTO_TEST_ARGS if (argc < 2) { RTPrintf("syntax: %s command [args]\n" "\n" "command Command to run under child process in fork.\n" "[args] Arguments to command.\n", argv[0]); return 1; } #endif /* * Create empty VM. */ RTPrintf(TESTCASE ": Initializing...\n"); PVM pVM; int rc = VMR3Create(1, NULL, NULL, NULL, NULL, NULL, &pVM); if (RT_SUCCESS(rc)) { /* * Do testing. */ int iCowTester = 0; char cCowTester = 'a'; #ifndef AUTO_TEST_ARGS int cArgs = argc - 1; char **ppszArgs = &argv[1]; #else int cArgs = 2; char *ppszArgs[3]; ppszArgs[0] = (char *)"/bin/sleep"; ppszArgs[1] = (char *)"3"; ppszArgs[2] = NULL; #endif RTPrintf(TESTCASE ": forking current process...\n"); pid_t pid = fork(); if (pid < 0) { /* Bad. fork() failed! */ RTPrintf(TESTCASE ": error: fork() failed.\n"); rcErrors++; } else if (pid == 0) { /* * The child process. * Write to some local variables to trigger copy-on-write if it's used. */ RTPrintf(TESTCASE ": running child process...\n"); RTPrintf(TESTCASE ": writing local variables...\n"); iCowTester = 2; cCowTester = 'z'; RTPrintf(TESTCASE ": calling execv() with command-line:\n"); for (int i = 0; i < cArgs; i++) RTPrintf(TESTCASE ": ppszArgs[%d]=%s\n", i, ppszArgs[i]); execv(ppszArgs[0], ppszArgs); RTPrintf(TESTCASE ": error: execv() returned to caller. errno=%d.\n", errno); _exit(-1); } else { /* * The parent process. * Wait for child & run VMM test to ensure things are fine. */ int result; while (waitpid(pid, &result, 0) < 0) ; if (!WIFEXITED(result) || WEXITSTATUS(result) != 0) { RTPrintf(TESTCASE ": error: failed to run child process. errno=%d\n", errno); rcErrors++; } if (rcErrors == 0) { RTPrintf(TESTCASE ": fork() returned fine.\n"); RTPrintf(TESTCASE ": testing VM after fork.\n"); VMR3ReqCallWait(pVM, VMCPUID_ANY, (PFNRT)VMMDoTest, 1, pVM); STAMR3Dump(pVM, "*"); } } if (rcErrors > 0) RTPrintf(TESTCASE ": error: %d error(s) during fork(). Cannot proceed to test the VM.\n"); else RTPrintf(TESTCASE ": fork() and VM test, SUCCESS.\n"); /* * Cleanup. */ rc = VMR3PowerOff(pVM); if (!RT_SUCCESS(rc)) { RTPrintf(TESTCASE ": error: failed to power off vm! rc=%Rrc\n", rc); rcErrors++; } rc = VMR3Destroy(pVM); if (!RT_SUCCESS(rc)) { RTPrintf(TESTCASE ": error: failed to destroy vm! rc=%Rrc\n", rc); rcErrors++; } } else { RTPrintf(TESTCASE ": fatal error: failed to create vm! rc=%Rrc\n", rc); rcErrors++; } return rcErrors; }
int main(int argc, char* argv[]) { pid_t pid; char dummy[16]; if (argc < 2) { printf("You need to specify a program as argument 1.\n"); exit(1); /* Terminate the process with error (1). */ } printf("P | Switch to a differen terminal.\n" "P | Execute the command \"ptree $USER\".\n" "P | It will show a list of processes you are running.\n" "P | You should see the process '%s' once.\n" "P | Press enter when you verified that.\n\n", argv[0]); /* Wait until enter is pressed (gives you time...) */ fgets(dummy, 16, stdin); printf("P | This process will now clone itself with fork.\n" "P | One (almost) identical copy will be started.\n" "P | The only difference is the result of fork()\n\n"); pid = fork(); if (pid == 0) { printf(" C | This is printed by the new process (the CHILD)\n" " C | The child get a 0 return value from fork.\n\n"); printf(" C | Repeat the previous command in the other terminal.\n" " C | You should see the process '%s' twice now.\n" " C | (grep for it if you run many processes)\n" " C | Press enter when you verified that.\n\n", argv[0]); /* Wait until enter is pressed (gives you time...) */ fgets(dummy, 16, stdin); printf(" C | The program specified as first argument (%s) on the \n" " C | command line will now be started by the child process.\n" " C | This will REPLACE the code of the child with the code\n" " C | of the specified program.\n\n", argv[1]); /* specify a terminal as argument 1 and check ptree again ... * you will see that the child is replaced, it have the same * process number, but a new command line */ execv(argv[1], argv + 1); printf(" C | This will never be printed, since after starting the new\n" " C | program by calling exec this old program is replaced by\n" " C | the new. This is only printed if the new program could not\n" " C | be started for some reason.\n\n"); exit(-1); /* Terminate the child with error (-1). */ } else { int ret = 0; /* Used to save the result of the child. */ printf("P | This is printed by the origingal process (the PARENT)\n" "P | It got the number (%d) from fork to identify the child.\n" "P | This process will now work for 5 seconds.\n\n", (int)pid); sleep(5); /* pretend */ printf("P | This is printed by the origingal process (the PARENT)\n" "P | It got the number (%d) from fork to identify the child.\n" "P | It is now used to wait for the result of that child\n\n", (int)pid); /* Wait for the child to finish and get it's status in ret. */ waitpid(pid, &ret, 0); /* Print the exit status of the child. */ if (WIFEXITED(ret)) { printf("P | Child finished with code %d\n\n", WEXITSTATUS(ret)); } else if (WIFSIGNALED(ret)) { printf("P | Child finished due to signal %d\n\n", WTERMSIG(ret)); } } return 0; }
static int init_compile( int what_todo, /* do a compile or clean */ char *base_dir, /* base directory of the test */ char *hname) /* hostname of the machine */ { int status; /* return status of execve process */ pid_t pid; /* pid of the process that does compile */ char *dirname; /* location where compile is initated */ char *command; /* make or make clean command. */ if ((dirname = malloc(sizeof(char) * 1024)) == NULL) /* just paranoid */ { perror("init_compile(): dirname malloc()"); return 1; } if ((command = malloc(1024)) == NULL) /* just paranoid */ { perror("init_compile(): dirname malloc()"); return 1; } what_todo ? sprintf(command, "make -s") : sprintf(command, "make -s clean"); sprintf(dirname, "%s/%s.%ld", base_dir, hname, gettid()); if (chdir(dirname) == -1) { dprt("pid[%d]: init_compile(): dir name = %s\n", gettid(), dirname); perror("init_compile() chdir()"); free(dirname); return 1; } dprt("pid[%d]: init_compile(): command = %s\n", gettid(), command); if ((pid = fork()) == -1) { perror("init_compile(): fork()"); return 1; } if (!pid) { char *argv[4]; char *envp[1]; argv[0] = "/bin/sh"; argv[1] = "-c"; argv[2] = command; argv[3] = 0; if (execv("/bin/sh", argv) == -1) { perror("init_compile(): execv()"); return 1; } } do { if (waitpid(pid, &status, 0) == -1) { if (errno != EINTR) { fprintf(stderr, "init_compile(): waitpid() failed\n"); return 1; } } else { if (chdir(base_dir) == -1) { dprt("pid[%d]: init_compile(): dir = %s\n", gettid(), dirname); perror("init_compile(): chdir()"); return 1; } dprt("pid[%d]: init_compile(): status = %d\n", status); dprt("we are here %d\n", __LINE__); return status; } } while(1); }
static int _StartBatch(MessageHandler *handler, char *name, char *param) { int pid; int pDBR[2], pDBW[2]; char line[SIZE_BUFF], **cmd; int rc; int pAPR[2], pAPW[2]; if (handler->loadpath == NULL) { handler->loadpath = ExecPath; } signal(SIGPIPE, SignalHandler); if (LibPath == NULL) { ExecPath = getenv("APS_EXEC_PATH"); } else { ExecPath = LibPath; } if (pipe(pAPR) != 0) { perror("pipe"); exit(1); } if (pipe(pAPW) != 0) { perror("pipe"); exit(1); } if (pipe(pDBR) != 0) { perror("pipe"); exit(1); } if (pipe(pDBW) != 0) { perror("pipe"); exit(1); } ExpandStart(line, handler->start, handler->loadpath, name, param); cmd = ParCommandLine(line); if (setjmp(SubError) == 0) { if ((pid = fork()) == 0) { dup2(pAPW[0], STDIN_FILENO); dup2(pAPR[1], STDOUT_FILENO); close(pAPW[0]); close(pAPW[1]); close(pAPR[0]); close(pAPR[1]); dup2(pDBW[0], DBIN_FILENO); dup2(pDBR[1], DBOUT_FILENO); close(pDBW[0]); close(pDBW[1]); close(pDBR[0]); close(pDBR[1]); execv(cmd[0], cmd); } else { close(pAPR[1]); close(pAPW[0]); fpDBR = FileToNet(pDBR[0]); close(pDBR[1]); fpDBW = FileToNet(pDBW[1]); close(pDBW[0]); StartDB(handler); } (void)wait(&pid); CancelDB(); CloseNet(fpDBW); CloseNet(fpDBR); rc = TRUE; } else { rc = FALSE; } return (rc); }
int main(int argc, char **argv) { char *me = argv[0]; char *lslash = strrchr(me, '/'); char root[1024]; int port = grpc_pick_unused_port_or_die(); char *args[10]; int status; pid_t svr, cli; /* seed rng with pid, so we don't end up with the same random numbers as a concurrently running test binary */ srand((unsigned)getpid()); /* figure out where we are */ if (lslash) { memcpy(root, me, (size_t)(lslash - me)); root[lslash - me] = 0; } else { strcpy(root, "."); } /* start the server */ svr = fork(); if (svr == 0) { gpr_asprintf(&args[0], "%s/fling_server", root); args[1] = "--bind"; gpr_join_host_port(&args[2], "::", port); args[3] = "--no-secure"; args[4] = 0; execv(args[0], args); gpr_free(args[0]); gpr_free(args[2]); return 1; } /* wait a little */ sleep(2); /* start the client */ cli = fork(); if (cli == 0) { gpr_asprintf(&args[0], "%s/fling_client", root); args[1] = "--target"; gpr_join_host_port(&args[2], "127.0.0.1", port); args[3] = "--scenario=ping-pong-stream"; args[4] = "--no-secure"; args[5] = 0; execv(args[0], args); gpr_free(args[0]); gpr_free(args[2]); return 1; } /* wait for completion */ printf("waiting for client\n"); if (waitpid(cli, &status, 0) == -1) return 2; if (!WIFEXITED(status)) return 4; if (WEXITSTATUS(status)) return WEXITSTATUS(status); printf("waiting for server\n"); kill(svr, SIGINT); if (waitpid(svr, &status, 0) == -1) return 2; if (!WIFEXITED(status)) return 4; if (WEXITSTATUS(status)) return WEXITSTATUS(status); return 0; }
gboolean g_spawn_command_line_sync (const gchar *command_line, gchar **standard_output, gchar **standard_error, gint *exit_status, GError **error) { #ifdef G_OS_WIN32 #else pid_t pid; gchar **argv; gint argc; int stdout_pipe [2] = { -1, -1 }; int stderr_pipe [2] = { -1, -1 }; int status; int res; if (!g_shell_parse_argv (command_line, &argc, &argv, error)) return FALSE; if (standard_output && !create_pipe (stdout_pipe, error)) return FALSE; if (standard_error && !create_pipe (stderr_pipe, error)) { if (standard_output) { CLOSE_PIPE (stdout_pipe); } return FALSE; } pid = fork (); if (pid == 0) { gint i; if (standard_output) { close (stdout_pipe [0]); dup2 (stdout_pipe [1], STDOUT_FILENO); } if (standard_error) { close (stderr_pipe [0]); dup2 (stderr_pipe [1], STDERR_FILENO); } for (i = getdtablesize () - 1; i >= 3; i--) close (i); /* G_SPAWN_SEARCH_PATH is always enabled for g_spawn_command_line_sync */ if (!g_path_is_absolute (argv [0])) { gchar *arg0; arg0 = g_find_program_in_path (argv [0]); if (arg0 == NULL) { exit (1); } //g_free (argv [0]); argv [0] = arg0; } execv (argv [0], argv); exit (1); /* TODO: What now? */ } g_strfreev (argv); if (standard_output) close (stdout_pipe [1]); if (standard_error) close (stderr_pipe [1]); if (standard_output || standard_error) { res = read_pipes (stdout_pipe [0], standard_output, stderr_pipe [0], standard_error, error); if (res) { waitpid (pid, &status, WNOHANG); /* avoid zombie */ return FALSE; } } NO_INTR (res, waitpid (pid, &status, 0)); /* TODO: What if error? */ if (WIFEXITED (status) && exit_status) { *exit_status = WEXITSTATUS (status); } #endif return TRUE; }
int main(int argc, char *argv[]) { Display *dpy; Bool ret; int screen, display_devices[2]; char* environment = getenv("XDG_CONFIG_HOME"); char* configuration; if (environment == NULL) { // no XDG_CONFIG_HOME set, default is $HOME/.config/ environment = getenv("HOME"); configuration = (char*)calloc(sizeof(char), strlen(environment) + strlen(CONFIG_FILE) + strlen("/.config/") + 1); strcpy(configuration, environment); strcat(configuration, "/.config/"); } else { configuration = (char*)calloc(sizeof(char), strlen(environment) + strlen(CONFIG_FILE) + 1); } strcat(configuration, CONFIG_FILE); printf("Using callback file %s\n", configuration); ret = setup(&dpy, &screen); if (!ret) { return 1; } ret = XNVCTRLQueryAttribute(dpy, screen, 0, NV_CTRL_PROBE_DISPLAYS, &display_devices[0]); if (!ret) { fprintf(stderr, "Failed to query the enabled Display Devices.\n\n"); return 1; } while (True) { usleep(2 * 1000 * 1000); /* * first, probe for new display devices; while * NV_CTRL_CONNECTED_DISPLAYS reports what the NVIDIA X driver * believes is currently connected to the GPU, * NV_CTRL_PROBE_DISPLAYS forces the driver to redetect what * is connected. */ ret = XNVCTRLQueryAttribute(dpy, screen, 0, NV_CTRL_PROBE_DISPLAYS, &display_devices[0]); if (display_devices[0] != display_devices[1]) { display_devices[1] = display_devices[0]; char** strs = identifier(dpy, display_devices[0], screen); strs[0] = configuration; // First argument is the executable, by convention if (fork() == 0) { // Child execv(configuration, strs); fprintf(stderr, "An error occured executing the daemon callback file\n"); return 0; } int i = 1; while(strs[i] != NULL) { #ifdef DEBUG printf("%d: \"%s\"\n", i, strs[i]); #endif free(strs[i++]); } } } return 0; }
int main(int argc, char **argv) { int pid, rc, status; security_context_t context_s; context_t context; if (argc != 3) { fprintf(stderr, "usage: %s newdomain program\n", argv[0]); exit(-1); } rc = getcon(&context_s); if (rc < 0) { fprintf(stderr, "%s: unable to get my context\n", argv[0]); exit(-1); } context = context_new(context_s); if (!context) { fprintf(stderr, "%s: unable to create context structure\n", argv[0]); exit(-1); } if (context_type_set(context, argv[1])) { fprintf(stderr, "%s: unable to set new type\n", argv[0]); exit(-1); } freecon(context_s); context_s = context_str(context); if (!context_s) { fprintf(stderr, "%s: unable to obtain new context string\n", argv[0]); exit(-1); } rc = setexeccon(context_s); if (rc < 0) { fprintf(stderr, "%s: unable to set exec context to %s\n", argv[0], context_s); exit(-1); } pid = fork(); if (pid < 0) { perror("fork"); exit(-1); } else if (pid == 0) { rc = execv(argv[2], argv + 2); perror(argv[3]); exit(1); } pid = wait(&status); if (pid < 0) { perror("wait"); exit(1); } if (WIFEXITED(status)) { exit(WEXITSTATUS(status)); } exit(-1); }
static void make_dist(const char *homedir, const char *pkg, const char *suff, Package *plist) { struct stat sb; char tball[FILENAME_MAX]; PackingList p; int ret; const char *args[50]; /* Much more than enough. */ int nargs = 0; int pipefds[2]; FILE *totar; pid_t pid; const char *cname; char *prefix = NULL; args[nargs++] = "tar"; /* argv[0] */ if (*pkg == '/') snprintf(tball, FILENAME_MAX, "%s.%s", pkg, suff); else snprintf(tball, FILENAME_MAX, "%s/%s.%s", homedir, pkg, suff); /* * If the package tarball exists already, and we are running in `no * clobber' mode, skip this package. */ if (stat(tball, &sb) == 0 && Regenerate == FALSE) { if (Verbose) printf("Skipping package '%s'. It already exists.\n", tball); return; } args[nargs++] = "-c"; args[nargs++] = "-f"; args[nargs++] = tball; if (strchr(suff, 'z')) { /* Compress/gzip/bzip2? */ if (Zipper == BZIP2) { args[nargs++] = "-j"; cname = "bzip'd "; } else if (Zipper == XZ) { args[nargs++] = "-J"; cname = "xz'd "; } else { args[nargs++] = "-z"; cname = "gzip'd "; } } else { cname = ""; } if (Dereference) args[nargs++] = "-h"; if (ExcludeFrom) { args[nargs++] = "-X"; args[nargs++] = ExcludeFrom; } args[nargs++] = "-T"; /* Take filenames from file instead of args. */ args[nargs++] = "-"; /* Use stdin for the file. */ args[nargs] = NULL; if (Verbose) printf("Creating %star ball in '%s'\n", cname, tball); /* Set up a pipe for passing the filenames, and fork off a tar process. */ if (pipe(pipefds) == -1) { cleanup(0); errx(2, "%s: cannot create pipe", __func__); } if ((pid = fork()) == -1) { cleanup(0); errx(2, "%s: cannot fork process for tar", __func__); } if (pid == 0) { /* The child */ dup2(pipefds[0], 0); close(pipefds[0]); close(pipefds[1]); execv("/usr/bin/tar", (char * const *)(uintptr_t)args); cleanup(0); errx(2, "%s: failed to execute tar command", __func__); } /* Meanwhile, back in the parent process ... */ close(pipefds[0]); if ((totar = fdopen(pipefds[1], "w")) == NULL) { cleanup(0); errx(2, "%s: fdopen failed", __func__); } fprintf(totar, "%s\n", CONTENTS_FNAME); fprintf(totar, "%s\n", COMMENT_FNAME); fprintf(totar, "%s\n", DESC_FNAME); if (Install) fprintf(totar, "%s\n", INSTALL_FNAME); if (PostInstall) fprintf(totar, "%s\n", POST_INSTALL_FNAME); if (DeInstall) fprintf(totar, "%s\n", DEINSTALL_FNAME); if (PostDeInstall) fprintf(totar, "%s\n", POST_DEINSTALL_FNAME); if (Require) fprintf(totar, "%s\n", REQUIRE_FNAME); if (Display) fprintf(totar, "%s\n", DISPLAY_FNAME); if (Mtree) fprintf(totar, "%s\n", MTREE_FNAME); for (p = plist->head; p; p = p->next) { if (p->type == PLIST_FILE) fprintf(totar, "%s\n", p->name); else if (p->type == PLIST_CWD && p->name == NULL) fprintf(totar, "-C\n%s\n", prefix); else if (p->type == PLIST_CWD && BaseDir && p->name && p->name[0] == '/') fprintf(totar, "-C\n%s%s\n", BaseDir, p->name); else if (p->type == PLIST_CWD || p->type == PLIST_SRC) fprintf(totar, "-C\n%s\n", p->name); else if (p->type == PLIST_IGNORE) p = p->next; if (p->type == PLIST_CWD && !prefix) prefix = p->name; } fclose(totar); wait(&ret); /* assume either signal or bad exit is enough for us */ if (ret) { cleanup(0); errx(2, "%s: tar command failed with code %d", __func__, ret); } }
static int poweroff(const char *msg, char **cmd_argv) { struct stat statbuf; pid_t pid, child; struct passwd *pwd; char *home, *user; char ehome[] = "HOME="; char euser[] = "LOGNAME="; int status; char **ca; if (mutex_trylock(&poweroff_mutex) != 0) return (0); if (stat("/dev/console", &statbuf) == -1 || (pwd = getpwuid(statbuf.st_uid)) == NULL) { (void) mutex_unlock(&poweroff_mutex); return (1); } if (msg) syslog(LOG_NOTICE, msg); if (*cmd_argv == NULL) { logerror("No command to run."); (void) mutex_unlock(&poweroff_mutex); return (1); } home = malloc(strlen(pwd->pw_dir) + sizeof (ehome)); user = malloc(strlen(pwd->pw_name) + sizeof (euser)); if (home == NULL || user == NULL) { free(home); free(user); logerror("No memory."); (void) mutex_unlock(&poweroff_mutex); return (1); } (void) strcpy(home, ehome); (void) strcat(home, pwd->pw_dir); (void) strcpy(user, euser); (void) strcat(user, pwd->pw_name); /* * Need to simulate the user enviroment, minimaly set HOME, and USER. */ if ((child = fork1()) == 0) { (void) putenv(home); (void) putenv(user); (void) setgid(pwd->pw_gid); (void) setuid(pwd->pw_uid); /* * check for shutdown flag and set environment */ for (ca = cmd_argv; *ca; ca++) { if (strcmp("-h", *ca) == 0) { (void) putenv("SYSSUSPENDDODEFAULT="); break; } } (void) execv(cmd_argv[0], cmd_argv); exit(EXIT_FAILURE); } else { free(home); free(user); if (child == -1) { (void) mutex_unlock(&poweroff_mutex); return (1); } } pid = 0; while (pid != child) pid = wait(&status); if (WEXITSTATUS(status)) { (void) syslog(LOG_ERR, "Failed to exec \"%s\".", cmd_argv[0]); (void) mutex_unlock(&poweroff_mutex); return (1); } (void) mutex_unlock(&poweroff_mutex); return (0); }
void CreateExecutionEnvironment(int *pargc, char ***pargv, char jrepath[], jint so_jrepath, char jvmpath[], jint so_jvmpath, char jvmcfg[], jint so_jvmcfg) { /* * First, determine if we are running the desired data model. If we * are running the desired data model, all the error messages * associated with calling GetJREPath, ReadKnownVMs, etc. should be * output. However, if we are not running the desired data model, * some of the errors should be suppressed since it is more * informative to issue an error message based on whether or not the * os/processor combination has dual mode capabilities. */ jboolean jvmpathExists; /* Compute/set the name of the executable */ SetExecname(*pargv); /* Check data model flags, and exec process, if needed */ { char *arch = (char *)GetArch(); /* like sparc or sparcv9 */ char * jvmtype = NULL; int argc = *pargc; char **argv = *pargv; int running = CURRENT_DATA_MODEL; int wanted = running; /* What data mode is being asked for? Current model is fine unless another model is asked for */ #ifdef SETENV_REQUIRED jboolean mustsetenv = JNI_FALSE; char *runpath = NULL; /* existing effective LD_LIBRARY_PATH setting */ char* new_runpath = NULL; /* desired new LD_LIBRARY_PATH string */ char* newpath = NULL; /* path on new LD_LIBRARY_PATH */ char* lastslash = NULL; char** newenvp = NULL; /* current environment */ #ifdef __solaris__ char* dmpath = NULL; /* data model specific LD_LIBRARY_PATH, Solaris only */ #endif /* __solaris__ */ #endif /* SETENV_REQUIRED */ char** newargv = NULL; int newargc = 0; /* * Starting in 1.5, all unix platforms accept the -d32 and -d64 * options. On platforms where only one data-model is supported * (e.g. ia-64 Linux), using the flag for the other data model is * an error and will terminate the program. */ { /* open new scope to declare local variables */ int i; newargv = (char **)JLI_MemAlloc((argc+1) * sizeof(char*)); newargv[newargc++] = argv[0]; /* scan for data model arguments and remove from argument list; last occurrence determines desired data model */ for (i=1; i < argc; i++) { if (JLI_StrCmp(argv[i], "-J-d64") == 0 || JLI_StrCmp(argv[i], "-d64") == 0) { wanted = 64; continue; } if (JLI_StrCmp(argv[i], "-J-d32") == 0 || JLI_StrCmp(argv[i], "-d32") == 0) { wanted = 32; continue; } newargv[newargc++] = argv[i]; if (IsJavaArgs()) { if (argv[i][0] != '-') continue; } else { if (JLI_StrCmp(argv[i], "-classpath") == 0 || JLI_StrCmp(argv[i], "-cp") == 0) { i++; if (i >= argc) break; newargv[newargc++] = argv[i]; continue; } if (argv[i][0] != '-') { i++; break; } } } /* copy rest of args [i .. argc) */ while (i < argc) { newargv[newargc++] = argv[i++]; } newargv[newargc] = NULL; /* * newargv has all proper arguments here */ argc = newargc; argv = newargv; } /* If the data model is not changing, it is an error if the jvmpath does not exist */ if (wanted == running) { /* Find out where the JRE is that we will be using. */ if (!GetJREPath(jrepath, so_jrepath, arch, JNI_FALSE) ) { JLI_ReportErrorMessage(JRE_ERROR1); exit(2); } JLI_Snprintf(jvmcfg, so_jvmcfg, "%s%slib%s%s%sjvm.cfg", jrepath, FILESEP, FILESEP, arch, FILESEP); /* Find the specified JVM type */ if (ReadKnownVMs(jvmcfg, JNI_FALSE) < 1) { JLI_ReportErrorMessage(CFG_ERROR7); exit(1); } jvmpath[0] = '\0'; jvmtype = CheckJvmType(pargc, pargv, JNI_FALSE); if (JLI_StrCmp(jvmtype, "ERROR") == 0) { JLI_ReportErrorMessage(CFG_ERROR9); exit(4); } if (!GetJVMPath(jrepath, jvmtype, jvmpath, so_jvmpath, arch, 0 )) { JLI_ReportErrorMessage(CFG_ERROR8, jvmtype, jvmpath); exit(4); } /* * we seem to have everything we need, so without further ado * we return back, otherwise proceed to set the environment. */ #ifdef SETENV_REQUIRED mustsetenv = RequiresSetenv(wanted, jvmpath); JLI_TraceLauncher("mustsetenv: %s\n", mustsetenv ? "TRUE" : "FALSE"); if (mustsetenv == JNI_FALSE) { return; } #else return; #endif /* SETENV_REQUIRED */ } else { /* do the same speculatively or exit */ #ifdef DUAL_MODE if (running != wanted) { /* Find out where the JRE is that we will be using. */ if (!GetJREPath(jrepath, so_jrepath, GetArchPath(wanted), JNI_TRUE)) { /* give up and let other code report error message */ JLI_ReportErrorMessage(JRE_ERROR2, wanted); exit(1); } JLI_Snprintf(jvmcfg, so_jvmcfg, "%s%slib%s%s%sjvm.cfg", jrepath, FILESEP, FILESEP, GetArchPath(wanted), FILESEP); /* * Read in jvm.cfg for target data model and process vm * selection options. */ if (ReadKnownVMs(jvmcfg, JNI_TRUE) < 1) { /* give up and let other code report error message */ JLI_ReportErrorMessage(JRE_ERROR2, wanted); exit(1); } jvmpath[0] = '\0'; jvmtype = CheckJvmType(pargc, pargv, JNI_TRUE); if (JLI_StrCmp(jvmtype, "ERROR") == 0) { JLI_ReportErrorMessage(CFG_ERROR9); exit(4); } /* exec child can do error checking on the existence of the path */ jvmpathExists = GetJVMPath(jrepath, jvmtype, jvmpath, so_jvmpath, GetArchPath(wanted), 0); #ifdef SETENV_REQUIRED mustsetenv = RequiresSetenv(wanted, jvmpath); #endif /* SETENV_REQUIRED */ } #else /* ! DUALMODE */ JLI_ReportErrorMessage(JRE_ERROR2, wanted); exit(1); #endif /* DUAL_MODE */ } #ifdef SETENV_REQUIRED if (mustsetenv) { /* * We will set the LD_LIBRARY_PATH as follows: * * o $JVMPATH (directory portion only) * o $JRE/lib/$LIBARCHNAME * o $JRE/../lib/$LIBARCHNAME * * followed by the user's previous effective LD_LIBRARY_PATH, if * any. */ #ifdef __solaris__ /* * Starting in Solaris 7, ld.so.1 supports three LD_LIBRARY_PATH * variables: * * 1. LD_LIBRARY_PATH -- used for 32 and 64 bit searches if * data-model specific variables are not set. * * 2. LD_LIBRARY_PATH_64 -- overrides and replaces LD_LIBRARY_PATH * for 64-bit binaries. * * 3. LD_LIBRARY_PATH_32 -- overrides and replaces LD_LIBRARY_PATH * for 32-bit binaries. * * The vm uses LD_LIBRARY_PATH to set the java.library.path system * property. To shield the vm from the complication of multiple * LD_LIBRARY_PATH variables, if the appropriate data model * specific variable is set, we will act as if LD_LIBRARY_PATH had * the value of the data model specific variant and the data model * specific variant will be unset. Note that the variable for the * *wanted* data model must be used (if it is set), not simply the * current running data model. */ switch (wanted) { case 0: if (running == 32) { dmpath = getenv("LD_LIBRARY_PATH_32"); wanted = 32; } else { dmpath = getenv("LD_LIBRARY_PATH_64"); wanted = 64; } break; case 32: dmpath = getenv("LD_LIBRARY_PATH_32"); break; case 64: dmpath = getenv("LD_LIBRARY_PATH_64"); break; default: JLI_ReportErrorMessage(JRE_ERROR3, __LINE__); exit(1); /* unknown value in wanted */ break; } /* * If dmpath is NULL, the relevant data model specific variable is * not set and normal LD_LIBRARY_PATH should be used. */ if (dmpath == NULL) { runpath = getenv("LD_LIBRARY_PATH"); } else { runpath = dmpath; } #else /* ! __solaris__ */ /* * If not on Solaris, assume only a single LD_LIBRARY_PATH * variable. */ runpath = getenv("LD_LIBRARY_PATH"); #endif /* __solaris__ */ /* runpath contains current effective LD_LIBRARY_PATH setting */ jvmpath = JLI_StringDup(jvmpath); new_runpath = JLI_MemAlloc(((runpath != NULL) ? JLI_StrLen(runpath) : 0) + 2 * JLI_StrLen(jrepath) + 2 * JLI_StrLen(arch) + JLI_StrLen(jvmpath) + 52); newpath = new_runpath + JLI_StrLen("LD_LIBRARY_PATH="); /* * Create desired LD_LIBRARY_PATH value for target data model. */ { /* remove the name of the .so from the JVM path */ lastslash = JLI_StrRChr(jvmpath, '/'); if (lastslash) *lastslash = '\0'; sprintf(new_runpath, "LD_LIBRARY_PATH=" "%s:" "%s/lib/%s:" "%s/../lib/%s", jvmpath, #ifdef DUAL_MODE jrepath, GetArchPath(wanted), jrepath, GetArchPath(wanted) #else /* !DUAL_MODE */ jrepath, arch, jrepath, arch #endif /* DUAL_MODE */ ); /* * Check to make sure that the prefix of the current path is the * desired environment variable setting, though the RequiresSetenv * checks if the desired runpath exists, this logic does a more * comprehensive check. */ if (runpath != NULL && JLI_StrNCmp(newpath, runpath, JLI_StrLen(newpath)) == 0 && (runpath[JLI_StrLen(newpath)] == 0 || runpath[JLI_StrLen(newpath)] == ':') && (running == wanted) /* data model does not have to be changed */ #ifdef __solaris__ && (dmpath == NULL) /* data model specific variables not set */ #endif /* __solaris__ */ ) { return; } } /* * Place the desired environment setting onto the prefix of * LD_LIBRARY_PATH. Note that this prevents any possible infinite * loop of execv() because we test for the prefix, above. */ if (runpath != 0) { JLI_StrCat(new_runpath, ":"); JLI_StrCat(new_runpath, runpath); } if (putenv(new_runpath) != 0) { exit(1); /* problem allocating memory; LD_LIBRARY_PATH not set properly */ } /* * Unix systems document that they look at LD_LIBRARY_PATH only * once at startup, so we have to re-exec the current executable * to get the changed environment variable to have an effect. */ #ifdef __solaris__ /* * If dmpath is not NULL, remove the data model specific string * in the environment for the exec'ed child. */ if (dmpath != NULL) (void)UnsetEnv((wanted == 32) ? "LD_LIBRARY_PATH_32" : "LD_LIBRARY_PATH_64"); #endif /* __solaris */ newenvp = environ; } #endif /* SETENV_REQUIRED */ { char *newexec = execname; #ifdef DUAL_MODE /* * If the data model is being changed, the path to the * executable must be updated accordingly; the executable name * and directory the executable resides in are separate. In the * case of 32 => 64, the new bits are assumed to reside in, e.g. * "olddir/LIBARCH64NAME/execname"; in the case of 64 => 32, * the bits are assumed to be in "olddir/../execname". For example, * * olddir/sparcv9/execname * olddir/amd64/execname * * for Solaris SPARC and Linux amd64, respectively. */ if (running != wanted) { char *oldexec = JLI_StrCpy(JLI_MemAlloc(JLI_StrLen(execname) + 1), execname); char *olddir = oldexec; char *oldbase = JLI_StrRChr(oldexec, '/'); newexec = JLI_MemAlloc(JLI_StrLen(execname) + 20); *oldbase++ = 0; sprintf(newexec, "%s/%s/%s", olddir, ((wanted == 64) ? LIBARCH64NAME : ".."), oldbase); argv[0] = newexec; } #endif /* DUAL_MODE */ JLI_TraceLauncher("TRACER_MARKER:About to EXEC\n"); (void) fflush(stdout); (void) fflush(stderr); #ifdef SETENV_REQUIRED if (mustsetenv) { execve(newexec, argv, newenvp); } else { execv(newexec, argv); } #else /* !SETENV_REQUIRED */ execv(newexec, argv); #endif /* SETENV_REQUIRED */ JLI_ReportErrorMessageSys(JRE_ERROR4, newexec); #ifdef DUAL_MODE if (running != wanted) { JLI_ReportErrorMessage(JRE_ERROR5, wanted, running); #ifdef __solaris__ #ifdef __sparc JLI_ReportErrorMessage(JRE_ERROR6); #else /* ! __sparc__ */ JLI_ReportErrorMessage(JRE_ERROR7); #endif /* __sparc */ #endif /* __solaris__ */ } #endif /* DUAL_MODE */ } exit(1); } }
int main(int argc, char *argv[]) { int userdir = 0; /* ~userdir flag */ uid_t uid; /* user information */ gid_t gid; /* target group placeholder */ char *target_uname; /* target user name */ char *target_gname; /* target group name */ char *target_homedir; /* target home directory */ char *actual_uname; /* actual user name */ char *actual_gname; /* actual group name */ char *prog; /* name of this program */ char *cmd; /* command to be executed */ char cwd[AP_MAXPATH]; /* current working directory */ char dwd[AP_MAXPATH]; /* docroot working directory */ struct passwd *pw; /* password entry holder */ struct group *gr; /* group entry holder */ struct stat dir_info; /* directory info holder */ struct stat prg_info; /* program info holder */ /* * Start with a "clean" environment */ clean_env(); prog = argv[0]; /* * Check existence/validity of the UID of the user * running this program. Error out if invalid. */ uid = getuid(); if ((pw = getpwuid(uid)) == NULL) { log_err("crit: invalid uid: (%ld)\n", uid); exit(102); } /* * See if this is a 'how were you compiled' request, and * comply if so. */ if ((argc > 1) && (! strcmp(argv[1], "-V")) && ((uid == 0) || (! strcmp(SUEXEC_USER, pw->pw_name))) ) { #ifdef SUEXEC_DOC_ROOT fprintf(stderr, " -D SUEXEC_DOCROOT=\"%s\"\n", SUEXEC_DOCROOT); #endif #ifdef SUEXEC_GID_MIN fprintf(stderr, " -D SUEXEC_GID_MIN=%d\n", SUEXEC_GID_MIN); #endif #ifdef SUEXEC_USER fprintf(stderr, " -D SUEXEC_USER=\"%s\"\n", SUEXEC_USER); #endif #ifdef SUEXEC_LOGFILE fprintf(stderr, " -D SUEXEC_LOGFILE=\"%s\"\n", SUEXEC_LOGFILE); #endif #ifdef SUEXEC_SAFE_PATH fprintf(stderr, " -D SUEXEC_PATH=\"%s\"\n", SUEXEC_PATH); #endif #ifdef SUEXEC_SUEXEC_UMASK fprintf(stderr, " -D SUEXEC_SUEXEC_UMASK=%03o\n", SUEXEC_SUEXEC_UMASK); #endif #ifdef SUEXEC_UID_MIN fprintf(stderr, " -D SUEXEC_UID_MIN=%d\n", SUEXEC_UID_MIN); #endif #ifdef SUEXEC_USERDIR fprintf(stderr, " -D SUEXEC_USERDIR=\"%s\"\n", SUEXEC_USERDIR); #endif exit(0); } /* * If there are a proper number of arguments, set * all of them to variables. Otherwise, error out. */ if (argc < 4) { log_err("too few arguments\n"); exit(101); } target_uname = argv[1]; target_gname = argv[2]; cmd = argv[3]; /* * Check to see if the user running this program * is the user allowed to do so as defined in * suexec.h. If not the allowed user, error out. */ if (strcmp(SUEXEC_USER, pw->pw_name)) { log_err("user mismatch (%s instead of %s)\n", pw->pw_name, SUEXEC_USER); exit(103); } /* * Check for a leading '/' (absolute path) in the command to be executed, * or attempts to back up out of the current directory, * to protect against attacks. If any are * found, error out. Naughty naughty crackers. */ if ((cmd[0] == '/') || (!strncmp(cmd, "../", 3)) || (strstr(cmd, "/../") != NULL)) { log_err("invalid command (%s)\n", cmd); exit(104); } /* * Check to see if this is a ~userdir request. If * so, set the flag, and remove the '~' from the * target username. */ if (!strncmp("~", target_uname, 1)) { target_uname++; userdir = 1; } /* * Error out if the target username is invalid. */ if (strspn(target_uname, "1234567890") != strlen(target_uname)) { if ((pw = getpwnam(target_uname)) == NULL) { log_err("invalid target user name: (%s)\n", target_uname); exit(105); } } else { if ((pw = getpwuid(atoi(target_uname))) == NULL) { log_err("invalid target user id: (%s)\n", target_uname); exit(121); } } /* * Error out if the target group name is invalid. */ if (strspn(target_gname, "1234567890") != strlen(target_gname)) { if ((gr = getgrnam(target_gname)) == NULL) { log_err("invalid target group name: (%s)\n", target_gname); exit(106); } } else { if ((gr = getgrgid(atoi(target_gname))) == NULL) { log_err("invalid target group id: (%s)\n", target_gname); exit(106); } } gid = gr->gr_gid; actual_gname = strdup(gr->gr_name); /* * Save these for later since initgroups will hose the struct */ uid = pw->pw_uid; actual_uname = strdup(pw->pw_name); target_homedir = strdup(pw->pw_dir); /* * Log the transaction here to be sure we have an open log * before we setuid(). */ log_no_err("uid: (%s/%s) gid: (%s/%s) cmd: %s\n", target_uname, actual_uname, target_gname, actual_gname, cmd); /* * Error out if attempt is made to execute as root or as * a UID less than AP_UID_MIN. Tsk tsk. */ if ((uid == 0) || (uid < SUEXEC_UID_MIN)) { log_err("cannot run as forbidden uid (%d/%s)\n", uid, cmd); exit(107); } /* * Error out if attempt is made to execute as root group * or as a GID less than AP_GID_MIN. Tsk tsk. */ if ((gid == 0) || (gid < SUEXEC_GID_MIN)) { log_err("cannot run as forbidden gid (%d/%s)\n", gid, cmd); exit(108); } /* * Change UID/GID here so that the following tests work over NFS. * * Initialize the group access list for the target user, * and setgid() to the target group. If unsuccessful, error out. */ if (((setgid(gid)) != 0) || (initgroups(actual_uname, gid) != 0)) { log_err("failed to setgid (%ld: %s)\n", gid, cmd); exit(109); } /* * setuid() to the target user. Error out on fail. */ if ((setuid(uid)) != 0) { log_err("failed to setuid (%ld: %s)\n", uid, cmd); exit(110); } /* * Get the current working directory, as well as the proper * document root (dependant upon whether or not it is a * ~userdir request). Error out if we cannot get either one, * or if the current working directory is not in the docroot. * Use chdir()s and getcwd()s to avoid problems with symlinked * directories. Yuck. */ if (getcwd(cwd, AP_MAXPATH) == NULL) { log_err("cannot get current working directory\n"); exit(111); } if (userdir) { if (((chdir(target_homedir)) != 0) || ((chdir(SUEXEC_USERDIR)) != 0) || ((getcwd(dwd, AP_MAXPATH)) == NULL) || ((chdir(cwd)) != 0)) { log_err("cannot get docroot information (%s)\n", target_homedir); exit(112); } } else { if (((chdir(SUEXEC_DOCROOT)) != 0) || ((getcwd(dwd, AP_MAXPATH)) == NULL) || ((chdir(cwd)) != 0)) { log_err("cannot get docroot information (%s)\n", SUEXEC_DOCROOT); exit(113); } } if ((strncmp(cwd, dwd, strlen(dwd))) != 0) { log_err("command not in docroot (%s/%s)\n", cwd, cmd); exit(114); } /* * Stat the cwd and verify it is a directory, or error out. */ if (((lstat(cwd, &dir_info)) != 0) || !(S_ISDIR(dir_info.st_mode))) { log_err("cannot stat directory: (%s)\n", cwd); exit(115); } /* * Error out if cwd is writable by others. */ if ((dir_info.st_mode & S_IWOTH) || (dir_info.st_mode & S_IWGRP)) { log_err("directory is writable by others: (%s)\n", cwd); exit(116); } /* * Error out if we cannot stat the program. */ if (((lstat(cmd, &prg_info)) != 0) || (S_ISLNK(prg_info.st_mode))) { log_err("cannot stat program: (%s)\n", cmd); exit(117); } /* * Error out if the program is writable by others. */ if ((prg_info.st_mode & S_IWOTH) || (prg_info.st_mode & S_IWGRP)) { log_err("file is writable by others: (%s/%s)\n", cwd, cmd); exit(118); } /* * Error out if the file is setuid or setgid. */ if ((prg_info.st_mode & S_ISUID) || (prg_info.st_mode & S_ISGID)) { log_err("file is either setuid or setgid: (%s/%s)\n", cwd, cmd); exit(119); } /* * Error out if the target name/group is different from * the name/group of the cwd or the program. */ if ((uid != dir_info.st_uid) || (gid != dir_info.st_gid) || (uid != prg_info.st_uid) || (gid != prg_info.st_gid)) { log_err("target uid/gid (%ld/%ld) mismatch " "with directory (%ld/%ld) or program (%ld/%ld)\n", uid, gid, dir_info.st_uid, dir_info.st_gid, prg_info.st_uid, prg_info.st_gid); exit(120); } /* * Error out if the program is not executable for the user. * Otherwise, she won't find any error in the logs except for * "[error] Premature end of script headers: ..." */ if (!(prg_info.st_mode & S_IXUSR)) { log_err("file has no execute permission: (%s/%s)\n", cwd, cmd); exit(121); } #ifdef SUEXEC_UMASK /* * umask() uses inverse logic; bits are CLEAR for allowed access. */ if ((~SUEXEC_UMASK) & 0022) { log_err("notice: AP_SUEXEC_UMASK of %03o allows " "write permission to group and/or other\n", AP_SUEXEC_UMASK); } umask(SUEXEC_UMASK); #endif /* SUEXEC_UMASK */ /* * Be sure to close the log file so the CGI can't * mess with it. If the exec fails, it will be reopened * automatically when log_err is called. Note that the log * might not actually be open if SUEXEC_LOGFILE isn't defined. * However, the "log" cell isn't ifdef'd so let's be defensive * and assume someone might have done something with it * outside an ifdef'd SUEXEC_LOGFILE block. */ if (log != NULL) { fclose(log); log = NULL; } /* * Execute the command, replacing our image with its own. */ execv(cmd, &argv[3]); /* * (I can't help myself...sorry.) * * Uh oh. Still here. Where's the kaboom? There was supposed to be an * EARTH-shattering kaboom! * * Oh well, log the failure and error out. */ log_err("(%d)%s: exec failed (%s)\n", errno, strerror(errno), cmd); exit(255); }
static void yaz_invoke_gdb(void) { int fd = yaz_panic_fd; pid_t pid; int fds[2]; if (pipe(fds) == -1) { const char *cp = "backtrace: pipe failed\n"; write(fd, cp, strlen(cp)); return; } pid = fork(); if (pid == (pid_t) (-1)) { /* error */ const char *cp = "backtrace: fork failure\n"; write(fd, cp, strlen(cp)); } else if (pid == 0) { /* child */ char *arg[20]; int arg_no = 0; char pidstr[40]; const char *cp = "backtrace: could not exec gdb\n"; close(fds[1]); close(0); dup(fds[0]); if (fd != 1) { close(1); dup(fd); } if (fd != 2) { close(2); dup(fd); } arg[arg_no++] = "/usr/bin/gdb"; arg[arg_no++] = "-n"; arg[arg_no++] = "-batch"; arg[arg_no++] = "-ex"; arg[arg_no++] = "info threads"; arg[arg_no++] = "-ex"; arg[arg_no++] = "thread apply all bt"; arg[arg_no++] = static_progname; sprintf(pidstr, NMEM_INT_PRINTF, (nmem_int_t) getppid()); arg[arg_no++] = pidstr; arg[arg_no] = 0; execv(arg[0], arg); write(2, cp, strlen(cp)); /* exec failure if we make it this far */ _exit(1); } else { /* parent */ int sec = 0; close(fds[0]); write(fds[1], "quit\n", 5); while (1) { int status; pid_t s = waitpid(pid, &status, WNOHANG); if (s != 0) break; if (sec == 9) kill(pid, SIGTERM); if (sec == 10) kill(pid, SIGKILL); if (sec == 11) break; if (sec > 3) write(fds[1], "quit\n", 5); sleep(1); sec++; } close(fds[1]); } }
/* * Start up the process with the given args */ INTERNAL int start_agent(AGENT_REQ *areq, char *cmd, char *args, int *retpid) { int argc; char *argv[MAX_ARGS]; char hostname[AGENTD_NAMELEN]; int childpid; int pid, exitstat; int pipeout[2], pipeerr[2]; int rc; EVENT_AGENTD_STAT estat; EVENT_AGENTD_LOG elogout, elogerr; char msg[200]; char cmdpath[PATHLEN]; if (WorkDir) make_path(cmdpath, ExecPath, cmd); else strcpy(cmdpath, cmd); argv[0] = cmd; argc = 1; if (Verbose) printf("0: %s (%s)\n", argv[0], cmdpath); rc = parse_args(args, argv, 1); if (rc < 0) { return(0); } argc = rc; /**************************/ /****** START DEBUG *******/ #ifdef FAKE_THIS_FOR_DEBUGGING printf("start_agent: sleeping\n"); if (areq) { areq->status = AGENTD_AGENT_RUNNING; areq->pid = 9999999; estat.reqseq = EventSeq(areq->ereq); estat.tag = areq->ereq.tag; estat.reqtype = AGENTD_CTL_START; estat.result = 9999999; estat.rstatus = AGENTD_STATUS_OK; SEND(EventFrom(areq->ereq), AGENTD_STAT, estat); } sleep(10); if (areq) { areq->status = AGENTD_AGENT_EXIT; estat.result = 0; estat.rstatus = AGENTD_AGENT_EXIT; SEND(EventFrom(areq->ereq), AGENTD_STAT, estat); } printf("start_agent: exiting\n"); return(AGENTD_STATUS_OK); #endif /******** END DEBUG *******/ /**************************/ if (pipe(pipeout) != SYS_OK) { fprintf(stderr, "start_agent: couldn't create stdout pipe\n"); perror("start_agent"); return(AGENTD_STATUS_RUNERR); } if (pipe(pipeerr) != SYS_OK) { fprintf(stderr, "start_agent: couldn't create stderr pipe\n"); perror("start_agent"); return(AGENTD_STATUS_RUNERR); } childpid = fork(); if (childpid < 0) { /* Error occurred */ fprintf(stderr, "start_agent: fork failed\n"); perror("start_agent"); close(pipeout[0]); close(pipeout[1]); close(pipeerr[0]); close(pipeerr[1]); return(AGENTD_STATUS_RUNERR); } /* * Exec command from newly forked process */ if (childpid == 0) { /* Child process */ int fdin; int argc; int rc; /**** event_exit_(); ****/ if (WorkDir) chdir(WorkPath); /* stdin */ fdin = open("/dev/null", O_RDONLY); dup2(fdin, 0); close(fdin); /* stdout */ rc = dup2(pipeout[1], 1); close(pipeout[0]); close(pipeout[1]); if (rc < 0) printf("start_agent: couldn't dup pipe as stdout"); /* stderr */ rc = dup2(pipeerr[1], 2); close(pipeerr[0]); close(pipeerr[1]); if (rc < 0) printf("start_agent: couldn't dup pipe as stderr"); /* Create a new process group */ setpgrp(); fprintf(stderr, "agentd: child proc %d, pgrp %d execing %s\n", getpid(), getpgrp(), cmd); execv(cmdpath, argv); /* If exec returns it means an error occurred */ close(0); close(1); close(2); exit(AGENTD_STATUS_RUNERR); } signal(SIGABRT, SIG_IGN); if (Verbose) printf("start_agent: created child process %d\n", childpid); /* Report startup status to requester */ if (areq) { areq->status = AGENTD_AGENT_RUNNING; areq->pid = childpid; estat.reqseq = EventSeq(areq->ereq); estat.tag = areq->ereq.tag; estat.reqtype = AGENTD_CTL_START; estat.result = childpid; estat.rstatus = AGENTD_STATUS_OK; SEND(EventFrom(areq->ereq), AGENTD_STAT, estat); } gethostname(hostname, sizeof(hostname)); /* Set up stderr */ elogerr.head.to = EVENT_BCAST_NOTME; elogerr.type = AGENTD_LOG_STDERR; elogerr.flags = pipeerr[0]; elogerr.pid = childpid; strcpy(elogerr.hostname, hostname); strcpy(elogerr.program, cmd); /* Start reader thread and wait for it to initialize */ if (Verbose) printf("start_agent: starting reader thread for stderr\n"); mp_task(reader, &elogerr, 0); mp_decsema(ReadInit); /* Broadcast a message */ sprintf(elogerr.msg, "agentd: agent started as pid %d\n", childpid); SEND(EVENT_BCAST_NOTME, AGENTD_LOG, elogerr); /* Now do the same for stdout */ elogout.head.to = EVENT_BCAST_NOTME; elogout.type = AGENTD_LOG_STDOUT; elogout.flags = pipeout[0]; elogout.pid = childpid; strcpy(elogout.hostname, hostname); strcpy(elogout.program, cmd); if (Verbose) printf("start_agent: starting reader thread for stdout\n"); mp_task(reader, &elogout, 0); mp_decsema(ReadInit); /* Wait for child (agent) process to exit */ if (Verbose) printf("start_agent: waiting for agent proc %d\n", childpid); pid = waitpid(childpid, &exitstat, 0); if (pid <= 0) { perror("start_agent: waitpid"); } if (WIFSIGNALED(exitstat)) sprintf(msg, "agent %d exited on signal %s with rc %d", childpid, signame(WTERMSIG(exitstat)), WEXITSTATUS(exitstat)); else sprintf(msg, "agent %d exited normally with rc %d", childpid, WEXITSTATUS(exitstat)); if (Verbose) printf("start_agent: %s\n", msg); /* Set exit and write to pipe to wake up readers */ mp_lock(Exitlock); Exit = childpid; sleep(5); /* delay to let things quiesce */ write(pipeout[1], EofStr, strlen(EofStr)+1); write(pipeerr[1], EofStr, strlen(EofStr)+1); if (Verbose) printf("start_agent: %d.%d waiting for 2 %d.readers to exit\n", getpid(), mp_gettid(), childpid); mp_decsema(Exitwait); if (Verbose) printf("start_agent: %d.%d waiting for 1 %d.reader to exit\n", getpid(), mp_gettid(), childpid); mp_decsema(Exitwait); if (Verbose) printf("start_agent: %d.%d all %d.readers exited\n", getpid(), mp_gettid(), childpid); Exit = 0; mp_unlock(Exitlock); /* Broadcast a message */ sprintf(elogerr.msg, "agentd: %s\n", msg); SEND(EVENT_BCAST_NOTME, AGENTD_LOG, elogerr); close(pipeout[0]); close(pipeout[1]); close(pipeerr[0]); close(pipeerr[1]); /* * Report exit status back to requester */ if (areq) { areq->status = AGENTD_AGENT_EXIT; estat.result = exitstat; estat.rstatus = AGENTD_AGENT_EXIT; SEND(EventFrom(areq->ereq), AGENTD_STAT, estat); } if (retpid) *retpid = childpid; return(AGENTD_STATUS_OK); }
void start_login(char *host, int autologin, char *name) { char **argv; #define TABBUFSIZ 512 char defent[TABBUFSIZ]; char defstrs[TABBUFSIZ]; #undef TABBUFSIZ const char *loginprog = NULL; extern struct sockaddr_storage from; char buf[sizeof(from) * 4 + 1]; scrub_env(); /* * -a : pass on the address of the host. * -h : pass on name of host. * WARNING: -h and -a are accepted by login * if and only if getuid() == 0. * -p : don't clobber the environment (so terminal type stays set). * * -f : force this login, he has already been authenticated */ argv = addarg(0, "login"); argv = addarg(argv, "-a"); (void)strvisx(buf, (const char *)(const void *)&from, sizeof(from), VIS_WHITE); argv = addarg(argv, buf); argv = addarg(argv, "-h"); argv = addarg(argv, host); argv = addarg(argv, "-p"); #ifdef LINEMODE /* * Set the environment variable "LINEMODE" to either * "real" or "kludge" if we are operating in either * real or kludge linemode. */ if (lmodetype == REAL_LINEMODE) setenv("LINEMODE", "real", 1); # ifdef KLUDGELINEMODE else if (lmodetype == KLUDGE_LINEMODE || lmodetype == KLUDGE_OK) setenv("LINEMODE", "kludge", 1); # endif #endif #ifdef SECURELOGIN /* * don't worry about the -f that might get sent. * A -s is supposed to override it anyhow. */ if (require_secure_login) argv = addarg(argv, "-s"); #endif #ifdef AUTHENTICATION if (auth_level >= 0 && autologin == AUTH_VALID) { argv = addarg(argv, "-f"); argv = addarg(argv, "--"); argv = addarg(argv, name); } else #endif if (getenv("USER")) { argv = addarg(argv, "--"); argv = addarg(argv, getenv("USER")); /* * Assume that login will set the USER variable * correctly. For SysV systems, this means that * USER will no longer be set, just LOGNAME by * login. (The problem is that if the auto-login * fails, and the user then specifies a different * account name, he can get logged in with both * LOGNAME and USER in his environment, but the * USER value will be wrong. */ unsetenv("USER"); } if (getent(defent, gettyname) == 1) { char *cp = defstrs; loginprog = getstr("lo", &cp); } if (loginprog == NULL) loginprog = _PATH_LOGIN; closelog(); /* * This sleep(1) is in here so that telnetd can * finish up with the tty. There's a race condition * the login banner message gets lost... */ sleep(1); execv(loginprog, argv); syslog(LOG_ERR, "%s: %m", loginprog); fatalperror(net, loginprog); /*NOTREACHED*/ }
int main(int argc, char *argv[]) { int cmd, r; unsigned retries; bool need_umount = true, need_swapoff = true, need_loop_detach = true, need_dm_detach = true; bool in_container, use_watchdog = false; char *arguments[3]; log_parse_environment(); log_set_target(LOG_TARGET_CONSOLE); /* syslog will die if not gone yet */ log_open(); umask(0022); if (getpid() != 1) { log_error("Not executed by init (pid 1)."); r = -EPERM; goto error; } if (argc != 2) { log_error("Invalid number of arguments."); r = -EINVAL; goto error; } in_container = detect_container(NULL) > 0; if (streq(argv[1], "reboot")) cmd = RB_AUTOBOOT; else if (streq(argv[1], "poweroff")) cmd = RB_POWER_OFF; else if (streq(argv[1], "halt")) cmd = RB_HALT_SYSTEM; else if (streq(argv[1], "kexec")) cmd = LINUX_REBOOT_CMD_KEXEC; else { log_error("Unknown action '%s'.", argv[1]); r = -EINVAL; goto error; } use_watchdog = !!getenv("WATCHDOG_USEC"); /* lock us into memory */ mlockall(MCL_CURRENT|MCL_FUTURE); log_info("Sending SIGTERM to remaining processes..."); broadcast_signal(SIGTERM, true); log_info("Sending SIGKILL to remaining processes..."); broadcast_signal(SIGKILL, true); if (in_container) { need_swapoff = false; need_dm_detach = false; need_loop_detach = false; } /* Unmount all mountpoints, swaps, and loopback devices */ for (retries = 0; retries < FINALIZE_ATTEMPTS; retries++) { bool changed = false; if (use_watchdog) watchdog_ping(); if (need_umount) { log_info("Unmounting file systems."); r = umount_all(&changed); if (r == 0) need_umount = false; else if (r > 0) log_info("Not all file systems unmounted, %d left.", r); else log_error("Failed to unmount file systems: %s", strerror(-r)); } if (need_swapoff) { log_info("Disabling swaps."); r = swapoff_all(&changed); if (r == 0) need_swapoff = false; else if (r > 0) log_info("Not all swaps are turned off, %d left.", r); else log_error("Failed to turn off swaps: %s", strerror(-r)); } if (need_loop_detach) { log_info("Detaching loop devices."); r = loopback_detach_all(&changed); if (r == 0) need_loop_detach = false; else if (r > 0) log_info("Not all loop devices detached, %d left.", r); else log_error("Failed to detach loop devices: %s", strerror(-r)); } if (need_dm_detach) { log_info("Detaching DM devices."); r = dm_detach_all(&changed); if (r == 0) need_dm_detach = false; else if (r > 0) log_warning("Not all DM devices detached, %d left.", r); else log_error("Failed to detach DM devices: %s", strerror(-r)); } if (!need_umount && !need_swapoff && !need_loop_detach && !need_dm_detach) { if (retries > 0) log_info("All filesystems, swaps, loop devices, DM devices detached."); /* Yay, done */ break; } /* If in this iteration we didn't manage to * unmount/deactivate anything, we simply give up */ if (!changed) { log_error("Cannot finalize remaining file systems and devices, giving up."); break; } log_debug("Couldn't finalize remaining file systems and devices after %u retries, trying again.", retries+1); } if (retries >= FINALIZE_ATTEMPTS) log_error("Too many iterations, giving up."); arguments[0] = NULL; arguments[1] = argv[1]; arguments[2] = NULL; execute_directory(SYSTEM_SHUTDOWN_PATH, NULL, arguments); /* If we are in a container, just exit, this will kill our * container for good. */ if (in_container) { log_error("Exiting container."); exit(0); } if (access("/run/initramfs/shutdown", X_OK) == 0) { if (prepare_new_root() >= 0 && pivot_to_new_root() >= 0) { execv("/shutdown", argv); log_error("Failed to execute shutdown binary: %m"); } } sync(); if (cmd == LINUX_REBOOT_CMD_KEXEC) { /* We cheat and exec kexec to avoid doing all its work */ pid_t pid = fork(); if (pid < 0) log_error("Could not fork: %m. Falling back to normal reboot."); else if (pid > 0) { wait_for_terminate_and_warn("kexec", pid); log_warning("kexec failed. Falling back to normal reboot."); } else { /* Child */ const char *args[3] = { "/sbin/kexec", "-e", NULL }; execv(args[0], (char * const *) args); return EXIT_FAILURE; } cmd = RB_AUTOBOOT; } reboot(cmd); log_error("Failed to invoke reboot(): %m"); r = -errno; error: log_error("Critical error while doing system shutdown: %s", strerror(-r)); freeze(); return EXIT_FAILURE; }
/* execute a compiler backend, capturing all output to the given paths the full path to the compiler to run is in argv[0] */ int execute(char **argv, const char *path_stdout, const char *path_stderr) { #ifdef _WIN32 PROCESS_INFORMATION pinfo; STARTUPINFO sinfo; BOOL ret; DWORD exitcode; char *args; HANDLE fd_out, fd_err; SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE}; fd_out = CreateFile(path_stdout, GENERIC_WRITE, 0, &sa, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (fd_out == INVALID_HANDLE_VALUE) { return STATUS_NOCACHE; } fd_err = CreateFile(path_stderr, GENERIC_WRITE, 0, &sa, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (fd_err == INVALID_HANDLE_VALUE) { return STATUS_NOCACHE; } ZeroMemory(&pinfo, sizeof(PROCESS_INFORMATION)); ZeroMemory(&sinfo, sizeof(STARTUPINFO)); sinfo.cb = sizeof(STARTUPINFO); sinfo.hStdError = fd_err; sinfo.hStdOutput = fd_out; sinfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE); sinfo.dwFlags |= STARTF_USESTDHANDLES; args = argvtos(argv); ret = CreateProcessA(argv[0], args, NULL, NULL, TRUE, 0, NULL, NULL, &sinfo, &pinfo); free(args); CloseHandle(fd_out); CloseHandle(fd_err); if (ret == 0) return -1; WaitForSingleObject(pinfo.hProcess, INFINITE); GetExitCodeProcess(pinfo.hProcess, &exitcode); CloseHandle(pinfo.hProcess); CloseHandle(pinfo.hThread); return exitcode; #else pid_t pid; int status; pid = fork(); if (pid == -1) fatal("Failed to fork"); if (pid == 0) { int fd; unlink(path_stdout); fd = open(path_stdout, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL|O_BINARY, 0666); if (fd == -1) { exit(STATUS_NOCACHE); } dup2(fd, 1); close(fd); unlink(path_stderr); fd = open(path_stderr, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL|O_BINARY, 0666); if (fd == -1) { exit(STATUS_NOCACHE); } dup2(fd, 2); close(fd); exit(execv(argv[0], argv)); } if (waitpid(pid, &status, 0) != pid) { fatal("waitpid failed"); } if (WEXITSTATUS(status) == 0 && WIFSIGNALED(status)) { return -1; } return WEXITSTATUS(status); #endif }
int execvp(const char *file, char *const argv[]) { const char *path; const char *p; int max_exe_len; /* * If the file contains a / use don't bother with * the PATH. Just fall back to execv */ if (strchr(file, '/')) { return execv(file, argv); } /* Get the PATH */ if ((path = getenv("PATH")) == NULL) { path = "/usr/local/bin:/usr/bin:/bin"; } max_exe_len = strlen(path) + 1 + strlen(file) + 1; p = path; while (*p) { char exename[max_exe_len]; char *d = exename; /* Get the next PATH entry */ while ((*d = *p)) { if (*d == ':') { *d = '\0'; ++p; break; } if (*d == '\0') { break; } ++d; ++p; } /* An empty path means look in the pwd, otherwise add '/' */ if (*exename != '\0') { strcat(exename, "/"); } strcat(exename, file); execve(exename, argv, environ); if (errno != ENOENT) { return -1; } } errno = ENOENT; return -1; }
static int recv_fd(int c) { int fd; uint8_t msgbuf[CMSG_SPACE(sizeof(fd))]; struct msghdr msg = { .msg_control = msgbuf, .msg_controllen = sizeof(msgbuf), }; struct cmsghdr *cmsg; struct iovec iov; uint8_t req[1]; ssize_t len; cmsg = CMSG_FIRSTHDR(&msg); cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_RIGHTS; cmsg->cmsg_len = CMSG_LEN(sizeof(fd)); msg.msg_controllen = cmsg->cmsg_len; iov.iov_base = req; iov.iov_len = sizeof(req); msg.msg_iov = &iov; msg.msg_iovlen = 1; len = recvmsg(c, &msg, 0); if (len > 0) { memcpy(&fd, CMSG_DATA(cmsg), sizeof(fd)); return fd; } return len; } static int net_bridge_run_helper(const char *helper, const char *bridge) { sigset_t oldmask, mask; int pid, status; char *args[5]; char **parg; int sv[2]; sigemptyset(&mask); sigaddset(&mask, SIGCHLD); sigprocmask(SIG_BLOCK, &mask, &oldmask); if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) == -1) { return -1; } /* try to launch bridge helper */ pid = fork(); if (pid == 0) { int open_max = sysconf(_SC_OPEN_MAX), i; char fd_buf[6+10]; char br_buf[6+IFNAMSIZ] = {0}; char helper_cmd[PATH_MAX + sizeof(fd_buf) + sizeof(br_buf) + 15]; for (i = 0; i < open_max; i++) { if (i != STDIN_FILENO && i != STDOUT_FILENO && i != STDERR_FILENO && i != sv[1]) { close(i); } } snprintf(fd_buf, sizeof(fd_buf), "%s%d", "--fd=", sv[1]); if (strrchr(helper, ' ') || strrchr(helper, '\t')) { /* assume helper is a command */ if (strstr(helper, "--br=") == NULL) { snprintf(br_buf, sizeof(br_buf), "%s%s", "--br=", bridge); } snprintf(helper_cmd, sizeof(helper_cmd), "%s %s %s %s", helper, "--use-vnet", fd_buf, br_buf); parg = args; *parg++ = (char *)"sh"; *parg++ = (char *)"-c"; *parg++ = helper_cmd; *parg++ = NULL; execv("/bin/sh", args); } else { /* assume helper is just the executable path name */ snprintf(br_buf, sizeof(br_buf), "%s%s", "--br=", bridge); parg = args; *parg++ = (char *)helper; *parg++ = (char *)"--use-vnet"; *parg++ = fd_buf; *parg++ = br_buf; *parg++ = NULL; execv(helper, args); } _exit(1); } else if (pid > 0) { int fd; close(sv[1]); do { fd = recv_fd(sv[0]); } while (fd == -1 && errno == EINTR); close(sv[0]); while (waitpid(pid, &status, 0) != pid) { /* loop */ } sigprocmask(SIG_SETMASK, &oldmask, NULL); if (fd < 0) { fprintf(stderr, "failed to recv file descriptor\n"); return -1; } if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { return fd; } } fprintf(stderr, "failed to launch bridge helper\n"); return -1; }
int main(int argc, char *argv[]) { bool need_umount, need_swapoff, need_loop_detach, need_dm_detach; bool in_container, use_watchdog = false; _cleanup_free_ char *cgroup = NULL; char *arguments[3]; unsigned retries; int cmd, r; static const char* const dirs[] = {SYSTEM_SHUTDOWN_PATH, NULL}; log_parse_environment(); r = parse_argv(argc, argv); if (r < 0) goto error; /* journald will die if not gone yet. The log target defaults * to console, but may have been changed by command line options. */ log_close_console(); /* force reopen of /dev/console */ log_open(); umask(0022); if (getpid() != 1) { log_error("Not executed by init (PID 1)."); r = -EPERM; goto error; } if (streq(arg_verb, "reboot")) cmd = RB_AUTOBOOT; else if (streq(arg_verb, "poweroff")) cmd = RB_POWER_OFF; else if (streq(arg_verb, "halt")) cmd = RB_HALT_SYSTEM; else if (streq(arg_verb, "kexec")) cmd = LINUX_REBOOT_CMD_KEXEC; else { r = -EINVAL; log_error("Unknown action '%s'.", arg_verb); goto error; } cg_get_root_path(&cgroup); use_watchdog = !!getenv("WATCHDOG_USEC"); /* lock us into memory */ mlockall(MCL_CURRENT|MCL_FUTURE); log_info("Sending SIGTERM to remaining processes..."); broadcast_signal(SIGTERM, true, true); log_info("Sending SIGKILL to remaining processes..."); broadcast_signal(SIGKILL, true, false); in_container = detect_container(NULL) > 0; need_umount = !in_container; need_swapoff = !in_container; need_loop_detach = !in_container; need_dm_detach = !in_container; /* Unmount all mountpoints, swaps, and loopback devices */ for (retries = 0; retries < FINALIZE_ATTEMPTS; retries++) { bool changed = false; if (use_watchdog) watchdog_ping(); /* Let's trim the cgroup tree on each iteration so that we leave an empty cgroup tree around, so that container managers get a nice notify event when we are down */ if (cgroup) cg_trim(SYSTEMD_CGROUP_CONTROLLER, cgroup, false); if (need_umount) { log_info("Unmounting file systems."); r = umount_all(&changed); if (r == 0) { need_umount = false; log_info("All filesystems unmounted."); } else if (r > 0) log_info("Not all file systems unmounted, %d left.", r); else log_error_errno(r, "Failed to unmount file systems: %m"); } if (need_swapoff) { log_info("Deactivating swaps."); r = swapoff_all(&changed); if (r == 0) { need_swapoff = false; log_info("All swaps deactivated."); } else if (r > 0) log_info("Not all swaps deactivated, %d left.", r); else log_error_errno(r, "Failed to deactivate swaps: %m"); } if (need_loop_detach) { log_info("Detaching loop devices."); r = loopback_detach_all(&changed); if (r == 0) { need_loop_detach = false; log_info("All loop devices detached."); } else if (r > 0) log_info("Not all loop devices detached, %d left.", r); else log_error_errno(r, "Failed to detach loop devices: %m"); } if (need_dm_detach) { log_info("Detaching DM devices."); r = dm_detach_all(&changed); if (r == 0) { need_dm_detach = false; log_info("All DM devices detached."); } else if (r > 0) log_info("Not all DM devices detached, %d left.", r); else log_error_errno(r, "Failed to detach DM devices: %m"); } if (!need_umount && !need_swapoff && !need_loop_detach && !need_dm_detach) { if (retries > 0) log_info("All filesystems, swaps, loop devices, DM devices detached."); /* Yay, done */ goto initrd_jump; } /* If in this iteration we didn't manage to * unmount/deactivate anything, we simply give up */ if (!changed) { log_info("Cannot finalize remaining%s%s%s%s continuing.", need_umount ? " file systems," : "", need_swapoff ? " swap devices," : "", need_loop_detach ? " loop devices," : "", need_dm_detach ? " DM devices," : ""); goto initrd_jump; } log_debug("After %u retries, couldn't finalize remaining %s%s%s%s trying again.", retries + 1, need_umount ? " file systems," : "", need_swapoff ? " swap devices," : "", need_loop_detach ? " loop devices," : "", need_dm_detach ? " DM devices," : ""); } log_error("Too many iterations, giving up."); initrd_jump: arguments[0] = NULL; arguments[1] = arg_verb; arguments[2] = NULL; execute_directories(dirs, DEFAULT_TIMEOUT_USEC, arguments); if (!in_container && !in_initrd() && access("/run/initramfs/shutdown", X_OK) == 0) { r = switch_root_initramfs(); if (r >= 0) { argv[0] = (char*) "/shutdown"; setsid(); make_console_stdio(); log_info("Successfully changed into root pivot.\n" "Returning to initrd..."); execv("/shutdown", argv); log_error_errno(errno, "Failed to execute shutdown binary: %m"); } else log_error_errno(r, "Failed to switch root to \"/run/initramfs\": %m"); } if (need_umount || need_swapoff || need_loop_detach || need_dm_detach) log_error("Failed to finalize %s%s%s%s ignoring", need_umount ? " file systems," : "", need_swapoff ? " swap devices," : "", need_loop_detach ? " loop devices," : "", need_dm_detach ? " DM devices," : ""); /* The kernel will automaticall flush ATA disks and suchlike * on reboot(), but the file systems need to be synce'd * explicitly in advance. So let's do this here, but not * needlessly slow down containers. */ if (!in_container) sync(); switch (cmd) { case LINUX_REBOOT_CMD_KEXEC: if (!in_container) { /* We cheat and exec kexec to avoid doing all its work */ pid_t pid; log_info("Rebooting with kexec."); pid = fork(); if (pid < 0) log_error_errno(errno, "Failed to fork: %m"); else if (pid == 0) { const char * const args[] = { KEXEC, "-e", NULL }; /* Child */ execv(args[0], (char * const *) args); _exit(EXIT_FAILURE); } else wait_for_terminate_and_warn("kexec", pid, true); } cmd = RB_AUTOBOOT; /* Fall through */ case RB_AUTOBOOT: if (!in_container) { _cleanup_free_ char *param = NULL; if (read_one_line_file(REBOOT_PARAM_FILE, ¶m) >= 0) { log_info("Rebooting with argument '%s'.", param); syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_RESTART2, param); } } log_info("Rebooting."); break; case RB_POWER_OFF: log_info("Powering off."); break; case RB_HALT_SYSTEM: log_info("Halting system."); break; default: assert_not_reached("Unknown magic"); } reboot(cmd); if (errno == EPERM && in_container) { /* If we are in a container, and we lacked * CAP_SYS_BOOT just exit, this will kill our * container for good. */ log_info("Exiting container."); exit(0); } log_error_errno(errno, "Failed to invoke reboot(): %m"); r = -errno; error: log_emergency_errno(r, "Critical error while doing system shutdown: %m"); freeze(); }
int main(int argc, char **argv) { char *prog; const char **user_argv; struct commands *cmd; int count; git_setup_gettext(); git_extract_argv0_path(argv[0]); /* * Always open file descriptors 0/1/2 to avoid clobbering files * in die(). It also avoids messing up when the pipes are dup'ed * onto stdin/stdout/stderr in the child processes we spawn. */ sanitize_stdfds(); /* * Special hack to pretend to be a CVS server */ if (argc == 2 && !strcmp(argv[1], "cvs server")) { argv--; } else if (argc == 1) { /* Allow the user to run an interactive shell */ cd_to_homedir(); if (access(COMMAND_DIR, R_OK | X_OK) == -1) { die("Interactive git shell is not enabled.\n" "hint: ~/" COMMAND_DIR " should exist " "and have read and execute access."); } run_shell(); exit(0); } else if (argc != 3 || strcmp(argv[1], "-c")) { /* * We do not accept any other modes except "-c" followed by * "cmd arg", where "cmd" is a very limited subset of git * commands or a command in the COMMAND_DIR */ die("Run with no arguments or with -c cmd"); } prog = xstrdup(argv[2]); if (!strncmp(prog, "git", 3) && isspace(prog[3])) /* Accept "git foo" as if the caller said "git-foo". */ prog[3] = '-'; for (cmd = cmd_list ; cmd->name ; cmd++) { int len = strlen(cmd->name); char *arg; if (strncmp(cmd->name, prog, len)) continue; arg = NULL; switch (prog[len]) { case '\0': arg = NULL; break; case ' ': arg = prog + len + 1; break; default: continue; } exit(cmd->exec(cmd->name, arg)); } cd_to_homedir(); count = split_cmdline(prog, &user_argv); if (count >= 0) { if (is_valid_cmd_name(user_argv[0])) { prog = make_cmd(user_argv[0]); user_argv[0] = prog; execv(user_argv[0], (char *const *) user_argv); } free(prog); free(user_argv); die("unrecognized command '%s'", argv[2]); } else { free(prog); die("invalid command format '%s': %s", argv[2], split_cmdline_strerror(count)); } }
int spawn(char *program, char *argv[], int sin, int sout, int serr, int search, char *envp[], char *pty_name, int wait) { int pid = fork(); int fd; sigset_t sset; if (pid != 0) return pid; /* Put us in our own process group, but only if we need not * share stdin with our parent. In the latter case we claim * control of the terminal. */ if (sin >= 0) { #if defined(LISP_FEATURE_HPUX) || defined(LISP_FEATURE_OPENBSD) setsid(); #elif defined(LISP_FEATURE_DARWIN) setpgid(0, getpid()); #elif defined(SVR4) || defined(__linux__) || defined(__osf__) setpgrp(); #else setpgrp(0, getpid()); #endif } else { tcsetpgrp(0, getpgrp()); } /* unblock signals */ sigemptyset(&sset); sigprocmask(SIG_SETMASK, &sset, NULL); /* If we are supposed to be part of some other pty, go for it. */ if (pty_name) set_pty(pty_name); else { /* Set up stdin, stdout, and stderr */ if (sin >= 0) dup2(sin, 0); if (sout >= 0) dup2(sout, 1); if (serr >= 0) dup2(serr, 2); } /* Close all other fds. */ #ifdef SVR4 for (fd = sysconf(_SC_OPEN_MAX)-1; fd >= 3; fd--) close(fd); #else for (fd = getdtablesize()-1; fd >= 3; fd--) close(fd); #endif environ = envp; /* Exec the program. */ if (search) execvp(program, argv); else execv(program, argv); exit (1); }
int main(int argc, char *argv[]) { #ifdef HAVE_EXECV char cmd[PATH_MAX+1], buf[PATH_MAX+8], buf2[1100], *p; int i, i0 = 0, ac = 0, res = 0, e_mode = 0, set_dp = 0; char **av; if(argc <= 1) { usage(); exit(1); } av = (char **) malloc((size_t) (argc+4)*sizeof(char *)); if(!av) { fprintf(stderr, "malloc failure\n"); exit(1); } p = getenv("RHOME"); #ifdef _WIN32 if(p && *p) snprintf(cmd, PATH_MAX+1, "%s\\%s\\Rterm.exe", p, BINDIR); else { char rhome[MAX_PATH]; GetModuleFileName(NULL, rhome, MAX_PATH); p = strrchr(rhome,'\\'); if(!p) { fprintf(stderr, "installation problem\n"); exit(1); } *p = '\0'; snprintf(cmd, PATH_MAX+1, "%s\\Rterm.exe", rhome); } #else if(!(p && *p)) p = rhome; /* avoid snprintf here */ if(strlen(p) + 6 > PATH_MAX) { fprintf(stderr, "impossibly long path for RHOME\n"); exit(1); } snprintf(cmd, PATH_MAX+1, "%s/bin/R", p); #endif av[ac++] = cmd; av[ac++] = "--slave"; av[ac++] = "--no-restore"; if(argc == 2) { if(strcmp(argv[1], "--help") == 0) { usage(); exit(0); } if(strcmp(argv[1], "--version") == 0) { if(strlen(R_STATUS) == 0) fprintf(stderr, "R scripting front-end version %s.%s (%s-%s-%s)\n", R_MAJOR, R_MINOR, R_YEAR, R_MONTH, R_DAY); else fprintf(stderr, "R scripting front-end version %s.%s %s (%s-%s-%s r%s)\n", R_MAJOR, R_MINOR, R_STATUS, R_YEAR, R_MONTH, R_DAY, R_GIT_REVISION); exit(0); } } /* first copy over any -e or --foo args */ for(i = 1; i < argc; i++) { if(strcmp(argv[i], "-e") == 0) { e_mode = 1; av[ac++] = argv[i]; if(!argv[++i]) { fprintf(stderr, "-e not followed by an expression\n"); exit(1); } av[ac++] = argv[i]; i0 = i; continue; } if(strncmp(argv[i], "--", 2) != 0) break; if(strcmp(argv[i], "--verbose") == 0) { verbose = 1; i0 = i; continue; } if(strncmp(argv[i], "--default-packages=", 18) == 0) { set_dp = 1; if(strlen(argv[i]) > 1000) { fprintf(stderr, "unable to set R_DEFAULT_PACKAGES\n"); exit(1); } snprintf(buf2, 1100, "R_DEFAULT_PACKAGES=%s", argv[i]+19); if(verbose) fprintf(stderr, "setting '%s'\n", buf2); #ifdef HAVE_PUTENV if(putenv(buf2)) #endif { fprintf(stderr, "unable to set R_DEFAULT_PACKAGES\n"); exit(1); } i0 = i; continue; } av[ac++] = argv[i]; i0 = i; } if(!e_mode) { if(++i0 >= argc) { fprintf(stderr, "file name is missing\n"); exit(1); } if(strlen(argv[i0]) > PATH_MAX) { fprintf(stderr, "file name is too long\n"); exit(1); } snprintf(buf, PATH_MAX+8, "--file=%s", argv[i0]); av[ac++] = buf; } // copy any user arguments, preceded by "--args" i = i0+1; if (i < argc) { av[ac++] = "--args"; for(; i < argc; i++) av[ac++] = argv[i]; } av[ac] = (char *) NULL; #ifdef HAVE_PUTENV if(!set_dp && !getenv("R_DEFAULT_PACKAGES")) putenv("R_DEFAULT_PACKAGES=datasets,utils,grDevices,graphics,stats"); #ifndef _WIN32 /* pass on r_arch from this binary to R as a default */ if (!getenv("R_ARCH") && *rarch) { /* we have to prefix / so we may as well use putenv */ if (strlen(rarch) + 9 > sizeof(buf2)) { fprintf(stderr, "impossibly long string for R_ARCH\n"); exit(1); } strcpy(buf2, "R_ARCH=/"); strcat(buf2, rarch); putenv(buf2); } #endif #endif if(verbose) { fprintf(stderr, "running\n '%s", cmd); for(i = 1; i < ac; i++) fprintf(stderr, " %s", av[i]); fprintf(stderr, "'\n\n"); } #ifndef _WIN32 res = execv(cmd, av); /* will not return if R is launched */ perror("Rscript execution error"); #else AppMain(ac, av); #endif return res; #else /* No execv*/ fprintf(stderr, "Rscript is not supported on this system"); exit(1); #endif }
Value * RunProgramFn (const char *name, State * state, int argc, Expr * argv[]) { if (argc < 1) { return ErrorAbort (state, "%s() expects at least 1 arg", name); } char **args = ReadVarArgs (state, argc, argv); if (args == NULL) { return NULL; } char **args2 = malloc (sizeof (char *) * (argc + 1)); memcpy (args2, args, sizeof (char *) * argc); args2[argc] = NULL; fprintf (stderr, "about to run program [%s] with %d args\n", args2[0], argc); pid_t child = fork (); if (child == 0) { execv (args2[0], args2); fprintf (stderr, "run_program: execv failed: %s\n", strerror (errno)); _exit (1); } int status; waitpid (child, &status, 0); if (WIFEXITED (status)) { if (WEXITSTATUS (status) != 0) { fprintf (stderr, "run_program: child exited with status %d\n", WEXITSTATUS (status)); } } else if (WIFSIGNALED (status)) { fprintf (stderr, "run_program: child terminated by signal %d\n", WTERMSIG (status)); } int i; for (i = 0; i < argc; ++i) { free (args[i]); } free (args); free (args2); char buffer[20]; sprintf (buffer, "%d", status); return StringValue (strdup (buffer)); }
static Bool _ExecuteProcess(MessageHandler *handler, ProcessNode *node) { char *module; int pid; int pAPR[2], pAPW[2], pDBR[2], pDBW[2]; Bool rc; NETFILE *fpAPR, *fpAPW; char line[SIZE_BUFF], **cmd; if (handler->loadpath == NULL) { handler->loadpath = ExecPath; } signal(SIGPIPE, SignalHandler); module = ValueStringPointer(GetItemLongName(node->mcprec->value, "dc.module")); ExpandStart(line, handler->start, handler->loadpath, module, ""); cmd = ParCommandLine(line); if (pipe(pAPR) != 0) { perror("pipe"); exit(1); } if (pipe(pAPW) != 0) { perror("pipe"); exit(1); } if (pipe(pDBR) != 0) { perror("pipe"); exit(1); } if (pipe(pDBW) != 0) { perror("pipe"); exit(1); } if (setjmp(SubError) == 0) { if ((pid = fork()) == 0) { dup2(pAPW[0], STDIN_FILENO); dup2(pAPR[1], STDOUT_FILENO); close(pAPW[0]); close(pAPW[1]); close(pAPR[0]); close(pAPR[1]); dup2(pDBW[0], DBIN_FILENO); dup2(pDBR[1], DBOUT_FILENO); close(pDBW[0]); close(pDBW[1]); close(pDBR[0]); close(pDBR[1]); execv(cmd[0], cmd); } else { fpAPR = FileToNet(pAPR[0]); close(pAPR[1]); fpAPW = FileToNet(pAPW[1]); close(pAPW[0]); fpDBR = FileToNet(pDBR[0]); close(pDBR[1]); fpDBW = FileToNet(pDBW[1]); close(pDBW[0]); StartDB(handler); PutApplication(handler, fpAPW, node); GetApplication(handler, fpAPR, node); (void)wait(&pid); CancelDB(); signal(SIGPIPE, SIG_DFL); CloseNet(fpAPW); CloseNet(fpAPR); CloseNet(fpDBW); CloseNet(fpDBR); } rc = TRUE; } else { rc = FALSE; } return (rc); }
// If the package contains an update binary, extract it and run it. static int try_update_binary(const char *path, ZipArchive *zip) { const ZipEntry* binary_entry = mzFindZipEntry(zip, ASSUMED_UPDATE_BINARY_NAME); if (binary_entry == NULL) { return INSTALL_CORRUPT; } char* binary = "/tmp/update_binary"; unlink(binary); int fd = creat(binary, 0755); if (fd < 0) { LOGE("Can't make %s\n", binary); return 1; } bool ok = mzExtractZipEntryToFile(zip, binary_entry, fd); close(fd); if (!ok) { LOGE("Can't copy %s\n", ASSUMED_UPDATE_BINARY_NAME); return 1; } int pipefd[2]; pipe(pipefd); // When executing the update binary contained in the package, the // arguments passed are: // // - the version number for this interface // // - an fd to which the program can write in order to update the // progress bar. The program can write single-line commands: // // progress <frac> <secs> // fill up the next <frac> part of of the progress bar // over <secs> seconds. If <secs> is zero, use // set_progress commands to manually control the // progress of this segment of the bar // // set_progress <frac> // <frac> should be between 0.0 and 1.0; sets the // progress bar within the segment defined by the most // recent progress command. // // firmware <"hboot"|"radio"> <filename> // arrange to install the contents of <filename> in the // given partition on reboot. (API v2: <filename> may // start with "PACKAGE:" to indicate taking a file from // the OTA package.) // // ui_print <string> // display <string> on the screen. // // - the name of the package zip file. // char** args = malloc(sizeof(char*) * 5); args[0] = binary; args[1] = EXPAND(RECOVERY_API_VERSION); // defined in Android.mk args[2] = malloc(10); sprintf(args[2], "%d", pipefd[1]); args[3] = (char*)path; args[4] = NULL; pid_t pid = fork(); if (pid == 0) { close(pipefd[0]); execv(binary, args); fprintf(stderr, "E:Can't run %s (%s)\n", binary, strerror(errno)); _exit(-1); } close(pipefd[1]); char* firmware_type = NULL; char* firmware_filename = NULL; char buffer[81]; FILE* from_child = fdopen(pipefd[0], "r"); while (fgets(buffer, sizeof(buffer), from_child) != NULL) { LOGI("read: %s", buffer); char* command = strtok(buffer, " \n"); if (command == NULL) { continue; } else if (strcmp(command, "progress") == 0) { char* fraction_s = strtok(NULL, " \n"); char* seconds_s = strtok(NULL, " \n"); float fraction = strtof(fraction_s, NULL); int seconds = strtol(seconds_s, NULL, 10); ui_show_progress(fraction * (1-VERIFICATION_PROGRESS_FRACTION), seconds); } else if (strcmp(command, "set_progress") == 0) { char* fraction_s = strtok(NULL, " \n"); float fraction = strtof(fraction_s, NULL); ui_set_progress(fraction); } else if (strcmp(command, "firmware") == 0) { char* type = strtok(NULL, " \n"); char* filename = strtok(NULL, " \n"); if (type != NULL && filename != NULL) { if (firmware_type != NULL) { LOGE("ignoring attempt to do multiple firmware updates"); } else { firmware_type = strdup(type); firmware_filename = strdup(filename); } } } else if (strcmp(command, "ui_print") == 0) { char* str = strtok(NULL, "\n"); if (str) { ui_print(str); } else { ui_print("\n"); } } else { LOGE("unknown command [%s]\n", command); } } fclose(from_child); int status; waitpid(pid, &status, 0); if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { LOGE("Error in %s\n(Status %d)\n", path, WEXITSTATUS(status)); return INSTALL_ERROR; } if (firmware_type != NULL) { return handle_firmware_update(firmware_type, firmware_filename, zip); } else { return INSTALL_SUCCESS; } }
int main(int argc, char *argv[]) { char dirid[PATH_MAX]; char outdir[PATH_MAX]; char bbgencmd[PATH_MAX]; char bbwebenv[PATH_MAX]; char bbgentimeopt[100]; char *bbgen_argv[20]; pid_t childpid; int childstat; char htmldelim[20]; char startstr[20]; int argi, newargi; char *envarea = NULL; char *useragent; int usemultipart = 1; newargi = 0; bbgen_argv[newargi++] = bbgencmd; bbgen_argv[newargi++] = bbgentimeopt; for (argi=1; (argi < argc); argi++) { if (argnmatch(argv[argi], "--env=")) { char *p = strchr(argv[argi], '='); loadenv(p+1, envarea); } else if (argnmatch(argv[argi], "--area=")) { char *p = strchr(argv[argi], '='); envarea = strdup(p+1); } else { bbgen_argv[newargi++] = argv[argi]; } } bbgen_argv[newargi++] = outdir; bbgen_argv[newargi++] = NULL; redirect_cgilog("bb-snapshot"); cgidata = cgi_request(); if (cgidata == NULL) { /* Present the query form */ sethostenv("", "", "", colorname(COL_BLUE), NULL); printf("Content-type: %s\n\n", xgetenv("HTMLCONTENTTYPE")); showform(stdout, "snapshot", "snapshot_form", COL_BLUE, getcurrenttime(NULL), NULL, NULL); return 0; } parse_query(); useragent = getenv("HTTP_USER_AGENT"); if (useragent && strstr(useragent, "KHTML")) { /* KHTML (Konqueror, Safari) cannot handle multipart documents. */ usemultipart = 0; } /* * Need to set these up AFTER putting them into bbgen_argv, since we * need to have option parsing done first. */ if (xgetenv("BBGEN")) sprintf(bbgencmd, "%s", xgetenv("BBGEN")); else sprintf(bbgencmd, "%s/bin/bbgen", xgetenv("BBHOME")); sprintf(bbgentimeopt, "--snapshot=%u", (unsigned int)starttime); sprintf(dirid, "%u-%u", (unsigned int)getpid(), (unsigned int)getcurrenttime(NULL)); sprintf(outdir, "%s/%s", xgetenv("BBSNAP"), dirid); if (mkdir(outdir, 0755) == -1) errormsg("Cannot create output directory"); sprintf(bbwebenv, "BBWEB=%s/%s", xgetenv("BBSNAPURL"), dirid); putenv(bbwebenv); if (usemultipart) { /* Output the "please wait for report ... " thing */ sprintf(htmldelim, "bbrep-%u-%u", (int)getpid(), (unsigned int)getcurrenttime(NULL)); printf("Content-type: multipart/mixed;boundary=%s\n", htmldelim); printf("\n"); printf("%s\n", htmldelim); printf("Content-type: %s\n\n", xgetenv("HTMLCONTENTTYPE")); /* It's ok with these hardcoded values, as they are not used for this page */ sethostenv("", "", "", colorname(COL_BLUE), NULL); sethostenv_report(starttime, starttime, 97.0, 99.995); headfoot(stdout, "snapshot", "", "header", COL_BLUE); strftime(startstr, sizeof(startstr), "%b %d %Y", localtime(&starttime)); printf("<CENTER><A NAME=begindata> </A>\n"); printf("<BR><BR><BR><BR>\n"); printf("<H3>Generating snapshot: %s<BR>\n", startstr); printf("<P><P>\n"); fflush(stdout); } /* Go do the report */ childpid = fork(); if (childpid == 0) { execv(bbgencmd, bbgen_argv); } else if (childpid > 0) { wait(&childstat); /* Ignore SIGHUP so we dont get killed during cleanup of BBSNAP */ signal(SIGHUP, SIG_IGN); if (WIFEXITED(childstat) && (WEXITSTATUS(childstat) != 0) ) { if (usemultipart) printf("%s\n\n", htmldelim); printf("Content-Type: %s\n\n", xgetenv("HTMLCONTENTTYPE")); errormsg("Could not generate report"); } else { /* Send the browser off to the report */ if (usemultipart) { printf("Done...<P></BODY></HTML>\n"); fflush(stdout); printf("%s\n\n", htmldelim); } printf("Content-Type: %s\n\n", xgetenv("HTMLCONTENTTYPE")); printf("<HTML><HEAD>\n"); printf("<META HTTP-EQUIV=\"REFRESH\" CONTENT=\"0; URL=%s/%s/\"\n", xgetenv("BBSNAPURL"), dirid); printf("</HEAD><BODY BGCOLOR=\"000000\"></BODY></HTML>\n"); if (usemultipart) printf("\n%s\n", htmldelim); fflush(stdout); } cleandir(xgetenv("BBSNAP")); } else { if (usemultipart) printf("%s\n\n", htmldelim); printf("Content-Type: %s\n\n", xgetenv("HTMLCONTENTTYPE")); errormsg("Fork failed"); } return 0; }
int main(int argc, char **argv, char **envp) { struct ELF_File *f; void **newstack; int i, envc, progarg; char *dir, *fil; int maybe = 0; progarg = -1; for (i = 1; i < argc; i++) { if (argv[i][0] == '-') { if (!strcmp(argv[i], "-m")) { maybe = 1; } else if (!strcmp(argv[i], "--")) { progarg = i + 1; break; } } else { progarg = i; break; } } if (progarg == -1) { fprintf(stderr, "Use: elfload [-m] <elf file> [arguments]\n"); return 1; } whereAmI(argv[0], &dir, &fil); elfload_dlinstdir = dir; /* load them all in */ f = loadELF(argv[progarg], dir, maybe); if (!f) { /* try just execing it */ execv(argv[progarg], argv + progarg); fprintf(stderr, "Failed to load %s.\n", argv[progarg]); return 1; } /* relocate them */ relocateELFs(); /* initialize .so files */ initELF(f); /* make its stack */ for (envc = 0; envp[envc]; envc++); newstack = (void**) alloca((argc + envc + 2) * sizeof(void*)); newstack[0] = (void*) (size_t) (argc - progarg); for (i = progarg; i < argc; i++) { newstack[i - progarg + 1] = (void*) argv[i]; } newstack[i - progarg + 1] = NULL; for (i = 0; i < envc; i++) { newstack[i-progarg+argc+2] = (void*) envp[i]; } newstack[i-progarg+argc+2] = NULL; /* and call it */ if (f->ehdr32) { WITHSTACK_JMP(newstack, f->ehdr32->e_entry + f->offset); } else if (f->ehdr64) { WITHSTACK_JMP(newstack, f->ehdr64->e_entry + f->offset); } else { return 1; } }
void execute_cmd(void) { currcmd = currcmd % MAXCMDS; int curr = currcmd; FILE *f; if(comtab[curr].external == 0) { // Built-in Command aliasroot = NULL; aliasDepth = 0; switch(comtab[curr].code) { case CHD : { if( chdir(getHOME) ) { printf("ERROR at line %d\n", __LINE__); break; } setenv("PWD", getHOME, 1); break; } case CDX : { char* dest = cleanInput(comtab[curr].atptr[0]); if( chdir(dest) == -1 ) { printf("ERROR: \n%s is not a directory\n", dest); } char pwd[5000]; getcwd( pwd, sizeof(pwd) ); setenv("PWD", pwd, 1); break; } case SETENV : { char* name = cleanInput(comtab[curr].atptr[0]); char* word = cleanInput(comtab[curr].atptr[1]); if( setenv( name, word, 1 ) == -1 ) { printf("setenv failed, could not set %s to %s\n", name, word ); } break; } case UNSETENV : { char* name = cleanInput(comtab[curr].atptr[0]); if( getenv(name) ){ unsetenv(name); } else { printf("unsetenv failed, could not find %s\n", name); } break; } case PRINTENV : { if(ofileredir) { if(comtab[curr].append) { f = fopen(comtab[curr].outfd, "a"); } else { f = fopen(comtab[curr].outfd, "w"); } if(f == NULL) return SYSERR; } else print_env(); if(ofileredir) fclose(f); break; } case SETALIAS : { char* name = cleanInput(comtab[curr].atptr[0]); char* word = cleanInput(comtab[curr].atptr[1]); setalias(name, word); break; } case UNALIAS : { char* name = cleanInput(comtab[curr].atptr[0]); removealias(name); break; } case PRINTALIAS : { if(ofileredir) { if(comtab[curr].append) { f = fopen(comtab[curr].outfd, "a"); } else { f = fopen(comtab[curr].outfd, "w"); } } else printalias(); if(ofileredir) fclose(f); break; } case PWD : { printf("%s\n", getPWD); break; } } } else { // Handle aliasing int acurr = isalias(comtab[curr].comname); if(acurr != -1) { comtab[curr].external = 0; if(aliasroot == NULL) { aliasroot = aliastab[acurr].alname; } // Check for infinite aliasing if( aliasDepth > 30 ) { printf("ERR: Infinite aliasing detected. Exiting...\n"); return; } else { ignoreEOF = 1; parse_string(aliastab[acurr].alstring); aliasDepth++; execute_cmd(); } } else { // External Command aliasroot = NULL; aliasDepth = 0; pid_t child = fork(); int stat; int success = -1; while(waitpid(child, &stat, 0) == -1) { if(errno != EINTR) { stat = -1; break; } } if(child < 0) exit(1); else if(child == 0) { // Prepare for execv call char tmp[256]; char *paths = strcpy(tmp, getenv("PATH")); char *tok = strtok(paths, ":"); char *cmp = "./"; while(tok) { char place[255]; if(comtab[curr].comname[0] == cmp[0] || comtab[curr].comname[0] == cmp[1]) { // If destination is specified strcpy(place, comtab[curr].comname); } else { // If destination is not specified strcpy(place, tok); strcat(place, "/"); // Append command name strcat(place, comtab[curr].comname); } char *cmds[comtab[curr].nargs + 2]; cmds[0] = place; cmds[comtab[curr].nargs + 1] = (char *)NULL; int i = 0; for(i; i<comtab[curr].nargs; i++) { cmds[i+1] = comtab[curr].atptr[i]; } if(execv(place, cmds) == -1) { tok = strtok(NULL, ":"); continue; } else { _exit(0); success = 1; break; } } if(success == -1) { printf("ERR: Command not found: %s\n", comtab[curr].comname); _exit(1); } } } } currcmd += 1; comtab[currcmd].external = 0; ignoreEOF = 0; }
/*! \fn int php_init(int php_process) * \brief initialize either a specific PHP Script Server or all of them. * \param php_process the process number to start or PHP_INIT * * This function will either start an individual PHP Script Server process * or all of them if the input parameter is the PHP_INIT constant. The function * will check the status of the process to verify that it is ready to process * scripts as well. * * \return TRUE if the PHP Script Server is know running or FALSE otherwise */ int php_init(int php_process) { int cacti2php_pdes[2]; int php2cacti_pdes[2]; pid_t pid; char poller_id[TINY_BUFSIZE]; char *argv[6]; int cancel_state; char *result_string = 0; int num_processes; int i; int retry_count = 0; /* special code to start all PHP Servers */ if (php_process == PHP_INIT) { num_processes = set.php_servers; } else { num_processes = 1; } for (i=0; i < num_processes; i++) { SPINE_LOG_DEBUG(("DEBUG: SS[%i] PHP Script Server Routine Starting", i)); /* create the output pipes from Spine to php*/ if (pipe(cacti2php_pdes) < 0) { SPINE_LOG(("ERROR: SS[%i] Could not allocate php server pipes", i)); return FALSE; } /* create the input pipes from php to Spine */ if (pipe(php2cacti_pdes) < 0) { SPINE_LOG(("ERROR: SS[%i] Could not allocate php server pipes", i)); return FALSE; } /* disable thread cancellation from this point forward. */ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cancel_state); /* establish arguments for script server execution */ argv[0] = set.path_php; argv[1] = "-q"; argv[2] = set.path_php_server; argv[3] = "spine"; snprintf(poller_id, TINY_BUFSIZE, "%d", set.poller_id); argv[4] = poller_id; argv[5] = NULL; /* fork a child process */ SPINE_LOG_DEBUG(("DEBUG: SS[%i] PHP Script Server About to FORK Child Process", i)); retry: pid = vfork(); /* check the pid status and process as required */ switch (pid) { case -1: /* ERROR: Could not fork() */ switch (errno) { case EAGAIN: if (retry_count < 3) { retry_count++; #ifndef SOLAR_THREAD /* take a moment */ usleep(50000); #endif goto retry; } else { SPINE_LOG(("ERROR: SS[%i] Could not fork PHP Script Server Out of Resources", i)); } case ENOMEM: if (retry_count < 3) { retry_count++; #ifndef SOLAR_THREAD /* take a moment */ usleep(50000); #endif goto retry; } else { SPINE_LOG(("ERROR: SS[%i] Could not fork PHP Script Server Out of Memory", i)); } default: SPINE_LOG(("ERROR: SS[%i] Could not fork PHP Script Server Unknown Reason", i)); } close(php2cacti_pdes[0]); close(php2cacti_pdes[1]); close(cacti2php_pdes[0]); close(cacti2php_pdes[1]); SPINE_LOG(("ERROR: SS[%i] Could not fork PHP Script Server", i)); pthread_setcancelstate(cancel_state, NULL); return FALSE; /* NOTREACHED */ case 0: /* SUCCESS: I am now the child */ /* set the standard input/output channels of the new process. */ dup2(cacti2php_pdes[0], STDIN_FILENO); dup2(php2cacti_pdes[1], STDOUT_FILENO); /* close unneeded Pipes */ (void)close(php2cacti_pdes[0]); (void)close(php2cacti_pdes[1]); (void)close(cacti2php_pdes[0]); (void)close(cacti2php_pdes[1]); /* start the php script server process */ execv(argv[0], argv); _exit(127); /* NOTREACHED */ default: /* I am the parent process */ SPINE_LOG_DEBUG(("DEBUG: SS[%i] PHP Script Server Child FORK Success", i)); } /* Parent */ /* close unneeded pipes */ close(cacti2php_pdes[0]); close(php2cacti_pdes[1]); if (php_process == PHP_INIT) { php_processes[i].php_pid = pid; php_processes[i].php_write_fd = cacti2php_pdes[1]; php_processes[i].php_read_fd = php2cacti_pdes[0]; } else { php_processes[php_process].php_pid = pid; php_processes[php_process].php_write_fd = cacti2php_pdes[1]; php_processes[php_process].php_read_fd = php2cacti_pdes[0]; } /* restore caller's cancellation state. */ pthread_setcancelstate(cancel_state, NULL); /* check pipe to insure startup took place */ if (php_process == PHP_INIT) { result_string = php_readpipe(i); } else { result_string = php_readpipe(php_process); } if (strstr(result_string, "Started")) { if (php_process == PHP_INIT) { SPINE_LOG_DEBUG(("DEBUG: SS[%i] Confirmed PHP Script Server running using readfd[%i], writefd[%i]", i, php2cacti_pdes[0], cacti2php_pdes[1])); php_processes[i].php_state = PHP_READY; } else { SPINE_LOG_DEBUG(("DEBUG: SS[%i] Confirmed PHP Script Server running using readfd[%i], writefd[%i]", php_process, php2cacti_pdes[0], cacti2php_pdes[1])); php_processes[php_process].php_state = PHP_READY; } } else { SPINE_LOG(("ERROR: SS[%i] Script Server did not start properly return message was: '%s'", php_process, result_string)); if (php_process == PHP_INIT) { php_processes[i].php_state = PHP_BUSY; } else { php_processes[php_process].php_state = PHP_BUSY; } } } free(result_string); return TRUE; }