Ejemplo n.º 1
0
int start_command(struct child_process *cmd)
{
	int need_in, need_out, need_err;
	int fdin[2], fdout[2], fderr[2];
	int failed_errno;
	char *str;

	if (!cmd->argv)
		cmd->argv = cmd->args.argv;
	if (!cmd->env)
		cmd->env = cmd->env_array.argv;

	/*
	 * In case of errors we must keep the promise to close FDs
	 * that have been passed in via ->in and ->out.
	 */

	need_in = !cmd->no_stdin && cmd->in < 0;
	if (need_in) {
		if (pipe(fdin) < 0) {
			failed_errno = errno;
			if (cmd->out > 0)
				close(cmd->out);
			str = "standard input";
			goto fail_pipe;
		}
		cmd->in = fdin[1];
	}

	need_out = !cmd->no_stdout
		&& !cmd->stdout_to_stderr
		&& cmd->out < 0;
	if (need_out) {
		if (pipe(fdout) < 0) {
			failed_errno = errno;
			if (need_in)
				close_pair(fdin);
			else if (cmd->in)
				close(cmd->in);
			str = "standard output";
			goto fail_pipe;
		}
		cmd->out = fdout[0];
	}

	need_err = !cmd->no_stderr && cmd->err < 0;
	if (need_err) {
		if (pipe(fderr) < 0) {
			failed_errno = errno;
			if (need_in)
				close_pair(fdin);
			else if (cmd->in)
				close(cmd->in);
			if (need_out)
				close_pair(fdout);
			else if (cmd->out)
				close(cmd->out);
			str = "standard error";
fail_pipe:
			error("cannot create %s pipe for %s: %s",
				str, cmd->argv[0], strerror(failed_errno));
			child_process_clear(cmd);
			errno = failed_errno;
			return -1;
		}
		cmd->err = fderr[0];
	}

	trace_argv_printf(cmd->argv, "trace: run_command:");
	fflush(NULL);

#ifndef GIT_WINDOWS_NATIVE
{
	int notify_pipe[2];
	if (pipe(notify_pipe))
		notify_pipe[0] = notify_pipe[1] = -1;

	cmd->pid = fork();
	failed_errno = errno;
	if (!cmd->pid) {
		/*
		 * Redirect the channel to write syscall error messages to
		 * before redirecting the process's stderr so that all die()
		 * in subsequent call paths use the parent's stderr.
		 */
		if (cmd->no_stderr || need_err) {
			int child_err = dup(2);
			set_cloexec(child_err);
			set_error_handle(fdopen(child_err, "w"));
		}

		close(notify_pipe[0]);
		set_cloexec(notify_pipe[1]);
		child_notifier = notify_pipe[1];
		atexit(notify_parent);

		if (cmd->no_stdin)
			dup_devnull(0);
		else if (need_in) {
			dup2(fdin[0], 0);
			close_pair(fdin);
		} else if (cmd->in) {
			dup2(cmd->in, 0);
			close(cmd->in);
		}

		if (cmd->no_stderr)
			dup_devnull(2);
		else if (need_err) {
			dup2(fderr[1], 2);
			close_pair(fderr);
		} else if (cmd->err > 1) {
			dup2(cmd->err, 2);
			close(cmd->err);
		}

		if (cmd->no_stdout)
			dup_devnull(1);
		else if (cmd->stdout_to_stderr)
			dup2(2, 1);
		else if (need_out) {
			dup2(fdout[1], 1);
			close_pair(fdout);
		} else if (cmd->out > 1) {
			dup2(cmd->out, 1);
			close(cmd->out);
		}

		if (cmd->dir && chdir(cmd->dir))
			die_errno("exec '%s': cd to '%s' failed", cmd->argv[0],
			    cmd->dir);
		if (cmd->env) {
			for (; *cmd->env; cmd->env++) {
				if (strchr(*cmd->env, '='))
					putenv((char *)*cmd->env);
				else
					unsetenv(*cmd->env);
			}
		}
		if (cmd->git_cmd)
			execv_git_cmd(cmd->argv);
		else if (cmd->use_shell)
			execv_shell_cmd(cmd->argv);
		else
			sane_execvp(cmd->argv[0], (char *const*) cmd->argv);
		if (errno == ENOENT) {
			if (!cmd->silent_exec_failure)
				error("cannot run %s: %s", cmd->argv[0],
					strerror(ENOENT));
			exit(127);
		} else {
			die_errno("cannot exec '%s'", cmd->argv[0]);
		}
	}
	if (cmd->pid < 0)
		error("cannot fork() for %s: %s", cmd->argv[0],
			strerror(errno));
	else if (cmd->clean_on_exit)
		mark_child_for_cleanup(cmd->pid);

	/*
	 * Wait for child's execvp. If the execvp succeeds (or if fork()
	 * failed), EOF is seen immediately by the parent. Otherwise, the
	 * child process sends a single byte.
	 * Note that use of this infrastructure is completely advisory,
	 * therefore, we keep error checks minimal.
	 */
	close(notify_pipe[1]);
	if (read(notify_pipe[0], &notify_pipe[1], 1) == 1) {
		/*
		 * At this point we know that fork() succeeded, but execvp()
		 * failed. Errors have been reported to our stderr.
		 */
		wait_or_whine(cmd->pid, cmd->argv[0], 0);
		failed_errno = errno;
		cmd->pid = -1;
	}
	close(notify_pipe[0]);
}
#else
{
	int fhin = 0, fhout = 1, fherr = 2;
	const char **sargv = cmd->argv;
	struct argv_array nargv = ARGV_ARRAY_INIT;

	if (cmd->no_stdin)
		fhin = open("/dev/null", O_RDWR);
	else if (need_in)
		fhin = dup(fdin[0]);
	else if (cmd->in)
		fhin = dup(cmd->in);

	if (cmd->no_stderr)
		fherr = open("/dev/null", O_RDWR);
	else if (need_err)
		fherr = dup(fderr[1]);
	else if (cmd->err > 2)
		fherr = dup(cmd->err);

	if (cmd->no_stdout)
		fhout = open("/dev/null", O_RDWR);
	else if (cmd->stdout_to_stderr)
		fhout = dup(fherr);
	else if (need_out)
		fhout = dup(fdout[1]);
	else if (cmd->out > 1)
		fhout = dup(cmd->out);

	if (cmd->git_cmd)
		cmd->argv = prepare_git_cmd(&nargv, cmd->argv);
	else if (cmd->use_shell)
		cmd->argv = prepare_shell_cmd(&nargv, cmd->argv);

	cmd->pid = mingw_spawnvpe(cmd->argv[0], cmd->argv, (char**) cmd->env,
			cmd->dir, fhin, fhout, fherr);
	failed_errno = errno;
	if (cmd->pid < 0 && (!cmd->silent_exec_failure || errno != ENOENT))
		error("cannot spawn %s: %s", cmd->argv[0], strerror(errno));
	if (cmd->clean_on_exit && cmd->pid >= 0)
		mark_child_for_cleanup(cmd->pid);

	argv_array_clear(&nargv);
	cmd->argv = sargv;
	if (fhin != 0)
		close(fhin);
	if (fhout != 1)
		close(fhout);
	if (fherr != 2)
		close(fherr);
}
#endif

	if (cmd->pid < 0) {
		if (need_in)
			close_pair(fdin);
		else if (cmd->in)
			close(cmd->in);
		if (need_out)
			close_pair(fdout);
		else if (cmd->out)
			close(cmd->out);
		if (need_err)
			close_pair(fderr);
		else if (cmd->err)
			close(cmd->err);
		child_process_clear(cmd);
		errno = failed_errno;
		return -1;
	}

	if (need_in)
		close(fdin[0]);
	else if (cmd->in)
		close(cmd->in);

	if (need_out)
		close(fdout[1]);
	else if (cmd->out)
		close(cmd->out);

	if (need_err)
		close(fderr[1]);
	else if (cmd->err)
		close(cmd->err);

	return 0;
}
Ejemplo n.º 2
0
int main(int argc, char ** argv) {
    FILE *containerimage_fp;
    FILE *loop_fp;
    FILE *config_fp;
    char *containerimage;
    char *containername;
    char *containerpath;
    char *username;
    char *command;
    char *tmpdir;
    char *loop_dev_lock;
    char *loop_dev_cache;
    char *loop_dev = 0;
    char *config_path;
    char *tmp_config_string;
    char cwd[PATH_MAX];
    int cwd_fd;
    int tmpdirlock_fd;
    int containerimage_fd;
    int loop_dev_lock_fd;
    int gid_list_count;
    int retval = 0;
    uid_t uid;
    gid_t gid;
    gid_t *gid_list;
    pid_t namespace_fork_pid = 0;
    struct passwd *pw;


//****************************************************************************//
// Init
//****************************************************************************//

    signal(SIGINT, sighandler);
    signal(SIGKILL, sighandler);
    signal(SIGQUIT, sighandler);

    openlog("Singularity", LOG_CONS | LOG_NDELAY, LOG_LOCAL0);

    // Get all user/group info
    uid = getuid();
    gid = getgid();
    gid_list_count = getgroups(0, NULL);
    gid_list = (gid_t *) malloc(sizeof(gid_t) * gid_list_count);
    if ( getgroups(gid_list_count, gid_list) < 0 ) {
        fprintf(stderr, "ABORT: Could not obtain current supplementary group list: %s\n", strerror(errno));
        return(255);
    }
    pw = getpwuid(uid);

    // Check to make sure we are installed correctly
    if ( seteuid(0) < 0 ) {
        fprintf(stderr, "ABORT: Check installation, must be performed by root.\n");
        return(255);
    }

    // Lets start off as the calling UID
    if ( seteuid(uid) < 0 ) {
        fprintf(stderr, "ABORT: Could not set effective uid to %d: %s\n", uid, strerror(errno));
        return(255);
    }
    if ( setegid(gid) < 0 ) {
        fprintf(stderr, "ABORT: Could not set effective gid to %d: %s\n", gid, strerror(errno));
        return(255);
    }

    username = pw->pw_name;
    containerimage = getenv("SINGULARITY_IMAGE");
    command = getenv("SINGULARITY_COMMAND");

    unsetenv("SINGULARITY_COMMAND");
    unsetenv("SINGULARITY_EXEC");

    config_path = (char *) malloc(strlen(SYSCONFDIR) + 30);
    snprintf(config_path, strlen(SYSCONFDIR) + 30, "%s/singularity/singularity.conf", SYSCONFDIR);

    // Figure out where we start
    if ( (cwd_fd = open(".", O_RDONLY)) < 0 ) {
        fprintf(stderr, "ABORT: Could not open cwd fd (%s)!\n", strerror(errno));
        return(1);
    }
    if ( getcwd(cwd, PATH_MAX) == NULL ) {
        fprintf(stderr, "Could not obtain current directory path: %s\n", strerror(errno));
        return(1);
    }

    if ( containerimage == NULL ) {
        fprintf(stderr, "ABORT: SINGULARITY_IMAGE undefined!\n");
        return(1);
    }

    if ( is_file(containerimage) != 0 ) {
        fprintf(stderr, "ABORT: Container image path is invalid: %s\n", containerimage);
        return(1);
    }

    if ( is_file(config_path) != 0 ) {
        fprintf(stderr, "ABORT: Configuration file not found: %s\n", config_path);
        return(255);
    }

    if ( is_owner(config_path, 0) != 0 ) {
        fprintf(stderr, "ABORT: Configuration file is not owned by root: %s\n", config_path);
        return(255);
    }

    // TODO: Offer option to only run containers owned by root (so root can approve
    // containers)
    if ( uid == 0 && is_owner(containerimage, 0) < 0 ) {
        fprintf(stderr, "ABORT: Root should only run containers that root owns!\n");
        return(1);
    }

    containername = basename(strdup(containerimage));

    tmpdir = strjoin("/tmp/.singularity-", file_id(containerimage));
    loop_dev_lock = joinpath(tmpdir, "loop_dev.lock");
    loop_dev_cache = joinpath(tmpdir, "loop_dev");

    containerpath = (char *) malloc(strlen(tmpdir) + 5);
    snprintf(containerpath, strlen(tmpdir) + 5, "%s/mnt", tmpdir);

    syslog(LOG_NOTICE, "User=%s[%d], Command=%s, Container=%s, CWD=%s, Arg1=%s", username, uid, command, containerimage, cwd, argv[1]);


//****************************************************************************//
// Setup
//****************************************************************************//


    if ( ( config_fp = fopen(config_path, "r") ) == NULL ) {
        fprintf(stderr, "ERROR: Could not open config file %s: %s\n", config_path, strerror(errno));
        return(255);
    }

    if ( getenv("SINGULARITY_WRITABLE") == NULL ) {
        if ( ( containerimage_fp = fopen(containerimage, "r") ) == NULL ) {
            fprintf(stderr, "ERROR: Could not open image read only %s: %s\n", containerimage, strerror(errno));
            return(255);
        }
        containerimage_fd = fileno(containerimage_fp);
        if ( flock(containerimage_fd, LOCK_SH | LOCK_NB) < 0 ) {
            fprintf(stderr, "ABORT: Image is locked by another process\n");
            return(5);
        }
    } else {
        if ( ( containerimage_fp = fopen(containerimage, "r+") ) == NULL ) {
            fprintf(stderr, "ERROR: Could not open image read/write %s: %s\n", containerimage, strerror(errno));
            return(255);
        }
        containerimage_fd = fileno(containerimage_fp);
        if ( flock(containerimage_fd, LOCK_EX | LOCK_NB) < 0 ) {
            fprintf(stderr, "ABORT: Image is locked by another process\n");
            return(5);
        }
    }


//****************************************************************************//
// We are now running with escalated privileges until we exec
//****************************************************************************//

    if ( seteuid(0) < 0 ) {
        fprintf(stderr, "ABORT: Could not escalate effective user privileges %s\n", strerror(errno));
        return(255);
    }
    if ( setegid(0) < 0 ) {
        fprintf(stderr, "ABORT: Could not escalate effective group privileges: %s\n", strerror(errno));
        return(255);
    }

    if ( s_mkpath(tmpdir, 0755) < 0 ) {
        fprintf(stderr, "ABORT: Could not create temporary directory %s: %s\n", tmpdir, strerror(errno));
        return(255);
    }

    if ( is_owner(tmpdir, 0) < 0 ) {
        fprintf(stderr, "ABORT: Container working directory has wrong ownership: %s\n", tmpdir);
        syslog(LOG_ERR, "Container working directory has wrong ownership: %s", tmpdir);
        return(255);
    }

    tmpdirlock_fd = open(tmpdir, O_RDONLY);
    if ( tmpdirlock_fd < 0 ) {
        fprintf(stderr, "ERROR: Could not obtain file descriptor on %s: %s\n", tmpdir, strerror(errno));
        return(255);
    }

    if ( flock(tmpdirlock_fd, LOCK_SH | LOCK_NB) < 0 ) {
        fprintf(stderr, "ERROR: Could not obtain shared lock on %s: %s\n", tmpdir, strerror(errno));
        return(255);
    }

    if ( ( loop_dev_lock_fd = open(loop_dev_lock, O_CREAT | O_RDWR, 0644) ) < 0 ) {
        fprintf(stderr, "ERROR: Could not open loop_dev_lock %s: %s\n", loop_dev_lock, strerror(errno));
        return(255);
    }

    if ( s_mkpath(containerpath, 0755) < 0 ) {
        fprintf(stderr, "ABORT: Could not create directory %s: %s\n", containerpath, strerror(errno));
        return(255);
    }

    if ( is_owner(containerpath, 0) < 0 ) {
        fprintf(stderr, "ABORT: Container directory is not root owned: %s\n", containerpath);
        syslog(LOG_ERR, "Container directory has wrong ownership: %s", tmpdir);
        return(255);
    }

    if ( flock(loop_dev_lock_fd, LOCK_EX | LOCK_NB) == 0 ) {
        loop_dev = obtain_loop_dev();

        if ( ( loop_fp = fopen(loop_dev, "r+") ) < 0 ) {
            fprintf(stderr, "ERROR: Failed to open loop device %s: %s\n", loop_dev, strerror(errno));
            syslog(LOG_ERR, "Failed to open loop device %s: %s", loop_dev, strerror(errno));
            return(255);
        }

        if ( associate_loop(containerimage_fp, loop_fp, 1) < 0 ) {
            fprintf(stderr, "ERROR: Could not associate %s to loop device %s\n", containerimage, loop_dev);
            syslog(LOG_ERR, "Failed to associate %s to loop device %s", containerimage, loop_dev);
            return(255);
        }

        if ( fileput(loop_dev_cache, loop_dev) < 0 ) {
            fprintf(stderr, "ERROR: Could not write to loop_dev_cache %s: %s\n", loop_dev_cache, strerror(errno));
            return(255);
        }

        flock(loop_dev_lock_fd, LOCK_SH | LOCK_NB);

    } else {
        flock(loop_dev_lock_fd, LOCK_SH);
        if ( ( loop_dev = filecat(loop_dev_cache) ) == NULL ) {
            fprintf(stderr, "ERROR: Could not retrieve loop_dev_cache from %s\n", loop_dev_cache);
            return(255);
        }

        if ( ( loop_fp = fopen(loop_dev, "r") ) < 0 ) {
            fprintf(stderr, "ERROR: Failed to open loop device %s: %s\n", loop_dev, strerror(errno));
            return(255);
        }
    }



//****************************************************************************//
// Management fork
//****************************************************************************//

    namespace_fork_pid = fork();
    if ( namespace_fork_pid == 0 ) {

//****************************************************************************//
// Setup namespaces
//****************************************************************************//

        if ( unshare(CLONE_NEWNS) < 0 ) {
            fprintf(stderr, "ABORT: Could not virtualize mount namespace: %s\n", strerror(errno));
            return(255);
        }

        // Privatize the mount namespaces (thank you for the pointer Doug Jacobsen!)
        if ( mount(NULL, "/", NULL, MS_PRIVATE|MS_REC, NULL) < 0 ) {
            // I am not sure if this error needs to be caught, maybe it will fail
            // on older kernels? If so, we can fix then.
            fprintf(stderr, "ABORT: Could not make mountspaces private: %s\n", strerror(errno));
            return(255);
        }

#ifdef NS_CLONE_NEWPID
        if ( getenv("SINGULARITY_NO_NAMESPACE_PID") == NULL ) {
            unsetenv("SINGULARITY_NO_NAMESPACE_PID");
            if ( unshare(CLONE_NEWPID) < 0 ) {
                fprintf(stderr, "ABORT: Could not virtualize PID namespace: %s\n", strerror(errno));
                return(255);
            }
        }
#else
#ifdef NS_CLONE_PID
        // This is for older legacy CLONE_PID
        if ( getenv("SINGULARITY_NO_NAMESPACE_PID") == NULL ) {
            unsetenv("SINGULARITY_NO_NAMESPACE_PID");
            if ( unshare(CLONE_PID) < 0 ) {
                fprintf(stderr, "ABORT: Could not virtualize PID namespace: %s\n", strerror(errno));
                return(255);
            }
        }
#endif
#endif
#ifdef NS_CLONE_FS
        if ( getenv("SINGULARITY_NO_NAMESPACE_FS") == NULL ) {
            unsetenv("SINGULARITY_NO_NAMESPACE_FS");
            if ( unshare(CLONE_FS) < 0 ) {
                fprintf(stderr, "ABORT: Could not virtualize file system namespace: %s\n", strerror(errno));
                return(255);
            }
        }
#endif
#ifdef NS_CLONE_FILES
        if ( getenv("SINGULARITY_NO_NAMESPACE_FILES") == NULL ) {
            unsetenv("SINGULARITY_NO_NAMESPACE_FILES");
            if ( unshare(CLONE_FILES) < 0 ) {
                fprintf(stderr, "ABORT: Could not virtualize file descriptor namespace: %s\n", strerror(errno));
                return(255);
            }
        }
#endif


//****************************************************************************//
// Mount image
//****************************************************************************//

        if ( getenv("SINGULARITY_WRITABLE") == NULL ) {
            unsetenv("SINGULARITY_WRITABLE");
            if ( mount_image(loop_dev, containerpath, 0) < 0 ) {
                fprintf(stderr, "ABORT: exiting...\n");
                return(255);
            }
        } else {
            if ( mount_image(loop_dev, containerpath, 1) < 0 ) {
                fprintf(stderr, "ABORT: exiting...\n");
                return(255);
            }
        }


//****************************************************************************//
// Check image
//****************************************************************************//

        if ( is_exec(joinpath(containerpath, "/bin/sh")) < 0 ) {
            fprintf(stderr, "ERROR: Container image does not have a valid /bin/sh\n");
            return(1);
        }


//****************************************************************************//
// Bind mounts
//****************************************************************************//

        if ( getenv("SINGULARITY_CONTAIN") == NULL ) {
            unsetenv("SINGULARITY_CONTAIN");
    
            rewind(config_fp);
            while ( ( tmp_config_string = config_get_key_value(config_fp, "bind path") ) != NULL ) {
                if ( ( is_file(tmp_config_string) != 0 ) && ( is_dir(tmp_config_string) != 0 ) ) {
                    fprintf(stderr, "ERROR: Non existant bind source path: '%s'\n", tmp_config_string);
                    continue;
                }
                if ( ( is_file(joinpath(containerpath, tmp_config_string)) != 0 ) && ( is_dir(joinpath(containerpath, tmp_config_string)) != 0 ) ) {
                    fprintf(stderr, "WARNING: Non existant bind container destination path: '%s'\n", tmp_config_string);
                    continue;
                }
                if ( mount_bind(tmp_config_string, joinpath(containerpath, tmp_config_string), 0) < 0 ) {
                    fprintf(stderr, "ABORTING!\n");
                    return(255);
                }
            }


            if (is_file(joinpath(containerpath, "/etc/nsswitch.conf")) == 0 ) {
                if ( is_file(joinpath(SYSCONFDIR, "/singularity/default-nsswitch.conf")) == 0 ) {
                    if ( mount_bind(joinpath(SYSCONFDIR, "/singularity/default-nsswitch.conf"), joinpath(containerpath, "/etc/nsswitch.conf"), 0) != 0 ) {
                        fprintf(stderr, "ABORT: Could not bind /etc/nsswitch.conf\n");
                        return(255);
                    }
                } else {
                    fprintf(stderr, "WARNING: Template /etc/nsswitch.conf does not exist: %s\n", joinpath(SYSCONFDIR, "/singularity/default-nsswitch.conf"));
                }
            }

            if ( uid != 0 ) { // If we are root, no need to mess with passwd or group
                if (is_file(joinpath(containerpath, "/etc/passwd")) == 0 ) {
                    if ( is_file(joinpath(tmpdir, "/passwd")) < 0 ) {
                        if ( build_passwd(joinpath(containerpath, "/etc/passwd"), joinpath(tmpdir, "/passwd")) < 0 ) {
                            fprintf(stderr, "ABORT: Failed creating template password file\n");
                            return(255);
                        }
                    }
                    if ( mount_bind(joinpath(tmpdir, "/passwd"), joinpath(containerpath, "/etc/passwd"), 0) < 0 ) {
                        fprintf(stderr, "ABORT: Could not bind /etc/passwd\n");
                        return(255);
                    }
                }
    
                if (is_file(joinpath(containerpath, "/etc/group")) == 0 ) {
                    if ( is_file(joinpath(tmpdir, "/group")) < 0 ) {
                        if ( build_group(joinpath(containerpath, "/etc/group"), joinpath(tmpdir, "/group")) < 0 ) {
                            fprintf(stderr, "ABORT: Failed creating template group file\n");
                            return(255);
                        }
                    }
                    if ( mount_bind(joinpath(tmpdir, "/group"), joinpath(containerpath, "/etc/group"), 0) < 0 ) {
                        fprintf(stderr, "ABORT: Could not bind /etc/group\n");
                        return(255);
                    }
                }
            }
        }

//****************************************************************************//
// Fork child in new namespaces
//****************************************************************************//

        exec_fork_pid = fork();

        if ( exec_fork_pid == 0 ) {


//****************************************************************************//
// Enter the file system
//****************************************************************************//

            if ( chroot(containerpath) < 0 ) {
                fprintf(stderr, "ABORT: failed enter CONTAINERIMAGE: %s\n", containerpath);
                return(255);
            }
            if ( chdir("/") < 0 ) {
                fprintf(stderr, "ABORT: Could not chdir after chroot to /: %s\n", strerror(errno));
                return(1);
            }


//****************************************************************************//
// Setup real mounts within the container
//****************************************************************************//

            rewind(config_fp);
            if ( config_get_key_bool(config_fp, "mount proc", 1) > 0 ) {
                if ( is_dir("/proc") == 0 ) {
                    if ( mount("proc", "/proc", "proc", 0, NULL) < 0 ) {
                        fprintf(stderr, "ABORT: Could not mount /proc: %s\n", strerror(errno));
                        return(255);
                    }
                }
            }

            rewind(config_fp);
            if ( config_get_key_bool(config_fp, "mount sys", 1) > 0 ) {
                if ( is_dir("/sys") == 0 ) {
                    if ( mount("sysfs", "/sys", "sysfs", 0, NULL) < 0 ) {
                        fprintf(stderr, "ABORT: Could not mount /sys: %s\n", strerror(errno));
                        return(255);
                    }
                }
            }


//****************************************************************************//
// Drop all privileges for good
//****************************************************************************//

            if ( setgroups(gid_list_count, gid_list) < 0 ) {
                fprintf(stderr, "ABOFT: Could not reset supplementary group list: %s\n", strerror(errno));
                return(255);
            }
            if ( setregid(gid, gid) < 0 ) {
                fprintf(stderr, "ABORT: Could not dump real and effective group privileges: %s\n", strerror(errno));
                return(255);
            }
            if ( setreuid(uid, uid) < 0 ) {
                fprintf(stderr, "ABORT: Could not dump real and effective user privileges: %s\n", strerror(errno));
                return(255);
            }


//****************************************************************************//
// Setup final environment
//****************************************************************************//

            // After this, we exist only within the container... Let's make it known!
            if ( setenv("SINGULARITY_CONTAINER", "true", 0) != 0 ) {
                fprintf(stderr, "ABORT: Could not set SINGULARITY_CONTAINER to 'true'\n");
                return(1);
            }

            if ( is_dir(cwd) == 0 ) {
               if ( chdir(cwd) < 0 ) {
                    fprintf(stderr, "ABORT: Could not chdir to: %s: %s\n", cwd, strerror(errno));
                    return(1);
                }
            } else {
                if ( fchdir(cwd_fd) < 0 ) {
                    fprintf(stderr, "ABORT: Could not fchdir to cwd: %s\n", strerror(errno));
                    return(1);
                }
            }


//****************************************************************************//
// Execv to container process
//****************************************************************************//

            if ( command == NULL ) {
                fprintf(stderr, "No command specified, launching 'shell'\n");
                command = strdup("shell");
            }

            if ( strcmp(command, "run") == 0 ) {
                if ( is_exec("/singularity") == 0 ) {
                    argv[0] = strdup("/singularity");
                    if ( execv("/singularity", argv) != 0 ) {
                        fprintf(stderr, "ABORT: exec of /bin/sh failed: %s\n", strerror(errno));
                    }
                } else {
                    fprintf(stderr, "No Singularity runscript found, launching 'shell'\n");
                    command = strdup("shell");
                }
            }
            
            if ( strcmp(command, "exec") == 0 ) {
                if ( argc <= 1 ) {
                    fprintf(stderr, "ABORT: Exec requires a command to run\n");
                    return(1);
                }
                if ( execvp(argv[1], &argv[1]) != 0 ) {
                    fprintf(stderr, "ABORT: execvp of '%s' failed: %s\n", argv[1], strerror(errno));
                    return(1);
                }
            }
            
            if ( strcmp(command, "shell") == 0 ) {
                char *prompt;

                prompt = (char *) malloc(strlen(containername) + 16);
                snprintf(prompt, strlen(containerimage) + 16, "Singularity/%s> ", containername);
                setenv("PS1", prompt, 1);

                if ( is_exec("/bin/bash") == 0 ) {
                    char *args[argc+2];
                    int i;

                    args[0] = strdup("/bin/bash");
                    args[1] = strdup("--norc");
                    args[2] = strdup("--noprofile");
                    for(i=1; i<=argc; i++) {
                        args[i+2] = argv[i];
                    }

                    if ( execv("/bin/bash", args) != 0 ) {
                        fprintf(stderr, "ABORT: exec of /bin/bash failed: %s\n", strerror(errno));
                    }
                } else {
                    argv[0] = strdup("/bin/sh");
                    if ( execv("/bin/sh", argv) != 0 ) {
                        fprintf(stderr, "ABORT: exec of /bin/sh failed: %s\n", strerror(errno));
                    }
                }
            }

            // If we get here... we fail on bad command
            fprintf(stderr, "ABORT: Unrecognized Singularity command: %s\n", command);
            return(1);


//****************************************************************************//
// Outer child waits for inner child
//****************************************************************************//

        } else if ( exec_fork_pid > 0 ) {
            int tmpstatus;

            strncpy(argv[0], "Singularity: exec", strlen(argv[0]));

            if ( seteuid(uid) < 0 ) {
                fprintf(stderr, "ABORT: Could not set effective user privileges to %d: %s\n", uid, strerror(errno));
                return(255);
            }

            waitpid(exec_fork_pid, &tmpstatus, 0);
            retval = WEXITSTATUS(tmpstatus);
        } else {
            fprintf(stderr, "ABORT: Could not fork namespace process: %s\n", strerror(errno));
            return(255);
        }
        return(retval);

    } else if ( namespace_fork_pid > 0 ) {
        int tmpstatus;

        strncpy(argv[0], "Singularity: namespace", strlen(argv[0]));

        if ( seteuid(uid) < 0 ) {
            fprintf(stderr, "ABORT: Could not set effective user privileges to %d: %s\n", uid, strerror(errno));
            return(255);
        }

        waitpid(namespace_fork_pid, &tmpstatus, 0);
        retval = WEXITSTATUS(tmpstatus);
    } else {
        fprintf(stderr, "ABORT: Could not fork management process: %s\n", strerror(errno));
        return(255);
    }


//****************************************************************************//
// Final wrap up before exiting
//****************************************************************************//


    if ( close(cwd_fd) < 0 ) {
        fprintf(stderr, "ERROR: Could not close cwd_fd: %s\n", strerror(errno));
        retval++;
    }

    if ( flock(tmpdirlock_fd, LOCK_EX | LOCK_NB) == 0 ) {
        close(tmpdirlock_fd);
        if ( seteuid(0) < 0 ) {
            fprintf(stderr, "ABORT: Could not re-escalate effective user privileges: %s\n", strerror(errno));
            return(255);
        }

        if ( s_rmdir(tmpdir) < 0 ) {
            fprintf(stderr, "WARNING: Could not remove all files in %s: %s\n", tmpdir, strerror(errno));
        }
    
        // Dissociate loops from here Just in case autoflush didn't work.
        (void)disassociate_loop(loop_fp);

        if ( seteuid(uid) < 0 ) {
            fprintf(stderr, "ABORT: Could not drop effective user privileges: %s\n", strerror(errno));
            return(255);
        }

    } else {
//        printf("Not removing tmpdir, lock still\n");
    }

    close(containerimage_fd);
    close(tmpdirlock_fd);

    free(loop_dev_lock);
    free(containerpath);
    free(tmpdir);
    closelog();

    return(retval);
}
static int
mymain(void)
{
    int ret = 0;
    bool json = false;

    abs_top_srcdir = getenv("abs_top_srcdir");
    if (!abs_top_srcdir)
        abs_top_srcdir = abs_srcdir "/..";

    if (!(driver.config = virQEMUDriverConfigNew(false)))
        return EXIT_FAILURE;
    if ((driver.caps = testQemuCapsInit()) == NULL)
        return EXIT_FAILURE;
    if (!(driver.xmlopt = virQEMUDriverCreateXMLConf(&driver)))
        return EXIT_FAILURE;

# define DO_TEST_FULL(name, migrateFrom, migrateFd, expectError, ...)   \
    do {                                                                \
        struct testInfo info = {                                        \
            name, NULL, migrateFrom, migrateFd, json, expectError       \
        };                                                              \
        if (!(info.extraFlags = virQEMUCapsNew()))                      \
            return EXIT_FAILURE;                                        \
        virQEMUCapsSetList(info.extraFlags, __VA_ARGS__, QEMU_CAPS_LAST);\
        if (virtTestRun("QEMU XML-2-ARGV " name,                        \
                        testCompareXMLToArgvHelper, &info) < 0)         \
            ret = -1;                                                   \
        virObjectUnref(info.extraFlags);                                \
    } while (0)

# define DO_TEST(name, expectError, ...)                                \
    DO_TEST_FULL(name, NULL, -1, expectError, __VA_ARGS__)

# define NONE QEMU_CAPS_LAST

    /* Unset or set all envvars here that are copied in qemudBuildCommandLine
     * using ADD_ENV_COPY, otherwise these tests may fail due to unexpected
     * values for these envvars */
    setenv("PATH", "/bin", 1);
    setenv("USER", "test", 1);
    setenv("LOGNAME", "test", 1);
    setenv("HOME", "/home/test", 1);
    unsetenv("TMPDIR");
    unsetenv("LD_PRELOAD");
    unsetenv("LD_LIBRARY_PATH");
    unsetenv("QEMU_AUDIO_DRV");
    unsetenv("SDL_AUDIODRIVER");

    DO_TEST("qemu-ns-domain", false, NONE);
    DO_TEST("qemu-ns-domain-ns0", false, NONE);
    DO_TEST("qemu-ns-domain-commandline", false, NONE);
    DO_TEST("qemu-ns-domain-commandline-ns0", false, NONE);
    DO_TEST("qemu-ns-commandline", false, NONE);
    DO_TEST("qemu-ns-commandline-ns0", false, NONE);
    DO_TEST("qemu-ns-commandline-ns1", false, NONE);

    virObjectUnref(driver.config);
    virObjectUnref(driver.caps);
    virObjectUnref(driver.xmlopt);

    return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
}
Ejemplo n.º 4
0
int locale_setup(void) {
    char *variables[_VARIABLE_MAX] = {};
    int r = 0, i;

    if (detect_container(NULL) <= 0) {
        r = parse_env_file("/proc/cmdline", WHITESPACE,
                           "locale.LANG",              &variables[VARIABLE_LANG],
                           "locale.LANGUAGE",          &variables[VARIABLE_LANGUAGE],
                           "locale.LC_CTYPE",          &variables[VARIABLE_LC_CTYPE],
                           "locale.LC_NUMERIC",        &variables[VARIABLE_LC_NUMERIC],
                           "locale.LC_TIME",           &variables[VARIABLE_LC_TIME],
                           "locale.LC_COLLATE",        &variables[VARIABLE_LC_COLLATE],
                           "locale.LC_MONETARY",       &variables[VARIABLE_LC_MONETARY],
                           "locale.LC_MESSAGES",       &variables[VARIABLE_LC_MESSAGES],
                           "locale.LC_PAPER",          &variables[VARIABLE_LC_PAPER],
                           "locale.LC_NAME",           &variables[VARIABLE_LC_NAME],
                           "locale.LC_ADDRESS",        &variables[VARIABLE_LC_ADDRESS],
                           "locale.LC_TELEPHONE",      &variables[VARIABLE_LC_TELEPHONE],
                           "locale.LC_MEASUREMENT",    &variables[VARIABLE_LC_MEASUREMENT],
                           "locale.LC_IDENTIFICATION", &variables[VARIABLE_LC_IDENTIFICATION],
                           NULL);

        if (r < 0 && r != -ENOENT)
            log_warning("Failed to read /proc/cmdline: %s", strerror(-r));
    }

    /* Hmm, nothing set on the kernel cmd line? Then let's
     * try /etc/locale.conf */
    if (r <= 0) {
        r = parse_env_file("/etc/locale.conf", NEWLINE,
                           "LANG",              &variables[VARIABLE_LANG],
                           "LANGUAGE",          &variables[VARIABLE_LANGUAGE],
                           "LC_CTYPE",          &variables[VARIABLE_LC_CTYPE],
                           "LC_NUMERIC",        &variables[VARIABLE_LC_NUMERIC],
                           "LC_TIME",           &variables[VARIABLE_LC_TIME],
                           "LC_COLLATE",        &variables[VARIABLE_LC_COLLATE],
                           "LC_MONETARY",       &variables[VARIABLE_LC_MONETARY],
                           "LC_MESSAGES",       &variables[VARIABLE_LC_MESSAGES],
                           "LC_PAPER",          &variables[VARIABLE_LC_PAPER],
                           "LC_NAME",           &variables[VARIABLE_LC_NAME],
                           "LC_ADDRESS",        &variables[VARIABLE_LC_ADDRESS],
                           "LC_TELEPHONE",      &variables[VARIABLE_LC_TELEPHONE],
                           "LC_MEASUREMENT",    &variables[VARIABLE_LC_MEASUREMENT],
                           "LC_IDENTIFICATION", &variables[VARIABLE_LC_IDENTIFICATION],
                           NULL);

        if (r < 0 && r != -ENOENT)
            log_warning("Failed to read /etc/locale.conf: %s", strerror(-r));
    }

    if (r <= 0 &&
            (r = parse_env_file("/etc/default/locale", NEWLINE,
                                "LANG",              &variables[VARIABLE_LANG],
                                "LC_CTYPE",          &variables[VARIABLE_LC_CTYPE],
                                "LC_NUMERIC",        &variables[VARIABLE_LC_NUMERIC],
                                "LC_TIME",           &variables[VARIABLE_LC_TIME],
                                "LC_COLLATE",        &variables[VARIABLE_LC_COLLATE],
                                "LC_MONETARY",       &variables[VARIABLE_LC_MONETARY],
                                "LC_MESSAGES",       &variables[VARIABLE_LC_MESSAGES],
                                "LC_PAPER",          &variables[VARIABLE_LC_PAPER],
                                "LC_NAME",           &variables[VARIABLE_LC_NAME],
                                "LC_ADDRESS",        &variables[VARIABLE_LC_ADDRESS],
                                "LC_TELEPHONE",      &variables[VARIABLE_LC_TELEPHONE],
                                "LC_MEASUREMENT",    &variables[VARIABLE_LC_MEASUREMENT],
                                "LC_IDENTIFICATION", &variables[VARIABLE_LC_IDENTIFICATION],
                                NULL)) < 0) {

        if (r != -ENOENT)
            log_warning("Failed to read /etc/default/locale: %s", strerror(-r));
    }

    if (!variables[VARIABLE_LANG]) {
        variables[VARIABLE_LANG] = strdup("C");
        if (!variables[VARIABLE_LANG]) {
            r = -ENOMEM;
            goto finish;
        }
    }

    for (i = 0; i < _VARIABLE_MAX; i++) {
        if (variables[i]) {
            if (setenv(variable_names[i], variables[i], 1) < 0) {
                r = -errno;
                goto finish;
            }
        } else
            unsetenv(variable_names[i]);
    }

    r = 0;

finish:
    for (i = 0; i < _VARIABLE_MAX; i++)
        free(variables[i]);

    return r;
}
Ejemplo n.º 5
0
void
test_str_screen_width (void)
{
    struct winsize  winsize;
    int             pty, pts;
    size_t          len = 0;

    TEST_FUNCTION ("nih_str_screen_width");
    unsetenv ("COLUMNS");

    winsize.ws_row = 24;
    winsize.ws_col = 40;
    winsize.ws_xpixel = 0;
    winsize.ws_ypixel = 0;
    openpty (&pty, &pts, NULL, NULL, &winsize);

    /* Check that we can obtain the width of a screen, where one
     * is available.  It should match the number of columns in the
     * pty we run this within.
     */
    TEST_FEATURE ("with screen width");
    TEST_DIVERT_STDOUT_FD (pts) {
        len = nih_str_screen_width ();
    }

    TEST_EQ (len, 40);


    /* Check that the COLUMNS environment variable overrides the width
     * of the screen that we detect.
     */
    TEST_FEATURE ("with COLUMNS variable");
    putenv ("COLUMNS=30");
    TEST_DIVERT_STDOUT_FD (pts) {
        len = nih_str_screen_width ();
    }

    TEST_EQ (len, 30);


    /* Check that we ignore a COLUMNS variable that's not an integer */
    TEST_FEATURE ("with illegal COLUMNS variable");
    putenv ("COLUMNS=30pt");
    TEST_DIVERT_STDOUT_FD (pts) {
        len = nih_str_screen_width ();
    }

    TEST_EQ (len, 40);

    unsetenv ("COLUMNS");
    close (pts);
    close (pty);


    /* Check that we fallback to assuming 80 columns if we don't have
     * any luck with either the tty or COLUMNS variable.
     */
    TEST_FEATURE ("with fallback to 80 columns");
    pts = open ("/dev/null", O_RDWR | O_NOCTTY);
    TEST_DIVERT_STDOUT_FD (pts) {
        len = nih_str_screen_width ();
    }

    TEST_EQ (len, 80);

    close (pts);
}
Ejemplo n.º 6
0
static void
TclCygwinPutenv(
    const char *str)
{
    char *name, *value;

    /*
     * Get the name and value, so that we can change the environment variable
     * for Windows.
     */

    name = alloca(strlen(str) + 1);
    strcpy(name, str);
    for (value=name ; *value!='=' && *value!='\0' ; ++value) {
	/* Empty body */
    }
    if (*value == '\0') {
	/* Can't happen. */
	return;
    }
    *value = '\0';
    ++value;
    if (*value == '\0') {
	value = NULL;
    }

    /*
     * Set the cygwin environment variable.
     */

#undef putenv
    if (value == NULL) {
	unsetenv(name);
    } else {
	putenv(str);
    }

    /*
     * Before changing the environment variable in Windows, if this is PATH,
     * we need to convert the value back to a Windows style path.
     *
     * FIXME: The calling program may know it is running under windows, and
     * may have set the path to a Windows path, or, worse, appended or
     * prepended a Windows path to PATH.
     */

    if (strcmp(name, "PATH") != 0) {
	/*
	 * If this is Path, eliminate any PATH variable, to prevent any
	 * confusion.
	 */

	if (strcmp(name, "Path") == 0) {
	    SetEnvironmentVariable("PATH", NULL);
	    unsetenv("PATH");
	}

	SetEnvironmentVariable(name, value);
    } else {
	char *buf;

	/*
	 * Eliminate any Path variable, to prevent any confusion.
	 */

	SetEnvironmentVariable("Path", NULL);
	unsetenv("Path");

	if (value == NULL) {
	    buf = NULL;
	} else {
	    int size;

	    size = cygwin_posix_to_win32_path_list_buf_size(value);
	    buf = alloca(size + 1);
	    cygwin_posix_to_win32_path_list(value, buf);
	}

	SetEnvironmentVariable(name, buf);
    }
}
Ejemplo n.º 7
0
Archivo: vlc.c Proyecto: Aseeker/vlc
/*****************************************************************************
 * main: parse command line, start interface and spawn threads.
 *****************************************************************************/
