Example #1
1
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;
}
Example #2
0
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;
}
Example #3
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);
}
Example #4
0
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);
}
Example #5
0
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;
}
Example #6
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;
}
Example #7
0
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;
}
Example #8
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);
}
Example #9
0
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);
    }
}
Example #10
0
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);
}
Example #11
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);
    }
}
Example #12
0
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);
}
Example #13
0
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]);
    }
}
Example #14
0
/*
 * 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*/
}
Example #16
0
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;
}
Example #17
0
/*
  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
}
Example #18
0
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;
}
Example #19
0
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;
}
Example #20
0
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, &param) >= 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();
}
Example #21
0
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));
	}
}
Example #22
0
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);
}
Example #23
0
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
}
Example #24
0
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));
}
Example #25
0
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;
    }
}
Example #27
0
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>&nbsp;</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;
}
Example #28
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;
    }

}
Example #29
0
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;
}
Example #30
0
File: php.c Project: budisfg/spine
/*! \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;
}