int main( int i_argc, const char *ppsz_argv[] )
{
    /* The so-called POSIX-compliant MacOS X reportedly processes SIGPIPE even
     * if it is blocked in all thread.
     * Note: this is NOT an excuse for not protecting against SIGPIPE. If
     * LibVLC runs outside of VLC, we cannot rely on this code snippet. */
    signal (SIGPIPE, SIG_IGN);
    /* Restore SIGCHLD in case our parent process ignores it. */
    signal (SIGCHLD, SIG_DFL);

#ifndef NDEBUG
    /* Activate malloc checking routines to detect heap corruptions. */
    setenv ("MALLOC_CHECK_", "2", 1);

    /* Disable the ugly Gnome crash dialog so that we properly segfault */
    setenv ("GNOME_DISABLE_CRASH_DIALOG", "1", 1);
#endif

#ifdef TOP_BUILDDIR
    setenv ("VLC_PLUGIN_PATH", TOP_BUILDDIR"/modules", 1);
    setenv ("VLC_DATA_PATH", TOP_SRCDIR"/share", 1);
#endif

    /* Clear the X.Org startup notification ID. Otherwise the UI might try to
     * change the environment while the process is multi-threaded. That could
     * crash. Screw you X.Org. Next time write a thread-safe specification. */
    unsetenv ("DESKTOP_STARTUP_ID");

#ifndef ALLOW_RUN_AS_ROOT
    if (geteuid () == 0)
    {
        fprintf (stderr, "VLC is not supposed to be run as root. Sorry.\n"
        "If you need to use real-time priorities and/or privileged TCP ports\n"
        "you can use %s-wrapper (make sure it is Set-UID root and\n"
        "cannot be run by non-trusted users first).\n", ppsz_argv[0]);
        return 1;
    }
#endif

    setlocale (LC_ALL, "");

    if (isatty (STDERR_FILENO))
        /* This message clutters error logs. It is printed only on a TTY.
         * Fortunately, LibVLC prints version info with -vv anyway. */
        fprintf (stderr, "VLC media player %s (revision %s)\n",
                 libvlc_get_version(), libvlc_get_changeset());

    sigset_t set;

    sigemptyset (&set);
    /* VLC uses sigwait() to dequeue interesting signals.
     * For this to work, those signals must be blocked in all threads,
     * including the thread calling sigwait() (see the man page for details).
     *
     * There are two advantages to sigwait() over traditional signal handlers:
     *  - delivery is synchronous: no need to worry about async-safety,
     *  - EINTR is not generated: other threads need not handle that error.
     * That being said, some LibVLC programs do not use sigwait(). Therefore
     * EINTR must still be handled cleanly, notably from poll() calls.
     *
     * Signals that request a clean shutdown, and force an unclean shutdown
     * if they are triggered again 2+ seconds later.
     * We have to handle SIGTERM cleanly because of daemon mode. */
    sigaddset (&set, SIGINT);
    sigaddset (&set, SIGHUP);
    sigaddset (&set, SIGQUIT);
    sigaddset (&set, SIGTERM);

    /* SIGPIPE can happen and would crash the process. On modern systems,
     * the MSG_NOSIGNAL flag protects socket write operations against SIGPIPE.
     * But we still need to block SIGPIPE when:
     *  - writing to pipes,
     *  - using write() instead of send() for code not specific to sockets.
     * LibVLC code assumes that SIGPIPE is blocked. Other LibVLC applications
     * shall block it (or handle it somehow) too.
     */
    sigaddset (&set, SIGPIPE);

    /* SIGCHLD must be dequeued to clean up zombie child processes.
     * Furthermore the handler must not be set to SIG_IGN (see above).
     * We cannot pragmatically handle EINTR, short reads and short writes
     * in every code paths (including underlying libraries). So we just
     * block SIGCHLD in all threads, and dequeue it below. */
    sigaddset (&set, SIGCHLD);

    /* Block all these signals */
    pthread_t self = pthread_self ();
    pthread_sigmask (SIG_SETMASK, &set, NULL);

    const char *argv[i_argc + 3];
    int argc = 0;

    argv[argc++] = "--no-ignore-config";
    argv[argc++] = "--media-library";
    argv[argc++] = "--stats";
    ppsz_argv++; i_argc--; /* skip executable path */

#ifdef __OS2__
    for (int i = 0; i < i_argc; i++)
        if ((argv[argc++] = FromSystem (ppsz_argv[i])) == NULL)
        {
            fprintf (stderr, "Converting '%s' to UTF-8 failed.\n",
                     ppsz_argv[i]);
            return 1;
        }
#else
    memcpy (argv + argc, ppsz_argv, i_argc * sizeof (*argv));
    argc += i_argc;
#endif
    argv[argc] = NULL;

    vlc_enable_override ();

    /* Initialize libvlc */
    libvlc_instance_t *vlc = libvlc_new (argc, argv);
    if (vlc == NULL)
        return 1;

    int ret = 1;
    libvlc_set_exit_handler (vlc, vlc_kill, &self);
    libvlc_set_app_id (vlc, "org.VideoLAN.VLC", PACKAGE_VERSION, PACKAGE_NAME);
    libvlc_set_user_agent (vlc, "VLC media player", "VLC/"PACKAGE_VERSION);

    libvlc_add_intf (vlc, "hotkeys,none");
#if !defined (__OS2__)
    libvlc_add_intf (vlc, "globalhotkeys,none");
#endif
#ifdef HAVE_DBUS
    libvlc_add_intf (vlc, "dbus,none");
#endif
    if (libvlc_add_intf (vlc, NULL))
        goto out;

    libvlc_playlist_play (vlc, -1, 0, NULL);

    /* Qt4 insists on catching SIGCHLD via signal handler. To work around that,
     * unblock it after all our child threads are created. */
    sigdelset (&set, SIGCHLD);
    pthread_sigmask (SIG_SETMASK, &set, NULL);

    /* Do not dequeue SIGHUP if it is ignored (nohup) */
    if (signal_ignored (SIGHUP))
        sigdelset (&set, SIGHUP);
    /* Ignore SIGPIPE */
    sigdelset (&set, SIGPIPE);

    int signum;
    sigwait (&set, &signum);

    /* Restore default signal behaviour after 3 seconds */
    sigemptyset (&set);
    sigaddset (&set, SIGINT);
    sigaddset (&set, SIGALRM);
    signal (SIGINT, SIG_IGN);
    signal (SIGALRM, exit_timeout);
    pthread_sigmask (SIG_UNBLOCK, &set, NULL);
    alarm (3);

    ret = 0;
    /* Cleanup */
out:
    libvlc_release (vlc);
#ifdef __OS2__
    for (int i = 2; i < argc; i++)
        free (argv[i]);
#endif
    return ret;
}
Ejemplo n.º 8
0
bool MinidumpCallback(const XP_CHAR* dump_path,
                      const XP_CHAR* minidump_id,
                      void* context,
#ifdef XP_WIN32
                      EXCEPTION_POINTERS* exinfo,
                      MDRawAssertionInfo* assertion,
#endif
                      bool succeeded)
{
  bool returnValue = showOSCrashReporter ? false : succeeded;

  XP_CHAR minidumpPath[XP_PATH_MAX];
  int size = XP_PATH_MAX;
  XP_CHAR* p = Concat(minidumpPath, dump_path, &size);
  p = Concat(p, XP_PATH_SEPARATOR, &size);
  p = Concat(p, minidump_id, &size);
  Concat(p, dumpFileExtension, &size);

  XP_CHAR extraDataPath[XP_PATH_MAX];
  size = XP_PATH_MAX;
  p = Concat(extraDataPath, dump_path, &size);
  p = Concat(p, XP_PATH_SEPARATOR, &size);
  p = Concat(p, minidump_id, &size);
  Concat(p, extraFileExtension, &size);

  // calculate time since last crash (if possible), and store
  // the time of this crash.
  time_t crashTime = time(NULL);
  time_t timeSinceLastCrash = 0;
  // stringified versions of the above
  char crashTimeString[32];
  int crashTimeStringLen = 0;
  char timeSinceLastCrashString[32];
  int timeSinceLastCrashStringLen = 0;

  XP_TTOA(crashTime, crashTimeString, 10);
  crashTimeStringLen = strlen(crashTimeString);
  if (lastCrashTime != 0) {
    timeSinceLastCrash = crashTime - lastCrashTime;
    XP_TTOA(timeSinceLastCrash, timeSinceLastCrashString, 10);
    timeSinceLastCrashStringLen = strlen(timeSinceLastCrashString);
  }
  // write crash time to file
  if (lastCrashTimeFilename[0] != 0) {
#if defined(XP_WIN32)
    HANDLE hFile = CreateFile(lastCrashTimeFilename, GENERIC_WRITE, 0,
                              NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
                              NULL);
    if(hFile != INVALID_HANDLE_VALUE) {
      DWORD nBytes;
      WriteFile(hFile, crashTimeString, crashTimeStringLen, &nBytes, NULL);
      CloseHandle(hFile);
    }
#elif defined(XP_UNIX)
    int fd = open(lastCrashTimeFilename,
                  O_WRONLY | O_CREAT | O_TRUNC,
                  0600);
    if (fd != -1) {
      write(fd, crashTimeString, crashTimeStringLen);
      close(fd);
    }
#endif
  }

#if defined(XP_WIN32)
  XP_CHAR cmdLine[CMDLINE_SIZE];
  size = CMDLINE_SIZE;
  p = Concat(cmdLine, L"\"", &size);
  p = Concat(p, crashReporterPath, &size);
  p = Concat(p, L"\" \"", &size);
  p = Concat(p, minidumpPath, &size);
  Concat(p, L"\"", &size);

  if (!crashReporterAPIData->IsEmpty()) {
    // write out API data
    HANDLE hFile = CreateFile(extraDataPath, GENERIC_WRITE, 0,
                              NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
                              NULL);
    if(hFile != INVALID_HANDLE_VALUE) {
      DWORD nBytes;
      WriteFile(hFile, crashReporterAPIData->get(),
                crashReporterAPIData->Length(), &nBytes, NULL);
      WriteFile(hFile, kCrashTimeParameter, kCrashTimeParameterLen,
                &nBytes, NULL);
      WriteFile(hFile, crashTimeString, crashTimeStringLen, &nBytes, NULL);
      WriteFile(hFile, "\n", 1, &nBytes, NULL);
      if (timeSinceLastCrash != 0) {
        WriteFile(hFile, kTimeSinceLastCrashParameter,
                  kTimeSinceLastCrashParameterLen, &nBytes, NULL);
        WriteFile(hFile, timeSinceLastCrashString, timeSinceLastCrashStringLen,
                  &nBytes, NULL);
        WriteFile(hFile, "\n", 1, &nBytes, NULL);
      }
      CloseHandle(hFile);
    }
  }

  if (!doReport) {
    return returnValue;
  }

  STARTUPINFO si;
  PROCESS_INFORMATION pi;

  ZeroMemory(&si, sizeof(si));
  si.cb = sizeof(si);
  si.dwFlags = STARTF_USESHOWWINDOW;
  si.wShowWindow = SW_SHOWNORMAL;
  ZeroMemory(&pi, sizeof(pi));

  if (CreateProcess(NULL, (LPWSTR)cmdLine, NULL, NULL, FALSE, 0,
                    NULL, NULL, &si, &pi)) {
    CloseHandle( pi.hProcess );
    CloseHandle( pi.hThread );
  }
  // we're not really in a position to do anything if the CreateProcess fails
  TerminateProcess(GetCurrentProcess(), 1);
#elif defined(XP_UNIX)
  if (!crashReporterAPIData->IsEmpty()) {
    // write out API data
    int fd = open(extraDataPath,
                  O_WRONLY | O_CREAT | O_TRUNC,
                  0666);

    if (fd != -1) {
      // not much we can do in case of error
      write(fd, crashReporterAPIData->get(), crashReporterAPIData->Length());
      write(fd, kCrashTimeParameter, kCrashTimeParameterLen);
      write(fd, crashTimeString, crashTimeStringLen);
      write(fd, "\n", 1);
      if (timeSinceLastCrash != 0) {
        write(fd, kTimeSinceLastCrashParameter,kTimeSinceLastCrashParameterLen);
        write(fd, timeSinceLastCrashString, timeSinceLastCrashStringLen);
        write(fd, "\n", 1);
      }
      close (fd);
    }
  }

  if (!doReport) {
    return returnValue;
  }

  pid_t pid = fork();

  if (pid == -1)
    return false;
  else if (pid == 0) {
    // need to clobber this, as libcurl might load NSS,
    // and we want it to load the system NSS.
    unsetenv("LD_LIBRARY_PATH");
    (void) execl(crashReporterPath,
                 crashReporterPath, minidumpPath, (char*)0);
    _exit(1);
  }
#endif

 return returnValue;
}
Ejemplo n.º 9
0
int main(int argc, char **argv){
  char **args;
  char *cmd;
  int i, match;
  FILE *f;
  char *cobalt_config_file;
  char line[1024];
  char python_exe[80];
  char poss_exe[80];
  char diag[80];

  strncpy(python_exe, "/usr/bin/python", 80);

  unsetenv("IFS");
  unsetenv("LD_PRELOAD");
  unsetenv("LD_LIBRARY_PATH");
  if (strlen(PYTHONPATH) > 0) {
      setenv("PYTHONPATH", PYTHONPATH, 1);
  } else {
      unsetenv("PYTHONPATH");
  }
  /* To disable the user's ability to override the default configuration file,
     uncomment the following line.  In addition, the argument processing code
     below should be modfied to strip the --config-files option from the
     arguments passed on to the python program. */
  /* unsetenv("COBALT_CONFIG_FILES"); */
  
  /* grab the python executable from the cobalt.conf file.  This should ultimately
   * be handled by a configure script.
   * --PMR */
  cobalt_config_file = getenv("COBALT_CONFIG_FILES");
  if (cobalt_config_file == NULL){
    cobalt_config_file = "/etc/cobalt.conf";
  }
  f = fopen(cobalt_config_file, "r");
  if(f == NULL){
    perror(argv[0]);
    return 1;
  }

  while ((fgets(line, 1024 ,f)) != NULL){
    match = sscanf(line, "[%[^]]]", diag);
    if (match && (!strncmp(diag, "components", 80))){
      break;
    }
  }
  while ((fgets(line, 1024 ,f)) != NULL){
    match = sscanf(line, "%[^=]=%s", diag, poss_exe);
    if (match != 2){
      match = sscanf(line, "%[^:]:%s", diag, poss_exe);
    }
    strip_whitespace(diag);
    strip_whitespace(poss_exe);
    if (match && (!strncmp(diag, "python", 80))){
      strncpy(python_exe, poss_exe, 80);
      break;
    }
    if (sscanf(line, "[%[^]]]", diag))
      break;
  }
  fclose(f);

  putenv("SSS_WRAPPER=1");
  args = malloc((argc+3) * sizeof(char *));
  /*prepend the python override*/
  args[0] = python_exe;
  args[1] = "-E";
  for (i=1;i<argc;i++)
    args[i+2] = argv[i];
  args[i+2] = NULL;
  if ( ( cmd = basename(argv[0]) ) == NULL ) {
    perror(argv[0]);
    return 1;
  }
  if (asprintf(&args[2], "%s/%s.py", PROGPREFIX, cmd) == -1) {
    perror(argv[0]);
    return 1;
  }
  /*for (i=0;i<argc+3;++i){
    printf("%s ", args[i]);
  }
  printf("\n");*/
  if (execv(args[0], args)) {
    perror(argv[0]);
    return 1;
  }

  return 0;
}
Ejemplo n.º 10
0
Archivo: wlc.c Proyecto: UIKit0/wlc
WLC_API bool
wlc_init(const struct wlc_interface *interface, int argc, char *argv[])
{
   assert(interface);

   if (!interface)
      die("no wlc_interface was given");

   if (wlc.display)
      return true;

   memset(&wlc, 0, sizeof(wlc));

   wl_log_set_handler_server(wl_cb_log);

   for (int i = 1; i < argc; ++i) {
      if (chck_cstreq(argv[i], "--log")) {
         if (i + 1 >= argc)
            die("--log takes an argument (filename)");
         wlc_set_log_file(fopen(argv[++i], "a"));
      }
   }

   unsetenv("TERM");
   const char *x11display = getenv("DISPLAY");
   bool privilidged = false;
   const bool has_logind  = wlc_logind_available();

   if (getuid() != geteuid() || getgid() != getegid()) {
      wlc_log(WLC_LOG_INFO, "Doing work on SUID/SGID side and dropping permissions");
      privilidged = true;
   } else if (getuid() == 0) {
      die("Do not run wlc compositor as root");
   } else if (!x11display && !has_logind && access("/dev/input/event0", R_OK | W_OK) != 0) {
      die("Not running from X11 and no access to /dev/input/event0 or logind available");
   }

#ifndef NDEBUG
   {
      struct sigaction action = {
         .sa_handler = backtrace
      };
      sigaction(SIGABRT, &action, NULL);
      sigaction(SIGSEGV, &action, NULL);

      // XXX: Some weird sigfpes seems to come when running
      // wlc compositor inside wlc compositor (X11 backend).
      // Seems to be caused by resolution changes and mouse clicks.
      // Gather more information about this later and see what's going on.
      if (!getenv("WAYLAND_DISPLAY"))
         fpesetup(&action);
   }
#endif

   int vt = 0;

#ifdef HAS_LOGIND
   // Init logind if we are not running as SUID.
   // We need event loop for logind to work, and thus we won't allow it on SUID process.
   if (!privilidged && !x11display && has_logind) {
      if (!(wlc.display = wl_display_create()))
         die("Failed to create wayland display");
      if (!(vt = wlc_logind_init("seat0")))
         die("Failed to init logind");
   }
#else
   (void)privilidged;
#endif

   if (!x11display)
      wlc_tty_init(vt);

   // -- we open tty before dropping permissions
   //    so the fd process can also handle cleanup in case of crash
   //    if logind initialized correctly, fd process does nothing but handle crash.

   {
      struct wl_display *display = wlc.display;
      wlc.display = NULL;
      wlc_fd_init(argc, argv, (vt != 0));
      wlc.display = display;
   }


   // -- permissions are now dropped

   wl_signal_init(&wlc.signals.terminate);
   wl_signal_init(&wlc.signals.activate);
   wl_signal_init(&wlc.signals.compositor);
   wl_signal_init(&wlc.signals.focus);
   wl_signal_init(&wlc.signals.surface);
   wl_signal_init(&wlc.signals.input);
   wl_signal_init(&wlc.signals.output);
   wl_signal_init(&wlc.signals.render);
   wl_signal_init(&wlc.signals.xwayland);
   wl_signal_add(&wlc.signals.compositor, &compositor_listener);

   if (!wlc_resources_init())
      die("Failed to init resource manager");

   if (!wlc.display && !(wlc.display = wl_display_create()))
      die("Failed to create wayland display");

   const char *socket_name;
   if (!(socket_name = wl_display_add_socket_auto(wlc.display)))
      die("Failed to add socket to wayland display");

   if (socket_name) // shut up static analyze
      setenv("WAYLAND_DISPLAY", socket_name, true);

   if (wl_display_init_shm(wlc.display) != 0)
      die("Failed to init shm");

   if (!wlc_udev_init())
      die("Failed to init udev");

   const char *libinput = getenv("WLC_LIBINPUT");
   if (!x11display || (libinput && !chck_cstreq(libinput, "0"))) {
      if (!wlc_input_init())
         die("Failed to init input");
   }

   memcpy(&wlc.interface, interface, sizeof(wlc.interface));

   if (!wlc_compositor(&wlc.compositor))
      die("Failed to init compositor");

   const char *xwayland = getenv("WLC_XWAYLAND");
   if (!xwayland || !chck_cstreq(xwayland, "0")) {
      if (!(wlc_xwayland_init()))
         die("Failed to init xwayland");
   } else {
      wlc.set_ready_on_run = true;
   }

   wlc_set_active(true);
   return wlc_compositor_is_good(&wlc.compositor);
}
Ejemplo n.º 11
0
int
start_stop_daemon(int argc, char **argv)
{
	int devnull_fd = -1;
#ifdef TIOCNOTTY
	int tty_fd = -1;
#endif

#ifdef HAVE_PAM
	pam_handle_t *pamh = NULL;
	int pamr;
	const char *const *pamenv = NULL;
#endif

	int opt;
	bool start = false;
	bool stop = false;
	bool oknodo = false;
	bool test = false;
	char *exec = NULL;
	char *startas = NULL;
	char *name = NULL;
	char *pidfile = NULL;
	char *retry = NULL;
	int sig = -1;
	int nicelevel = 0, ionicec = -1, ioniced = 0;
	bool background = false;
	bool makepidfile = false;
	bool interpreted = false;
	bool progress = false;
	uid_t uid = 0;
	gid_t gid = 0;
	char *home = NULL;
	int tid = 0;
	char *redirect_stderr = NULL;
	char *redirect_stdout = NULL;
	int stdout_fd;
	int stderr_fd;
	pid_t pid, spid;
	int i;
	char *svcname = getenv("RC_SVCNAME");
	RC_STRINGLIST *env_list;
	RC_STRING *env;
	char *tmp, *newpath, *np;
	char *p;
	char *token;
	char exec_file[PATH_MAX];
	struct passwd *pw;
	struct group *gr;
	char line[130];
	FILE *fp;
	size_t len;
	mode_t numask = 022;
	char **margv;
	unsigned int start_wait = 0;

	TAILQ_INIT(&schedule);
#ifdef DEBUG_MEMORY
	atexit(cleanup);
#endif

	signal_setup(SIGINT, handle_signal);
	signal_setup(SIGQUIT, handle_signal);
	signal_setup(SIGTERM, handle_signal);

	if ((tmp = getenv("SSD_NICELEVEL")))
		if (sscanf(tmp, "%d", &nicelevel) != 1)
			eerror("%s: invalid nice level `%s' (SSD_NICELEVEL)",
			    applet, tmp);

	/* Get our user name and initial dir */
	p = getenv("USER");
	home = getenv("HOME");
	if (home == NULL || p == NULL) {
		pw = getpwuid(getuid());
		if (pw != NULL) {
			if (p == NULL)
				setenv("USER", pw->pw_name, 1);
			if (home == NULL) {
				setenv("HOME", pw->pw_dir, 1);
				home = pw->pw_dir;
			}
		}
	}

	while ((opt = getopt_long(argc, argv, getoptstring, longopts,
		    (int *) 0)) != -1)
		switch (opt) {
		case 'I': /* --ionice */
			if (sscanf(optarg, "%d:%d", &ionicec, &ioniced) == 0)
				eerrorx("%s: invalid ionice `%s'",
				    applet, optarg);
			if (ionicec == 0)
				ioniced = 0;
			else if (ionicec == 3)
				ioniced = 7;
			ionicec <<= 13; /* class shift */
			break;

		case 'K':  /* --stop */
			stop = true;
			break;

		case 'N':  /* --nice */
			if (sscanf(optarg, "%d", &nicelevel) != 1)
				eerrorx("%s: invalid nice level `%s'",
				    applet, optarg);
			break;

		case 'P':  /* --progress */
			progress = true;
			break;

		case 'R':  /* --retry <schedule>|<timeout> */
			retry = optarg;
			break;

		case 'S':  /* --start */
			start = true;
			break;

		case 'b':  /* --background */
			background = true;
			break;

		case 'c':  /* --chuid <username>|<uid> */
			/* DEPRECATED */
			ewarn("WARNING: -c/--chuid is deprecated and will be removed in the future, please use -u/--user instead");
		case 'u':  /* --user <username>|<uid> */
		{
			p = optarg;
			tmp = strsep(&p, ":");
			changeuser = xstrdup(tmp);
			if (sscanf(tmp, "%d", &tid) != 1)
				pw = getpwnam(tmp);
			else
				pw = getpwuid((uid_t)tid);

			if (pw == NULL)
				eerrorx("%s: user `%s' not found",
				    applet, tmp);
			uid = pw->pw_uid;
			home = pw->pw_dir;
			unsetenv("HOME");
			if (pw->pw_dir)
				setenv("HOME", pw->pw_dir, 1);
			unsetenv("USER");
			if (pw->pw_name)
				setenv("USER", pw->pw_name, 1);
			if (gid == 0)
				gid = pw->pw_gid;

			if (p) {
				tmp = strsep (&p, ":");
				if (sscanf(tmp, "%d", &tid) != 1)
					gr = getgrnam(tmp);
				else
					gr = getgrgid((gid_t) tid);

				if (gr == NULL)
					eerrorx("%s: group `%s'"
					    " not found",
					    applet, tmp);
				gid = gr->gr_gid;
			}
		}
		break;

		case 'd':  /* --chdir /new/dir */
			ch_dir = optarg;
			break;

		case 'e': /* --env */
			putenv(optarg);
			break;

		case 'g':  /* --group <group>|<gid> */
			if (sscanf(optarg, "%d", &tid) != 1)
				gr = getgrnam(optarg);
			else
				gr = getgrgid((gid_t)tid);
			if (gr == NULL)
				eerrorx("%s: group `%s' not found",
				    applet, optarg);
			gid = gr->gr_gid;
			break;

		case 'i': /* --interpreted */
			interpreted = true;
			break;

		case 'k':
			if (parse_mode(&numask, optarg))
				eerrorx("%s: invalid mode `%s'",
				    applet, optarg);
			break;

		case 'm':  /* --make-pidfile */
			makepidfile = true;
			break;

		case 'n':  /* --name <process-name> */
			name = optarg;
			break;

		case 'o':  /* --oknodo */
			/* DEPRECATED */
			ewarn("WARNING: -o/--oknodo is deprecated and will be removed in the future");
			oknodo = true;
			break;

		case 'p':  /* --pidfile <pid-file> */
			pidfile = optarg;
			break;

		case 's':  /* --signal <signal> */
			sig = parse_signal(optarg);
			break;

		case 't':  /* --test */
			test = true;
			break;

		case 'r':  /* --chroot /new/root */
			ch_root = optarg;
			break;

		case 'a': /* --startas <name> */
			/* DEPRECATED */
			ewarn("WARNING: -a/--startas is deprecated and will be removed in the future, please use -x/--exec or -n/--name instead");
			startas = optarg;
			break;
		case 'w':
			if (sscanf(optarg, "%d", &start_wait) != 1)
				eerrorx("%s: `%s' not a number",
				    applet, optarg);
			break;
		case 'x':  /* --exec <executable> */
			exec = optarg;
			break;

		case '1':   /* --stdout /path/to/stdout.lgfile */
			redirect_stdout = optarg;
			break;

		case '2':  /* --stderr /path/to/stderr.logfile */
			redirect_stderr = optarg;
			break;

		case_RC_COMMON_GETOPT
		}

	endpwent();
	argc -= optind;
	argv += optind;

	/* Allow start-stop-daemon --signal HUP --exec /usr/sbin/dnsmasq
	 * instead of forcing --stop --oknodo as well */
	if (!start &&
	    !stop &&
	    sig != SIGINT &&
	    sig != SIGTERM &&
	    sig != SIGQUIT &&
	    sig != SIGKILL)
		oknodo = true;

	if (!exec)
		exec = startas;
	else if (!name)
		name = startas;

	if (!exec) {
		exec = *argv;
		if (!exec)
			exec = name;
		if (name && start)
			*argv = name;
	} else if (name)
		*--argv = name;
	else if (exec)
		*--argv = exec;

	if (stop || sig != -1) {
		if (sig == -1)
			sig = SIGTERM;
		if (!*argv && !pidfile && !name && !uid)
			eerrorx("%s: --stop needs --exec, --pidfile,"
			    " --name or --user", applet);
		if (background)
			eerrorx("%s: --background is only relevant with"
			    " --start", applet);
		if (makepidfile)
			eerrorx("%s: --make-pidfile is only relevant with"
			    " --start", applet);
		if (redirect_stdout || redirect_stderr)
			eerrorx("%s: --stdout and --stderr are only relevant"
			    " with --start", applet);
	} else {
		if (!exec)
			eerrorx("%s: nothing to start", applet);
		if (makepidfile && !pidfile)
			eerrorx("%s: --make-pidfile is only relevant with"
			    " --pidfile", applet);
		if ((redirect_stdout || redirect_stderr) && !background)
			eerrorx("%s: --stdout and --stderr are only relevant"
			    " with --background", applet);
	}

	/* Expand ~ */
	if (ch_dir && *ch_dir == '~')
		ch_dir = expand_home(home, ch_dir);
	if (ch_root && *ch_root == '~')
		ch_root = expand_home(home, ch_root);
	if (exec) {
		if (*exec == '~')
			exec = expand_home(home, exec);

		/* Validate that the binary exists if we are starting */
		if (*exec == '/' || *exec == '.') {
			/* Full or relative path */
			if (ch_root)
				snprintf(exec_file, sizeof(exec_file),
				    "%s/%s", ch_root, exec);
			else
				snprintf(exec_file, sizeof(exec_file),
				    "%s", exec);
		} else {
			/* Something in $PATH */
			p = tmp = xstrdup(getenv("PATH"));
			*exec_file = '\0';
			while ((token = strsep(&p, ":"))) {
				if (ch_root)
					snprintf(exec_file, sizeof(exec_file),
					    "%s/%s/%s",
					    ch_root, token, exec);
				else
					snprintf(exec_file, sizeof(exec_file),
					    "%s/%s", token, exec);
				if (exists(exec_file))
					break;
				*exec_file = '\0';
			}
			free(tmp);
		}
	}
	if (start && !exists(exec_file)) {
		eerror("%s: %s does not exist", applet,
		    *exec_file ? exec_file : exec);
		exit(EXIT_FAILURE);
	}

	/* If we don't have a pidfile we should check if it's interpreted
	 * or not. If it we, we need to pass the interpreter through
	 * to our daemon calls to find it correctly. */
	if (interpreted && !pidfile) {
		fp = fopen(exec_file, "r");
		if (fp) {
			p = fgets(line, sizeof(line), fp);
			fclose(fp);
			if (p != NULL && line[0] == '#' && line[1] == '!') {
				p = line + 2;
				/* Strip leading spaces */
				while (*p == ' ' || *p == '\t')
					p++;
				/* Remove the trailing newline */
				len = strlen(p) - 1;
				if (p[len] == '\n')
					p[len] = '\0';
				token = strsep(&p, " ");
				strncpy(exec_file, token, sizeof(exec_file));
				opt = 0;
				for (nav = argv; *nav; nav++)
					opt++;
				nav = xmalloc(sizeof(char *) * (opt + 3));
				nav[0] = exec_file;
				len = 1;
				if (p)
					nav[len++] = p;
				for (i = 0; i < opt; i++)
					nav[i + len] = argv[i];
				nav[i + len] = '\0';
			}
		}
	}
	margv = nav ? nav : argv;

	if (stop || sig != -1) {
		if (sig == -1)
			sig = SIGTERM;
		if (!stop)
			oknodo = true;
		if (retry)
			parse_schedule(retry, sig);
		else if (test || oknodo)
			parse_schedule("0", sig);
		else
			parse_schedule(NULL, sig);
		i = run_stop_schedule(exec, (const char *const *)margv,
		    pidfile, uid, test, progress);

		if (i < 0)
			/* We failed to stop something */
			exit(EXIT_FAILURE);
		if (test || oknodo)
			return i > 0 ? EXIT_SUCCESS : EXIT_FAILURE;

		/* Even if we have not actually killed anything, we should
		 * remove information about it as it may have unexpectedly
		 * crashed out. We should also return success as the end
		 * result would be the same. */
		if (pidfile && exists(pidfile))
			unlink(pidfile);
		if (svcname)
			rc_service_daemon_set(svcname, exec,
			    (const char *const *)argv,
			    pidfile, false);
		exit(EXIT_SUCCESS);
	}

	if (pidfile)
		pid = get_pid(pidfile);
	else
		pid = 0;

	if (do_stop(exec, (const char * const *)margv, pid, uid,
		0, test) > 0)
		eerrorx("%s: %s is already running", applet, exec);

	if (test) {
		if (rc_yesno(getenv("EINFO_QUIET")))
			exit (EXIT_SUCCESS);

		einfon("Would start");
		while (argc-- >= 0)
			printf(" %s", *argv++);
		printf("\n");
		eindent();
		if (uid != 0)
			einfo("as user id %d", uid);
		if (gid != 0)
			einfo("as group id %d", gid);
		if (ch_root)
			einfo("in root `%s'", ch_root);
		if (ch_dir)
			einfo("in dir `%s'", ch_dir);
		if (nicelevel != 0)
			einfo("with a priority of %d", nicelevel);
		if (name)
			einfo ("with a process name of %s", name);
		eoutdent();
		exit(EXIT_SUCCESS);
	}

	ebeginv("Detaching to start `%s'", exec);
	eindentv();

	/* Remove existing pidfile */
	if (pidfile)
		unlink(pidfile);

	if (background)
		signal_setup(SIGCHLD, handle_signal);

	if ((pid = fork()) == -1)
		eerrorx("%s: fork: %s", applet, strerror(errno));

	/* Child process - lets go! */
	if (pid == 0) {
		pid_t mypid = getpid();
		umask(numask);

#ifdef TIOCNOTTY
		tty_fd = open("/dev/tty", O_RDWR);
#endif

		devnull_fd = open("/dev/null", O_RDWR);

		if (nicelevel) {
			if (setpriority(PRIO_PROCESS, mypid, nicelevel) == -1)
				eerrorx("%s: setpritory %d: %s",
				    applet, nicelevel,
				    strerror(errno));
		}

		if (ionicec != -1 &&
		    ioprio_set(1, mypid, ionicec | ioniced) == -1)
			eerrorx("%s: ioprio_set %d %d: %s", applet,
			    ionicec, ioniced, strerror(errno));

		if (ch_root && chroot(ch_root) < 0)
			eerrorx("%s: chroot `%s': %s",
			    applet, ch_root, strerror(errno));

		if (ch_dir && chdir(ch_dir) < 0)
			eerrorx("%s: chdir `%s': %s",
			    applet, ch_dir, strerror(errno));

		if (makepidfile && pidfile) {
			fp = fopen(pidfile, "w");
			if (! fp)
				eerrorx("%s: fopen `%s': %s", applet, pidfile,
				    strerror(errno));
			fprintf(fp, "%d\n", mypid);
			fclose(fp);
		}

#ifdef HAVE_PAM
		if (changeuser != NULL) {
			pamr = pam_start("start-stop-daemon",
			    changeuser, &conv, &pamh);

			if (pamr == PAM_SUCCESS)
				pamr = pam_acct_mgmt(pamh, PAM_SILENT);
			if (pamr == PAM_SUCCESS)
				pamr = pam_open_session(pamh, PAM_SILENT);
			if (pamr != PAM_SUCCESS)
				eerrorx("%s: pam error: %s",
					applet, pam_strerror(pamh, pamr));
		}
#endif

		if (gid && setgid(gid))
			eerrorx("%s: unable to set groupid to %d",
			    applet, gid);
		if (changeuser && initgroups(changeuser, gid))
			eerrorx("%s: initgroups (%s, %d)",
			    applet, changeuser, gid);
		if (uid && setuid(uid))
			eerrorx ("%s: unable to set userid to %d",
			    applet, uid);

		/* Close any fd's to the passwd database */
		endpwent();

#ifdef TIOCNOTTY
		ioctl(tty_fd, TIOCNOTTY, 0);
		close(tty_fd);
#endif

		/* Clean the environment of any RC_ variables */
		env_list = rc_stringlist_new();
		i = 0;
		while (environ[i])
			rc_stringlist_add(env_list, environ[i++]);

#ifdef HAVE_PAM
		if (changeuser != NULL) {
			pamenv = (const char *const *)pam_getenvlist(pamh);
			if (pamenv) {
				while (*pamenv) {
					/* Don't add strings unless they set a var */
					if (strchr(*pamenv, '='))
						putenv(xstrdup(*pamenv));
					else
						unsetenv(*pamenv);
					pamenv++;
				}
			}
		}
#endif

		TAILQ_FOREACH(env, env_list, entries) {
			if ((strncmp(env->value, "RC_", 3) == 0 &&
				strncmp(env->value, "RC_SERVICE=", 10) != 0 &&
				strncmp(env->value, "RC_SVCNAME=", 10) != 0) ||
			    strncmp(env->value, "SSD_NICELEVEL=", 14) == 0)
			{
				p = strchr(env->value, '=');
				*p = '\0';
				unsetenv(env->value);
				continue;
			}
		}
		rc_stringlist_free(env_list);

		/* For the path, remove the rcscript bin dir from it */
		if ((token = getenv("PATH"))) {
			len = strlen(token);
			newpath = np = xmalloc(len + 1);
			while (token && *token) {
				p = strchr(token, ':');
				if (p) {
					*p++ = '\0';
					while (*p == ':')
						p++;
				}
				if (strcmp(token, RC_LIBEXECDIR "/bin") != 0 &&
				    strcmp(token, RC_LIBEXECDIR "/sbin") != 0)
				{
					len = strlen(token);
					if (np != newpath)
						*np++ = ':';
					memcpy(np, token, len);
					np += len;
				}
				token = p;
			}
			*np = '\0';
			unsetenv("PATH");
			setenv("PATH", newpath, 1);
		}

		stdout_fd = devnull_fd;
		stderr_fd = devnull_fd;
		if (redirect_stdout) {
			if ((stdout_fd = open(redirect_stdout,
				    O_WRONLY | O_CREAT | O_APPEND,
				    S_IRUSR | S_IWUSR)) == -1)
				eerrorx("%s: unable to open the logfile"
				    " for stdout `%s': %s",
				    applet, redirect_stdout, strerror(errno));
		}
		if (redirect_stderr) {
			if ((stderr_fd = open(redirect_stderr,
				    O_WRONLY | O_CREAT | O_APPEND,
				    S_IRUSR | S_IWUSR)) == -1)
				eerrorx("%s: unable to open the logfile"
				    " for stderr `%s': %s",
				    applet, redirect_stderr, strerror(errno));
		}

		/* We don't redirect stdin as some daemons may need it */
		if (background || redirect_stdout || rc_yesno(getenv("EINFO_QUIET")))
			dup2(stdout_fd, STDOUT_FILENO);
		if (background || redirect_stderr || rc_yesno(getenv("EINFO_QUIET")))
			dup2(stderr_fd, STDERR_FILENO);

		for (i = getdtablesize() - 1; i >= 3; --i)
			close(i);

		setsid();
		execvp(exec, argv);
#ifdef HAVE_PAM
		if (changeuser != NULL && pamr == PAM_SUCCESS)
			pam_close_session(pamh, PAM_SILENT);
#endif
		eerrorx("%s: failed to exec `%s': %s",
		    applet, exec,strerror(errno));
	}
Ejemplo n.º 12
0
static int
multiboot_exec(struct preloaded_file *fp)
{
	vm_offset_t			 module_start, last_addr, metadata_size;
	vm_offset_t			 modulep, kernend, entry;
	struct file_metadata		*md;
	Elf_Ehdr			*ehdr;
	struct multiboot_info		*mb_info = NULL;
	struct multiboot_mod_list	*mb_mod = NULL;
	char				*cmdline = NULL;
	size_t				 len;
	int				 error, mod_num;

	/*
	 * Don't pass the memory size found by the bootloader, the memory
	 * available to Dom0 will be lower than that.
	 */
	unsetenv("smbios.memory.enabled");

	/* Allocate the multiboot struct and fill the basic details. */
	mb_info = malloc(sizeof(struct multiboot_info));
	if (mb_info == NULL) {
		error = ENOMEM;
		goto error;
	}
	bzero(mb_info, sizeof(struct multiboot_info));
	mb_info->flags = MULTIBOOT_INFO_MEMORY|MULTIBOOT_INFO_BOOT_LOADER_NAME;
	mb_info->mem_lower = bios_basemem / 1024;
	mb_info->mem_upper = bios_extmem / 1024;
	mb_info->boot_loader_name = VTOP(mbl_name);

	/* Set the Xen command line. */
	if (fp->f_args == NULL) {
		/* Add the Xen command line if it is set. */
		cmdline = getenv("xen_cmdline");
		if (cmdline != NULL) {
			fp->f_args = strdup(cmdline);
			if (fp->f_args == NULL) {
				error = ENOMEM;
				goto error;
			}
		}
	}
	if (fp->f_args != NULL) {
		len = strlen(fp->f_name) + 1 + strlen(fp->f_args) + 1;
		cmdline = malloc(len);
		if (cmdline == NULL) {
			error = ENOMEM;
			goto error;
		}
		snprintf(cmdline, len, "%s %s", fp->f_name, fp->f_args);
		mb_info->cmdline = VTOP(cmdline);
		mb_info->flags |= MULTIBOOT_INFO_CMDLINE;
	}

	/* Find the entry point of the Xen kernel and save it for later */
	if ((md = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL) {
		printf("Unable to find %s entry point\n", fp->f_name);
		error = EINVAL;
		goto error;
	}
	ehdr = (Elf_Ehdr *)&(md->md_data);
	entry = ehdr->e_entry & 0xffffff;

	/*
	 * Prepare the multiboot module list, Xen assumes the first
	 * module is the Dom0 kernel, and the second one is the initramfs.
	 * This is not optimal for FreeBSD, that doesn't have a initramfs
	 * but instead loads modules dynamically and creates the metadata
	 * info on-the-fly.
	 *
	 * As expected, the first multiboot module is going to be the
	 * FreeBSD kernel loaded as a raw file. The second module is going
	 * to contain the metadata info and the loaded modules.
	 *
	 * On native FreeBSD loads all the modules and then places the
	 * metadata info at the end, but this is painful when running on Xen,
	 * because it relocates the second multiboot module wherever it
	 * likes. In order to workaround this limitation the metadata
	 * information is placed at the start of the second module and
	 * the original modulep value is saved together with the other
	 * metadata, so we can relocate everything.
	 *
	 * Native layout:
	 *           fp->f_addr + fp->f_size
	 * +---------+----------------+------------+
	 * |         |                |            |
	 * | Kernel  |    Modules     |  Metadata  |
	 * |         |                |            |
	 * +---------+----------------+------------+
	 * fp->f_addr                 modulep      kernend
	 *
	 * Xen layout:
	 *
	 * Initial:
	 *                      fp->f_addr + fp->f_size
	 * +---------+----------+----------------+------------+
	 * |         |          |                |            |
	 * | Kernel  | Reserved |    Modules     |  Metadata  |
	 * |         |          |                |  dry run   |
	 * +---------+----------+----------------+------------+
	 * fp->f_addr
	 *
	 * After metadata polacement (ie: final):
	 *                                  fp->f_addr + fp->f_size
	 * +-----------+---------+----------+----------------+
	 * |           |         |          |                |
	 * |  Kernel   |  Free   | Metadata |    Modules     |
	 * |           |         |          |                |
	 * +-----------+---------+----------+----------------+
	 * fp->f_addr            modulep                     kernend
	 * \__________/          \__________________________/
	 *  Multiboot module 0    Multiboot module 1
	 */

	fp = file_findfile(NULL, "elf kernel");
	if (fp == NULL) {
		printf("No FreeBSD kernel provided, aborting\n");
		error = EINVAL;
		goto error;
	}

	if (fp->f_metadata != NULL) {
		printf("FreeBSD kernel already contains metadata, aborting\n");
		error = EINVAL;
		goto error;
	}


	mb_mod = malloc(sizeof(struct multiboot_mod_list) * NUM_MODULES);
	if (mb_mod == NULL) {
		error = ENOMEM;
		goto error;
	}

	bzero(mb_mod, sizeof(struct multiboot_mod_list) * NUM_MODULES);

	/*
	 * Calculate how much memory is needed for the metatdata. We did
	 * an approximation of the maximum size when loading the kernel,
	 * but now we know the exact size, so we can release some of this
	 * preallocated memory if not needed.
	 */
	last_addr = roundup(max_addr(), PAGE_SIZE);
	mod_num = num_modules(fp);

	/*
	 * Place the metadata after the last used address in order to
	 * calculate it's size, this will not be used.
	 */
	error = bi_load64(fp->f_args, last_addr, &modulep, &kernend, 0);
	if (error != 0) {
		printf("bi_load64 failed: %d\n", error);
		goto error;
	}
	metadata_size = roundup(kernend - last_addr, PAGE_SIZE);

	/* Check that the size is not greater than what we have reserved */
	if (metadata_size > METADATA_RESV_SIZE(mod_num)) {
		printf("Required memory for metadata is greater than reserved "
		    "space, please increase METADATA_FIXED_SIZE and "
		    "METADATA_MODULE_SIZE and rebuild the loader\n");
		error = ENOMEM;
		goto error;
	}

	/* Clean the metadata added to the kernel in the bi_load64 dry run */
	file_removemetadata(fp);

	/*
	 * This is the position where the second multiboot module
	 * will be placed.
	 */
	module_start = fp->f_addr + fp->f_size - metadata_size;

	error = bi_load64(fp->f_args, module_start, &modulep, &kernend, 0);
	if (error != 0) {
		printf("bi_load64 failed: %d\n", error);
		goto error;
	}

	mb_mod[0].mod_start = fp->f_addr;
	mb_mod[0].mod_end = fp->f_addr + fp->f_size;
	mb_mod[0].mod_end -= METADATA_RESV_SIZE(mod_num);

	mb_mod[1].mod_start = module_start;
	mb_mod[1].mod_end = last_addr;

	mb_info->mods_count = NUM_MODULES;
	mb_info->mods_addr = VTOP(mb_mod);
	mb_info->flags |= MULTIBOOT_INFO_MODS;

	dev_cleanup();
	__exec((void *)VTOP(multiboot_tramp), (void *)entry,
	    (void *)VTOP(mb_info));

	panic("exec returned");

error:
	if (mb_mod)
		free(mb_mod);
	if (mb_info)
		free(mb_info);
	if (cmdline)
		free(cmdline);
	return (error);
}
Ejemplo n.º 13
0
int
main(int argc, char *argv[], char *envp[])
{
	extern int mdb_kvm_is_compressed_dump(mdb_io_t *);
	mdb_tgt_ctor_f *tgt_ctor = NULL;
	const char **tgt_argv = alloca(argc * sizeof (char *));
	int tgt_argc = 0;
	mdb_tgt_t *tgt;

	char object[MAXPATHLEN], execname[MAXPATHLEN];
	mdb_io_t *in_io, *out_io, *err_io, *null_io;
	struct termios tios;
	int status, c;
	char *p;

	const char *Iflag = NULL, *Lflag = NULL, *Vflag = NULL, *pidarg = NULL;
	int fflag = 0, Kflag = 0, Rflag = 0, Sflag = 0, Oflag = 0, Uflag = 0;

	int ttylike;
	int longmode = 0;

	stack_t sigstack;

	if (realpath(getexecname(), execname) == NULL) {
		(void) strncpy(execname, argv[0], MAXPATHLEN);
		execname[MAXPATHLEN - 1] = '\0';
	}

	mdb_create(execname, argv[0]);
	bzero(tgt_argv, argc * sizeof (char *));
	argv[0] = (char *)mdb.m_pname;
	_mdb_self_fd = open("/proc/self/as", O_RDONLY);

	mdb.m_env = envp;

	out_io = mdb_fdio_create(STDOUT_FILENO);
	mdb.m_out = mdb_iob_create(out_io, MDB_IOB_WRONLY);

	err_io = mdb_fdio_create(STDERR_FILENO);
	mdb.m_err = mdb_iob_create(err_io, MDB_IOB_WRONLY);
	mdb_iob_clrflags(mdb.m_err, MDB_IOB_AUTOWRAP);

	null_io = mdb_nullio_create();
	mdb.m_null = mdb_iob_create(null_io, MDB_IOB_WRONLY);

	in_io = mdb_fdio_create(STDIN_FILENO);
	if ((mdb.m_termtype = getenv("TERM")) != NULL) {
		mdb.m_termtype = strdup(mdb.m_termtype);
		mdb.m_flags |= MDB_FL_TERMGUESS;
	}
	mdb.m_term = NULL;

	mdb_dmode(mdb_dstr2mode(getenv("MDB_DEBUG")));
	mdb.m_pgid = getpgrp();

	if (getenv("_MDB_EXEC") != NULL)
		mdb.m_flags |= MDB_FL_EXEC;

	/*
	 * Setup an alternate signal stack.  When tearing down pipelines in
	 * terminate(), we may have to destroy the stack of the context in
	 * which we are currently executing the signal handler.
	 */
	sigstack.ss_sp = mmap(NULL, SIGSTKSZ, PROT_READ | PROT_WRITE,
	    MAP_PRIVATE | MAP_ANON, -1, 0);
	if (sigstack.ss_sp == MAP_FAILED)
		die("could not allocate signal stack");
	sigstack.ss_size = SIGSTKSZ;
	sigstack.ss_flags = 0;
	if (sigaltstack(&sigstack, NULL) != 0)
		die("could not set signal stack");

	(void) mdb_signal_sethandler(SIGPIPE, SIG_IGN, NULL);
	(void) mdb_signal_sethandler(SIGQUIT, SIG_IGN, NULL);

	(void) mdb_signal_sethandler(SIGILL, flt_handler, NULL);
	(void) mdb_signal_sethandler(SIGTRAP, flt_handler, NULL);
	(void) mdb_signal_sethandler(SIGIOT, flt_handler, NULL);
	(void) mdb_signal_sethandler(SIGEMT, flt_handler, NULL);
	(void) mdb_signal_sethandler(SIGFPE, flt_handler, NULL);
	(void) mdb_signal_sethandler(SIGBUS, flt_handler, NULL);
	(void) mdb_signal_sethandler(SIGSEGV, flt_handler, NULL);

	(void) mdb_signal_sethandler(SIGHUP, (mdb_signal_f *)terminate, NULL);
	(void) mdb_signal_sethandler(SIGTERM, (mdb_signal_f *)terminate, NULL);

	for (mdb.m_rdvers = RD_VERSION; mdb.m_rdvers > 0; mdb.m_rdvers--) {
		if (rd_init(mdb.m_rdvers) == RD_OK)
			break;
	}

	for (mdb.m_ctfvers = CTF_VERSION; mdb.m_ctfvers > 0; mdb.m_ctfvers--) {
		if (ctf_version(mdb.m_ctfvers) != -1)
			break;
	}

	if ((p = getenv("HISTSIZE")) != NULL && strisnum(p)) {
		mdb.m_histlen = strtoi(p);
		if (mdb.m_histlen < 1)
			mdb.m_histlen = 1;
	}

	while (optind < argc) {
		while ((c = getopt(argc, argv,
		    "fkmo:p:s:uwyACD:FI:KL:MOP:R:SUV:W")) != (int)EOF) {
			switch (c) {
			case 'f':
				fflag++;
				tgt_ctor = mdb_rawfile_tgt_create;
				break;
			case 'k':
				tgt_ctor = mdb_kvm_tgt_create;
				break;
			case 'm':
				mdb.m_tgtflags |= MDB_TGT_F_NOLOAD;
				mdb.m_tgtflags &= ~MDB_TGT_F_PRELOAD;
				break;
			case 'o':
				if (!mdb_set_options(optarg, TRUE))
					terminate(2);
				break;
			case 'p':
				tgt_ctor = mdb_proc_tgt_create;
				pidarg = optarg;
				break;
			case 's':
				if (!strisnum(optarg)) {
					warn("expected integer following -s\n");
					terminate(2);
				}
				mdb.m_symdist = (size_t)(uint_t)strtoi(optarg);
				break;
			case 'u':
				tgt_ctor = mdb_proc_tgt_create;
				break;
			case 'w':
				mdb.m_tgtflags |= MDB_TGT_F_RDWR;
				break;
			case 'y':
				mdb.m_flags |= MDB_FL_USECUP;
				break;
			case 'A':
				(void) mdb_set_options("nomods", TRUE);
				break;
			case 'C':
				(void) mdb_set_options("noctf", TRUE);
				break;
			case 'D':
				mdb_dmode(mdb_dstr2mode(optarg));
				break;
			case 'F':
				mdb.m_tgtflags |= MDB_TGT_F_FORCE;
				break;
			case 'I':
				Iflag = optarg;
				break;
			case 'L':
				Lflag = optarg;
				break;
			case 'K':
				Kflag++;
				break;
			case 'M':
				mdb.m_tgtflags |= MDB_TGT_F_PRELOAD;
				mdb.m_tgtflags &= ~MDB_TGT_F_NOLOAD;
				break;
			case 'O':
				Oflag++;
				break;
			case 'P':
				if (!mdb_set_prompt(optarg))
					terminate(2);
				break;
			case 'R':
				(void) strncpy(mdb.m_root, optarg, MAXPATHLEN);
				mdb.m_root[MAXPATHLEN - 1] = '\0';
				Rflag++;
				break;
			case 'S':
				Sflag++;
				break;
			case 'U':
				Uflag++;
				break;
			case 'V':
				Vflag = optarg;
				break;
			case 'W':
				mdb.m_tgtflags |= MDB_TGT_F_ALLOWIO;
				break;
			case '?':
				if (optopt == '?')
					usage(0);
				/* FALLTHROUGH */
			default:
				usage(2);
			}
		}

		if (optind < argc) {
			const char *arg = argv[optind++];

			if (arg[0] == '+' && strlen(arg) == 2) {
				if (arg[1] != 'o') {
					warn("illegal option -- %s\n", arg);
					terminate(2);
				}
				if (optind >= argc) {
					warn("option requires an argument -- "
					    "%s\n", arg);
					terminate(2);
				}
				if (!mdb_set_options(argv[optind++], FALSE))
					terminate(2);
			} else
				tgt_argv[tgt_argc++] = arg;
		}
	}

	if (rd_ctl(RD_CTL_SET_HELPPATH, (void *)mdb.m_root) != RD_OK) {
		warn("cannot set librtld_db helper path to %s\n", mdb.m_root);
		terminate(2);
	}

	if (mdb.m_debug & MDB_DBG_HELP)
		terminate(0); /* Quit here if we've printed out the tokens */


	if (Iflag != NULL && strchr(Iflag, ';') != NULL) {
		warn("macro path cannot contain semicolons\n");
		terminate(2);
	}

	if (Lflag != NULL && strchr(Lflag, ';') != NULL) {
		warn("module path cannot contain semicolons\n");
		terminate(2);
	}

	if (Kflag || Uflag) {
		char *nm;

		if (tgt_ctor != NULL || Iflag != NULL) {
			warn("neither -f, -k, -p, -u, nor -I "
			    "may be used with -K\n");
			usage(2);
		}

		if (Lflag != NULL)
			mdb_set_lpath(Lflag);

		if ((nm = ttyname(STDIN_FILENO)) == NULL ||
		    strcmp(nm, "/dev/console") != 0) {
			/*
			 * Due to the consequences of typing mdb -K instead of
			 * mdb -k on a tty other than /dev/console, we require
			 * -F when starting kmdb from a tty other than
			 * /dev/console.
			 */
			if (!(mdb.m_tgtflags & MDB_TGT_F_FORCE)) {
				die("-F must also be supplied to start kmdb "
				    "from non-console tty\n");
			}

			if (mdb.m_termtype == NULL || (mdb.m_flags &
			    MDB_FL_TERMGUESS)) {
				if (mdb.m_termtype != NULL)
					strfree(mdb.m_termtype);

				if ((mdb.m_termtype = mdb_scf_console_term()) !=
				    NULL)
					mdb.m_flags |= MDB_FL_TERMGUESS;
			}
		} else {
			/*
			 * When on console, $TERM (if set) takes precedence over
			 * the SMF setting.
			 */
			if (mdb.m_termtype == NULL && (mdb.m_termtype =
			    mdb_scf_console_term()) != NULL)
				mdb.m_flags |= MDB_FL_TERMGUESS;
		}

		control_kmdb(Kflag);
		terminate(0);
		/*NOTREACHED*/
	}

	/*
	 * If standard input appears to have tty attributes, attempt to
	 * initialize a terminal i/o backend on top of stdin and stdout.
	 */
	ttylike = (IOP_CTL(in_io, TCGETS, &tios) == 0);
	if (ttylike) {
		if ((mdb.m_term = mdb_termio_create(mdb.m_termtype,
		    in_io, out_io)) == NULL) {
			if (!(mdb.m_flags & MDB_FL_EXEC)) {
				warn("term init failed: command-line editing "
				    "and prompt will not be available\n");
			}
		} else {
			in_io = mdb.m_term;
		}
	}

	mdb.m_in = mdb_iob_create(in_io, MDB_IOB_RDONLY);
	if (mdb.m_term != NULL) {
		mdb_iob_setpager(mdb.m_out, mdb.m_term);
		if (mdb.m_flags & MDB_FL_PAGER)
			mdb_iob_setflags(mdb.m_out, MDB_IOB_PGENABLE);
		else
			mdb_iob_clrflags(mdb.m_out, MDB_IOB_PGENABLE);
	} else if (ttylike)
		mdb_iob_setflags(mdb.m_in, MDB_IOB_TTYLIKE);
	else
		mdb_iob_setbuf(mdb.m_in, mdb_alloc(1, UM_SLEEP), 1);

	mdb_pservice_init();
	mdb_lex_reset();

	if ((mdb.m_shell = getenv("SHELL")) == NULL)
		mdb.m_shell = "/bin/sh";

	/*
	 * If the debugger state is to be inherited from a previous instance,
	 * restore it now prior to path evaluation so that %R is updated.
	 */
	if ((p = getenv(MDB_CONFIG_ENV_VAR)) != NULL) {
		mdb_set_config(p);
		(void) unsetenv(MDB_CONFIG_ENV_VAR);
	}

	/*
	 * Path evaluation part 1: Create the initial module path to allow
	 * the target constructor to load a support module.  Then expand
	 * any command-line arguments that modify the paths.
	 */
	if (Iflag != NULL)
		mdb_set_ipath(Iflag);
	else
		mdb_set_ipath(MDB_DEF_IPATH);

	if (Lflag != NULL)
		mdb_set_lpath(Lflag);
	else
		mdb_set_lpath(MDB_DEF_LPATH);

	if (mdb_get_prompt() == NULL && !(mdb.m_flags & MDB_FL_ADB))
		(void) mdb_set_prompt(MDB_DEF_PROMPT);

	if (tgt_ctor == mdb_kvm_tgt_create) {
		if (pidarg != NULL) {
			warn("-p and -k options are mutually exclusive\n");
			terminate(2);
		}

		if (tgt_argc == 0)
			tgt_argv[tgt_argc++] = "/dev/ksyms";
		if (tgt_argc == 1 && strisnum(tgt_argv[0]) == 0) {
			if (mdb.m_tgtflags & MDB_TGT_F_ALLOWIO)
				tgt_argv[tgt_argc++] = "/dev/allkmem";
			else
				tgt_argv[tgt_argc++] = "/dev/kmem";
		}
	}

	if (pidarg != NULL) {
		if (tgt_argc != 0) {
			warn("-p may not be used with other arguments\n");
			terminate(2);
		}
		if (proc_arg_psinfo(pidarg, PR_ARG_PIDS, NULL, &status) == -1) {
			die("cannot attach to %s: %s\n",
			    pidarg, Pgrab_error(status));
		}
		if (strchr(pidarg, '/') != NULL)
			(void) mdb_iob_snprintf(object, MAXPATHLEN,
			    "%s/object/a.out", pidarg);
		else
			(void) mdb_iob_snprintf(object, MAXPATHLEN,
			    "/proc/%s/object/a.out", pidarg);
		tgt_argv[tgt_argc++] = object;
		tgt_argv[tgt_argc++] = pidarg;
	}

	/*
	 * Find the first argument that is not a special "-" token.  If one is
	 * found, we will examine this file and make some inferences below.
	 */
	for (c = 0; c < tgt_argc && strcmp(tgt_argv[c], "-") == 0; c++)
		continue;

	if (c < tgt_argc) {
		Elf32_Ehdr ehdr;
		mdb_io_t *io;

		/*
		 * If special "-" tokens preceded an argument, shift the entire
		 * argument list to the left to remove the leading "-" args.
		 */
		if (c > 0) {
			bcopy(&tgt_argv[c], tgt_argv,
			    sizeof (const char *) * (tgt_argc - c));
			tgt_argc -= c;
		}

		if (fflag)
			goto tcreate; /* skip re-exec and just create target */

		/*
		 * If we just have an object file name, and that file doesn't
		 * exist, and it's a string of digits, infer it to be a
		 * sequence number referring to a pair of crash dump files.
		 */
		if (tgt_argc == 1 && access(tgt_argv[0], F_OK) == -1 &&
		    strisnum(tgt_argv[0])) {

			size_t len = strlen(tgt_argv[0]) + 8;
			const char *object = tgt_argv[0];

			tgt_argv[0] = mdb_alloc(len, UM_SLEEP);
			tgt_argv[1] = mdb_alloc(len, UM_SLEEP);

			(void) strcpy((char *)tgt_argv[0], "unix.");
			(void) strcat((char *)tgt_argv[0], object);
			(void) strcpy((char *)tgt_argv[1], "vmcore.");
			(void) strcat((char *)tgt_argv[1], object);

			if (access(tgt_argv[0], F_OK) == -1 &&
			    access(tgt_argv[1], F_OK) == -1) {
				(void) strcpy((char *)tgt_argv[1], "vmdump.");
				(void) strcat((char *)tgt_argv[1], object);
				if (access(tgt_argv[1], F_OK) == 0) {
					mdb_iob_printf(mdb.m_err,
					    "cannot open compressed dump; "
					    "decompress using savecore -f %s\n",
					    tgt_argv[1]);
					terminate(0);
				}
			}

			tgt_argc = 2;
		}

		/*
		 * We need to open the object file in order to determine its
		 * ELF class and potentially re-exec ourself.
		 */
		if ((io = mdb_fdio_create_path(NULL, tgt_argv[0],
		    O_RDONLY, 0)) == NULL)
			die("failed to open %s", tgt_argv[0]);

		/*
		 * Check for a single vmdump.N compressed dump file,
		 * and give a helpful message.
		 */
		if (tgt_argc == 1) {
			if (mdb_kvm_is_compressed_dump(io)) {
				mdb_iob_printf(mdb.m_err,
				    "cannot open compressed dump; "
				    "decompress using savecore -f %s\n",
				    tgt_argv[0]);
				terminate(0);
			}
		}

		/*
		 * If the target is unknown or is not the rawfile target, do
		 * a gelf_check to determine if the file is an ELF file.  If
		 * it is not and the target is unknown, use the rawfile tgt.
		 * Otherwise an ELF-based target is needed, so we must abort.
		 */
		if (mdb_gelf_check(io, &ehdr, ET_NONE) == -1) {
			if (tgt_ctor != NULL) {
				(void) mdb_gelf_check(io, &ehdr, ET_EXEC);
				mdb_io_destroy(io);
				terminate(1);
			} else
				tgt_ctor = mdb_rawfile_tgt_create;
		}

		mdb_io_destroy(io);

		if (identify_xvm_file(tgt_argv[0], &longmode) == 1) {
#ifdef _LP64
			if (!longmode)
				goto reexec;
#else
			if (longmode)
				goto reexec;
#endif
			tgt_ctor = mdb_kvm_tgt_create;
			goto tcreate;
		}

		/*
		 * The object file turned out to be a user core file (ET_CORE),
		 * and no other arguments were specified, swap 0 and 1.  The
		 * proc target will infer the executable for us.
		 */
		if (ehdr.e_type == ET_CORE) {
			tgt_argv[tgt_argc++] = tgt_argv[0];
			tgt_argv[0] = NULL;
			tgt_ctor = mdb_proc_tgt_create;
		}

		/*
		 * If tgt_argv[1] is filled in, open it up and determine if it
		 * is a vmcore file.  If it is, gelf_check will fail and we
		 * set tgt_ctor to 'kvm'; otherwise we use the default.
		 */
		if (tgt_argc > 1 && strcmp(tgt_argv[1], "-") != 0 &&
		    tgt_argv[0] != NULL && pidarg == NULL) {
			Elf32_Ehdr chdr;

			if (access(tgt_argv[1], F_OK) == -1)
				die("failed to access %s", tgt_argv[1]);

			/* *.N case: drop vmdump.N from the list */
			if (tgt_argc == 3) {
				if ((io = mdb_fdio_create_path(NULL,
				    tgt_argv[2], O_RDONLY, 0)) == NULL)
					die("failed to open %s", tgt_argv[2]);
				if (mdb_kvm_is_compressed_dump(io))
					tgt_argv[--tgt_argc] = NULL;
				mdb_io_destroy(io);
			}

			if ((io = mdb_fdio_create_path(NULL, tgt_argv[1],
			    O_RDONLY, 0)) == NULL)
				die("failed to open %s", tgt_argv[1]);

			if (mdb_gelf_check(io, &chdr, ET_NONE) == -1)
				tgt_ctor = mdb_kvm_tgt_create;

			mdb_io_destroy(io);
		}

		/*
		 * At this point, we've read the ELF header for either an
		 * object file or core into ehdr.  If the class does not match
		 * ours, attempt to exec the mdb of the appropriate class.
		 */
#ifdef _LP64
		if (ehdr.e_ident[EI_CLASS] == ELFCLASS32)
			goto reexec;
#else
		if (ehdr.e_ident[EI_CLASS] == ELFCLASS64)
			goto reexec;
#endif
	}

tcreate:
	if (tgt_ctor == NULL)
		tgt_ctor = mdb_proc_tgt_create;

	tgt = mdb_tgt_create(tgt_ctor, mdb.m_tgtflags, tgt_argc, tgt_argv);

	if (tgt == NULL) {
		if (errno == EINVAL)
			usage(2); /* target can return EINVAL to get usage */
		if (errno == EMDB_TGT)
			terminate(1); /* target already printed error msg */
		die("failed to initialize target");
	}

	mdb_tgt_activate(tgt);

	mdb_create_loadable_disasms();

	if (Vflag != NULL && mdb_dis_select(Vflag) == -1)
		warn("invalid disassembler mode -- %s\n", Vflag);


	if (Rflag && mdb.m_term != NULL)
		warn("Using proto area %s\n", mdb.m_root);

	/*
	 * If the target was successfully constructed and -O was specified,
	 * we now attempt to enter piggy-mode for debugging jurassic problems.
	 */
	if (Oflag) {
		pcinfo_t pci;

		(void) strcpy(pci.pc_clname, "RT");

		if (priocntl(P_LWPID, P_MYID, PC_GETCID, (caddr_t)&pci) != -1) {
			pcparms_t pcp;
			rtparms_t *rtp = (rtparms_t *)pcp.pc_clparms;

			rtp->rt_pri = 35;
			rtp->rt_tqsecs = 0;
			rtp->rt_tqnsecs = RT_TQDEF;

			pcp.pc_cid = pci.pc_cid;

			if (priocntl(P_LWPID, P_MYID, PC_SETPARMS,
			    (caddr_t)&pcp) == -1) {
				warn("failed to set RT parameters");
				Oflag = 0;
			}
		} else {
			warn("failed to get RT class id");
			Oflag = 0;
		}

		if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1) {
			warn("failed to lock address space");
			Oflag = 0;
		}

		if (Oflag)
			mdb_printf("%s: oink, oink!\n", mdb.m_pname);
	}

	/*
	 * Path evaluation part 2: Re-evaluate the path now that the target
	 * is ready (and thus we have access to the real platform string).
	 * Do this before reading ~/.mdbrc to allow path modifications prior
	 * to performing module auto-loading.
	 */
	mdb_set_ipath(mdb.m_ipathstr);
	mdb_set_lpath(mdb.m_lpathstr);

	if (!Sflag && (p = getenv("HOME")) != NULL) {
		char rcpath[MAXPATHLEN];
		mdb_io_t *rc_io;
		int fd;

		(void) mdb_iob_snprintf(rcpath, MAXPATHLEN, "%s/.mdbrc", p);
		fd = open64(rcpath, O_RDONLY);

		if (fd >= 0 && (rc_io = mdb_fdio_create_named(fd, rcpath))) {
			mdb_iob_t *iob = mdb_iob_create(rc_io, MDB_IOB_RDONLY);
			mdb_iob_t *old = mdb.m_in;

			mdb.m_in = iob;
			(void) mdb_run();
			mdb.m_in = old;
		}
	}

	if (!(mdb.m_flags & MDB_FL_NOMODS))
		mdb_module_load_all(0);

	(void) mdb_signal_sethandler(SIGINT, int_handler, NULL);
	while ((status = mdb_run()) == MDB_ERR_ABORT ||
	    status == MDB_ERR_OUTPUT) {
		/*
		 * If a write failed on stdout, give up.  A more informative
		 * error message will already have been printed by mdb_run().
		 */
		if (status == MDB_ERR_OUTPUT &&
		    mdb_iob_getflags(mdb.m_out) & MDB_IOB_ERR) {
			mdb_warn("write to stdout failed, exiting\n");
			break;
		}
		continue;
	}

	terminate((status == MDB_ERR_QUIT || status == 0) ? 0 : 1);
	/*NOTREACHED*/
	return (0);

reexec:
	if ((p = strrchr(execname, '/')) == NULL)
		die("cannot determine absolute pathname\n");
#ifdef _LP64
#ifdef __sparc
	(void) strcpy(p, "/../sparcv7/");
#else
	(void) strcpy(p, "/../i86/");
#endif
#else
#ifdef __sparc
	(void) strcpy(p, "/../sparcv9/");
#else
	(void) strcpy(p, "/../amd64/");
#endif
#endif
	(void) strcat(p, mdb.m_pname);

	if (mdb.m_term != NULL)
		(void) IOP_CTL(in_io, TCSETSW, &tios);

	(void) putenv("_MDB_EXEC=1");
	(void) execv(execname, argv);

	/*
	 * If execv fails, suppress ENOEXEC.  Experience shows the most common
	 * reason is that the machine is booted under a 32-bit kernel, in which
	 * case it is clearer to only print the message below.
	 */
	if (errno != ENOEXEC)
		warn("failed to exec %s", execname);
#ifdef _LP64
	die("64-bit %s cannot debug 32-bit program %s\n",
	    mdb.m_pname, tgt_argv[0] ?
	    tgt_argv[0] : tgt_argv[1]);
#else
	die("32-bit %s cannot debug 64-bit program %s\n",
	    mdb.m_pname, tgt_argv[0] ?
	    tgt_argv[0] : tgt_argv[1]);
#endif

	goto tcreate;
}
Ejemplo n.º 14
0
/*
 * Any Postgres server process begins execution here.
 */
int
main(int argc, char *argv[])
{
	bool		do_check_root = true;

	progname = get_progname(argv[0]);

	/*
	 * Platform-specific startup hacks
	 */
	startup_hacks(progname);

	/*
	 * Remember the physical location of the initially given argv[] array for
	 * possible use by ps display.  On some platforms, the argv[] storage must
	 * be overwritten in order to set the process title for ps. In such cases
	 * save_ps_display_args makes and returns a new copy of the argv[] array.
	 *
	 * save_ps_display_args may also move the environment strings to make
	 * extra room. Therefore this should be done as early as possible during
	 * startup, to avoid entanglements with code that might save a getenv()
	 * result pointer.
	 */
	argv = save_ps_display_args(argc, argv);

	/*
	 * If supported on the current platform, set up a handler to be called if
	 * the backend/postmaster crashes with a fatal signal or exception.
	 */
#if defined(WIN32) && defined(HAVE_MINIDUMP_TYPE)
	pgwin32_install_crashdump_handler();
#endif

	/*
	 * Fire up essential subsystems: error and memory management
	 *
	 * Code after this point is allowed to use elog/ereport, though
	 * localization of messages may not work right away, and messages won't go
	 * anywhere but stderr until GUC settings get loaded.
	 */
	MemoryContextInit();

	/*
	 * Set up locale information from environment.  Note that LC_CTYPE and
	 * LC_COLLATE will be overridden later from pg_control if we are in an
	 * already-initialized database.  We set them here so that they will be
	 * available to fill pg_control during initdb.  LC_MESSAGES will get set
	 * later during GUC option processing, but we set it here to allow startup
	 * error messages to be localized.
	 */

	set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("postgres"));

#ifdef WIN32

	/*
	 * Windows uses codepages rather than the environment, so we work around
	 * that by querying the environment explicitly first for LC_COLLATE and
	 * LC_CTYPE. We have to do this because initdb passes those values in the
	 * environment. If there is nothing there we fall back on the codepage.
	 */
	{
		char	   *env_locale;

		if ((env_locale = getenv("LC_COLLATE")) != NULL)
			init_locale("LC_COLLATE", LC_COLLATE, env_locale);
		else
			init_locale("LC_COLLATE", LC_COLLATE, "");

		if ((env_locale = getenv("LC_CTYPE")) != NULL)
			init_locale("LC_CTYPE", LC_CTYPE, env_locale);
		else
			init_locale("LC_CTYPE", LC_CTYPE, "");
	}
#else
	init_locale("LC_COLLATE", LC_COLLATE, "");
	init_locale("LC_CTYPE", LC_CTYPE, "");
#endif

#ifdef LC_MESSAGES
	init_locale("LC_MESSAGES", LC_MESSAGES, "");
#endif

	/*
	 * We keep these set to "C" always, except transiently in pg_locale.c; see
	 * that file for explanations.
	 */
	init_locale("LC_MONETARY", LC_MONETARY, "C");
	init_locale("LC_NUMERIC", LC_NUMERIC, "C");
	init_locale("LC_TIME", LC_TIME, "C");

	/*
	 * Now that we have absorbed as much as we wish to from the locale
	 * environment, remove any LC_ALL setting, so that the environment
	 * variables installed by pg_perm_setlocale have force.
	 */
	unsetenv("LC_ALL");

	check_strxfrm_bug();

	/*
	 * Catch standard options before doing much else, in particular before we
	 * insist on not being root.
	 */
	if (argc > 1)
	{
		if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
		{
			help(progname);
			exit(0);
		}
		if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
		{
			puts("postgres (PostgreSQL) " PG_VERSION);
			exit(0);
		}

		/*
		 * In addition to the above, we allow "--describe-config" and "-C var"
		 * to be called by root.  This is reasonably safe since these are
		 * read-only activities.  The -C case is important because pg_ctl may
		 * try to invoke it while still holding administrator privileges on
		 * Windows.  Note that while -C can normally be in any argv position,
		 * if you wanna bypass the root check you gotta put it first.  This
		 * reduces the risk that we might misinterpret some other mode's -C
		 * switch as being the postmaster/postgres one.
		 */
		if (strcmp(argv[1], "--describe-config") == 0)
			do_check_root = false;
		else if (argc > 2 && strcmp(argv[1], "-C") == 0)
			do_check_root = false;
	}

	/*
	 * Make sure we are not running as root, unless it's safe for the selected
	 * option.
	 */
	if (do_check_root)
		check_root(progname);

	/*
	 * Dispatch to one of various subprograms depending on first argument.
	 */

#ifdef EXEC_BACKEND
	if (argc > 1 && strncmp(argv[1], "--fork", 6) == 0)
		SubPostmasterMain(argc, argv);	/* does not return */
#endif

#ifdef WIN32

	/*
	 * Start our win32 signal implementation
	 *
	 * SubPostmasterMain() will do this for itself, but the remaining modes
	 * need it here
	 */
	pgwin32_signal_initialize();
#endif

	if (argc > 1 && strcmp(argv[1], "--boot") == 0)
		AuxiliaryProcessMain(argc, argv);		/* does not return */
	else if (argc > 1 && strcmp(argv[1], "--describe-config") == 0)
		GucInfoMain();			/* does not return */
	else if (argc > 1 && strcmp(argv[1], "--single") == 0)
		PostgresMain(argc, argv,
					 NULL,		/* no dbname */
					 strdup(get_user_name_or_exit(progname)));	/* does not return */
	else
		PostmasterMain(argc, argv);		/* does not return */
	abort();					/* should not get here */
}
Ejemplo n.º 15
0
int __attribute__ ((constructor)) initfunc()
{
    int idfd, len;
    char idbuf[20];
    unsetenv("LD_PRELOAD");
    fprintf(stderr, "shmoverride constructor running\n");
    real_shmat = dlsym(RTLD_NEXT, "shmat");
    real_shmctl = dlsym(RTLD_NEXT, "shmctl");
    real_shmdt = dlsym(RTLD_NEXT, "shmdt");
    if (!real_shmat || !real_shmctl || !real_shmdt) {
        perror("shmoverride: missing shm API");
        exit(1);
    }
    addr_list = list_new();
#ifdef XENCTRL_HAS_XC_INTERFACE
    xc_hnd = xc_interface_open(NULL, NULL, 0);
    if (!xc_hnd) {
#else
    xc_hnd = xc_interface_open();
    if (xc_hnd < 0) {
#endif
        perror("shmoverride xc_interface_open");
        return 0;	//allow it to run when not under Xen
    }
    idfd = open(SHMID_FILENAME, O_WRONLY | O_CREAT | O_EXCL, 0600);
    if (idfd < 0) {
        perror("shmoverride creating " SHMID_FILENAME);
        xc_interface_close(xc_hnd);
        return 0;
    }
    local_shmid =
        shmget(IPC_PRIVATE, SHM_CMD_NUM_PAGES * 4096,
                IPC_CREAT | 0700);
    if (local_shmid == -1) {
        unlink(SHMID_FILENAME);
        perror("shmoverride shmget");
        exit(1);
    }
    sprintf(idbuf, "%d", local_shmid);
    len = strlen(idbuf);
    if (write(idfd, idbuf, len) != len) {
        unlink(SHMID_FILENAME);
        perror("shmoverride writing " SHMID_FILENAME);
        exit(1);
    }
    if (close(idfd) < 0) {
        unlink(SHMID_FILENAME);
        perror("shmoverride closing " SHMID_FILENAME);
        exit(1);
    }
    cmd_pages = real_shmat(local_shmid, 0, 0);
    if (!cmd_pages) {
        unlink(SHMID_FILENAME);
        perror("real_shmat");
        exit(1);
    }
    cmd_pages->shmid = local_shmid;
    return 0;
}

int __attribute__ ((destructor)) descfunc()
{
    if (cmd_pages) {
        real_shmdt(cmd_pages);
        real_shmctl(local_shmid, IPC_RMID, 0);
        unlink(SHMID_FILENAME);
    }
    return 0;
}
Ejemplo n.º 16
0
/*
 * Set history and editing status.  Called whenever the status may
 * have changed (figures out what to do).
 */
void
histedit(void)
{
	FILE *el_err;

#define editing (Eflag || Vflag)

	if (iflag == 1) {
		if (!hist) {
			/*
			 * turn history on
			 */
			INTOFF;
			hist = history_init();
			INTON;

			if (hist != NULL)
				sethistsize(histsizeval());
			else
				out2str("sh: can't initialize history\n");
		}
		if (editing && !el && isatty(0)) { /* && isatty(2) ??? */
			/*
			 * turn editing on
			 */
			char *term, *shname;

			INTOFF;
			if (el_in == NULL)
				el_in = fdopen(0, "r");
			if (el_out == NULL)
				el_out = fdopen(2, "w");
			if (el_in == NULL || el_out == NULL)
				goto bad;
			el_err = el_out;
#if DEBUG
			if (tracefile)
				el_err = tracefile;
#endif
			term = lookupvar("TERM");
			if (term)
				setenv("TERM", term, 1);
			else
				unsetenv("TERM");
			shname = arg0;
			if (shname[0] == '-')
				shname++;
			el = el_init(shname, el_in, el_out, el_err);
			if (el != NULL) {
				if (hist)
					el_set(el, EL_HIST, history, hist);
				el_set(el, EL_PROMPT, getprompt);
				el_set(el, EL_SIGNAL, 1);
				el_set(el, EL_ADDFN, "rl-complete",
				    "ReadLine compatible completion function",
				    _el_fn_complete);
			} else {
bad:
				out2str("sh: can't initialize editing\n");
			}
			INTON;
		} else if (!editing && el) {
			INTOFF;
			el_end(el);
			el = NULL;
			INTON;
		}
		if (el) {
			el_source(el, NULL);
			if (Vflag)
				el_set(el, EL_EDITOR, "vi");
			else if (Eflag)
				el_set(el, EL_EDITOR, "emacs");
			el_set(el, EL_BIND, "^I", 
			    tabcomplete ? "rl-complete" : "ed-insert", NULL);
		}
	} else {
		INTOFF;
		if (el) {	/* no editing if not interactive */
			el_end(el);
			el = NULL;
		}
		if (hist) {
			history_end(hist);
			hist = NULL;
		}
		INTON;
	}
}
Ejemplo n.º 17
0
bool
execute_java_class (const char *class_name,
		    const char * const *classpaths,
		    unsigned int classpaths_count,
		    bool use_minimal_classpath,
		    const char *exe_dir,
		    const char * const *args,
		    bool verbose, bool quiet,
		    execute_fn *executer, void *private_data)
{
  bool err = false;
  unsigned int nargs;
  char *old_JAVA_HOME;

  /* Count args.  */
  {
    const char * const *arg;

    for (nargs = 0, arg = args; *arg != NULL; nargs++, arg++)
     ;
  }

  /* First, try a class compiled to a native code executable.  */
  if (exe_dir != NULL)
    {
      char *exe_pathname = concatenated_pathname (exe_dir, class_name, EXEEXT);
      char *old_classpath;
      char **argv = (char **) xallocsa ((1 + nargs + 1) * sizeof (char *));
      unsigned int i;

      /* Set CLASSPATH.  */
      old_classpath =
	set_classpath (classpaths, classpaths_count, use_minimal_classpath,
		       verbose);

      argv[0] = exe_pathname;
      for (i = 0; i <= nargs; i++)
	argv[1 + i] = (char *) args[i];

      if (verbose)
	{
	  char *command = shell_quote_argv (argv);
	  printf ("%s\n", command);
	  free (command);
	}

      err = executer (class_name, exe_pathname, argv, private_data);

      /* Reset CLASSPATH.  */
      reset_classpath (old_classpath);

      freesa (argv);

      goto done1;
    }

  {
    const char *java = getenv ("JAVA");
    if (java != NULL && java[0] != '\0')
      {
	/* Because $JAVA may consist of a command and options, we use the
	   shell.  Because $JAVA has been set by the user, we leave all
	   all environment variables in place, including JAVA_HOME, and
	   we don't erase the user's CLASSPATH.  */
	char *old_classpath;
	unsigned int command_length;
	char *command;
	char *argv[4];
	const char * const *arg;
	char *p;

	/* Set CLASSPATH.  */
	old_classpath =
	  set_classpath (classpaths, classpaths_count, false,
			 verbose);

	command_length = strlen (java);
	command_length += 1 + shell_quote_length (class_name);
	for (arg = args; *arg != NULL; arg++)
	  command_length += 1 + shell_quote_length (*arg);
	command_length += 1;

	command = (char *) xallocsa (command_length);
	p = command;
	/* Don't shell_quote $JAVA, because it may consist of a command
	   and options.  */
	memcpy (p, java, strlen (java));
	p += strlen (java);
	*p++ = ' ';
	p = shell_quote_copy (p, class_name);
	for (arg = args; *arg != NULL; arg++)
	  {
	    *p++ = ' ';
	    p = shell_quote_copy (p, *arg);
	  }
	*p++ = '\0';
	/* Ensure command_length was correctly calculated.  */
	if (p - command > command_length)
	  abort ();

	if (verbose)
	  printf ("%s\n", command);

	argv[0] = "/bin/sh";
	argv[1] = "-c";
	argv[2] = command;
	argv[3] = NULL;
	err = executer (java, "/bin/sh", argv, private_data);

	freesa (command);

	/* Reset CLASSPATH.  */
	reset_classpath (old_classpath);

	goto done1;
      }
  }

  /* Unset the JAVA_HOME environment variable.  */
  old_JAVA_HOME = getenv ("JAVA_HOME");
  if (old_JAVA_HOME != NULL)
    {
      old_JAVA_HOME = xstrdup (old_JAVA_HOME);
      unsetenv ("JAVA_HOME");
    }

  {
    static bool gij_tested;
    static bool gij_present;

    if (!gij_tested)
      {
	/* Test for presence of gij: "gij --version > /dev/null"  */
	char *argv[3];
	int exitstatus;

	argv[0] = "gij";
	argv[1] = "--version";
	argv[2] = NULL;
	exitstatus = execute ("gij", "gij", argv, false, false, true, true,
			      true, false);
	gij_present = (exitstatus == 0);
	gij_tested = true;
      }

    if (gij_present)
      {
	char *old_classpath;
	char **argv = (char **) xallocsa ((2 + nargs + 1) * sizeof (char *));
	unsigned int i;

	/* Set CLASSPATH.  */
	old_classpath =
	  set_classpath (classpaths, classpaths_count, use_minimal_classpath,
			 verbose);

	argv[0] = "gij";
	argv[1] = (char *) class_name;
	for (i = 0; i <= nargs; i++)
	  argv[2 + i] = (char *) args[i];

	if (verbose)
	  {
	    char *command = shell_quote_argv (argv);
	    printf ("%s\n", command);
	    free (command);
	  }

	err = executer ("gij", "gij", argv, private_data);

	/* Reset CLASSPATH.  */
	reset_classpath (old_classpath);

	freesa (argv);

	goto done2;
      }
  }

  {
    static bool java_tested;
    static bool java_present;

    if (!java_tested)
      {
	/* Test for presence of java: "java -version 2> /dev/null"  */
	char *argv[3];
	int exitstatus;

	argv[0] = "java";
	argv[1] = "-version";
	argv[2] = NULL;
	exitstatus = execute ("java", "java", argv, false, false, true, true,
			      true, false);
	java_present = (exitstatus == 0);
	java_tested = true;
      }

    if (java_present)
      {
	char *old_classpath;
	char **argv = (char **) xallocsa ((2 + nargs + 1) * sizeof (char *));
	unsigned int i;

	/* Set CLASSPATH.  We don't use the "-classpath ..." option because
	   in JDK 1.1.x its argument should also contain the JDK's classes.zip,
	   but we don't know its location.  (In JDK 1.3.0 it would work.)  */
	old_classpath =
	  set_classpath (classpaths, classpaths_count, use_minimal_classpath,
			 verbose);

	argv[0] = "java";
	argv[1] = (char *) class_name;
	for (i = 0; i <= nargs; i++)
	  argv[2 + i] = (char *) args[i];

	if (verbose)
	  {
	    char *command = shell_quote_argv (argv);
	    printf ("%s\n", command);
	    free (command);
	  }

	err = executer ("java", "java", argv, private_data);

	/* Reset CLASSPATH.  */
	reset_classpath (old_classpath);

	freesa (argv);

	goto done2;
      }
  }

  {
    static bool jre_tested;
    static bool jre_present;

    if (!jre_tested)
      {
	/* Test for presence of jre: "jre 2> /dev/null ; test $? = 1"  */
	char *argv[2];
	int exitstatus;

	argv[0] = "jre";
	argv[1] = NULL;
	exitstatus = execute ("jre", "jre", argv, false, false, true, true,
			      true, false);
	jre_present = (exitstatus == 0 || exitstatus == 1);
	jre_tested = true;
      }

    if (jre_present)
      {
	char *old_classpath;
	char **argv = (char **) xallocsa ((2 + nargs + 1) * sizeof (char *));
	unsigned int i;

	/* Set CLASSPATH.  We don't use the "-classpath ..." option because
	   in JDK 1.1.x its argument should also contain the JDK's classes.zip,
	   but we don't know its location.  */
	old_classpath =
	  set_classpath (classpaths, classpaths_count, use_minimal_classpath,
			 verbose);

	argv[0] = "jre";
	argv[1] = (char *) class_name;
	for (i = 0; i <= nargs; i++)
	  argv[2 + i] = (char *) args[i];

	if (verbose)
	  {
	    char *command = shell_quote_argv (argv);
	    printf ("%s\n", command);
	    free (command);
	  }

	err = executer ("jre", "jre", argv, private_data);

	/* Reset CLASSPATH.  */
	reset_classpath (old_classpath);

	freesa (argv);

	goto done2;
      }
  }

#if defined _WIN32 || defined __WIN32__
  /* Win32 */
  {
    static bool jview_tested;
    static bool jview_present;

    if (!jview_tested)
      {
	/* Test for presence of jview: "jview -? >nul ; test $? = 1"  */
	char *argv[3];
	int exitstatus;

	argv[0] = "jview";
	argv[1] = "-?";
	argv[2] = NULL;
	exitstatus = execute ("jview", "jview", argv, false, false, true, true,
			      true, false);
	jview_present = (exitstatus == 0 || exitstatus == 1);
	jview_tested = true;
      }

    if (jview_present)
      {
	char *old_classpath;
	char **argv = (char **) xallocsa ((2 + nargs + 1) * sizeof (char *));
	unsigned int i;

	/* Set CLASSPATH.  */
	old_classpath =
	  set_classpath (classpaths, classpaths_count, use_minimal_classpath,
			 verbose);

	argv[0] = "jview";
	argv[1] = (char *) class_name;
	for (i = 0; i <= nargs; i++)
	  argv[2 + i] = (char *) args[i];

	if (verbose)
	  {
	    char *command = shell_quote_argv (argv);
	    printf ("%s\n", command);
	    free (command);
	  }

	err = executer ("jview", "jview", argv, private_data);

	/* Reset CLASSPATH.  */
	reset_classpath (old_classpath);

	freesa (argv);

	goto done2;
      }
  }
#endif

  if (!quiet)
    error (0, 0, _("Java virtual machine not found, try installing gij or set $JAVA"));
  err = true;

 done2:
  if (old_JAVA_HOME != NULL)
    {
      xsetenv ("JAVA_HOME", old_JAVA_HOME, 1);
      free (old_JAVA_HOME);
    }

 done1:
  return err;
}
Ejemplo n.º 18
0
static void py2app_setPythonPath(void) {
    CFMutableArrayRef paths;
    CFURLRef resDir;
    CFStringRef resPath;
    CFArrayRef resPackages;
    CFDictionaryRef options;

    paths = py2app_CFArrayCreateMutable(NULL, 0, py2app_kCFTypeArrayCallBacks);
    resDir = py2app_CFBundleCopyResourcesDirectoryURL(CFBundleGetMainBundle());

    resPath = pathFromURL(resDir);
    py2app_CFArrayAppendValue(paths, resPath);
    py2app_CFRelease(resPath);

    resPackages = py2app_getKey("PyResourcePackages");
    if (resPackages) {
        int i;
        int cnt = py2app_CFArrayGetCount(resPackages);
        for (i = 0; i < cnt; i++) {
            resPath = tildeExpand(py2app_CFArrayGetValueAtIndex(resPackages, i));
            if (py2app_CFStringGetLength(resPath)) {
                if (py2app_CFStringGetCharacterAtIndex(resPath, 0) != '/') {
                    CFURLRef absURL = py2app_CFURLCreateWithString(
                        NULL, resPath, resDir);
                    py2app_CFRelease(resPath);
                    resPath = pathFromURL(absURL);
                    py2app_CFRelease(absURL);
                }
                py2app_CFArrayAppendValue(paths, resPath);
            }
            py2app_CFRelease(resPath);
        }
    }

    py2app_CFRelease(resDir);

    options = py2app_getKey("PyOptions");
    if (options) {
        CFBooleanRef use_pythonpath;
	CFNumberRef optimize;
        use_pythonpath = py2app_CFDictionaryGetValue(
            options, py2app_CFSTR("use_pythonpath"));
        if (use_pythonpath && py2app_CFBooleanGetValue(use_pythonpath)) {
            char *ppath = getenv("PYTHONPATH");
            if (ppath) {
                CFArrayRef oldPath;
                oldPath = py2app_CFStringCreateArrayBySeparatingStrings(
                    NULL, py2app_CFSTR(ppath), py2app_CFSTR(":"));
                if (oldPath) {
                    CFRange rng;
                    rng.location = 0;
                    rng.length = py2app_CFArrayGetCount(oldPath);
                    py2app_CFArrayAppendArray(paths, oldPath, rng);
                    py2app_CFRelease(oldPath);
                }
            }
        }

	optimize = py2app_CFDictionaryGetValue(
		options, py2app_CFSTR("optimize"));
	if (optimize) {
		int v = 0;
		char buf[32];
		py2app_CFNumberGetValue(optimize, kCFNumberIntType, &v);
		snprintf(buf, 31, "%d", v);
		setenv("PYTHONOPTIMIZE", buf, 1);
	}
    }

    if (py2app_CFArrayGetCount(paths)) {
        resPath = py2app_CFStringCreateByCombiningStrings(NULL, paths, py2app_CFSTR(":"));
        setcfenv("PYTHONPATH", resPath);
        py2app_CFRelease(resPath);
    } else {
	 if (getenv("PYTHONPATH") != NULL) {
	     unsetenv("PYTHONPATH");
	 }
    }

    py2app_CFRelease(paths);
}
Ejemplo n.º 19
0
/**
 * Try load VBoxXPCOMC.so/dylib/dll from the specified location and resolve all
 * the symbols we need.
 *
 * @returns 0 on success, -1 on failure and 1 if VBoxXPCOMC was not found.
 * @param   dir           The directory where to try load VBoxXPCOMC from. Can
 *                        be NULL.
 * @param   setAppHome    Whether to set the VBOX_APP_HOME env.var. or not.
 * @param   ignoreMissing Whether to ignore missing library or not.
 * @param   version       Version number of the loaded API.
 */
static int
tryLoadOne(const char *dir, bool setAppHome, bool ignoreMissing,
           unsigned int *version)
{
    int result = -1;
    char *name = NULL;
    PFNVBOXGETXPCOMCFUNCTIONS pfnGetFunctions;

    if (dir != NULL) {
        if (virAsprintf(&name, "%s/%s", dir, DYNLIB_NAME) < 0)
            return -1;

        if (!virFileExists(name)) {
            if (!ignoreMissing)
                VIR_ERROR(_("Library '%s' doesn't exist"), name);

            VIR_FREE(name);
            return -1;
        }
    } else {
        if (VIR_STRDUP(name, DYNLIB_NAME) < 0)
            return -1;
    }

    /*
     * Try load it by that name, setting the VBOX_APP_HOME first (for now).
     * Then resolve and call the function table getter.
     */
    if (setAppHome) {
        if (dir != NULL) {
            setenv("VBOX_APP_HOME", dir, 1 /* always override */);
        } else {
            unsetenv("VBOX_APP_HOME");
        }
    }

    hVBoxXPCOMC = dlopen(name, RTLD_NOW | RTLD_LOCAL);

    if (hVBoxXPCOMC == NULL) {
        /*
         * FIXME: Don't warn in this case as it currently breaks make check
         *        on systems without VirtualBox.
         */
        if (dir != NULL)
            VIR_WARN("Could not dlopen '%s': %s", name, dlerror());

        goto cleanup;
    }

    pfnGetFunctions = (PFNVBOXGETXPCOMCFUNCTIONS)
        dlsym(hVBoxXPCOMC, VBOX_GET_XPCOMC_FUNCTIONS_SYMBOL_NAME);

    if (pfnGetFunctions == NULL) {
        VIR_ERROR(_("Could not dlsym %s from '%s': %s"),
                  VBOX_GET_XPCOMC_FUNCTIONS_SYMBOL_NAME, name, dlerror());
        goto cleanup;
    }

    pVBoxFuncs_v2_2 = pfnGetFunctions(VBOX_XPCOMC_VERSION);

    if (pVBoxFuncs_v2_2 == NULL) {
        VIR_ERROR(_("Calling %s from '%s' failed"),
                  VBOX_GET_XPCOMC_FUNCTIONS_SYMBOL_NAME, name);
        goto cleanup;
    }

    *version = pVBoxFuncs_v2_2->pfnGetVersion();
    g_pfnGetFunctions = pfnGetFunctions;
    result = 0;

    if (dir != NULL) {
        VIR_DEBUG("Found %s in '%s'", DYNLIB_NAME, dir);
    } else {
        VIR_DEBUG("Found %s in dynamic linker search path", DYNLIB_NAME);
    }

 cleanup:
    if (hVBoxXPCOMC != NULL && result < 0) {
        dlclose(hVBoxXPCOMC);
        hVBoxXPCOMC = NULL;
    }

    VIR_FREE(name);

    return result;
}
Ejemplo n.º 20
0
static int py2app_main(int argc, char * const *argv, char * const *envp) {
    CFArrayRef pyLocations;
    CFStringRef pyLocation;
    CFStringRef mainScript;
    CFStringRef pythonInterpreter;
    char *resource_path;
    char buf[PATH_MAX];
    char c_pythonInterpreter[PATH_MAX];
    char c_mainScript[PATH_MAX];
    char **argv_new;
    struct stat sb;
    void *py_dylib;
    int rval;
    FILE *mainScriptFile;
    char* curenv = NULL;
    char* curlocale = NULL;


    if (getenv("PYTHONOPTIMIZE") != NULL) {
        unsetenv("PYTHONOPTIMIZE");
    }
    if (getenv("PYTHONDEBUG") != NULL) {
        unsetenv("PYTHONDEBUG");
    }
    if (getenv("PYTHONDONTWRITEBYTECODE") != NULL) {
        unsetenv("PYTHONDONTWRITEBYTECODE");
    }
    if (getenv("PYTHONIOENCODING") != NULL) {
        unsetenv("PYTHONIOENCODING");
    }
    if (getenv("PYTHONDUMPREFS") != NULL) {
        unsetenv("PYTHONDUMPREFS");
    }
    if (getenv("PYTHONMALLOCSTATS") != NULL) {
        unsetenv("PYTHONMALLOCSTATS");
    }

    /* Ensure that the interpreter won't try to write bytecode files
     * Two reasons:
     * - Apps are often read-only for users
     * - Writing byte-code will be blocked by the sandbox
     *   when running a sandboxed application.
     */
    setenv("PYTHONDONTWRITEBYTECODE", "1", 1);

#ifndef PY2APP_SECONDARY
    /*
     * Force stdout/stderr to be unbuffered, needed when using the ASL
     * output redirection because Python 3's IO library won't use
     * line buffering with that.
     */
    setenv("PYTHONUNBUFFERED", "1", 1);
#endif


    if (!py2app_getApplicationName()) return report_error(ERR_NONAME);
    pyLocations = (CFArrayRef)py2app_getKey("PyRuntimeLocations");
    if (!pyLocations) return report_error(ERR_PYRUNTIMELOCATIONS);
    pyLocation = py2app_findPyLocation(pyLocations);
    if (!pyLocation) return report_error(ERR_NOPYTHONRUNTIME);

    setExecutablePath();
    setResourcePath();
    /* check for ':' in path, not compatible with Python due to Py_GetPath */
    /* XXX: Could work-around by creating something in /tmp I guess */
    resource_path = getenv("RESOURCEPATH");
    if ((resource_path == NULL) || (strchr(resource_path, ':') != NULL)) {
        return report_error(ERR_COLONPATH);
    }
    py2app_setPythonPath();
    setenv("ARGVZERO", argv[0], 1);

    /* Clear unwanted environment variable that could be set
     * by a PyObjC bundle in a parent process. Not clearing causes
     * problems in PyObjC.
     */
    if (getenv("PYOBJC_BUNDLE_ADDRESS") != NULL) {
        unsetenv("PYOBJC_BUNDLE_ADDRESS");
    }
    snprintf(buf, sizeof(buf)-1, "PYOBJC_BUNDLE_ADDRESS%ld", (long)getpid());
    if (getenv(buf) != NULL) {
        unsetenv(buf);
    }

    mainScript = getMainScript();
    if (!mainScript) return report_error(ERR_NOPYTHONSCRIPT);

    pythonInterpreter = getPythonInterpreter(pyLocation);
    py2app_CFStringGetCString(
        pythonInterpreter, c_pythonInterpreter,
        sizeof(c_pythonInterpreter), kCFStringEncodingUTF8);
    py2app_CFRelease(pythonInterpreter);
    if (lstat(c_pythonInterpreter, &sb) == 0) {
        if (!((sb.st_mode & S_IFLNK) == S_IFLNK)) {
            setenv("PYTHONHOME", resource_path, 1);
        }
    }

    py2app_CFStringGetCString(pyLocation, buf, sizeof(buf), kCFStringEncodingUTF8);
    py_dylib = dlopen(buf, RTLD_LAZY);
    if (!py_dylib) return report_linkEdit_error();

#define LOOKUP(NAME) \
	    NAME ## Ptr py2app_ ## NAME = (NAME ## Ptr)dlsym(py_dylib, #NAME); \
	    if (!py2app_ ## NAME) { \
		return report_linkEdit_error(); \
	    }

#define OPT_LOOKUP(NAME) \
	    NAME ## Ptr py2app_ ## NAME = (NAME ## Ptr)dlsym(py_dylib, #NAME);

    LOOKUP(Py_SetProgramName);
    LOOKUP(Py_Initialize);
    LOOKUP(PyRun_SimpleFile);
    LOOKUP(Py_Finalize);
    LOOKUP(PySys_GetObject);
    LOOKUP(PySys_SetArgv);
    LOOKUP(PyObject_GetAttrString);
    LOOKUP(Py_BuildValue);
#if 0
    OPT_LOOKUP(Py_SetPath);
#endif
    OPT_LOOKUP(_Py_DecodeUTF8_surrogateescape);
    LOOKUP(PySys_SetObject);


    int isPy3K = dlsym(py_dylib, "PyBytes_FromString") != NULL;

#undef OPT_LOOKUP
#undef LOOKUP

    if (isPy3K) {
	    /*
	     * When apps are started from the Finder (or anywhere
	     * except from the terminal), the LANG and LC_* variables
	     * aren't set in the environment. This confuses Py_Initialize
	     * when it tries to import the codec for UTF-8,
	     * therefore explicitly set the locale.
	     *
	     * Also set the LC_CTYPE environment variable because Py_Initialize
	     * resets the locale information using the environment :-(
	     */
	    curlocale = setlocale(LC_ALL, NULL);
	    if (curlocale != NULL) {
	      curlocale = strdup(curlocale);
	      if (curlocale == NULL) {
		(void)report_error("cannot save locale information");
		return -1;
	      }
	    }
	    setlocale(LC_ALL, "en_US.UTF-8");

	    curenv = getenv("LC_CTYPE");
	    if (curenv == NULL) {
		setenv("LC_CTYPE", "en_US.UTF-8", 1);
	    }

	    wchar_t w_pythonInterpreter[PATH_MAX+1];
    	    mbstowcs(w_pythonInterpreter, c_pythonInterpreter, PATH_MAX+1);
    	    py2app_Py_SetProgramName((char*)w_pythonInterpreter);


    } else {
	    py2app_Py_SetProgramName(c_pythonInterpreter);
    }

    py2app_Py_Initialize();

    /*
     * Reset the environment and locale information
     */
    if (isPy3K) {
	    if (curenv == NULL) {
		unsetenv("LC_CTYPE");
	    }

	    setlocale(LC_CTYPE, curlocale);
	    free(curlocale);
    }

    py2app_CFStringGetCString(
        mainScript, c_mainScript,
        sizeof(c_mainScript), kCFStringEncodingUTF8);
    py2app_CFRelease(mainScript);

    if (isPy3K) {
       int i;

       argv_new = alloca((argc+1) * sizeof(wchar_t));
       argv_new[argc] = NULL;
       argv_new[0] = (char*)py2app__Py_DecodeUTF8_surrogateescape(c_mainScript, strlen(c_mainScript));

       for (i = 1; i < argc; i++) {
	  argv_new[i] = (char*)py2app__Py_DecodeUTF8_surrogateescape(argv[i], strlen(argv[i]));
       }

    } else {
       argv_new = alloca((argc + 1) * sizeof(char *));
       argv_new[argc] = NULL;
       argv_new[0] = c_mainScript;
       memcpy(&argv_new[1], &argv[1], (argc - 1) * sizeof(char *));
    }
    py2app_PySys_SetArgv(argc, argv_new);

    mainScriptFile = fopen(c_mainScript, "r");
    rval = py2app_PyRun_SimpleFile(mainScriptFile, c_mainScript);
    fclose(mainScriptFile);

    if (rval) {
        rval = report_script_error(ERR_PYTHONEXCEPTION);
    }

    py2app_Py_Finalize();

    return rval;
}
Ejemplo n.º 21
0
int cl_setenv(const char *name, const char *value)
{
	return (value == NULL) ? unsetenv(name) : setenv(name, value, 1);
}
Ejemplo n.º 22
0
void execunsetenv(Cmd c, int inPipeId, int outPipeId)
{
  int newfd;
  int i=0;
  char* str;

  if(c->next == NULL)
  {
  //if(fork() == 0)
  //  {  
      redirection(c, inPipeId, outPipeId);

      if(c->args[1] == NULL)
      {
        perror("Variable not input");
      }
      else{
        //printf("TP");
        
            //printf("Invoking Putenv for %s to null",c->args[1]);
            str = strdup(c->args[1]);
            unsetenv(str);

      }

    //  exit(0);
    //}
    //else
    //{
    //  wait(); 
    //}


  }
  else
  {


    if(fork() == 0)
    {  
      redirection(c, inPipeId, outPipeId);

      if(c->args[1] == NULL)
      {
        perror("Variable not input");
      }
      else{
        //printf("TP");
        
            //printf("Invoking Putenv for %s to null",c->args[1]);
            str = strdup(c->args[1]);
            unsetenv(str);

      }

      exit(0);
    }
    else
    {
      close((pipes+(2*outPipeId))[1]);
      wait(); 
    }

  }

}
Ejemplo n.º 23
0
static int
command_boot(int argc, char *argv[])
{
    struct preloaded_file	*fp;
    char *local_module_path;
    char *exported_module_path;

    /*
     * See if the user has specified an explicit kernel to boot.
     */
    if ((argc > 1) && (argv[1][0] != '-')) {

	/* XXX maybe we should discard everything and start again? */
	if (file_findfile(NULL, NULL) != NULL) {
	    sprintf(command_errbuf, "can't boot '%s', kernel module already loaded", argv[1]);
	    return(CMD_ERROR);
	}

	/* find/load the kernel module */
	if (mod_loadkld(argv[1], argc - 2, argv + 2) != 0)
	    return(CMD_ERROR);
	/* we have consumed all arguments */
	argc = 1;
    }

    /*
     * See if there is a kernel module already loaded
     */
    if (file_findfile(NULL, NULL) == NULL)
	if (loadakernel(0, argc - 1, argv + 1))
	    /* we have consumed all arguments */
	    argc = 1;

    /*
     * Loaded anything yet?
     */
    if ((fp = file_findfile(NULL, NULL)) == NULL) {
	command_errmsg = "no bootable kernel";
	return(CMD_ERROR);
    }

    /*
     * If we were given arguments, discard any previous.
     * XXX should we merge arguments?  Hard to DWIM.
     */
    if (argc > 1) {
	if (fp->f_args != NULL)
	    free(fp->f_args);
	fp->f_args = unargv(argc - 1, argv + 1);
    }

    /* Hook for platform-specific autoloading of modules */
    if (archsw.arch_autoload() != 0)
	return(CMD_ERROR);

    /*
     * Exec the kernel.  We have to shift our exported_module_path
     * (which has the correct /boot prefix for the kernel) over to
     * module_path.  If the exec fails we switch it back.
     */
    exported_module_path = getenv("exported_module_path");
    if (exported_module_path) {
	    exported_module_path = strdup(exported_module_path);
	    local_module_path = getenv("module_path");
	    if (local_module_path)
		local_module_path = strdup(local_module_path);
	    setenv("module_path", exported_module_path, 1);
	    unsetenv("exported_module_path");
    }

    /* Call the exec handler from the loader matching the kernel */
    file_formats[fp->f_loader]->l_exec(fp);

    if (exported_module_path) {
	    if (local_module_path) {
		setenv("module_path", local_module_path, 1);
		free(local_module_path);
	    } else {
		unsetenv("module_path");
	    }
	    setenv("exported_module_path", exported_module_path, 1);
	    free(exported_module_path);
    }
    return(CMD_ERROR);
}
Ejemplo n.º 24
0
void
launch_client_init(void)
{
	struct sockaddr_un sun;
	char *where = getenv(LAUNCHD_SOCKET_ENV);
	char *_launchd_fd = getenv(LAUNCHD_TRUSTED_FD_ENV);
	int dfd, lfd = -1, cifd = -1;
#ifdef __APPLE__
    name_t spath;
#else
#warning "PORT: Figure out how to handle this path from bootstrap
    void *spath;
#endif

	if (_launchd_fd) {
		cifd = strtol(_launchd_fd, NULL, 10);
		if ((dfd = dup(cifd)) >= 0) {
			close(dfd);
			_fd(cifd);
		} else {
			cifd = -1;
		}
		unsetenv(LAUNCHD_TRUSTED_FD_ENV);
	}

	memset(&sun, 0, sizeof(sun));
	sun.sun_family = AF_UNIX;

	/* The rules are as follows.
	 * - All users (including root) talk to their per-user launchd's by default.
	 * - If we have been invoked under sudo, talk to the system launchd.
	 * - If we're the root user and the __USE_SYSTEM_LAUNCHD environment variable is set, then
	 *   talk to the system launchd.
	 */
	if (where && where[0] != '\0') {
		strncpy(sun.sun_path, where, sizeof(sun.sun_path));
	} else {
		if (_vprocmgr_getsocket(spath) == 0) {
			if ((getenv("SUDO_COMMAND") || getenv("__USE_SYSTEM_LAUNCHD")) && geteuid() == 0) {
				/* Talk to the system launchd. */
				strncpy(sun.sun_path, LAUNCHD_SOCK_PREFIX "/sock", sizeof(sun.sun_path));
			} else {
				/* Talk to our per-user launchd. */
				size_t min_len;

				min_len = sizeof(sun.sun_path) < sizeof(spath) ? sizeof(sun.sun_path) : sizeof(spath);

				strncpy(sun.sun_path, spath, min_len);
			}
		}
	}

	launch_globals_t globals = _launch_globals();
	if ((lfd = _fd(socket(AF_UNIX, SOCK_STREAM, 0))) == -1) {
		goto out_bad;
	}

#if TARGET_OS_EMBEDDED
	(void)vproc_swap_integer(NULL, VPROC_GSK_EMBEDDEDROOTEQUIVALENT, NULL, &globals->s_am_embedded_god);
#endif
	if (-1 == connect(lfd, (struct sockaddr *)&sun, sizeof(sun))) {
		if (cifd != -1 || globals->s_am_embedded_god) {
			/* There is NO security enforced by this check. This is just a hint to our
			 * library that we shouldn't error out due to failing to open this socket. If
			 * we inherited a trusted file descriptor, we shouldn't fail. This should be
			 * adequate for clients' expectations.
			 */
			close(lfd);
			lfd = -1;
		} else {
			goto out_bad;
		}
	}

	if (!(globals->l = launchd_fdopen(lfd, cifd))) {
		goto out_bad;
	}

	if (!(globals->async_resp = launch_data_alloc(LAUNCH_DATA_ARRAY))) {
		goto out_bad;
	}

	return;
out_bad:
	if (globals->l) {
		launchd_close(globals->l, close);
		globals->l = NULL;
	} else if (lfd != -1) {
		close(lfd);
	}
	if (cifd != -1) {
		close(cifd);
	}
}
Ejemplo n.º 25
0
void
test_str_screen_wrap (void)
{
    char           *str = NULL;
    struct winsize  winsize;
    int             pty, pts;

    TEST_FUNCTION ("nih_str_screen_wrap");
    unsetenv ("COLUMNS");

    winsize.ws_row = 24;
    winsize.ws_col = 40;
    winsize.ws_xpixel = 0;
    winsize.ws_ypixel = 0;
    openpty (&pty, &pts, NULL, NULL, &winsize);

    /* Check that we correctly wrap text to the width of the screen
     * when it is available.
     */
    TEST_FEATURE ("with screen width");
    TEST_ALLOC_FAIL {
        TEST_DIVERT_STDOUT_FD (pts) {
            str = nih_str_screen_wrap (
                NULL, ("this is a string that "
            "should need wrapping at "
            "any different screen width "
            "that we choose to set"),
                0, 0);
        }

        if (test_alloc_failed) {
            TEST_EQ_P (str, NULL);
            continue;
        }

        TEST_EQ_STR (str, ("this is a string that should need\n"
        "wrapping at any different screen width\n"
        "that we choose to set"));

        nih_free (str);
    }


    /* Check that we wrap at the number specified in the COLUMNS
     * variable in preference to the width of the screen.
     */
    TEST_FEATURE ("with COLUMNS variable");
    putenv ("COLUMNS=30");
    TEST_ALLOC_FAIL {
        TEST_DIVERT_STDOUT_FD (pts) {
            str = nih_str_screen_wrap (
                NULL, ("this is a string that "
            "should need wrapping at "
            "any different screen width "
            "that we choose to set"),
                0, 0);
        }

        if (test_alloc_failed) {
            TEST_EQ_P (str, NULL);
            continue;
        }

        TEST_EQ_STR (str, ("this is a string that should\n"
        "need wrapping at any\n"
        "different screen width that\n"
        "we choose to set"));

        nih_free (str);
    }

    unsetenv ("COLUMNS");
    close (pts);
    close (pty);


    /* Check that we fallback to assuming 80 columns if we don't have
     * any luck with either the tty or COLUMNS variable.
     */
    TEST_FEATURE ("with fallback to 80 columns");
    pts = open ("/dev/null", O_RDWR | O_NOCTTY);

    TEST_ALLOC_FAIL {
        TEST_DIVERT_STDOUT_FD (pts) {
            str = nih_str_screen_wrap (
                NULL, ("this is a string that "
            "should need wrapping at "
            "any different screen width "
            "that we choose to set"),
                0, 0);
        }

        if (test_alloc_failed) {
            TEST_EQ_P (str, NULL);
            continue;
        }

        TEST_EQ_STR (str, ("this is a string that should need "
        "wrapping at any different screen width "
        "that\n"
        "we choose to set"));

        nih_free (str);
    }

    close (pts);
}
Ejemplo n.º 26
0
int main(int argc, char **argv)
{
  char buf[MAXLEN];
  char line[83];
  int i, f, ch;
  int len = 0;
  int remote = 0;
  char *p;
  char *whoami;
  struct passwd *pwd;

  buf[0] = 0;
  if ((pwd = getpwuid(getuid())) == NULL) {
	if (getuid() == 0)
		whoami = "root";
	else {
		fprintf(stderr, "You don't exist. Go away.\n");
		exit(1);
	}
  } else
	whoami = pwd->pw_name;

  while((ch = getopt(argc, argv, "n")) != EOF)
	switch(ch) {
		case 'n':
			/*
			 *	Undocumented option for suppressing
			 *	banner from rpc.rwalld. Only works if
			 *	we are root or if we're NOT setgid.
			 */
			if (geteuid() != 0 && getgid() != getegid()) {
				fprintf(stderr, "wall -n: not priviliged\n");
				exit(1);
			}
			remote = 1;
			break;
		default:
			fprintf(stderr, "usage: wall [message]\n");
			return 1;
			break;
	}

  if ((argc - optind) > 0) {
	for(f = optind; f < argc; f++) {
		len += strlen(argv[f]) + 1;
		if (len >= MAXLEN-2) break;
		strcat(buf, argv[f]);
		if (f < argc-1) strcat(buf, " ");
	}
	strcat(buf, "\r\n");
  } else {
	while(fgets(line, 80, stdin)) {
		/*
		 *	Make sure that line ends in \r\n
		 */
		for(p = line; *p && *p != '\r' && *p != '\n'; p++)
			;
		strcpy(p, "\r\n");
		len += strlen(line);
		if (len >= MAXLEN) break;
		strcat(buf, line);
	}
  }

  i = 0;
  for (p = buf; *p; p++) {
	if (*p == '\n' && ++i >= MAXLINES) {
		*++p = 0;
		break;
	}
  }

  openlog("wall", LOG_PID, LOG_USER);
  syslog(LOG_INFO, "wall: user %s broadcasted %d lines (%zu chars)",
	whoami, i, strlen(buf));
  closelog();

  unsetenv("TZ");
  wall(buf, remote);

  /*NOTREACHED*/
  return 0;
}
Ejemplo n.º 27
0
NS_IMETHODIMP
nsNativeAppSupportUnix::Start(bool *aRetVal)
{
  NS_ASSERTION(gAppData, "gAppData must not be null.");

// The dbus library is used by both nsWifiScannerDBus and BluetoothDBusService,
// from diffrent threads. This could lead to race conditions if the dbus is not
// initialized before making any other library calls.
#ifdef MOZ_ENABLE_DBUS
  dbus_threads_init_default();
#endif

#if (MOZ_WIDGET_GTK == 2)
  if (gtk_major_version < MIN_GTK_MAJOR_VERSION ||
      (gtk_major_version == MIN_GTK_MAJOR_VERSION && gtk_minor_version < MIN_GTK_MINOR_VERSION)) {
    GtkWidget* versionErrDialog = gtk_message_dialog_new(nullptr,
                     GtkDialogFlags(GTK_DIALOG_MODAL |
                                    GTK_DIALOG_DESTROY_WITH_PARENT),
                     GTK_MESSAGE_ERROR,
                     GTK_BUTTONS_OK,
                     UNSUPPORTED_GTK_MSG,
                     gtk_major_version,
                     gtk_minor_version,
                     MIN_GTK_MAJOR_VERSION,
                     MIN_GTK_MINOR_VERSION);
    gtk_dialog_run(GTK_DIALOG(versionErrDialog));
    gtk_widget_destroy(versionErrDialog);
    exit(0);
  }
#endif

  *aRetVal = true;

#ifdef MOZ_X11
  gboolean sm_disable = FALSE;
  if (!getenv("SESSION_MANAGER")) {
    sm_disable = TRUE;
  }

  nsAutoCString prev_client_id;

  char **curarg = gArgv + 1;
  while (*curarg) {
    char *arg = *curarg;
    if (arg[0] == '-' && arg[1] == '-') {
      arg += 2;
      if (!strcmp(arg, "sm-disable")) {
        RemoveArg(curarg);
        sm_disable = TRUE;
        continue;
      } else if (!strcmp(arg, "sm-client-id")) {
        RemoveArg(curarg);
        if (*curarg[0] != '-') {
          prev_client_id = *curarg;
          RemoveArg(curarg);
        }
        continue;
      }
    }

    ++curarg;
  }

  if (prev_client_id.IsEmpty()) {
    prev_client_id = getenv("DESKTOP_AUTOSTART_ID");
  }

  // We don't want child processes to use the same ID
  unsetenv("DESKTOP_AUTOSTART_ID");

  char *client_id = nullptr;
  if (!sm_disable) {
    PRLibrary *iceLib = PR_LoadLibrary("libICE.so.6");
    if (!iceLib) {
      return NS_OK;
    }

    PRLibrary *smLib = PR_LoadLibrary("libSM.so.6");
    if (!smLib) {
      PR_UnloadLibrary(iceLib);
      return NS_OK;
    }

    IceSetIOErrorHandler = (IceSetIOErrorHandlerFn)PR_FindFunctionSymbol(iceLib, "IceSetIOErrorHandler");
    IceAddConnectionWatch = (IceAddConnectionWatchFn)PR_FindFunctionSymbol(iceLib, "IceAddConnectionWatch");
    IceConnectionNumber = (IceConnectionNumberFn)PR_FindFunctionSymbol(iceLib, "IceConnectionNumber");
    IceProcessMessages = (IceProcessMessagesFn)PR_FindFunctionSymbol(iceLib, "IceProcessMessages");
    IceGetConnectionContext = (IceGetConnectionContextFn)PR_FindFunctionSymbol(iceLib, "IceGetConnectionContext");
    if (!IceSetIOErrorHandler || !IceAddConnectionWatch ||
	!IceConnectionNumber  || !IceProcessMessages || !IceGetConnectionContext) {
      PR_UnloadLibrary(iceLib);
      PR_UnloadLibrary(smLib);
      return NS_OK;
    }

    SmcInteractDone = (SmcInteractDoneFn)PR_FindFunctionSymbol(smLib, "SmcInteractDone");
    SmcSaveYourselfDone = (SmcSaveYourselfDoneFn)PR_FindFunctionSymbol(smLib, "SmcSaveYourselfDone");
    SmcInteractRequest = (SmcInteractRequestFn)PR_FindFunctionSymbol(smLib, "SmcInteractRequest");
    SmcCloseConnection = (SmcCloseConnectionFn)PR_FindFunctionSymbol(smLib, "SmcCloseConnection");
    SmcOpenConnection = (SmcOpenConnectionFn)PR_FindFunctionSymbol(smLib, "SmcOpenConnection");
    SmcSetProperties = (SmcSetPropertiesFn)PR_FindFunctionSymbol(smLib, "SmcSetProperties");
    if (!SmcInteractDone || !SmcSaveYourselfDone || !SmcInteractRequest ||
        !SmcCloseConnection || !SmcOpenConnection || !SmcSetProperties) {
      PR_UnloadLibrary(iceLib);
      PR_UnloadLibrary(smLib);
      return NS_OK;
    }

    ice_init();

    // all callbacks are mandatory in libSM 1.0, so listen even if we don't care.
    unsigned long mask = SmcSaveYourselfProcMask | SmcDieProcMask |
                         SmcSaveCompleteProcMask | SmcShutdownCancelledProcMask;

    SmcCallbacks callbacks;
    callbacks.save_yourself.callback = nsNativeAppSupportUnix::SaveYourselfCB;
    callbacks.save_yourself.client_data = static_cast<SmPointer>(this);

    callbacks.die.callback = nsNativeAppSupportUnix::DieCB;
    callbacks.die.client_data = static_cast<SmPointer>(this);

    callbacks.save_complete.callback = nsNativeAppSupportUnix::SaveCompleteCB;
    callbacks.save_complete.client_data = nullptr;

    callbacks.shutdown_cancelled.callback =
      nsNativeAppSupportUnix::ShutdownCancelledCB;
    callbacks.shutdown_cancelled.client_data = static_cast<SmPointer>(this);

    char errbuf[256];
    mSessionConnection = SmcOpenConnection(nullptr, this, SmProtoMajor,
                                           SmProtoMinor, mask, &callbacks,
                                           prev_client_id.get(), &client_id,
                                           sizeof(errbuf), errbuf);
  }

  if (!mSessionConnection) {
    return NS_OK;
  }

  LogModule::Init();  // need to make sure initialized before SetClientState
  if (prev_client_id.IsEmpty() ||
      (client_id && !prev_client_id.Equals(client_id))) {
    SetClientState(STATE_REGISTERING);
  } else {
    SetClientState(STATE_IDLE);
  }

  gdk_x11_set_sm_client_id(client_id);

  // Set SM Properties
  // SmCloneCommand, SmProgram, SmRestartCommand, SmUserID are required
  // properties so must be set, and must have a sensible fallback value.

  // Determine executable path to use for XSMP session restore

  // Is there a request to suppress default binary launcher?
  nsAutoCString path(getenv("MOZ_APP_LAUNCHER"));

  if (path.IsEmpty()) {
    NS_ASSERTION(gDirServiceProvider, "gDirServiceProvider is NULL! This shouldn't happen!");
    nsCOMPtr<nsIFile> executablePath;
    nsresult rv;

    bool dummy;
    rv = gDirServiceProvider->GetFile(XRE_EXECUTABLE_FILE, &dummy, getter_AddRefs(executablePath));

    if (NS_SUCCEEDED(rv)) {
      // Strip off the -bin suffix to get the shell script we should run; this is what Breakpad does
      nsAutoCString leafName;
      rv = executablePath->GetNativeLeafName(leafName);
      if (NS_SUCCEEDED(rv) && StringEndsWith(leafName, NS_LITERAL_CSTRING("-bin"))) {
        leafName.SetLength(leafName.Length() - strlen("-bin"));
        executablePath->SetNativeLeafName(leafName);
      }

      executablePath->GetNativePath(path);
    }
  }

  if (path.IsEmpty()) {
    // can't determine executable path. Best fallback is name from
    // application.ini but it might not resolve to the same executable at
    // launch time.
    path = gAppData->name;  // will always be set
    ToLowerCase(path);
    MOZ_LOG(sMozSMLog, LogLevel::Warning,
        ("Could not determine executable path. Falling back to %s.", path.get()));
  }

  SmProp propRestart, propClone, propProgram, propUser, *props[4];
  SmPropValue valsRestart[3], valsClone[1], valsProgram[1], valsUser[1];
  int n = 0;

  NS_NAMED_LITERAL_CSTRING(kClientIDParam, "--sm-client-id");

  SetSMValue(valsRestart[0], path);
  SetSMValue(valsRestart[1], kClientIDParam);
  SetSMValue(valsRestart[2], nsDependentCString(client_id));
  SetSMProperty(propRestart, SmRestartCommand, SmLISTofARRAY8, 3, valsRestart);
  props[n++] = &propRestart;

  SetSMValue(valsClone[0], path);
  SetSMProperty(propClone, SmCloneCommand, SmLISTofARRAY8, 1, valsClone);
  props[n++] = &propClone;

  nsAutoCString appName(gAppData->name);  // will always be set
  ToLowerCase(appName);

  SetSMValue(valsProgram[0], appName);
  SetSMProperty(propProgram, SmProgram, SmARRAY8, 1, valsProgram);
  props[n++] = &propProgram;

  nsAutoCString userName;  // username that started the program
  struct passwd* pw = getpwuid(getuid());
  if (pw && pw->pw_name) {
    userName = pw->pw_name;
  } else {
    userName = NS_LITERAL_CSTRING("nobody");
    MOZ_LOG(sMozSMLog, LogLevel::Warning,
        ("Could not determine user-name. Falling back to %s.", userName.get()));
  }

  SetSMValue(valsUser[0], userName);
  SetSMProperty(propUser, SmUserID, SmARRAY8, 1, valsUser);
  props[n++] = &propUser;

  SmcSetProperties(mSessionConnection, n, props);

  g_free(client_id);
#endif /* MOZ_X11 */

  return NS_OK;
}
Ejemplo n.º 28
0
int
main (int argc, char **argv)
{
  int print_domlist = 0;
  domlist_t domlist[32];
  char *opt, *p;
  int print_current = 0;
  int print_builtin = 1;
  char *print_unix = NULL;
  const char *sep_char = (const char *) cygwin_internal (CW_GETNSSSEP);
  DWORD id_offset = 0x10000, off;
  int c, i;
  char *disp_groupname = NULL;
  //BOOL in_domain;
  int optional_args = 0;

  if (!isatty (1))
    setmode (1, O_BINARY);

  /* Use locale from environment.  If not set or set to "C", use UTF-8. */
  setlocale (LC_CTYPE, "");
  if (!strcmp (setlocale (LC_CTYPE, NULL), "C"))
    setlocale (LC_CTYPE, "en_US.UTF-8");
  fetch_current_pgrp_sid ();

  if (argc == 1)
    {
      int enums = ENUM_PRIMARY | ENUM_LOCAL | ENUM_BUILTIN;
      uintptr_t ticket = cygwin_internal (CW_SETENT, TRUE, enums, NULL);
      if (ticket)
	{
	  struct group *grp;

	  while ((grp = (struct group *) cygwin_internal (CW_GETENT, TRUE,
							  ticket)))
	    printf ("%s:%s:%u:\n", grp->gr_name, grp->gr_passwd, grp->gr_gid);
	  cygwin_internal (CW_ENDENT, TRUE, ticket);
	}
      return 0;
    }

  unsetenv ("POSIXLY_CORRECT"); /* To get optional arg processing right. */
  while ((c = getopt_long (argc, argv, opts, longopts, NULL)) != EOF)
    switch (c)
      {
      case 'd':
      case 'D':
      case 'l':
      case 'L':
	if (print_domlist >= 32)
	  {
	    fprintf (stderr, "%s: Can not enumerate from more than 32 "
			     "domains and machines.\n",
			     program_invocation_short_name);
	    return 1;
	  }
	domlist[print_domlist].domain = (c == 'd' || c == 'D');
	opt = optarg ?:
	      argv[optind] && argv[optind][0] != '-' ? argv[optind] : NULL;
	if (argv[optind] && opt == argv[optind])
	  ++optional_args;
	for (i = 0; i < print_domlist; ++i)
	  if (domlist[i].domain == domlist[print_domlist].domain
	      && ((!domlist[i].str && !opt)
		  || (domlist[i].str && opt
		      && (off = strlen (domlist[i].str))
		      && !strncmp (domlist[i].str, opt, off)
		      && (!opt[off] || opt[off] == ','))))
	    {
	      fprintf (stderr, "%s: Duplicate %s '%s'.  Skipping...\n",
		       program_invocation_short_name,
		       domlist[i].domain ? "domain" : "machine",
		       domlist[i].str);
	      goto skip;
	    }
	domlist[print_domlist].str = opt;
	if (opt && (p = strchr (opt, ',')))
	  {
	    if (p == opt)
	      {
		fprintf (stderr, "%s: Malformed machine,offset string '%s'.  "
			 "Skipping...\n", program_invocation_short_name, opt);
		break;
	      }
	    *p = '\0';
	  }
	domlist[print_domlist++].with_dom = (c == 'L');
skip:
	break;
      case 'S':
	sep_char = optarg;
	if (strlen (sep_char) > 1)
	  {
	    fprintf (stderr, "%s: Only one ASCII character allowed as "
			     "domain\\user separator character.\n",
			     program_invocation_short_name);
	    return 1;
	  }
	if (*sep_char == ':')
	  {
	    fprintf (stderr, "%s: Colon not allowed as domain\\user separator "
			     "character.\n", program_invocation_short_name);
	    return 1;
	  }
	break;
      case 'U':
	print_unix = optarg;
	break;
      case 'c':
      case 'C':
	print_current = 1;
	break;
      case 'o':
	id_offset = strtol (optarg, NULL, 10);
	break;
      case 'b':
	print_builtin = 0;
	break;
      case 's':
	break;
      case 'u':
	break;
      case 'g':
	disp_groupname = optarg;
	break;
      case 'h':
	usage (stdout);
	return 0;
      case 'V':
	print_version ();
	return 0;
      default:
	fprintf (stderr, "Try `%s --help' for more information.\n", argv[0]);
	return 1;
      }

  optind += optional_args;
  if (argv[optind])
    {
      fprintf (stderr,
	       "mkgroup: non-option command line argument `%s' is not allowed.\n"
	       "Try `mkgroup --help' for more information.\n", argv[optind]);
      exit (1);
    }

  struct group *pgrp = NULL;
  if (print_current)
    pgrp = (struct group *) cygwin_internal (CW_GETGRSID, TRUE, curr_pgrp.psid);

  int enums = ENUM_NONE;
  WCHAR tdoms[print_domlist * 258];
  PWCHAR t = tdoms;
  if (!disp_groupname && print_builtin && print_domlist)
    enums |= ENUM_BUILTIN;
  for (i = 0; i < print_domlist; ++i)
    {
      if (domlist[i].domain)
	{
	  if (domlist[i].str)
	    {
	      enums |= ENUM_TDOMS;
	      t += mbstowcs (t, domlist[i].str, 257);
	      *t++ = L'\0';
	    }
	  else
	    enums |= ENUM_PRIMARY;
	}
      else if (!domlist[i].str)
	enums |= ENUM_LOCAL;
    }
  if (t > tdoms)
    *t++ = L'\0';
  if (enums)
    {
      uintptr_t ticket = cygwin_internal (CW_SETENT, TRUE, enums,
					  t > tdoms ? tdoms : NULL);
      if (ticket)
	{
	  struct group *grp;
	  const char *nss_sep = (const char *) cygwin_internal (CW_GETNSSSEP);

	  while ((grp = (struct group *)
			cygwin_internal (CW_GETENT, TRUE, ticket)))
	    {
	      if (disp_groupname
		  && strcasecmp (disp_groupname, grp->gr_name) != 0
		  && (!(p = strchr (grp->gr_name, nss_sep[0]))
		      || strcasecmp (disp_groupname, p + 1) != 0))
		continue;
	      printf ("%s:%s:%u:\n", grp->gr_name, grp->gr_passwd,
				     grp->gr_gid);
	      if (pgrp && !strcmp (grp->gr_passwd, pgrp->gr_passwd))
		got_curr_pgrp = TRUE;
	    }
	  cygwin_internal (CW_ENDENT, TRUE, ticket);
	}
    }

  if (print_current && !got_curr_pgrp)
    printf ("%s:%s:%u:\n", pgrp->gr_name, pgrp->gr_passwd, pgrp->gr_gid);

  off = 0xfd000000;
  for (i = 0; i < print_domlist; ++i)
    {
      if (domlist[i].domain || !domlist[i].str)
	continue;
      if (!enum_local_groups (domlist + i, sep_char, off, disp_groupname,
			      print_builtin, print_current))
	{
	  enum_groups (domlist + i, sep_char, off, disp_groupname,
		       print_current);
	  if (!domlist[i].domain && domlist[i].str && print_unix)
	    enum_unix_groups (domlist + i, sep_char, 0xff000000, print_unix);
	  off += id_offset;
	}
    }

  return 0;
}
Ejemplo n.º 29
0
int
main(int argc, char ** argv)
{
    const char * line;
    unsigned     i;

    if (argc > 1) {
        test_program_arg = argv[1];
        sxe_log_hook_line_out(test_log_line_out_to_stdout);
        SXEA10(sxe_log_hook_line_out(test_log_line_out_to_stdout) == test_log_line_out_to_stdout,
               "sxe_log_hook_line_out failed to hook test_log_line_out_to_stdout");

        if (strcmp(argv[1], "1") == 0) {
            if (getenv("SXE_LOG_LEVEL") != NULL) {
                SXED80("should not see this (level too high)", strlen("should not see this (level too high)"));    /* Cover early out in dump */
            }

            SXEL40("BOO");
        }
        else if (strcmp(argv[1], "2") == 0) {
#ifndef LOCAL_SXE_DEBUG
            sxe_log_set_indent_maximum(~0U);
#endif
            sxe_log_set_level(SXE_LOG_LEVEL_WARNING);
            SXEE50("level_five()");
            test_level_six(SXE_LOG_LEVEL_LIBRARY_DUMP);
            SXER50("return // five");
            SXEE50("level_five()");
            test_level_six(SXE_LOG_LEVEL_WARNING);
            SXER50("return // five");
            SXEL20("that's all, folks");
        }

        exit(0);
    }

    test_program_name = argv[0];
    plan_tests(3 * TEST_LINES_EXPECTED + 3);

    /* Tests for different log level settings */

    tap_test_case_name("Level settings");
    ok((line = test_log_first("1")) != NULL,                        "Test log at default level wrote a line");
    diag("line = %s", line);

    SXEA12(putenv((char *)(intptr_t)"SXE_LOG_LEVEL=2") >= 0,        "%s: Failed to putenv: %s", test_program_name, strerror(errno));
    ok(test_log_first("1") == NULL,                                 "Test log with SXE_LOG_LEVEL=2 failed to write a line");

    /* TODO: Replace putenvs with calls to the TBD function that allows setting fine grained levels programmatically. */

    SXEA12(putenv((char *)(intptr_t)"SXE_LOG_LEVEL_LIBSXE=5") >= 0, "%s: Failed to putenv: %s", test_program_name, strerror(errno));
    ok((line = test_log_first("1")) != NULL,                        "Test log with SXE_LOG_LEVEL_LIBSXE=5 wrote a line");
    diag("line = %s", line);
    SXEA12(putenv((char *)(intptr_t)"SXE_LOG_LEVEL_LIBSXE_LIB_SXE_LOG=2") >= 0, "%s: Failed to setenv: %s", test_program_name, strerror(errno));
    ok(test_log_first("1") == NULL,                                 "Test log with SXE_LOG_LEVEL_LIBSXE_LIB_SXE_LOG=2 failed to write a line");
    SXEA12(putenv((char *)(intptr_t)"SXE_LOG_LEVEL_LIBSXE_LIB_SXE_LOG_TEST_TEST_SXE_LOG_LEVELS=7") >= 0, "%s: Failed to putenv: %s", test_program_name, strerror(errno));
    ok((line = test_log_first("1")) != NULL,                        "Test log with SXE_LOG_LEVEL_LIBSXE_LIB_SXE_LOG_TEST_TEST_SXE_LOG_LEVELS=7 wrote a line");
    diag("line = %s", line);

    /* Remove the more specific environment variables
     */
    SXEA12(unsetenv("SXE_LOG_LEVEL_LIBSXE") == 0,                                      "%s: unsetenv failed: %s", test_program_name, strerror(errno));
    SXEA12(unsetenv("SXE_LOG_LEVEL_LIBSXE_LIB_SXE_LOG") == 0,                          "%s: unsetenv failed: %s", test_program_name, strerror(errno));
    SXEA12(unsetenv("SXE_LOG_LEVEL_LIBSXE_LIB_SXE_LOG_TEST_TEST_SXE_LOG_LEVELS") == 0, "%s: unsetenv failed: %s", test_program_name, strerror(errno));

    /* Tests for indentation interacting with log level */

    tap_test_case_name("Indentation");
    line = test_log_first("2");

    for (i = 0; i < TEST_LINES_EXPECTED; i++) {
        ok(line != NULL,                                            "Got line %u", 2 * i + 1);
        ok(strstr(line, test_expected[i]) != NULL,                  "Found '%s' in '%.*s'", test_expected[i], (int)strlen(line) - 1, line);

        if (i > 2) {
            ok(test_log_next() != NULL,                             "Got line %u", 2 * i + 2);
        }

        line = test_log_next();
    }

    ok(line == NULL,                                                "Got EOF");
    return exit_status();
}
Ejemplo n.º 30
0
int unset_env(char *name) {
	return unsetenv(name);
}