示例#1
0
int lc_wrap_filter(int (*func)(FILE *in, FILE *out), FILE *in, FILE *out,
		   const struct lc_capability *caps, size_t ncaps) {
  int ifd,  ofd, pid, status;
  int pfds[2];

  ifd = fileno(in);
  ofd = fileno(out);

  if (pipe(pfds) < 0)
    lc_panic("Cannot pipe");

  if ((pid = fork()) < 0)
    lc_panic("Cannot fork");

  if (pid != 0) {
    /* Parent process */
    close(pfds[1]);
    lc_process_messages(pfds[0], caps, ncaps);

    wait(&status);
    if(WIFEXITED(status)) {
      status = WEXITSTATUS(status);
      if (status != 0 && status != FILTER_EXIT)
	lc_panic("Unexpected child status");
      return status == 0;
    } else {
      lc_panic("Child exited abnormally");
    }
  } else { 
    /* Child process */
    int fds[4];

    lc_wrapped = 1;
    close(pfds[0]);
    lc_parent_fd = pfds[1];
    if(lc_limitfd(ifd, CAP_READ | CAP_SEEK) < 0
       || lc_limitfd(ofd, CAP_WRITE | CAP_SEEK) < 0
       // FIXME: CAP_SEEK should not be needed!
       || lc_limitfd(lc_parent_fd, CAP_READ | CAP_WRITE | CAP_SEEK) < 0) {
      lc_panic("Cannot limit descriptors");
    }
    fds[0] = 2;
    fds[1] = ofd;
    fds[2] = ifd;
    fds[3] = lc_parent_fd;
    lc_closeallbut(fds, 4);

    if (lc_available() && cap_enter() < 0)
      lc_panic("cap_enter() failed");

    if((*func)(in, out)) {
      exit(0);
    } else {
      exit(FILTER_EXIT);
    }
    /* NOTREACHED */
  }
  /* NOTREACHED */
  return 0;
}
示例#2
0
文件: iscsid.c 项目: Zer0day/freebsd
/*
 * XXX: I CANT INTO LATIN
 */
static void
capsicate(struct connection *conn)
{
    int error;
    cap_rights_t rights;
#ifdef ICL_KERNEL_PROXY
    const unsigned long cmds[] = { ISCSIDCONNECT, ISCSIDSEND, ISCSIDRECEIVE,
                                   ISCSIDHANDOFF, ISCSIDFAIL, ISCSISADD, ISCSISREMOVE
                                 };
#else
    const unsigned long cmds[] = { ISCSIDHANDOFF, ISCSIDFAIL, ISCSISADD,
                                   ISCSISREMOVE
                                 };
#endif

    cap_rights_init(&rights, CAP_IOCTL);
    error = cap_rights_limit(conn->conn_iscsi_fd, &rights);
    if (error != 0 && errno != ENOSYS)
        log_err(1, "cap_rights_limit");

    error = cap_ioctls_limit(conn->conn_iscsi_fd, cmds,
                             sizeof(cmds) / sizeof(cmds[0]));
    if (error != 0 && errno != ENOSYS)
        log_err(1, "cap_ioctls_limit");

    error = cap_enter();
    if (error != 0 && errno != ENOSYS)
        log_err(1, "cap_enter");

    if (cap_sandboxed())
        log_debugx("Capsicum capability mode enabled");
    else
        log_warnx("Capsicum capability mode not supported");
}
示例#3
0
int
main(int argc, char *argv[])
{
	int c;
	int status = 0;

	if (caph_limit_stdio() < 0 || (cap_enter() < 0 && errno != ENOSYS))
		err(1, "capsicum");

	optind = 2;	/* Past the program name and the option letters. */
	while ((c = getopt(argc, argv, argv[1])) != -1)
		switch (c) {
		case '?':
			status = 1;	/* getopt routine gave message */
			break;
		default:
			if (optarg != NULL)
				printf(" -%c %s", c, optarg);
			else
				printf(" -%c", c);
			break;
		}
	printf(" --");
	for (; optind < argc; optind++)
		printf(" %s", argv[optind]);
	printf("\n");
	return status;
}
示例#4
0
/*
 * Ensure that fcntl() works consistently for both regular file descriptors and
 * capability-wrapped ones.
 */
int
test_fcntl(void)
{
	int success = PASSED;
	cap_rights_t rights = CAP_READ | CAP_FCNTL;

	/*
	 * Open some files of different types, and wrap them in capabilities.
	 */
	struct fd files[] = {
		{ "file",         open("/etc/passwd", O_RDONLY) },
		{ "socket",       socket(PF_LOCAL, SOCK_STREAM, 0) },
		{ "SHM",          shm_open(SHM_ANON, O_RDWR, 0600) },
	};
	REQUIRE(files[0].f_fd);
	REQUIRE(files[1].f_fd);
	REQUIRE(files[2].f_fd);

	struct fd caps[] = {
		{ "file cap",     cap_new(files[0].f_fd, rights) },
		{ "socket cap",   cap_new(files[1].f_fd, rights) },
		{ "SHM cap",      cap_new(files[2].f_fd, rights) },
	};
	REQUIRE(caps[0].f_fd);
	REQUIRE(caps[1].f_fd);
	REQUIRE(caps[2].f_fd);

	struct fd all[] = {
		files[0], caps[0],
		files[1], caps[1],
		files[2], caps[2],
	};
	const size_t len = sizeof(all) / sizeof(struct fd);

	REQUIRE(cap_enter());

	/*
	 * Ensure that we can fcntl() all the files that we opened above.
	 */
	for (size_t i = 0; i < len; i++)
	{
		struct fd f = all[i];
		int cap;

		CHECK_SYSCALL_SUCCEEDS(fcntl, f.f_fd, F_GETFL, 0);
		REQUIRE(cap = cap_new(f.f_fd, CAP_READ));
		if (fcntl(f.f_fd, F_GETFL, 0) == -1)
			FAIL("Error calling fcntl('%s', F_GETFL)", f.f_name);
		else
			CHECK_NOTCAPABLE(fcntl, cap, F_GETFL, 0);
	}

	return (success);
}
示例#5
0
文件: event.c 项目: dotike/pkg
static int
event_sandboxed_call(pkg_sandbox_cb func, int fd, void *ud)
{
	pid_t pid;
	int status, ret;

	ret = -1;
	pid = fork();

	switch(pid) {
	case -1:
		warn("fork failed");
		return (EPKG_FATAL);
		break;
	case 0:
		break;
	default:
		/* Parent process */
		while (waitpid(pid, &status, 0) == -1) {
			if (errno != EINTR) {
				warn("Sandboxed process pid=%d", (int)pid);
				ret = -1;
				break;
			}
		}

		if (WIFEXITED(status)) {
			ret = WEXITSTATUS(status);
		}
		if (WIFSIGNALED(status)) {
			/* Process got some terminating signal, hence stop the loop */
			fprintf(stderr, "Sandboxed process pid=%d terminated abnormally by signal: %d\n",
					(int)pid, WTERMSIG(status));
			ret = -1;
		}
		return (ret);
	}

	/* Here comes child process */
#ifdef HAVE_CAPSICUM
	if (cap_enter() < 0 && errno != ENOSYS) {
		warn("cap_enter() failed");
		return (EPKG_FATAL);
	}
#endif

	/*
	 * XXX: if capsicum is not enabled we basically have no idea of how to
	 * make a sandbox
	 */
	ret = func(fd, ud);

	_exit(ret);
}
示例#6
0
static int
ksandbox_capsicum_init_control(void *arg, int fd1, int fd2)
{
	int rc;
	struct rlimit	 rl_zero;
	cap_rights_t	 rights;

	cap_rights_init(&rights);

	cap_rights_init(&rights, CAP_EVENT, CAP_FCNTL, CAP_ACCEPT);
	if (cap_rights_limit(STDIN_FILENO, &rights) < 0 && 
		 errno != ENOSYS) {
 		XWARN("cap_rights_limit: STDIN_FILENO");
		return(0);
	}

	cap_rights_init(&rights, CAP_WRITE, CAP_FSTAT);
	if (cap_rights_limit(STDERR_FILENO, &rights) < 0 && 
		 errno != ENOSYS) {
		XWARN("cap_rights_limit: STDERR_FILENO");
		return(0);
	}

	cap_rights_init(&rights, CAP_EVENT, 
		CAP_FCNTL, CAP_READ, CAP_WRITE);
	if (cap_rights_limit(fd1, &rights) < 0 && 
		 errno != ENOSYS) {
		XWARN("cap_rights_limit: internal socket");
		return(0);
	}

	rl_zero.rlim_cur = rl_zero.rlim_max = 0;

	if (-1 == setrlimit(RLIMIT_FSIZE, &rl_zero)) {
		XWARNX("setrlimit: rlimit_fsize");
		return(0);
	} else if (-1 == setrlimit(RLIMIT_NPROC, &rl_zero)) {
		XWARNX("setrlimit: rlimit_nproc");
		return(0);
	}

	rc = cap_enter();
	if (0 != rc && errno != ENOSYS) {
		XWARN("cap_enter");
		rc = 0;
	} else
		rc = 1;

	return(rc);
}
示例#7
0
int
child(const char *inpath, const char *outpath, int pipefd,
      bool Vflag, bool vflag)
{
    int error;
    FILE *outfp = NULL, *infp = NULL;
    struct executable *x;

    infp = checked_fopen(inpath, "r");
    if (outpath != NULL)
        outfp = checked_fopen(outpath, "w");

    error = cap_enter();
    if (error != 0 && errno != ENOSYS)
        err(1, "cap_enter");

    x = calloc(1, sizeof(*x));
    if (x == NULL)
        err(1, "calloc");
    x->x_path = inpath;
    x->x_fp = infp;

    load(x);
    parse(x);
    if (Vflag) {
        if (signature_size(x) == 0)
            errx(1, "file not signed");

        printf("file contains signature\n");
        if (vflag) {
            digest(x);
            show_digest(x);
            show_certificate(x);
        }
    } else {
        if (signature_size(x) != 0)
            errx(1, "file already signed");

        digest(x);
        if (vflag)
            show_digest(x);
        send_digest(x, pipefd);
        receive_signature(x, pipefd);
        update(x);
        save(x, outfp, outpath);
    }

    return (0);
}
示例#8
0
// Attempt to enter the specified sandbox mode.
int SBCELT_EnterSandbox(int mode) {
	switch (mode) {
		case SBCELT_SANDBOX_NONE:
			// No sandbox was requsted.
			return 0;
		case SBCELT_SANDBOX_CAPSICUM: {
			int err = cap_enter();
			if (err == -1) {
				fprintf(stderr, "unable to cap_enter(): %s (%i)\n", strerror(errno), errno);
			}
			return err;
		}	
	}
	return -1;
}
示例#9
0
int
next(char **argv)
{
	static int done;
	int statok;

	if (argv) {
		_argv = argv;
		return(1);
	}
	for (;;) {
		if (*_argv) {
			done = 1;
			if (!(freopen(*_argv, "r", stdin))) {
				warn("%s", *_argv);
				exitval = 1;
				++_argv;
				continue;
			}
			statok = 1;
		} else {
			if (done++)
				return(0);
			statok = 0;
		}

		if (caph_limit_stream(fileno(stdin), CAPH_READ) < 0)
			err(1, "unable to restrict %s",
			    statok ? _argv[-1] : "stdin");

		/*
		 * We've opened our last input file; enter capsicum sandbox.
		 */
		if (*_argv == NULL) {
			if (cap_enter() < 0 && errno != ENOSYS)
				err(1, "unable to enter capability mode");
		}

		if (skip)
			doskip(statok ? *_argv : "stdin", statok);
		if (*_argv)
			++_argv;
		if (!skip)
			return(1);
	}
	/* NOTREACHED */
}
void
ssh_sandbox_child(struct ssh_sandbox *box)
{
	struct rlimit rl_zero;
	cap_rights_t rights;

	caph_cache_tzdata();

	rl_zero.rlim_cur = rl_zero.rlim_max = 0;

	if (setrlimit(RLIMIT_FSIZE, &rl_zero) == -1)
		fatal("%s: setrlimit(RLIMIT_FSIZE, { 0, 0 }): %s",
			__func__, strerror(errno));
#ifndef SANDBOX_SKIP_RLIMIT_NOFILE
	if (setrlimit(RLIMIT_NOFILE, &rl_zero) == -1)
		fatal("%s: setrlimit(RLIMIT_NOFILE, { 0, 0 }): %s",
			__func__, strerror(errno));
#endif
	if (setrlimit(RLIMIT_NPROC, &rl_zero) == -1)
		fatal("%s: setrlimit(RLIMIT_NPROC, { 0, 0 }): %s",
			__func__, strerror(errno));

	cap_rights_init(&rights);

	if (cap_rights_limit(STDIN_FILENO, &rights) < 0 && errno != ENOSYS)
		fatal("can't limit stdin: %m");
	if (cap_rights_limit(STDOUT_FILENO, &rights) < 0 && errno != ENOSYS)
		fatal("can't limit stdout: %m");
	if (cap_rights_limit(STDERR_FILENO, &rights) < 0 && errno != ENOSYS)
		fatal("can't limit stderr: %m");

	cap_rights_init(&rights, CAP_READ, CAP_WRITE);
	if (cap_rights_limit(box->monitor->m_recvfd, &rights) < 0 &&
	    errno != ENOSYS)
		fatal("%s: failed to limit the network socket", __func__);
	cap_rights_init(&rights, CAP_WRITE);
	if (cap_rights_limit(box->monitor->m_log_sendfd, &rights) < 0 &&
	    errno != ENOSYS)
		fatal("%s: failed to limit the logging socket", __func__);
	if (cap_enter() < 0 && errno != ENOSYS)
		fatal("%s: failed to enter capability mode", __func__);

}
示例#11
0
文件: main.c 项目: chijicodes/capsh
int main(int argc, char *argv[])
{
    char *fullPath;
    fullPath = getenv("PATH");
    int i= 0, fd;
    
    if(argc < 2){
        printf("no argument passed \n");
        return 1;
    }
     //*Passing argument to parameters of function find_executable and returning the              	value of the executable file as to file discriptor*//
        fd = find_executable(fullPath, argv[1]);
	if (fd < 0)
	err(-1, "failed to find %s in %s", argv[1], fullPath);
	printf("Executing FD: %d\n", fd);
	cap_enter();//*Enabling Capsicum capability mode*// 
        fexecve(fd, argv + 1, environ);
	err(-1, "fexecve() failed");

}
示例#12
0
int
main(int argc, char *argv[])
{
	struct timespec time_to_sleep;
	double d;
	time_t original;
	char buf[2];

	if (caph_limit_stdio() < 0 || (cap_enter() < 0 && errno != ENOSYS))
		err(1, "capsicum");

	if (argc != 2)
		usage();

	if (sscanf(argv[1], "%lf%1s", &d, buf) != 1)
		usage();
	if (d > INT_MAX)
		usage();
	if (d <= 0)
		return (0);
	original = time_to_sleep.tv_sec = (time_t)d;
	time_to_sleep.tv_nsec = 1e9 * (d - time_to_sleep.tv_sec);

	signal(SIGINFO, report_request);

	/*
	 * Note: [EINTR] is supposed to happen only when a signal was handled
	 * but the kernel also returns it when a ptrace-based debugger
	 * attaches. This is a bug but it is hard to fix.
	 */
	while (nanosleep(&time_to_sleep, &time_to_sleep) != 0) {
		if (report_requested) {
			/* Reporting does not bother with nanoseconds. */
			warnx("about %d second(s) left out of the original %d",
			    (int)time_to_sleep.tv_sec, (int)original);
			report_requested = 0;
		} else if (errno != EINTR)
			err(1, "nanosleep");
	}
	return (0);
}
示例#13
0
R_API bool r_sandbox_enable (bool e) {
	if (enabled) {
		if (!e) {
			// eprintf ("Cant disable sandbox\n");
		}
		return true;
	}
	enabled = e;
#if LIBC_HAVE_PLEDGE
	if (enabled && pledge ("stdio rpath tty prot_exec inet", NULL) == -1) {
		eprintf ("sandbox: pledge call failed\n");
		return false;
	}
#endif
#if HAVE_CAPSICUM
	if (enabled && cap_enter () != 0) {
		eprintf ("sandbox: call_enter failed\n");
		return false;
	}
#endif
	return enabled;
}
示例#14
0
int
test_capabilities(void)
{
	int filefd, dirfd, tmpfd;
	int success = PASSED;
	char file[] = "/tmp/cap_test.XXXXXXXXXX";
	char dir[] = "/tmp/cap_test.XXXXXXXXXX";

	filefd = mkstemp(file);
	if (filefd < 0)
		err(-1, "mkstemp");
	if (mkdtemp(dir) == NULL) {
		KEEP_ERRNO(unlink(file));
		err(-1, "mkdtemp");
	}
	dirfd = open(dir, O_RDONLY | O_DIRECTORY);
	if (dirfd == -1) {
		KEEP_ERRNO(unlink(file));
		KEEP_ERRNO(rmdir(dir));
		err(-1, "open");
	}
	tmpfd = open("/tmp", O_RDONLY | O_DIRECTORY);
	if (tmpfd == -1) {
		KEEP_ERRNO(unlink(file));
		KEEP_ERRNO(rmdir(dir));
		err(-1, "open");
	}

	if (cap_enter() == -1) {
		KEEP_ERRNO(unlink(file));
		KEEP_ERRNO(rmdir(dir));
		err(-1, "cap_enter");
	}

	TRY(CAP_READ);
	TRY(CAP_WRITE);
	TRY(CAP_SEEK);
	TRY(CAP_PREAD);
	TRY(CAP_PWRITE);
	TRY(CAP_READ | CAP_WRITE);
	TRY(CAP_PREAD | CAP_PWRITE);
	TRY(CAP_MMAP);
	TRY(CAP_MMAP_R);
	TRY(CAP_MMAP_W);
	TRY(CAP_MMAP_X);
	TRY(CAP_MMAP_RW);
	TRY(CAP_MMAP_RX);
	TRY(CAP_MMAP_WX);
	TRY(CAP_MMAP_RWX);
	TRY(CAP_CREATE | CAP_READ | CAP_LOOKUP);
	TRY(CAP_CREATE | CAP_WRITE | CAP_LOOKUP);
	TRY(CAP_CREATE | CAP_READ | CAP_WRITE | CAP_LOOKUP);
#ifdef TODO
	TRY(CAP_FEXECVE);
#endif
	TRY(CAP_FSYNC);
	TRY(CAP_FSYNC | CAP_READ | CAP_LOOKUP);
	TRY(CAP_FSYNC | CAP_WRITE | CAP_LOOKUP);
	TRY(CAP_FSYNC | CAP_READ | CAP_WRITE | CAP_LOOKUP);
	TRY(CAP_FTRUNCATE);
	TRY(CAP_FTRUNCATE | CAP_READ | CAP_LOOKUP);
	TRY(CAP_FTRUNCATE | CAP_WRITE | CAP_LOOKUP);
	TRY(CAP_FTRUNCATE | CAP_READ | CAP_WRITE | CAP_LOOKUP);
#ifdef TODO
	TRY(CAP_FCHDIR);
#endif
	TRY(CAP_FCHFLAGS);
	TRY(CAP_FCHOWN);
	TRY(CAP_FCHOWN | CAP_LOOKUP);
	TRY(CAP_FCHMOD | CAP_LOOKUP);
	TRY(CAP_FCNTL);
#ifdef TODO
	TRY(CAP_FLOCK);
#endif
	TRY(CAP_FPATHCONF);
#ifdef TODO
	TRY(CAP_FSCK);
#endif
	TRY(CAP_FSTAT | CAP_LOOKUP);
	TRY(CAP_FSTATFS);
	TRY(CAP_FUTIMES | CAP_LOOKUP);
	TRY(CAP_LINKAT | CAP_LOOKUP);
	TRY(CAP_MKDIRAT | CAP_LOOKUP);
	TRY(CAP_MKFIFOAT | CAP_LOOKUP);
	TRY(CAP_MKNODAT | CAP_LOOKUP);
	TRY(CAP_SYMLINKAT | CAP_LOOKUP);
	TRY(CAP_UNLINKAT | CAP_LOOKUP);
	/* Rename needs CAP_RENAMEAT on source directory and CAP_LINKAT on destination directory. */
	TRY(CAP_RENAMEAT | CAP_UNLINKAT | CAP_LOOKUP);
#ifdef TODO
	TRY(CAP_LOOKUP);
	TRY(CAP_EXTATTR_DELETE);
	TRY(CAP_EXTATTR_GET);
	TRY(CAP_EXTATTR_LIST);
	TRY(CAP_EXTATTR_SET);
	TRY(CAP_ACL_CHECK);
	TRY(CAP_ACL_DELETE);
	TRY(CAP_ACL_GET);
	TRY(CAP_ACL_SET);
	TRY(CAP_ACCEPT);
	TRY(CAP_BIND);
	TRY(CAP_CONNECT);
	TRY(CAP_GETPEERNAME);
	TRY(CAP_GETSOCKNAME);
	TRY(CAP_GETSOCKOPT);
	TRY(CAP_LISTEN);
	TRY(CAP_PEELOFF);
	TRY(CAP_RECV);
	TRY(CAP_SEND);
	TRY(CAP_SETSOCKOPT);
	TRY(CAP_SHUTDOWN);
	TRY(CAP_MAC_GET);
	TRY(CAP_MAC_SET);
	TRY(CAP_SEM_GETVALUE);
	TRY(CAP_SEM_POST);
	TRY(CAP_SEM_WAIT);
	TRY(CAP_POST_EVENT);
	TRY(CAP_EVENT);
	TRY(CAP_IOCTL);
	TRY(CAP_TTYHOOK);
	TRY(CAP_PDGETPID);
	TRY(CAP_PDWAIT);
	TRY(CAP_PDKILL);
#endif

	(void)unlinkat(tmpfd, file + strlen("/tmp/"), 0);
	(void)unlinkat(tmpfd, dir + strlen("/tmp/"), AT_REMOVEDIR);

	return (success);
}
示例#15
0
int
main(void)
{
	unsigned int mode;
	pid_t pid;
	int pfd;

	printf("1..27\n");

	mode = 666;
	CHECK(cap_getmode(&mode) == 0);
	/* If cap_getmode() succeeded mode should be modified. */
	CHECK(mode != 666);
	/* We are not in capability mode. */
	CHECK(mode == 0);

	/* Expect EFAULT. */
	errno = 0;
	CHECK(cap_getmode(NULL) == -1);
	CHECK(errno == EFAULT);
	errno = 0;
	CHECK(cap_getmode((void *)(uintptr_t)0xdeadc0de) == -1);
	CHECK(errno == EFAULT);

	/* If parent is not in capability mode, child after fork() also won't be. */
	pid = fork();
	switch (pid) {
	case -1:
		err(1, "fork() failed");
	case 0:
		mode = 666;
		CHECK(cap_getmode(&mode) == 0);
		/* If cap_getmode() succeeded mode should be modified. */
		CHECK(mode != 666);
		/* We are not in capability mode. */
		CHECK(mode == 0);
		exit(0);
	default:
		if (waitpid(pid, NULL, 0) == -1)
			err(1, "waitpid() failed");
	}

	/* If parent is not in capability mode, child after pdfork() also won't be. */
	pid = pdfork(&pfd, 0);
	switch (pid) {
	case -1:
		err(1, "pdfork() failed");
	case 0:
		mode = 666;
		CHECK(cap_getmode(&mode) == 0);
		/* If cap_getmode() succeeded mode should be modified. */
		CHECK(mode != 666);
		/* We are not in capability mode. */
		CHECK(mode == 0);
		exit(0);
	default:
		if (pdwait(pfd) == -1)
			err(1, "pdwait() failed");
		close(pfd);
	}

	/* In capability mode... */

	CHECK(cap_enter() == 0);

	mode = 666;
	CHECK(cap_getmode(&mode) == 0);
	/* If cap_getmode() succeeded mode should be modified. */
	CHECK(mode != 666);
	/* We are in capability mode. */
	CHECK(mode == 1);

	/* Expect EFAULT. */
	errno = 0;
	CHECK(cap_getmode(NULL) == -1);
	CHECK(errno == EFAULT);
	errno = 0;
	CHECK(cap_getmode((void *)(uintptr_t)0xdeadc0de) == -1);
	CHECK(errno == EFAULT);

	/* If parent is in capability mode, child after fork() also will be. */
	pid = fork();
	switch (pid) {
	case -1:
		err(1, "fork() failed");
	case 0:
		mode = 666;
		CHECK(cap_getmode(&mode) == 0);
		/* If cap_getmode() succeeded mode should be modified. */
		CHECK(mode != 666);
		/* We are in capability mode. */
		CHECK(mode == 1);
		exit(0);
	default:
		/*
		 * wait(2) and friends are not permitted in the capability mode,
		 * so we can only just wait for a while.
		 */
		sleep(1);
	}

	/* If parent is in capability mode, child after pdfork() also will be. */
	pid = pdfork(&pfd, 0);
	switch (pid) {
	case -1:
		err(1, "pdfork() failed");
	case 0:
		mode = 666;
		CHECK(cap_getmode(&mode) == 0);
		/* If cap_getmode() succeeded mode should be modified. */
		CHECK(mode != 666);
		/* We are in capability mode. */
		CHECK(mode == 1);
		exit(0);
	default:
		if (pdwait(pfd) == -1)
			err(1, "pdwait() failed");
		close(pfd);
	}

	exit(0);
}
示例#16
0
文件: sandbox.c 项目: openbsm/openbsm
int
sandbox(const char *user, bool capsicum, const char *fmt, ...)
{
#ifdef HAVE_JAIL
	struct jail jailst;
	char *jailhost;
	va_list ap;
#endif
	struct passwd *pw;
	uid_t ruid, euid;
	gid_t rgid, egid;
#ifdef HAVE_GETRESUID
	uid_t suid;
#endif
#ifdef HAVE_GETRESGID
	gid_t sgid;
#endif
	gid_t *groups, *ggroups;
	bool jailed;
	int ngroups, ret;

	PJDLOG_ASSERT(user != NULL);
	PJDLOG_ASSERT(fmt != NULL);

	ret = -1;
	groups = NULL;
	ggroups = NULL;

	/*
	 * According to getpwnam(3) we have to clear errno before calling the
	 * function to be able to distinguish between an error and missing
	 * entry (with is not treated as error by getpwnam(3)).
	 */
	errno = 0;
	pw = getpwnam(user);
	if (pw == NULL) {
		if (errno != 0) {
			pjdlog_errno(LOG_ERR,
			    "Unable to find info about '%s' user", user);
			goto out;
		} else {
			pjdlog_error("'%s' user doesn't exist.", user);
			errno = ENOENT;
			goto out;
		}
	}

	ngroups = sysconf(_SC_NGROUPS_MAX);
	if (ngroups == -1) {
		pjdlog_errno(LOG_WARNING,
		    "Unable to obtain maximum number of groups");
		ngroups = NGROUPS_MAX;
	}
	ngroups++;	/* For base gid. */
	groups = malloc(sizeof(groups[0]) * ngroups);
	if (groups == NULL) {
		pjdlog_error("Unable to allocate memory for %d groups.",
		    ngroups);
		goto out;
	}
	if (getgrouplist(user, pw->pw_gid, groups, &ngroups) == -1) {
		pjdlog_error("Unable to obtain groups of user %s.", user);
		goto out;
	}

#ifdef HAVE_JAIL
	va_start(ap, fmt);
	(void)vasprintf(&jailhost, fmt, ap);
	va_end(ap);
	if (jailhost == NULL) {
		pjdlog_error("Unable to allocate memory for jail host name.");
		goto out;
	}
	bzero(&jailst, sizeof(jailst));
	jailst.version = JAIL_API_VERSION;
	jailst.path = pw->pw_dir;
	jailst.hostname = jailhost;
	if (jail(&jailst) >= 0) {
		jailed = true;
	} else {
		jailed = false;
		pjdlog_errno(LOG_WARNING,
		    "Unable to jail to directory %s", pw->pw_dir);
	}
	free(jailhost);
#else	/* !HAVE_JAIL */
	jailed = false;
#endif	/* !HAVE_JAIL */

	if (!jailed) {
		if (chroot(pw->pw_dir) == -1) {
			pjdlog_errno(LOG_ERR,
			    "Unable to change root directory to %s",
			    pw->pw_dir);
			goto out;
		}
	}
	PJDLOG_VERIFY(chdir("/") == 0);

	if (setgroups(ngroups, groups) == -1) {
		pjdlog_errno(LOG_ERR, "Unable to set groups");
		goto out;
	}
	if (setgid(pw->pw_gid) == -1) {
		pjdlog_errno(LOG_ERR, "Unable to set gid to %u",
		    (unsigned int)pw->pw_gid);
		goto out;
	}
	if (setuid(pw->pw_uid) == -1) {
		pjdlog_errno(LOG_ERR, "Unable to set uid to %u",
		    (unsigned int)pw->pw_uid);
		goto out;
	}

#ifdef HAVE_CAP_ENTER
	if (capsicum) {
		capsicum = (cap_enter() == 0);
		if (!capsicum) {
			pjdlog_common(LOG_DEBUG, 1, errno,
			    "Unable to sandbox using capsicum");
		}
	}
#else	/* !HAVE_CAP_ENTER */
	capsicum = false;
#endif	/* !HAVE_CAP_ENTER */

	/*
	 * Better be sure that everything succeeded.
	 */
#ifdef HAVE_GETRESUID
	PJDLOG_VERIFY(getresuid(&ruid, &euid, &suid) == 0);
	PJDLOG_VERIFY(suid == pw->pw_uid);
#else
	ruid = getuid();
	euid = geteuid();
#endif
	PJDLOG_VERIFY(ruid == pw->pw_uid);
	PJDLOG_VERIFY(euid == pw->pw_uid);
#ifdef HAVE_GETRESGID
	PJDLOG_VERIFY(getresgid(&rgid, &egid, &sgid) == 0);
	PJDLOG_VERIFY(sgid == pw->pw_gid);
#else
	rgid = getgid();
	egid = getegid();
#endif
	PJDLOG_VERIFY(rgid == pw->pw_gid);
	PJDLOG_VERIFY(egid == pw->pw_gid);
	PJDLOG_VERIFY(getgroups(0, NULL) == ngroups);
	ggroups = malloc(sizeof(ggroups[0]) * ngroups);
	if (ggroups == NULL) {
		pjdlog_error("Unable to allocate memory for %d groups.",
		    ngroups);
		goto out;
	}
	PJDLOG_VERIFY(getgroups(ngroups, ggroups) == ngroups);
	qsort(groups, (size_t)ngroups, sizeof(groups[0]), groups_compare);
	qsort(ggroups, (size_t)ngroups, sizeof(ggroups[0]), groups_compare);
	PJDLOG_VERIFY(bcmp(groups, ggroups, sizeof(groups[0]) * ngroups) == 0);

	pjdlog_debug(1,
	    "Privileges successfully dropped using %s%s+setgid+setuid.",
	    capsicum ? "capsicum+" : "", jailed ? "jail" : "chroot");

	ret = 0;
out:
	if (groups != NULL)
		free(groups);
	if (ggroups != NULL)
		free(ggroups);
	return (ret);
}
示例#17
0
文件: info.c 项目: grembo/pkg
int
exec_info(int argc, char **argv)
{
	struct pkgdb *db = NULL;
	struct pkgdb_it *it = NULL;
	int query_flags;
	struct pkg *pkg = NULL;
	uint64_t opt = INFO_TAG_NAMEVER;
	match_t match = MATCH_GLOB;
	char *pkgname;
	char *pkgversion = NULL, *pkgversion2 = NULL;
	const char *file = NULL;
	int ch, fd;
	int ret = EPKG_OK;
	int retcode = 0;
	bool gotone = false;
	int i, j;
	int sign = 0;
	int sign2 = 0;
	int open_flags = 0;
	bool pkg_exists = false;
	bool origin_search = false;
	bool e_flag = false;
	struct pkg_manifest_key *keys = NULL;
#ifdef HAVE_CAPSICUM
	cap_rights_t rights;
#endif

	struct option longopts[] = {
		{ "all",		no_argument,		NULL,	'a' },
		{ "annotations",	no_argument,		NULL,	'A' },
		{ "provided-shlibs",	no_argument,		NULL,	'b' },
		{ "required-shlibs",	no_argument,		NULL,	'B' },
		{ "case-sensitive",	no_argument,		NULL,	'C' },
		{ "dependencies",	no_argument,		NULL,	'd' },
		{ "pkg-message",	no_argument,		NULL,	'D' },
		{ "exists",		no_argument,		NULL,	'e' },
		{ "show-name-only",	no_argument,		NULL,	'E' },
		{ "full",		no_argument,		NULL,	'f' },
		{ "file",		required_argument,	NULL,	'F' },
		{ "glob",		no_argument,		NULL,	'g' },
		{ "case-insensitive",	no_argument,		NULL,	'i' },
		{ "comment",		no_argument,		NULL,	'I' },
		{ "locked",		no_argument,		NULL,	'k' },
		{ "list-files",		no_argument,		NULL,	'l' },
		{ "origin",		no_argument,		NULL,	'o' },
		{ "by-origin",		no_argument,		NULL,	'O' },
		{ "prefix",		no_argument,		NULL,	'p' },
		{ "quiet",		no_argument,		NULL,	'q' },
		{ "required-by",	no_argument,		NULL,	'r' },
		{ "raw",		no_argument,		NULL,	'R' },
		{ "size",		no_argument,		NULL,	's' },
		{ "regex",		no_argument,		NULL,	'x' },
		{ "raw-format",		required_argument,	NULL, 	1   },
		{ NULL,			0,			NULL,	0   },
	};

	/* TODO: exclusive opts ? */
	while ((ch = getopt_long(argc, argv, "+aAbBCdDeEfF:giIkloOpqrRsx", longopts, NULL)) != -1) {
		switch (ch) {
		case 'a':
			match = MATCH_ALL;
			break;
		case 'A':
			opt |= INFO_ANNOTATIONS;
			break;
		case 'b':
			opt |= INFO_SHLIBS_PROVIDED;
			break;
		case 'B':
			opt |= INFO_SHLIBS_REQUIRED;
			break;
		case 'C':
			pkgdb_set_case_sensitivity(true);
			break;
		case 'd':
			opt |= INFO_DEPS;
			break;
		case 'D':
			opt |= INFO_MESSAGE;
			break;
		case 'e':
			pkg_exists = true;;
			retcode = 1;
			break;
		case 'E': /* ports compatibility */
			e_flag = true;
			break;
		case 'f':
			opt |= INFO_FULL;
			break;
		case 'F':
			file = optarg;
			break;
		case 'g':
			match = MATCH_GLOB;
			break;
		case 'i':
			pkgdb_set_case_sensitivity(false);
			break;
		case 'I':
			opt |= INFO_COMMENT;
			break;
		case 'k':
			opt |= INFO_LOCKED;
			break;
		case 'l':
			opt |= INFO_FILES;
			break;
		case 'o':
			opt |= INFO_ORIGIN;
			break;
		case 'O':
			origin_search = true;  /* only for ports compat */
			break;
		case 'p':
			opt |= INFO_PREFIX;
			break;
		case 'q':
			quiet = true;
			break;
		case 'r':
			opt |= INFO_RDEPS;
			break;
		case 'R':
			opt |= INFO_RAW;
			break;
		case 's':
			opt |= INFO_FLATSIZE;
			break;
		case 'x':
			match = MATCH_REGEX;
			break;
		case 1:
			if (strcasecmp(optarg, "json") == 0)
				opt |= INFO_RAW_JSON;
			else if (strcasecmp(optarg, "json-compact") == 0)
				opt |= INFO_RAW_JSON_COMPACT;
			else if (strcasecmp(optarg, "yaml") == 0)
				opt |= INFO_RAW_YAML;
			else if (strcasecmp(optarg, "ucl") == 0)
				opt |= INFO_RAW_UCL;
			else
				errx(EX_USAGE, "Invalid format '%s' for the "
				    "raw output, expecting json, json-compact "
				    "or yaml", optarg);
			break;
		default:
			usage_info();
			return(EX_USAGE);
		}
	}

	if (argc == 1 || (argc == 2 && quiet))
		match = MATCH_ALL;

	argc -= optind;
	argv += optind;

	if (argc == 0 && file == NULL && match != MATCH_ALL) {
		/* which -O bsd.*.mk always execpt clean output */
		if (origin_search)
			return (EX_OK);
		usage_info();
		return (EX_USAGE);
	}

	/* When no other data is requested, default is to print
	 * 'name-ver comment' For -O, just print name-ver */
	if (!origin_search && (opt & INFO_ALL) == 0 && match == MATCH_ALL &&
	    !quiet)
		opt |= INFO_COMMENT;

	/* Special compatibility: handle -O and -q -O */
	if (origin_search) {
		if (quiet) {
			opt = INFO_TAG_NAMEVER;
			quiet = false;
		} else {
			opt = INFO_TAG_NAMEVER|INFO_COMMENT;
		}
	}

	if (match == MATCH_ALL && opt == INFO_TAG_NAMEVER)
		quiet = false;

	if (file != NULL) {
		if ((fd = open(file, O_RDONLY)) == -1) {
			warn("Unable to open %s", file);
			return (EX_IOERR);
		}

#ifdef HAVE_CAPSICUM
		cap_rights_init(&rights, CAP_READ, CAP_FSTAT);
		if (cap_rights_limit(fd, &rights) < 0 && errno != ENOSYS ) {
			warn("cap_rights_limit() failed");
			close(fd);
			return (EX_SOFTWARE);
		}

		if (cap_enter() < 0 && errno != ENOSYS) {
			warn("cap_enter() failed");
			close(fd);
			return (EX_SOFTWARE);
		}
#endif
		if (opt == INFO_TAG_NAMEVER)
			opt |= INFO_FULL;
		pkg_manifest_keys_new(&keys);
		if (opt & INFO_RAW) {
			if ((opt & (INFO_RAW_JSON|INFO_RAW_JSON_COMPACT|INFO_RAW_UCL)) == 0)
				opt |= INFO_RAW_YAML;
		}

		if ((opt & (INFO_RAW | INFO_FILES |
				INFO_DIRS)) == 0)
			open_flags = PKG_OPEN_MANIFEST_COMPACT;

		if (pkg_open_fd(&pkg, fd, keys, open_flags) != EPKG_OK) {
			close(fd);
			return (1);
		}
		pkg_manifest_keys_free(keys);
		print_info(pkg, opt);
		close(fd);
		pkg_free(pkg);
		return (EX_OK);
	}

	ret = pkgdb_access(PKGDB_MODE_READ, PKGDB_DB_LOCAL);
	if (ret == EPKG_ENOACCESS) {
		warnx("Insufficient privileges to query the package database");
		return (EX_NOPERM);
	} else if (ret == EPKG_ENODB) {
		if (match == MATCH_ALL)
			return (EX_OK);
		if (origin_search)
			return (EX_OK);
		if (!quiet)
			warnx("No packages installed");
		return (EX_UNAVAILABLE);
	} else if (ret != EPKG_OK)
		return (EX_IOERR);
		
	ret = pkgdb_open(&db, PKGDB_DEFAULT);
	if (ret != EPKG_OK)
		return (EX_IOERR);

	if (pkgdb_obtain_lock(db, PKGDB_LOCK_READONLY) != EPKG_OK) {
		pkgdb_close(db);
		warnx("Cannot get a read lock on a database, it is locked by another process");
		return (EX_TEMPFAIL);
	}

	i = 0;
	do {
		gotone = false;
		pkgname = argv[i];

		/*
		 * allow to search for origin with a trailing /
		 * likes audio/linux-vsound depending on ${PORTSDIR}/audio/sox/
		 */
		if (argc > 0 && pkgname[strlen(pkgname) -1] == '/')
			pkgname[strlen(pkgname) -1] = '\0';

		if (argc > 0) {
			j=0;
			while (pkgname[j] != '\0') {
				if (pkgname[j] == '<') {
					if (pkgversion) {
						pkgversion2 = pkgname + j;
						sign2 = LT;
						pkgversion2[0] = '\0';
						pkgversion2++;
						if (pkgversion2[0] == '=') {
							pkgversion2++;
							sign=LE;
							j++;
						}
					} else {
						pkgversion = pkgname + j;
						sign = LT;
						pkgversion[0] = '\0';
						pkgversion++;
						if (pkgversion[0] == '=') {
							pkgversion++;
							sign=LE;
							j++;
						}
					}
				} else if (pkgname[j] == '>') {
					if (pkgversion) {
						pkgversion2 = pkgname + j;
						sign2 = GT;
						pkgversion2[0] = '\0';
						pkgversion2++;
						if (pkgversion2[0] == '=') {
							pkgversion2++;
							sign=GE;
							j++;
						}
					} else {
						pkgversion = pkgname + j;
						sign = GT;
						pkgversion[0] = '\0';
						pkgversion++;
						if (pkgversion[0] == '=') {
							pkgversion++;
							sign=GE;
							j++;
						}
					}
				} else if (pkgname[j] == '=') {
					if (pkgversion) {
						pkgversion2 = pkgname + j;
						sign2 = EQ;
						pkgversion2[0] = '\0';
						pkgversion2++;
						if (pkgversion2[0] == '=') {
							pkgversion2++;
							sign=EQ;
							j++;
						}
					} else {
						pkgversion = pkgname + j;
						sign = EQ;
						pkgversion[0] = '\0';
						pkgversion++;
						if (pkgversion[0] == '=') {
							pkgversion++;
							sign=EQ;
							j++;
						}
					}
				}
				j++;
			}
		}

		if (match != MATCH_ALL && pkgname[0] == '\0') {
			fprintf(stderr, "Pattern must not be empty.\n");
			i++;
			continue;
		}

		if ((it = pkgdb_query(db, pkgname, match)) == NULL) {
			goto cleanup;
		}

		/* this is place for compatibility hacks */

		/* ports infrastructure expects pkg info -q -O to
		 * always return 0 even if the ports doesn't exists */

		if (origin_search)
			gotone = true;

		/* end of compatibility hacks */

		/*
		 * only show full version in case of match glob with a
		 * single argument specified which does not contains
		 * any glob pattern
		 */
		if (argc == 1 && !origin_search && !quiet && !e_flag &&
		    match == MATCH_GLOB &&
		    strcspn(pkgname, "*[]{}()") == strlen(pkgname) &&
		    opt == INFO_TAG_NAMEVER)
			opt |= INFO_FULL;

		query_flags = info_flags(opt, false);
		while ((ret = pkgdb_it_next(it, &pkg, query_flags)) == EPKG_OK) {
			gotone = true;
			const char *version;

			pkg_get(pkg, PKG_VERSION, &version);
			if (pkgversion != NULL) {
				switch (pkg_version_cmp(version, pkgversion)) {
				case -1:
					if (sign != LT && sign != LE) {
						gotone = false;
						continue;
					}
					break;
				case 0:
					if (sign != LE &&
					    sign != GE &&
					    sign != EQ) {
						gotone = false;
						continue;
					}
					break;
				case 1:
					if (sign != GT && sign != GE) {
						gotone = false;
						continue;
					}
					break;
				}
			}
			if (pkgversion2 != NULL) {
				switch (pkg_version_cmp(version, pkgversion2)) {
				case -1:
					if (sign2 != LT && sign2 != LE) {
						gotone = false;
						continue;
					}
					break;
				case 0:
					if (sign2 != LE &&
					    sign2 != GE &&
					    sign2 != EQ) {
						gotone = false;
						continue;
					}
					break;
				case 1:
					if (sign2 != GT && sign2 != GE) {
						gotone = false;
						continue;
					}
					break;
				}
			}
			if (pkg_exists)
				retcode = EX_OK;
			else
				print_info(pkg, opt);
		}
		if (ret != EPKG_END) {
			retcode = EX_IOERR;
		}

		if (retcode == EX_OK && !gotone && match != MATCH_ALL) {
			if (!quiet)
				warnx("No package(s) matching %s", argv[i]);
			retcode = EX_SOFTWARE;
		}

		pkgdb_it_free(it);

		i++;
	} while (i < argc);

cleanup:
	pkg_free(pkg);

	pkgdb_release_lock(db, PKGDB_LOCK_READONLY);
	pkgdb_close(db);

	return (retcode);
}
示例#18
0
文件: uniq.c 项目: JabirTech/Source
int
main (int argc, char *argv[])
{
	wchar_t *tprev, *tthis;
	FILE *ifp, *ofp;
	int ch, comp;
	size_t prevbuflen, thisbuflen, b1;
	char *prevline, *thisline, *p;
	const char *ifn;
	cap_rights_t rights;

	(void) setlocale(LC_ALL, "");

	obsolete(argv);
	while ((ch = getopt(argc, argv, "cdif:s:u")) != -1)
		switch (ch) {
		case 'c':
			cflag = 1;
			break;
		case 'd':
			dflag = 1;
			break;
		case 'i':
			iflag = 1;
			break;
		case 'f':
			numfields = strtol(optarg, &p, 10);
			if (numfields < 0 || *p)
				errx(1, "illegal field skip value: %s", optarg);
			break;
		case 's':
			numchars = strtol(optarg, &p, 10);
			if (numchars < 0 || *p)
				errx(1, "illegal character skip value: %s", optarg);
			break;
		case 'u':
			uflag = 1;
			break;
		case '?':
		default:
			usage();
		}

	argc -= optind;
	argv += optind;

	/* If no flags are set, default is -d -u. */
	if (cflag) {
		if (dflag || uflag)
			usage();
	} else if (!dflag && !uflag)
		dflag = uflag = 1;

	if (argc > 2)
		usage();

	ifp = stdin;
	ifn = "stdin";
	ofp = stdout;
	if (argc > 0 && strcmp(argv[0], "-") != 0)
		ifp = file(ifn = argv[0], "r");
	cap_rights_init(&rights, CAP_FSTAT, CAP_READ);
	if (cap_rights_limit(fileno(ifp), &rights) < 0 && errno != ENOSYS)
		err(1, "unable to limit rights for %s", ifn);
	cap_rights_init(&rights, CAP_FSTAT, CAP_WRITE);
	if (argc > 1)
		ofp = file(argv[1], "w");
	else
		cap_rights_set(&rights, CAP_IOCTL);
	if (cap_rights_limit(fileno(ofp), &rights) < 0 && errno != ENOSYS) {
		err(1, "unable to limit rights for %s",
		    argc > 1 ? argv[1] : "stdout");
	}
	if (cap_rights_is_set(&rights, CAP_IOCTL)) {
		unsigned long cmd;

		cmd = TIOCGETA; /* required by isatty(3) in printf(3) */

		if (cap_ioctls_limit(fileno(ofp), &cmd, 1) < 0 &&
		    errno != ENOSYS) {
			err(1, "unable to limit ioctls for %s",
			    argc > 1 ? argv[1] : "stdout");
		}
	}

	strerror_init();
	if (cap_enter() < 0 && errno != ENOSYS)
		err(1, "unable to enter capability mode");

	prevbuflen = thisbuflen = 0;
	prevline = thisline = NULL;

	if (getline(&prevline, &prevbuflen, ifp) < 0) {
		if (ferror(ifp))
			err(1, "%s", ifn);
		exit(0);
	}
	tprev = convert(prevline);

	if (!cflag && uflag && dflag)
		show(ofp, prevline);

	tthis = NULL;
	while (getline(&thisline, &thisbuflen, ifp) >= 0) {
		if (tthis != NULL)
			free(tthis);
		tthis = convert(thisline);

		if (tthis == NULL && tprev == NULL)
			comp = inlcmp(thisline, prevline);
		else if (tthis == NULL || tprev == NULL)
			comp = 1;
		else
			comp = wcscoll(tthis, tprev);

		if (comp) {
			/* If different, print; set previous to new value. */
			if (cflag || !dflag || !uflag)
				show(ofp, prevline);
			p = prevline;
			b1 = prevbuflen;
			prevline = thisline;
			prevbuflen = thisbuflen;
			if (tprev != NULL)
				free(tprev);
			tprev = tthis;
			if (!cflag && uflag && dflag)
				show(ofp, prevline);
			thisline = p;
			thisbuflen = b1;
			tthis = NULL;
			repeats = 0;
		} else
			++repeats;
	}
	if (ferror(ifp))
		err(1, "%s", ifn);
	if (cflag || !dflag || !uflag)
		show(ofp, prevline);
	exit(0);
}
示例#19
0
int
main(int argc, char **argv)
{
	int ch, error, i, nbytes;
	bool ignore_type = false, show_label = false;
	char label[LABEL_LEN + 1], strvised[LABEL_LEN * 4 + 1];
	char *path;
	FILE *fp;
	fstyp_function fstyp_f;

	while ((ch = getopt(argc, argv, "ls")) != -1) {
		switch (ch) {
		case 'l':
			show_label = true;
			break;
		case 's':
			ignore_type = true;
			break;
		default:
			usage();
		}
	}

	argc -= optind;
	argv += optind;
	if (argc != 1)
		usage();

	path = argv[0];

	fp = fopen(path, "r");
	if (fp == NULL)
		err(1, "%s", path);

	error = cap_enter();
	if (error != 0 && errno != ENOSYS)
		err(1, "cap_enter");

	if (ignore_type == false)
		type_check(path, fp);

	memset(label, '\0', sizeof(label));

	for (i = 0;; i++) {
		fstyp_f = fstypes[i].function;
		if (fstyp_f == NULL)
			break;

		error = fstyp_f(fp, label, sizeof(label));
		if (error == 0)
			break;
	}

	if (fstypes[i].name == NULL) {
		warnx("%s: filesystem not recognized", path);
		return (1);
	}

	if (show_label && label[0] != '\0') {
		/*
		 * XXX: I'd prefer VIS_HTTPSTYLE, but it unconditionally
		 *      encodes spaces.
		 */
		nbytes = strsnvis(strvised, sizeof(strvised), label,
		    VIS_GLOB | VIS_NL, "\"'$");
		if (nbytes == -1)
			err(1, "strsnvis");

		printf("%s %s\n", fstypes[i].name, strvised);
	} else {
		printf("%s\n", fstypes[i].name);
	}

	return (0);
}
示例#20
0
文件: subr.c 项目: coyizumi/cs111
int
drop_privs(const struct hast_resource *res)
{
    char jailhost[sizeof(res->hr_name) * 2];
    struct jail jailst;
    struct passwd *pw;
    uid_t ruid, euid, suid;
    gid_t rgid, egid, sgid;
    gid_t gidset[1];
    bool capsicum, jailed;

    /*
     * According to getpwnam(3) we have to clear errno before calling the
     * function to be able to distinguish between an error and missing
     * entry (with is not treated as error by getpwnam(3)).
     */
    errno = 0;
    pw = getpwnam(HAST_USER);
    if (pw == NULL) {
        if (errno != 0) {
            pjdlog_errno(LOG_ERR,
                         "Unable to find info about '%s' user", HAST_USER);
            return (-1);
        } else {
            pjdlog_error("'%s' user doesn't exist.", HAST_USER);
            errno = ENOENT;
            return (-1);
        }
    }

    bzero(&jailst, sizeof(jailst));
    jailst.version = JAIL_API_VERSION;
    jailst.path = pw->pw_dir;
    if (res == NULL) {
        (void)snprintf(jailhost, sizeof(jailhost), "hastctl");
    } else {
        (void)snprintf(jailhost, sizeof(jailhost), "hastd: %s (%s)",
                       res->hr_name, role2str(res->hr_role));
    }
    jailst.hostname = jailhost;
    jailst.jailname = NULL;
    jailst.ip4s = 0;
    jailst.ip4 = NULL;
    jailst.ip6s = 0;
    jailst.ip6 = NULL;
    if (jail(&jailst) >= 0) {
        jailed = true;
    } else {
        jailed = false;
        pjdlog_errno(LOG_WARNING,
                     "Unable to jail to directory to %s", pw->pw_dir);
        if (chroot(pw->pw_dir) == -1) {
            pjdlog_errno(LOG_ERR,
                         "Unable to change root directory to %s",
                         pw->pw_dir);
            return (-1);
        }
    }
    PJDLOG_VERIFY(chdir("/") == 0);
    gidset[0] = pw->pw_gid;
    if (setgroups(1, gidset) == -1) {
        pjdlog_errno(LOG_ERR, "Unable to set groups to gid %u",
                     (unsigned int)pw->pw_gid);
        return (-1);
    }
    if (setgid(pw->pw_gid) == -1) {
        pjdlog_errno(LOG_ERR, "Unable to set gid to %u",
                     (unsigned int)pw->pw_gid);
        return (-1);
    }
    if (setuid(pw->pw_uid) == -1) {
        pjdlog_errno(LOG_ERR, "Unable to set uid to %u",
                     (unsigned int)pw->pw_uid);
        return (-1);
    }

#ifdef HAVE_CAPSICUM
    capsicum = (cap_enter() == 0);
    if (!capsicum) {
        pjdlog_common(LOG_DEBUG, 1, errno,
                      "Unable to sandbox using capsicum");
    } else if (res != NULL) {
        cap_rights_t rights;
        static const unsigned long geomcmds[] = {
            DIOCGDELETE,
            DIOCGFLUSH
        };

        PJDLOG_ASSERT(res->hr_role == HAST_ROLE_PRIMARY ||
                      res->hr_role == HAST_ROLE_SECONDARY);

        cap_rights_init(&rights, CAP_FLOCK, CAP_IOCTL, CAP_PREAD,
                        CAP_PWRITE);
        if (cap_rights_limit(res->hr_localfd, &rights) == -1) {
            pjdlog_errno(LOG_ERR,
                         "Unable to limit capability rights on local descriptor");
        }
        if (cap_ioctls_limit(res->hr_localfd, geomcmds,
                             sizeof(geomcmds) / sizeof(geomcmds[0])) == -1) {
            pjdlog_errno(LOG_ERR,
                         "Unable to limit allowed GEOM ioctls");
        }

        if (res->hr_role == HAST_ROLE_PRIMARY) {
            static const unsigned long ggatecmds[] = {
                G_GATE_CMD_MODIFY,
                G_GATE_CMD_START,
                G_GATE_CMD_DONE,
                G_GATE_CMD_DESTROY
            };

            cap_rights_init(&rights, CAP_IOCTL);
            if (cap_rights_limit(res->hr_ggatefd, &rights) == -1) {
                pjdlog_errno(LOG_ERR,
                             "Unable to limit capability rights to CAP_IOCTL on ggate descriptor");
            }
            if (cap_ioctls_limit(res->hr_ggatefd, ggatecmds,
                                 sizeof(ggatecmds) / sizeof(ggatecmds[0])) == -1) {
                pjdlog_errno(LOG_ERR,
                             "Unable to limit allowed ggate ioctls");
            }
        }
    }
#else
    capsicum = false;
#endif

    /*
     * Better be sure that everything succeeded.
     */
    PJDLOG_VERIFY(getresuid(&ruid, &euid, &suid) == 0);
    PJDLOG_VERIFY(ruid == pw->pw_uid);
    PJDLOG_VERIFY(euid == pw->pw_uid);
    PJDLOG_VERIFY(suid == pw->pw_uid);
    PJDLOG_VERIFY(getresgid(&rgid, &egid, &sgid) == 0);
    PJDLOG_VERIFY(rgid == pw->pw_gid);
    PJDLOG_VERIFY(egid == pw->pw_gid);
    PJDLOG_VERIFY(sgid == pw->pw_gid);
    PJDLOG_VERIFY(getgroups(0, NULL) == 1);
    PJDLOG_VERIFY(getgroups(1, gidset) == 1);
    PJDLOG_VERIFY(gidset[0] == pw->pw_gid);

    pjdlog_debug(1,
                 "Privileges successfully dropped using %s%s+setgid+setuid.",
                 capsicum ? "capsicum+" : "", jailed ? "jail" : "chroot");

    return (0);
}
示例#21
0
文件: rwho.c 项目: ChaosJohn/freebsd
int
main(int argc, char *argv[])
{
	int ch;
	struct dirent *dp;
	int width;
	ssize_t cc;
	struct whod *w;
	struct whoent *we;
	struct myutmp *mp;
	cap_rights_t rights;
	int f, n, i;
	int d_first;
	int dfd;
	time_t ct;

	w = &wd;
	(void) setlocale(LC_TIME, "");
	d_first = (*nl_langinfo(D_MD_ORDER) == 'd');

	while ((ch = getopt(argc, argv, "a")) != -1) {
		switch ((char)ch) {
		case 'a':
			aflg = 1;
			break;
		case '?':
		default:
			usage();
		}
	}
	argc -= optind;
	argv += optind;

	if (argc != 0)
		usage();

	if (chdir(_PATH_RWHODIR) < 0)
		err(1, "chdir(%s)", _PATH_RWHODIR);
	if ((dirp = opendir(".")) == NULL)
		err(1, "opendir(%s)", _PATH_RWHODIR);
	dfd = dirfd(dirp);
	mp = myutmp;
	cap_rights_init(&rights, CAP_READ, CAP_LOOKUP);
	if (cap_rights_limit(dfd, &rights) < 0 && errno != ENOSYS)
		err(1, "cap_rights_limit failed: %s", _PATH_RWHODIR);
	/*
	 * Cache files required for time(3) and localtime(3) before entering
	 * capability mode.
	 */
	(void) time(&ct);
	(void) localtime(&ct);
	if (cap_enter() < 0 && errno != ENOSYS)
		err(1, "cap_enter");
	(void) time(&now);
	cap_rights_init(&rights, CAP_READ);
	while ((dp = readdir(dirp)) != NULL) {
		if (dp->d_ino == 0 || strncmp(dp->d_name, "whod.", 5) != 0)
			continue;
		f = openat(dfd, dp->d_name, O_RDONLY);
		if (f < 0)
			continue;
		if (cap_rights_limit(f, &rights) < 0 && errno != ENOSYS)
			err(1, "cap_rights_limit failed: %s", dp->d_name);
		cc = read(f, (char *)&wd, sizeof(struct whod));
		if (cc < WHDRSIZE) {
			(void) close(f);
			continue;
		}
		if (down(w, now) != 0) {
			(void) close(f);
			continue;
		}
		cc -= WHDRSIZE;
		we = w->wd_we;
		for (n = cc / sizeof(struct whoent); n > 0; n--) {
			if (aflg == 0 && we->we_idle >= 60 * 60) {
				we++;
				continue;
			}
			if (nusers >= NUSERS)
				errx(1, "too many users");
			mp->myutmp = we->we_utmp;
			mp->myidle = we->we_idle;
			(void) strcpy(mp->myhost, w->wd_hostname);
			nusers++;
			we++;
			mp++;
		}
		(void) close(f);
	}
	qsort((char *)myutmp, nusers, sizeof(struct myutmp), utmpcmp);
	mp = myutmp;
	width = 0;
	for (i = 0; i < nusers; i++) {
		/* append one for the blank and use 8 for the out_line */
		int j;

		j = strlen(mp->myhost) + 1 + sizeof(mp->myutmp.out_line);
		if (j > width)
			width = j;
		mp++;
	}
	mp = myutmp;
	for (i = 0; i < nusers; i++) {
		char buf[BUFSIZ], cbuf[80];
		time_t t;

		t = _int_to_time(mp->myutmp.out_time);
		strftime(cbuf, sizeof(cbuf), d_first ? "%e %b %R" : "%b %e %R",
		    localtime(&t));
		(void) sprintf(buf, "%s:%-.*s", mp->myhost,
		    (int)sizeof(mp->myutmp.out_line), mp->myutmp.out_line);
		printf("%-*.*s %-*s %s",
		    (int)sizeof(mp->myutmp.out_name),
		    (int)sizeof(mp->myutmp.out_name),
		    mp->myutmp.out_name, width, buf, cbuf);
		mp->myidle /= 60;
		if (mp->myidle != 0) {
			if (aflg != 0) {
				if (mp->myidle >= 100 * 60)
					mp->myidle = 100 * 60 - 1;
				if (mp->myidle >= 60)
					printf(" %2d", mp->myidle / 60);
				else
					printf("   ");
			} else {
				printf(" ");
			}
			printf(":%02d", mp->myidle % 60);
		}
		printf("\n");
		mp++;
	}
	exit(0);
}
示例#22
0
int
main(int argc, char **argv)
{
	const char *setfilenames[MAX_DS - 1];
	struct dataset *ds[MAX_DS - 1];
	FILE *setfiles[MAX_DS - 1];
	int nds;
	double a;
	const char *delim = " \t";
	char *p;
	int c, i, ci;
	int column = 1;
	int flag_s = 0;
	int flag_n = 0;
	int termwidth = 74;
	int suppress_plot = 0;

	if (isatty(STDOUT_FILENO)) {
		struct winsize wsz;

		if ((p = getenv("COLUMNS")) != NULL && *p != '\0')
			termwidth = atoi(p);
		else if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &wsz) != -1 &&
			 wsz.ws_col > 0)
			termwidth = wsz.ws_col - 2;
	}

	ci = -1;
	while ((c = getopt(argc, argv, "AC:c:d:snw:")) != -1)
		switch (c) {
		case 'A':
			suppress_plot = 1;
			break;
		case 'C':
			column = strtol(optarg, &p, 10);
			if (p != NULL && *p != '\0')
				usage("Invalid column number.");
			if (column <= 0)
				usage("Column number should be positive.");
			break;
		case 'c':
			a = strtod(optarg, &p);
			if (p != NULL && *p != '\0')
				usage("Not a floating point number");
			for (i = 0; i < NCONF; i++)
				if (a == studentpct[i])
					ci = i;
			if (ci == -1)
				usage("No support for confidence level");
			break;
		case 'd':
			if (*optarg == '\0')
				usage("Can't use empty delimiter string");
			delim = optarg;
			break;
		case 'n':
			flag_n = 1;
			break;
		case 's':
			flag_s = 1;
			break;
		case 'w':
			termwidth = strtol(optarg, &p, 10);
			if (p != NULL && *p != '\0')
				usage("Invalid width, not a number.");
			if (termwidth < 0)
				usage("Unable to move beyond left margin.");
			break;
		default:
			usage("Unknown option");
			break;
		}
	if (ci == -1)
		ci = 2;
	argc -= optind;
	argv += optind;

	if (argc == 0) {
		setfilenames[0] = "<stdin>";
		setfiles[0] = stdin;
		nds = 1;
	} else {
		if (argc > (MAX_DS - 1))
			usage("Too many datasets.");
		nds = argc;
		for (i = 0; i < nds; i++) {
			setfilenames[i] = argv[i];
			setfiles[i] = fopen(argv[i], "r");
			if (setfiles[i] == NULL)
				err(2, "Cannot open %s", argv[i]);
		}
	}

	if (caph_limit_stdio() < 0)
		err(2, "capsicum");

	for (i = 0; i < nds; i++)
		if (caph_limit_stream(fileno(setfiles[i]), CAPH_READ) < 0)
			err(2, "unable to limit rights for %s",
			    setfilenames[i]);

	/* Enter Capsicum sandbox. */
	if (cap_enter() < 0 && errno != ENOSYS)
		err(2, "unable to enter capability mode");

	for (i = 0; i < nds; i++) {
		ds[i] = ReadSet(setfiles[i], setfilenames[i], column, delim);
		fclose(setfiles[i]);
	}

	for (i = 0; i < nds; i++) 
		printf("%c %s\n", symbol[i+1], ds[i]->name);

	if (!flag_n && !suppress_plot) {
		SetupPlot(termwidth, flag_s, nds);
		for (i = 0; i < nds; i++)
			DimPlot(ds[i]);
		for (i = 0; i < nds; i++)
			PlotSet(ds[i], i + 1);
		DumpPlot();
	}
	VitalsHead();
	Vitals(ds[0], 1);
	for (i = 1; i < nds; i++) {
		Vitals(ds[i], i + 1);
		if (!flag_n)
			Relative(ds[i], ds[0], ci);
	}
	exit(0);
}
示例#23
0
int
main(int argc, char *argv[])
{
	int nflag;	/* if not set, output a trailing newline. */
	int veclen;	/* number of writev arguments. */
	struct iovec *iov, *vp; /* Elements to write, current element. */
	char space[] = " ";
	char newline[] = "\n";
	char *progname = argv[0];

	if (caph_limit_stdio() < 0 || (cap_enter() < 0 && errno != ENOSYS))
		err(1, "capsicum");

	/* This utility may NOT do getopt(3) option parsing. */
	if (*++argv && !strcmp(*argv, "-n")) {
		++argv;
		--argc;
		nflag = 1;
	} else
		nflag = 0;

	veclen = (argc >= 2) ? (argc - 2) * 2 + 1 : 0;

	if ((vp = iov = malloc((veclen + 1) * sizeof(struct iovec))) == NULL)
		errexit(progname, "malloc");

	while (argv[0] != NULL) {
		size_t len;
		
		len = strlen(argv[0]);

		/*
		 * If the next argument is NULL then this is this
		 * the last argument, therefore we need to check
		 * for a trailing \c.
		 */
		if (argv[1] == NULL) {
			/* is there room for a '\c' and is there one? */
			if (len >= 2 &&
			    argv[0][len - 2] == '\\' &&
			    argv[0][len - 1] == 'c') {
				/* chop it and set the no-newline flag. */
				len -= 2;
				nflag = 1;
			}
		}
		vp->iov_base = *argv;
		vp++->iov_len = len;
		if (*++argv) {
			vp->iov_base = space;
			vp++->iov_len = 1;
		}
	}
	if (!nflag) {
		veclen++;
		vp->iov_base = newline;
		vp++->iov_len = 1;
	}
	/* assert(veclen == (vp - iov)); */
	while (veclen) {
		int nwrite;

		nwrite = (veclen > IOV_MAX) ? IOV_MAX : veclen;
		if (writev(STDOUT_FILENO, iov, nwrite) == -1)
			errexit(progname, "write");
		iov += nwrite;
		veclen -= nwrite;
	}
	return 0;
}
示例#24
0
int
main(int argc, char **argv)
{
	int ch;
	int i;
#ifdef HAVE_CAP_ENTER
	int retval;
	pid_t childpid, pid;
#endif
	FILE *fp;

	while ((ch = getopt(argc, argv, "d:lnprsx")) != -1) {
		switch(ch) {
		case 'd':
			del = optarg;
			break;

		case 'l':
			oneline = 1;
			break;

		case 'n':
			oflags |= AU_OFLAG_NORESOLVE;
			break;

		case 'p':
			partial = 1;
			break;

		case 'r':
			if (oflags & AU_OFLAG_SHORT)
				usage();	/* Exclusive from shortfrm. */
			oflags |= AU_OFLAG_RAW;
			break;

		case 's':
			if (oflags & AU_OFLAG_RAW)
				usage();	/* Exclusive from raw. */
			oflags |= AU_OFLAG_SHORT;
			break;

		case 'x':
			oflags |= AU_OFLAG_XML;
			break;

		case '?':
		default:
			usage();
		}
	}

#ifdef HAVE_CAP_ENTER
	/*
	 * Prime group, password, and audit-event files to be opened before we
	 * enter capability mode.
	 */
	(void)getgrgid(0);
	(void)setgroupent(1);
	(void)getpwuid(0);
	(void)setpassent(1);
	(void)getauevent();
#endif

	if (oflags & AU_OFLAG_XML)
		au_print_xml_header(stdout);

	/* For each of the files passed as arguments dump the contents. */
	if (optind == argc) {
#ifdef HAVE_CAP_ENTER
		retval = cap_enter();
		if (retval != 0 && errno != ENOSYS)
			err(EXIT_FAILURE, "cap_enter");
#endif
		print_tokens(stdin);
		return (1);
	}
	for (i = optind; i < argc; i++) {
		fp = fopen(argv[i], "r");
		if (fp == NULL) {
			perror(argv[i]);
			continue;
		}

		/*
		 * If operating with sandboxing, create a sandbox process for
		 * each trail file we operate on.  This avoids the need to do
		 * fancy things with file descriptors, etc, when iterating on
		 * a list of arguments.
		 */
#ifdef HAVE_CAP_ENTER
		childpid = fork();
		if (childpid == 0) {
			/* Child. */
			retval = cap_enter();
			if (retval != 0 && errno != ENOSYS)
				err(EXIT_FAILURE, "cap_enter");
			if (print_tokens(fp) == -1)
				perror(argv[i]);
			exit(0);
		}

		/* Parent.  Await child termination. */
		while ((pid = waitpid(childpid, NULL, 0)) != childpid);
#else
		if (print_tokens(fp) == -1)
			perror(argv[i]);
#endif
		fclose(fp);
	}

	if (oflags & AU_OFLAG_XML)
		au_print_xml_footer(stdout);

	return (0);
}
示例#25
0
文件: upgrade.c 项目: Absolight/pkg
static void
check_vulnerable(struct pkg_audit *audit, struct pkgdb *db, int sock)
{
	struct pkgdb_it	*it = NULL;
	struct pkg		*pkg = NULL;
	kh_pkgs_t		*check = NULL;
	const char		*uid;
	UT_string		*sb;
	int				ret;
	FILE			*out;

	out = fdopen(sock, "w");
	if (out == NULL) {
		warn("unable to open stream");
		return;
	}

	if ((it = pkgdb_query(db, NULL, MATCH_ALL)) == NULL) {
		warnx("Error accessing the package database");
		pkg_audit_free(audit);
		fclose(out);
		return;
	}
	else {
		check = kh_init_pkgs();

		while ((ret = pkgdb_it_next(it, &pkg, PKG_LOAD_BASIC|PKG_LOAD_RDEPS))
				== EPKG_OK) {
			add_to_check(check, pkg);
			pkg = NULL;
		}

		ret = EX_OK;
	}

	if (db != NULL) {
		pkgdb_it_free(it);
		pkgdb_close(db);
	}

	if (ret != EX_OK) {
		pkg_audit_free(audit);
		kh_destroy_pkgs(check);
		fclose(out);
		return;
	}

	drop_privileges();

	if (pkg_audit_load(audit, NULL) != EPKG_OK) {
		warn("unable to open vulnxml file");
		fclose(out);
		pkg_audit_free(audit);
		return;
	}

#ifdef HAVE_CAPSICUM
	if (cap_enter() < 0 && errno != ENOSYS) {
		warn("cap_enter() failed");
		pkg_audit_free(audit);
		kh_destroy_pkgs(check);
		fclose(out);
		return;
	}
#endif

	if (pkg_audit_process(audit) == EPKG_OK) {
		kh_foreach_value(check, pkg, {
				if (pkg_audit_is_vulnerable(audit, pkg, true, &sb)) {
					pkg_get(pkg, PKG_UNIQUEID, &uid);
					fprintf(out, "%s\n", uid);
					fflush(out);
					utstring_free(sb);
				}
				pkg_free(pkg);
		});
示例#26
0
int
main(int argc, char **argv)
{
	bool quiet = false;
	int ch, i, *fds, fd;
	int ret = EXIT_SUCCESS;
	size_t nfds;
	FILE *fp;

	while ((ch = getopt(argc, argv, "qV")) != -1) {
		switch (ch) {
		case 'q':
			quiet = true;
			break;
		case 'V':
			/* Do nothing, compat with GNU rcs's ident */
			return (EXIT_SUCCESS);
		default:
			errx(EXIT_FAILURE, "usage: %s [-q] [-V] [file...]",
			    getprogname());
		}
	}

	argc -= optind;
	argv += optind;

	if (caph_limit_stdio() < 0)
		err(EXIT_FAILURE, "unable to limit stdio");

	if (argc == 0) {
		nfds = 1;
		fds = malloc(sizeof(*fds));
		if (fds == NULL)
			err(EXIT_FAILURE, "unable to allocate fds array");
		fds[0] = STDIN_FILENO;
	} else {
		nfds = argc;
		fds = malloc(sizeof(*fds) * nfds);
		if (fds == NULL)
			err(EXIT_FAILURE, "unable to allocate fds array");

		for (i = 0; i < argc; i++) {
			fds[i] = fd = open(argv[i], O_RDONLY);
			if (fd < 0) {
				warn("%s", argv[i]);
				ret = EXIT_FAILURE;
				continue;
			}
			if (caph_limit_stream(fd, CAPH_READ) < 0)
				err(EXIT_FAILURE,
				    "unable to limit fcntls/rights for %s",
				    argv[i]);
		}
	}

	/* Enter Capsicum sandbox. */
	if (cap_enter() < 0 && errno != ENOSYS)
		err(EXIT_FAILURE, "unable to enter capability mode");

	for (i = 0; i < (int)nfds; i++) {
		if (fds[i] < 0)
			continue;

		fp = fdopen(fds[i], "r");
		if (fp == NULL) {
			warn("%s", argv[i]);
			ret = EXIT_FAILURE;
			continue;
		}
		if (scan(fp, argc == 0 ? NULL : argv[i], quiet) != EXIT_SUCCESS)
			ret = EXIT_FAILURE;
		fclose(fp);
	}

	return (ret);
}
示例#27
0
int
main(int argc, char **argv)
{
    cap_rights_t rights;

    int         dec_ind;	/* current indentation for declarations */
    int         di_stack[20];	/* a stack of structure indentation levels */
    int         force_nl;	/* when true, code must be broken */
    int         hd_type = 0;	/* used to store type of stmt for if (...),
				 * for (...), etc */
    int		i;		/* local loop counter */
    int         scase;		/* set to true when we see a case, so we will
				 * know what to do with the following colon */
    int         sp_sw;		/* when true, we are in the expression of
				 * if(...), while(...), etc. */
    int         squest;		/* when this is positive, we have seen a ?
				 * without the matching : in a <c>?<s>:<s>
				 * construct */
    const char *t_ptr;		/* used for copying tokens */
    int		tabs_to_var;	/* true if using tabs to indent to var name */
    int         type_code;	/* the type of token, returned by lexi */

    int         last_else = 0;	/* true iff last keyword was an else */
    const char *profile_name = NULL;
    const char *envval = NULL;
    struct parser_state transient_state; /* a copy for lookup */

    /*-----------------------------------------------*\
    |		      INITIALIZATION		      |
    \*-----------------------------------------------*/

    found_err = 0;

    ps.p_stack[0] = stmt;	/* this is the parser's stack */
    ps.last_nl = true;		/* this is true if the last thing scanned was
				 * a newline */
    ps.last_token = semicolon;
    combuf = (char *) malloc(bufsize);
    if (combuf == NULL)
	err(1, NULL);
    labbuf = (char *) malloc(bufsize);
    if (labbuf == NULL)
	err(1, NULL);
    codebuf = (char *) malloc(bufsize);
    if (codebuf == NULL)
	err(1, NULL);
    tokenbuf = (char *) malloc(bufsize);
    if (tokenbuf == NULL)
	err(1, NULL);
    alloc_typenames();
    l_com = combuf + bufsize - 5;
    l_lab = labbuf + bufsize - 5;
    l_code = codebuf + bufsize - 5;
    l_token = tokenbuf + bufsize - 5;
    combuf[0] = codebuf[0] = labbuf[0] = ' ';	/* set up code, label, and
						 * comment buffers */
    combuf[1] = codebuf[1] = labbuf[1] = '\0';
    ps.else_if = 1;		/* Default else-if special processing to on */
    s_lab = e_lab = labbuf + 1;
    s_code = e_code = codebuf + 1;
    s_com = e_com = combuf + 1;
    s_token = e_token = tokenbuf + 1;

    in_buffer = (char *) malloc(10);
    if (in_buffer == NULL)
	err(1, NULL);
    in_buffer_limit = in_buffer + 8;
    buf_ptr = buf_end = in_buffer;
    line_no = 1;
    had_eof = ps.in_decl = ps.decl_on_line = break_comma = false;
    sp_sw = force_nl = false;
    ps.in_or_st = false;
    ps.bl_line = true;
    dec_ind = 0;
    di_stack[ps.dec_nest = 0] = 0;
    ps.want_blank = ps.in_stmt = ps.ind_stmt = false;

    scase = ps.pcase = false;
    squest = 0;
    sc_end = NULL;
    bp_save = NULL;
    be_save = NULL;

    output = NULL;
    tabs_to_var = 0;

    envval = getenv("SIMPLE_BACKUP_SUFFIX");
    if (envval)
        simple_backup_suffix = envval;

    /*--------------------------------------------------*\
    |   		COMMAND LINE SCAN		 |
    \*--------------------------------------------------*/

#ifdef undef
    max_col = 78;		/* -l78 */
    lineup_to_parens = 1;	/* -lp */
    lineup_to_parens_always = 0;	/* -nlpl */
    ps.ljust_decl = 0;		/* -ndj */
    ps.com_ind = 33;		/* -c33 */
    star_comment_cont = 1;	/* -sc */
    ps.ind_size = 8;		/* -i8 */
    verbose = 0;
    ps.decl_indent = 16;	/* -di16 */
    ps.local_decl_indent = -1;	/* if this is not set to some nonnegative value
				 * by an arg, we will set this equal to
				 * ps.decl_ind */
    ps.indent_parameters = 1;	/* -ip */
    ps.decl_com_ind = 0;	/* if this is not set to some positive value
				 * by an arg, we will set this equal to
				 * ps.com_ind */
    btype_2 = 1;		/* -br */
    cuddle_else = 1;		/* -ce */
    ps.unindent_displace = 0;	/* -d0 */
    ps.case_indent = 0;		/* -cli0 */
    format_block_comments = 1;	/* -fcb */
    format_col1_comments = 1;	/* -fc1 */
    procnames_start_line = 1;	/* -psl */
    proc_calls_space = 0;	/* -npcs */
    comment_delimiter_on_blankline = 1;	/* -cdb */
    ps.leave_comma = 1;		/* -nbc */
#endif

    for (i = 1; i < argc; ++i)
	if (strcmp(argv[i], "-npro") == 0)
	    break;
	else if (argv[i][0] == '-' && argv[i][1] == 'P' && argv[i][2] != '\0')
	    profile_name = argv[i];	/* non-empty -P (set profile) */
    set_defaults();
    if (i >= argc)
	set_profile(profile_name);

    for (i = 1; i < argc; ++i) {

	/*
	 * look thru args (if any) for changes to defaults
	 */
	if (argv[i][0] != '-') {/* no flag on parameter */
	    if (input == NULL) {	/* we must have the input file */
		in_name = argv[i];	/* remember name of input file */
		input = fopen(in_name, "r");
		if (input == NULL)	/* check for open error */
			err(1, "%s", in_name);
		continue;
	    }
	    else if (output == NULL) {	/* we have the output file */
		out_name = argv[i];	/* remember name of output file */
		if (strcmp(in_name, out_name) == 0) {	/* attempt to overwrite
							 * the file */
		    errx(1, "input and output files must be different");
		}
		output = fopen(out_name, "w");
		if (output == NULL)	/* check for create error */
			err(1, "%s", out_name);
		continue;
	    }
	    errx(1, "unknown parameter: %s", argv[i]);
	}
	else
	    set_option(argv[i]);
    }				/* end of for */
    if (input == NULL)
	input = stdin;
    if (output == NULL) {
	if (input == stdin)
	    output = stdout;
	else {
	    out_name = in_name;
	    bakcopy();
	}
    }

    /* Restrict input/output descriptors and enter Capsicum sandbox. */
    cap_rights_init(&rights, CAP_FSTAT, CAP_WRITE);
    if (cap_rights_limit(fileno(output), &rights) < 0 && errno != ENOSYS)
	err(EXIT_FAILURE, "unable to limit rights for %s", out_name);
    cap_rights_init(&rights, CAP_FSTAT, CAP_READ);
    if (cap_rights_limit(fileno(input), &rights) < 0 && errno != ENOSYS)
	err(EXIT_FAILURE, "unable to limit rights for %s", in_name);
    if (cap_enter() < 0 && errno != ENOSYS)
	err(EXIT_FAILURE, "unable to enter capability mode");

    if (ps.com_ind <= 1)
	ps.com_ind = 2;		/* dont put normal comments before column 2 */
    if (block_comment_max_col <= 0)
	block_comment_max_col = max_col;
    if (ps.local_decl_indent < 0)	/* if not specified by user, set this */
	ps.local_decl_indent = ps.decl_indent;
    if (ps.decl_com_ind <= 0)	/* if not specified by user, set this */
	ps.decl_com_ind = ps.ljust_decl ? (ps.com_ind <= 10 ? 2 : ps.com_ind - 8) : ps.com_ind;
    if (continuation_indent == 0)
	continuation_indent = ps.ind_size;
    fill_buffer();		/* get first batch of stuff into input buffer */

    parse(semicolon);
    {
	char *p = buf_ptr;
	int col = 1;

	while (1) {
	    if (*p == ' ')
		col++;
	    else if (*p == '\t')
		col = tabsize * (1 + (col - 1) / tabsize) + 1;
	    else
		break;
	    p++;
	}
	if (col > ps.ind_size)
	    ps.ind_level = ps.i_l_follow = col / ps.ind_size;
    }

    /*
     * START OF MAIN LOOP
     */

    while (1) {			/* this is the main loop.  it will go until we
				 * reach eof */
	int comment_buffered = false;

	type_code = lexi(&ps);	/* lexi reads one token.  The actual
				 * characters read are stored in "token". lexi
				 * returns a code indicating the type of token */

	/*
	 * The following code moves newlines and comments following an if (),
	 * while (), else, etc. up to the start of the following stmt to
	 * a buffer. This allows proper handling of both kinds of brace
	 * placement (-br, -bl) and cuddling "else" (-ce).
	 */

	while (ps.search_brace) {
	    switch (type_code) {
	    case newline:
		if (sc_end == NULL) {
		    save_com = sc_buf;
		    save_com[0] = save_com[1] = ' ';
		    sc_end = &save_com[2];
		}
		*sc_end++ = '\n';
		/*
		 * We may have inherited a force_nl == true from the previous
		 * token (like a semicolon). But once we know that a newline
		 * has been scanned in this loop, force_nl should be false.
		 *
		 * However, the force_nl == true must be preserved if newline
		 * is never scanned in this loop, so this assignment cannot be
		 * done earlier.
		 */
		force_nl = false;
	    case form_feed:
		break;
	    case comment:
		if (sc_end == NULL) {
		    /*
		     * Copy everything from the start of the line, because
		     * pr_comment() will use that to calculate original
		     * indentation of a boxed comment.
		     */
		    memcpy(sc_buf, in_buffer, buf_ptr - in_buffer - 4);
		    save_com = sc_buf + (buf_ptr - in_buffer - 4);
		    save_com[0] = save_com[1] = ' ';
		    sc_end = &save_com[2];
		}
		comment_buffered = true;
		*sc_end++ = '/';	/* copy in start of comment */
		*sc_end++ = '*';
		for (;;) {	/* loop until we get to the end of the comment */
		    *sc_end = *buf_ptr++;
		    if (buf_ptr >= buf_end)
			fill_buffer();
		    if (*sc_end++ == '*' && *buf_ptr == '/')
			break;	/* we are at end of comment */
		    if (sc_end >= &save_com[sc_size]) {	/* check for temp buffer
							 * overflow */
			diag2(1, "Internal buffer overflow - Move big comment from right after if, while, or whatever");
			fflush(output);
			exit(1);
		    }
		}
		*sc_end++ = '/';	/* add ending slash */
		if (++buf_ptr >= buf_end)	/* get past / in buffer */
		    fill_buffer();
		break;
	    case lbrace:
		/*
		 * Put KNF-style lbraces before the buffered up tokens and
		 * jump out of this loop in order to avoid copying the token
		 * again under the default case of the switch below.
		 */
		if (sc_end != NULL && btype_2) {
		    save_com[0] = '{';
		    /*
		     * Originally the lbrace may have been alone on its own
		     * line, but it will be moved into "the else's line", so
		     * if there was a newline resulting from the "{" before,
		     * it must be scanned now and ignored.
		     */
		    while (isspace((unsigned char)*buf_ptr)) {
			if (++buf_ptr >= buf_end)
			    fill_buffer();
			if (*buf_ptr == '\n')
			    break;
		    }
		    goto sw_buffer;
		}
		/* FALLTHROUGH */
	    default:		/* it is the start of a normal statement */
		{
		    int remove_newlines;

		    remove_newlines =
			/* "} else" */
			(type_code == sp_nparen && *token == 'e' &&
			    e_code != s_code && e_code[-1] == '}')
			/* "else if" */
			|| (type_code == sp_paren && *token == 'i' &&
			    last_else && ps.else_if);
		    if (remove_newlines)
			force_nl = false;
		    if (sc_end == NULL) {	/* ignore buffering if
						 * comment wasn't saved up */
			ps.search_brace = false;
			goto check_type;
		    }
		    while (sc_end > save_com && isblank((unsigned char)sc_end[-1])) {
			sc_end--;
		    }
		    if (swallow_optional_blanklines ||
			(!comment_buffered && remove_newlines)) {
			force_nl = !remove_newlines;
			while (sc_end > save_com && sc_end[-1] == '\n') {
			    sc_end--;
			}
		    }
		    if (force_nl) {	/* if we should insert a nl here, put
					 * it into the buffer */
			force_nl = false;
			--line_no;	/* this will be re-increased when the
					 * newline is read from the buffer */
			*sc_end++ = '\n';
			*sc_end++ = ' ';
			if (verbose)	/* print error msg if the line was
					 * not already broken */
			    diag2(0, "Line broken");
		    }
		    for (t_ptr = token; *t_ptr; ++t_ptr)
			*sc_end++ = *t_ptr;

	    sw_buffer:
		    ps.search_brace = false;	/* stop looking for start of
						 * stmt */
		    bp_save = buf_ptr;	/* save current input buffer */
		    be_save = buf_end;
		    buf_ptr = save_com;	/* fix so that subsequent calls to
					 * lexi will take tokens out of
					 * save_com */
		    *sc_end++ = ' ';/* add trailing blank, just in case */
		    buf_end = sc_end;
		    sc_end = NULL;
		    break;
		}
	    }			/* end of switch */
	    /*
	     * We must make this check, just in case there was an unexpected
	     * EOF.
	     */
	    if (type_code != 0) {
		/*
		 * The only intended purpose of calling lexi() below is to
		 * categorize the next token in order to decide whether to
		 * continue buffering forthcoming tokens. Once the buffering
		 * is over, lexi() will be called again elsewhere on all of
		 * the tokens - this time for normal processing.
		 *
		 * Calling it for this purpose is a bug, because lexi() also
		 * changes the parser state and discards leading whitespace,
		 * which is needed mostly for comment-related considerations.
		 *
		 * Work around the former problem by giving lexi() a copy of
		 * the current parser state and discard it if the call turned
		 * out to be just a look ahead.
		 *
		 * Work around the latter problem by copying all whitespace
		 * characters into the buffer so that the later lexi() call
		 * will read them.
		 */
		if (sc_end != NULL) {
		    while (*buf_ptr == ' ' || *buf_ptr == '\t') {
			*sc_end++ = *buf_ptr++;
			if (sc_end >= &save_com[sc_size]) {
			    errx(1, "input too long");
			}
		    }
		    if (buf_ptr >= buf_end) {
			fill_buffer();
		    }
		}
		transient_state = ps;
		type_code = lexi(&transient_state);	/* read another token */
		if (type_code != newline && type_code != form_feed &&
		    type_code != comment && !transient_state.search_brace) {
		    ps = transient_state;
		}
	    }
	}			/* end of while (search_brace) */
	last_else = 0;
check_type:
	if (type_code == 0) {	/* we got eof */
	    if (s_lab != e_lab || s_code != e_code
		    || s_com != e_com)	/* must dump end of line */
		dump_line();
	    if (ps.tos > 1)	/* check for balanced braces */
		diag2(1, "Stuff missing from end of file");

	    if (verbose) {
		printf("There were %d output lines and %d comments\n",
		       ps.out_lines, ps.out_coms);
		printf("(Lines with comments)/(Lines with code): %6.3f\n",
		       (1.0 * ps.com_lines) / code_lines);
	    }
	    fflush(output);
	    exit(found_err);
	}
	if (
		(type_code != comment) &&
		(type_code != newline) &&
		(type_code != preesc) &&
		(type_code != form_feed)) {
	    if (force_nl &&
		    (type_code != semicolon) &&
		    (type_code != lbrace || !btype_2)) {
		/* we should force a broken line here */
		if (verbose)
		    diag2(0, "Line broken");
		dump_line();
		ps.want_blank = false;	/* dont insert blank at line start */
		force_nl = false;
	    }
	    ps.in_stmt = true;	/* turn on flag which causes an extra level of
				 * indentation. this is turned off by a ; or
				 * '}' */
	    if (s_com != e_com) {	/* the turkey has embedded a comment
					 * in a line. fix it */
		int len = e_com - s_com;

		CHECK_SIZE_CODE(len + 3);
		*e_code++ = ' ';
		memcpy(e_code, s_com, len);
		e_code += len;
		*e_code++ = ' ';
		*e_code = '\0';	/* null terminate code sect */
		ps.want_blank = false;
		e_com = s_com;
	    }
	}
	else if (type_code != comment)	/* preserve force_nl thru a comment */
	    force_nl = false;	/* cancel forced newline after newline, form
				 * feed, etc */



	/*-----------------------------------------------------*\
	|	   do switch on type of token scanned		|
	\*-----------------------------------------------------*/
	CHECK_SIZE_CODE(3);	/* maximum number of increments of e_code
				 * before the next CHECK_SIZE_CODE or
				 * dump_line() is 2. After that there's the
				 * final increment for the null character. */
	switch (type_code) {	/* now, decide what to do with the token */

	case form_feed:	/* found a form feed in line */
	    ps.use_ff = true;	/* a form feed is treated much like a newline */
	    dump_line();
	    ps.want_blank = false;
	    break;

	case newline:
	    if (ps.last_token != comma || ps.p_l_follow > 0
		    || !ps.leave_comma || ps.block_init || !break_comma || s_com != e_com) {
		dump_line();
		ps.want_blank = false;
	    }
	    ++line_no;		/* keep track of input line number */
	    break;

	case lparen:		/* got a '(' or '[' */
	    /* count parens to make Healy happy */
	    if (++ps.p_l_follow == nitems(ps.paren_indents)) {
		diag3(0, "Reached internal limit of %d unclosed parens",
		    nitems(ps.paren_indents));
		ps.p_l_follow--;
	    }
	    if (*token == '[')
		/* not a function pointer declaration or a function call */;
	    else if (ps.in_decl && !ps.block_init && !ps.dumped_decl_indent &&
		ps.procname[0] == '\0' && ps.paren_level == 0) {
		/* function pointer declarations */
		indent_declaration(dec_ind, tabs_to_var);
		ps.dumped_decl_indent = true;
	    }
	    else if (ps.want_blank &&
		    ((ps.last_token != ident && ps.last_token != funcname) ||
		    proc_calls_space ||
		    /* offsetof (1) is never allowed a space; sizeof (2) gets
		     * one iff -bs; all other keywords (>2) always get a space
		     * before lparen */
			ps.keyword + Bill_Shannon > 2))
		*e_code++ = ' ';
	    ps.want_blank = false;
	    *e_code++ = token[0];
	    ps.paren_indents[ps.p_l_follow - 1] = count_spaces_until(1, s_code, e_code) - 1;
	    if (sp_sw && ps.p_l_follow == 1 && extra_expression_indent
		    && ps.paren_indents[0] < 2 * ps.ind_size)
		ps.paren_indents[0] = 2 * ps.ind_size;
	    if (ps.in_or_st && *token == '(' && ps.tos <= 2) {
		/*
		 * this is a kluge to make sure that declarations will be
		 * aligned right if proc decl has an explicit type on it, i.e.
		 * "int a(x) {..."
		 */
		parse(semicolon);	/* I said this was a kluge... */
		ps.in_or_st = false;	/* turn off flag for structure decl or
					 * initialization */
	    }
	    /* parenthesized type following sizeof or offsetof is not a cast */
	    if (ps.keyword == 1 || ps.keyword == 2)
		ps.not_cast_mask |= 1 << ps.p_l_follow;
	    break;

	case rparen:		/* got a ')' or ']' */
	    if (ps.cast_mask & (1 << ps.p_l_follow) & ~ps.not_cast_mask) {
		ps.last_u_d = true;
		ps.cast_mask &= (1 << ps.p_l_follow) - 1;
		ps.want_blank = space_after_cast;
	    } else
		ps.want_blank = true;
	    ps.not_cast_mask &= (1 << ps.p_l_follow) - 1;
	    if (--ps.p_l_follow < 0) {
		ps.p_l_follow = 0;
		diag3(0, "Extra %c", *token);
	    }
	    if (e_code == s_code)	/* if the paren starts the line */
		ps.paren_level = ps.p_l_follow;	/* then indent it */

	    *e_code++ = token[0];

	    if (sp_sw && (ps.p_l_follow == 0)) {	/* check for end of if
							 * (...), or some such */
		sp_sw = false;
		force_nl = true;/* must force newline after if */
		ps.last_u_d = true;	/* inform lexi that a following
					 * operator is unary */
		ps.in_stmt = false;	/* dont use stmt continuation
					 * indentation */

		parse(hd_type);	/* let parser worry about if, or whatever */
	    }
	    ps.search_brace = btype_2;	/* this should insure that constructs
					 * such as main(){...} and int[]{...}
					 * have their braces put in the right
					 * place */
	    break;

	case unary_op:		/* this could be any unary operation */
	    if (!ps.dumped_decl_indent && ps.in_decl && !ps.block_init &&
		ps.procname[0] == '\0' && ps.paren_level == 0) {
		/* pointer declarations */

		/*
		 * if this is a unary op in a declaration, we should indent
		 * this token
		 */
		for (i = 0; token[i]; ++i)
		    /* find length of token */;
		indent_declaration(dec_ind - i, tabs_to_var);
		ps.dumped_decl_indent = true;
	    }
	    else if (ps.want_blank)
		*e_code++ = ' ';

	    {
		int len = e_token - s_token;

		CHECK_SIZE_CODE(len);
		memcpy(e_code, token, len);
		e_code += len;
	    }
	    ps.want_blank = false;
	    break;

	case binary_op:	/* any binary operation */
	    {
		int len = e_token - s_token;

		CHECK_SIZE_CODE(len + 1);
		if (ps.want_blank)
		    *e_code++ = ' ';
		memcpy(e_code, token, len);
		e_code += len;
	    }
	    ps.want_blank = true;
	    break;

	case postop:		/* got a trailing ++ or -- */
	    *e_code++ = token[0];
	    *e_code++ = token[1];
	    ps.want_blank = true;
	    break;

	case question:		/* got a ? */
	    squest++;		/* this will be used when a later colon
				 * appears so we can distinguish the
				 * <c>?<n>:<n> construct */
	    if (ps.want_blank)
		*e_code++ = ' ';
	    *e_code++ = '?';
	    ps.want_blank = true;
	    break;

	case casestmt:		/* got word 'case' or 'default' */
	    scase = true;	/* so we can process the later colon properly */
	    goto copy_id;

	case colon:		/* got a ':' */
	    if (squest > 0) {	/* it is part of the <c>?<n>: <n> construct */
		--squest;
		if (ps.want_blank)
		    *e_code++ = ' ';
		*e_code++ = ':';
		ps.want_blank = true;
		break;
	    }
	    if (ps.in_or_st) {
		*e_code++ = ':';
		ps.want_blank = false;
		break;
	    }
	    ps.in_stmt = false;	/* seeing a label does not imply we are in a
				 * stmt */
	    /*
	     * turn everything so far into a label
	     */
	    {
		int len = e_code - s_code;

		CHECK_SIZE_LAB(len + 3);
		memcpy(e_lab, s_code, len);
		e_lab += len;
		*e_lab++ = ':';
		*e_lab = '\0';
		e_code = s_code;
	    }
	    force_nl = ps.pcase = scase;	/* ps.pcase will be used by
						 * dump_line to decide how to
						 * indent the label. force_nl
						 * will force a case n: to be
						 * on a line by itself */
	    scase = false;
	    ps.want_blank = false;
	    break;

	case semicolon:	/* got a ';' */
	    if (ps.dec_nest == 0)
		ps.in_or_st = false;/* we are not in an initialization or
				     * structure declaration */
	    scase = false;	/* these will only need resetting in an error */
	    squest = 0;
	    if (ps.last_token == rparen)
		ps.in_parameter_declaration = 0;
	    ps.cast_mask = 0;
	    ps.not_cast_mask = 0;
	    ps.block_init = 0;
	    ps.block_init_level = 0;
	    ps.just_saw_decl--;

	    if (ps.in_decl && s_code == e_code && !ps.block_init &&
		!ps.dumped_decl_indent && ps.paren_level == 0) {
		/* indent stray semicolons in declarations */
		indent_declaration(dec_ind - 1, tabs_to_var);
		ps.dumped_decl_indent = true;
	    }

	    ps.in_decl = (ps.dec_nest > 0);	/* if we were in a first level
						 * structure declaration, we
						 * arent any more */

	    if ((!sp_sw || hd_type != forstmt) && ps.p_l_follow > 0) {

		/*
		 * This should be true iff there were unbalanced parens in the
		 * stmt.  It is a bit complicated, because the semicolon might
		 * be in a for stmt
		 */
		diag2(1, "Unbalanced parens");
		ps.p_l_follow = 0;
		if (sp_sw) {	/* this is a check for an if, while, etc. with
				 * unbalanced parens */
		    sp_sw = false;
		    parse(hd_type);	/* dont lose the if, or whatever */
		}
	    }
	    *e_code++ = ';';
	    ps.want_blank = true;
	    ps.in_stmt = (ps.p_l_follow > 0);	/* we are no longer in the
						 * middle of a stmt */

	    if (!sp_sw) {	/* if not if for (;;) */
		parse(semicolon);	/* let parser know about end of stmt */
		force_nl = true;/* force newline after an end of stmt */
	    }
	    break;

	case lbrace:		/* got a '{' */
	    ps.in_stmt = false;	/* dont indent the {} */
	    if (!ps.block_init)
		force_nl = true;/* force other stuff on same line as '{' onto
				 * new line */
	    else if (ps.block_init_level <= 0)
		ps.block_init_level = 1;
	    else
		ps.block_init_level++;

	    if (s_code != e_code && !ps.block_init) {
		if (!btype_2) {
		    dump_line();
		    ps.want_blank = false;
		}
		else if (ps.in_parameter_declaration && !ps.in_or_st) {
		    ps.i_l_follow = 0;
		    if (function_brace_split) {	/* dump the line prior to the
						 * brace ... */
			dump_line();
			ps.want_blank = false;
		    } else	/* add a space between the decl and brace */
			ps.want_blank = true;
		}
	    }
	    if (ps.in_parameter_declaration)
		prefix_blankline_requested = 0;

	    if (ps.p_l_follow > 0) {	/* check for preceding unbalanced
					 * parens */
		diag2(1, "Unbalanced parens");
		ps.p_l_follow = 0;
		if (sp_sw) {	/* check for unclosed if, for, etc. */
		    sp_sw = false;
		    parse(hd_type);
		    ps.ind_level = ps.i_l_follow;
		}
	    }
	    if (s_code == e_code)
		ps.ind_stmt = false;	/* dont put extra indentation on line
					 * with '{' */
	    if (ps.in_decl && ps.in_or_st) {	/* this is either a structure
						 * declaration or an init */
		di_stack[ps.dec_nest] = dec_ind;
		if (++ps.dec_nest == nitems(di_stack)) {
		    diag3(0, "Reached internal limit of %d struct levels",
			nitems(di_stack));
		    ps.dec_nest--;
		}
		/* ?		dec_ind = 0; */
	    }
	    else {
		ps.decl_on_line = false;	/* we can't be in the middle of
						 * a declaration, so don't do
						 * special indentation of
						 * comments */
		if (blanklines_after_declarations_at_proctop
			&& ps.in_parameter_declaration)
		    postfix_blankline_requested = 1;
		ps.in_parameter_declaration = 0;
		ps.in_decl = false;
	    }
	    dec_ind = 0;
	    parse(lbrace);	/* let parser know about this */
	    if (ps.want_blank)	/* put a blank before '{' if '{' is not at
				 * start of line */
		*e_code++ = ' ';
	    ps.want_blank = false;
	    *e_code++ = '{';
	    ps.just_saw_decl = 0;
	    break;

	case rbrace:		/* got a '}' */
	    if (ps.p_stack[ps.tos] == decl && !ps.block_init)	/* semicolons can be
								 * omitted in
								 * declarations */
		parse(semicolon);
	    if (ps.p_l_follow) {/* check for unclosed if, for, else. */
		diag2(1, "Unbalanced parens");
		ps.p_l_follow = 0;
		sp_sw = false;
	    }
	    ps.just_saw_decl = 0;
	    ps.block_init_level--;
	    if (s_code != e_code && !ps.block_init) {	/* '}' must be first on
							 * line */
		if (verbose)
		    diag2(0, "Line broken");
		dump_line();
	    }
	    *e_code++ = '}';
	    ps.want_blank = true;
	    ps.in_stmt = ps.ind_stmt = false;
	    if (ps.dec_nest > 0) {	/* we are in multi-level structure
					 * declaration */
		dec_ind = di_stack[--ps.dec_nest];
		if (ps.dec_nest == 0 && !ps.in_parameter_declaration)
		    ps.just_saw_decl = 2;
		ps.in_decl = true;
	    }
	    prefix_blankline_requested = 0;
	    parse(rbrace);	/* let parser know about this */
	    ps.search_brace = cuddle_else && ps.p_stack[ps.tos] == ifhead
		&& ps.il[ps.tos] >= ps.ind_level;
	    if (ps.tos <= 1 && blanklines_after_procs && ps.dec_nest <= 0)
		postfix_blankline_requested = 1;
	    break;

	case swstmt:		/* got keyword "switch" */
	    sp_sw = true;
	    hd_type = swstmt;	/* keep this for when we have seen the
				 * expression */
	    goto copy_id;	/* go move the token into buffer */

	case sp_paren:		/* token is if, while, for */
	    sp_sw = true;	/* the interesting stuff is done after the
				 * expression is scanned */
	    hd_type = (*token == 'i' ? ifstmt :
		       (*token == 'w' ? whilestmt : forstmt));

	    /*
	     * remember the type of header for later use by parser
	     */
	    goto copy_id;	/* copy the token into line */

	case sp_nparen:	/* got else, do */
	    ps.in_stmt = false;
	    if (*token == 'e') {
		if (e_code != s_code && (!cuddle_else || e_code[-1] != '}')) {
		    if (verbose)
			diag2(0, "Line broken");
		    dump_line();/* make sure this starts a line */
		    ps.want_blank = false;
		}
		force_nl = true;/* also, following stuff must go onto new line */
		last_else = 1;
		parse(elselit);
	    }
	    else {
		if (e_code != s_code) {	/* make sure this starts a line */
		    if (verbose)
			diag2(0, "Line broken");
		    dump_line();
		    ps.want_blank = false;
		}
		force_nl = true;/* also, following stuff must go onto new line */
		last_else = 0;
		parse(dolit);
	    }
	    goto copy_id;	/* move the token into line */

	case type_def:
	case storage:
	    prefix_blankline_requested = 0;
	    goto copy_id;

	case structure:
	    if (ps.p_l_follow > 0)
		goto copy_id;
	case decl:		/* we have a declaration type (int, etc.) */
	    parse(decl);	/* let parser worry about indentation */
	    if (ps.last_token == rparen && ps.tos <= 1) {
		if (s_code != e_code) {
		    dump_line();
		    ps.want_blank = 0;
		}
	    }
	    if (ps.in_parameter_declaration && ps.indent_parameters && ps.dec_nest == 0) {
		ps.ind_level = ps.i_l_follow = 1;
		ps.ind_stmt = 0;
	    }
	    ps.in_or_st = true;	/* this might be a structure or initialization
				 * declaration */
	    ps.in_decl = ps.decl_on_line = ps.last_token != type_def;
	    if ( /* !ps.in_or_st && */ ps.dec_nest <= 0)
		ps.just_saw_decl = 2;
	    prefix_blankline_requested = 0;
	    for (i = 0; token[i++];);	/* get length of token */

	    if (ps.ind_level == 0 || ps.dec_nest > 0) {
		/* global variable or struct member in local variable */
		dec_ind = ps.decl_indent > 0 ? ps.decl_indent : i;
		tabs_to_var = (use_tabs ? ps.decl_indent > 0 : 0);
	    } else {
		/* local variable */
		dec_ind = ps.local_decl_indent > 0 ? ps.local_decl_indent : i;
		tabs_to_var = (use_tabs ? ps.local_decl_indent > 0 : 0);
	    }
	    goto copy_id;

	case funcname:
	case ident:		/* got an identifier or constant */
	    if (ps.in_decl) {
		if (type_code == funcname) {
		    ps.in_decl = false;
		    if (procnames_start_line && s_code != e_code) {
			*e_code = '\0';
			dump_line();
		    }
		    else if (ps.want_blank) {
			*e_code++ = ' ';
		    }
		    ps.want_blank = false;
		}
		else if (!ps.block_init && !ps.dumped_decl_indent &&
		    ps.paren_level == 0) { /* if we are in a declaration, we
					    * must indent identifier */
		    indent_declaration(dec_ind, tabs_to_var);
		    ps.dumped_decl_indent = true;
		    ps.want_blank = false;
		}
	    }
	    else if (sp_sw && ps.p_l_follow == 0) {
		sp_sw = false;
		force_nl = true;
		ps.last_u_d = true;
		ps.in_stmt = false;
		parse(hd_type);
	    }
    copy_id:
	    {
		int len = e_token - s_token;

		CHECK_SIZE_CODE(len + 1);
		if (ps.want_blank)
		    *e_code++ = ' ';
		memcpy(e_code, s_token, len);
		e_code += len;
	    }
	    if (type_code != funcname)
		ps.want_blank = true;
	    break;

	case strpfx:
	    {
		int len = e_token - s_token;

		CHECK_SIZE_CODE(len + 1);
		if (ps.want_blank)
		    *e_code++ = ' ';
		memcpy(e_code, token, len);
		e_code += len;
	    }
	    ps.want_blank = false;
	    break;

	case period:		/* treat a period kind of like a binary
				 * operation */
	    *e_code++ = '.';	/* move the period into line */
	    ps.want_blank = false;	/* dont put a blank after a period */
	    break;

	case comma:
	    ps.want_blank = (s_code != e_code);	/* only put blank after comma
						 * if comma does not start the
						 * line */
	    if (ps.in_decl && ps.procname[0] == '\0' && !ps.block_init &&
		!ps.dumped_decl_indent && ps.paren_level == 0) {
		/* indent leading commas and not the actual identifiers */
		indent_declaration(dec_ind - 1, tabs_to_var);
		ps.dumped_decl_indent = true;
	    }
	    *e_code++ = ',';
	    if (ps.p_l_follow == 0) {
		if (ps.block_init_level <= 0)
		    ps.block_init = 0;
		if (break_comma && (!ps.leave_comma ||
		    count_spaces_until(compute_code_target(), s_code, e_code) >
		    max_col - tabsize))
		    force_nl = true;
	    }
	    break;

	case preesc:		/* got the character '#' */
	    if ((s_com != e_com) ||
		    (s_lab != e_lab) ||
		    (s_code != e_code))
		dump_line();
	    CHECK_SIZE_LAB(1);
	    *e_lab++ = '#';	/* move whole line to 'label' buffer */
	    {
		int         in_comment = 0;
		int         com_start = 0;
		char        quote = 0;
		int         com_end = 0;

		while (*buf_ptr == ' ' || *buf_ptr == '\t') {
		    buf_ptr++;
		    if (buf_ptr >= buf_end)
			fill_buffer();
		}
		while (*buf_ptr != '\n' || (in_comment && !had_eof)) {
		    CHECK_SIZE_LAB(2);
		    *e_lab = *buf_ptr++;
		    if (buf_ptr >= buf_end)
			fill_buffer();
		    switch (*e_lab++) {
		    case BACKSLASH:
			if (!in_comment) {
			    *e_lab++ = *buf_ptr++;
			    if (buf_ptr >= buf_end)
				fill_buffer();
			}
			break;
		    case '/':
			if (*buf_ptr == '*' && !in_comment && !quote) {
			    in_comment = 1;
			    *e_lab++ = *buf_ptr++;
			    com_start = e_lab - s_lab - 2;
			}
			break;
		    case '"':
			if (quote == '"')
			    quote = 0;
			break;
		    case '\'':
			if (quote == '\'')
			    quote = 0;
			break;
		    case '*':
			if (*buf_ptr == '/' && in_comment) {
			    in_comment = 0;
			    *e_lab++ = *buf_ptr++;
			    com_end = e_lab - s_lab;
			}
			break;
		    }
		}

		while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t'))
		    e_lab--;
		if (e_lab - s_lab == com_end && bp_save == NULL) {
		    /* comment on preprocessor line */
		    if (sc_end == NULL) {	/* if this is the first comment,
						 * we must set up the buffer */
			save_com = sc_buf;
			sc_end = &save_com[0];
		    }
		    else {
			*sc_end++ = '\n';	/* add newline between
						 * comments */
			*sc_end++ = ' ';
			--line_no;
		    }
		    if (sc_end - save_com + com_end - com_start > sc_size)
			errx(1, "input too long");
		    memmove(sc_end, s_lab + com_start, com_end - com_start);
		    sc_end += com_end - com_start;
		    e_lab = s_lab + com_start;
		    while (e_lab > s_lab && (e_lab[-1] == ' ' || e_lab[-1] == '\t'))
			e_lab--;
		    bp_save = buf_ptr;	/* save current input buffer */
		    be_save = buf_end;
		    buf_ptr = save_com;	/* fix so that subsequent calls to
					 * lexi will take tokens out of
					 * save_com */
		    *sc_end++ = ' ';	/* add trailing blank, just in case */
		    buf_end = sc_end;
		    sc_end = NULL;
		}
		CHECK_SIZE_LAB(1);
		*e_lab = '\0';	/* null terminate line */
		ps.pcase = false;
	    }

	    if (strncmp(s_lab, "#if", 3) == 0) { /* also ifdef, ifndef */
		if ((size_t)ifdef_level < nitems(state_stack)) {
		    match_state[ifdef_level].tos = -1;
		    state_stack[ifdef_level++] = ps;
		}
		else
		    diag2(1, "#if stack overflow");
	    }
	    else if (strncmp(s_lab, "#el", 3) == 0) { /* else, elif */
		if (ifdef_level <= 0)
		    diag2(1, s_lab[3] == 'i' ? "Unmatched #elif" : "Unmatched #else");
		else {
		    match_state[ifdef_level - 1] = ps;
		    ps = state_stack[ifdef_level - 1];
		}
	    }
	    else if (strncmp(s_lab, "#endif", 6) == 0) {
		if (ifdef_level <= 0)
		    diag2(1, "Unmatched #endif");
		else
		    ifdef_level--;
	    } else {
		struct directives {
		    int size;
		    const char *string;
		}
		recognized[] = {
		    {7, "include"},
		    {6, "define"},
		    {5, "undef"},
		    {4, "line"},
		    {5, "error"},
		    {6, "pragma"}
		};
		int d = nitems(recognized);
		while (--d >= 0)
		    if (strncmp(s_lab + 1, recognized[d].string, recognized[d].size) == 0)
			break;
		if (d < 0) {
		    diag2(1, "Unrecognized cpp directive");
		    break;
		}
	    }
	    if (blanklines_around_conditional_compilation) {
		postfix_blankline_requested++;
		n_real_blanklines = 0;
	    }
	    else {
		postfix_blankline_requested = 0;
		prefix_blankline_requested = 0;
	    }
	    break;		/* subsequent processing of the newline
				 * character will cause the line to be printed */

	case comment:		/* we have gotten a / followed by * this is a biggie */
	    pr_comment();
	    break;
	}			/* end of big switch stmt */

	*e_code = '\0';		/* make sure code section is null terminated */
	if (type_code != comment && type_code != newline && type_code != preesc)
	    ps.last_token = type_code;
    }				/* end of main while (1) loop */
}
示例#28
0
文件: jot.c 项目: mulichao/freebsd
int
main(int argc, char **argv)
{
	cap_rights_t rights;
	bool	have_format = false;
	bool	infinity = false;
	bool	nofinalnl = false;
	bool	randomize = false;
	bool	use_random = false;
	int	ch;
	int	mask = 0;
	int	n = 0;
	double	begin = BEGIN_DEF;
	double	divisor;
	double	ender = ENDER_DEF;
	double	s = STEP_DEF;
	double	x, y;
	long	i;
	long	reps = REPS_DEF;

	if (caph_limit_stdio() < 0)
		err(1, "unable to limit rights for stdio");
	cap_rights_init(&rights);
	if (cap_rights_limit(STDIN_FILENO, &rights) < 0 && errno != ENOSYS)
		err(1, "unable to limit rights for stdin");

	/*
	 * Cache NLS data, for strerror, for err(3), before entering capability
	 * mode.
	 */
	caph_cache_catpages();

	if (cap_enter() < 0 && errno != ENOSYS)
		err(1, "unable to enter capability mode");

	while ((ch = getopt(argc, argv, "b:cnp:rs:w:")) != -1)
		switch (ch) {
		case 'b':
			boring = true;
			/* FALLTHROUGH */
		case 'w':
			if (strlcpy(format, optarg, sizeof(format)) >=
			    sizeof(format))
				errx(1, "-%c word too long", ch);
			have_format = true;
			break;
		case 'c':
			chardata = true;
			break;
		case 'n':
			nofinalnl = true;
			break;
		case 'p':
			prec = atoi(optarg);
			if (prec < 0)
				errx(1, "bad precision value");
			have_format = true;
			break;
		case 'r':
			randomize = true;
			break;
		case 's':
			sepstring = optarg;
			break;
		default:
			usage();
		}
	argc -= optind;
	argv += optind;

	switch (argc) {	/* examine args right to left, falling thru cases */
	case 4:
		if (!is_default(argv[3])) {
			if (!sscanf(argv[3], "%lf", &s))
				errx(1, "bad s value: %s", argv[3]);
			mask |= HAVE_STEP;
			if (randomize)
				use_random = true;
		}
		/* FALLTHROUGH */
	case 3:
		if (!is_default(argv[2])) {
			if (!sscanf(argv[2], "%lf", &ender))
				ender = argv[2][strlen(argv[2])-1];
			mask |= HAVE_ENDER;
			if (prec < 0)
				n = getprec(argv[2]);
		}
		/* FALLTHROUGH */
	case 2:
		if (!is_default(argv[1])) {
			if (!sscanf(argv[1], "%lf", &begin))
				begin = argv[1][strlen(argv[1])-1];
			mask |= HAVE_BEGIN;
			if (prec < 0)
				prec = getprec(argv[1]);
			if (n > prec)		/* maximum precision */
				prec = n;
		}
		/* FALLTHROUGH */
	case 1:
		if (!is_default(argv[0])) {
			if (!sscanf(argv[0], "%ld", &reps))
				errx(1, "bad reps value: %s", argv[0]);
			mask |= HAVE_REPS;
		}
		break;
	case 0:
		usage();
	default:
		errx(1, "too many arguments.  What do you mean by %s?",
		    argv[4]);
	}
	getformat();

	if (prec == -1)
		prec = 0;

	while (mask)	/* 4 bit mask has 1's where last 4 args were given */
		switch (mask) {	/* fill in the 0's by default or computation */
		case HAVE_STEP:
		case HAVE_ENDER:
		case HAVE_ENDER | HAVE_STEP:
		case HAVE_BEGIN:
		case HAVE_BEGIN | HAVE_STEP:
			reps = REPS_DEF;
			mask |= HAVE_REPS;
			break;
		case HAVE_BEGIN | HAVE_ENDER:
			s = ender > begin ? 1 : -1;
			mask |= HAVE_STEP;
			break;
		case HAVE_BEGIN | HAVE_ENDER | HAVE_STEP:
			if (randomize)
				reps = REPS_DEF;
			else if (s == 0.0)
				reps = 0;
			else
				reps = (ender - begin + s) / s;
			if (reps <= 0)
				errx(1, "impossible stepsize");
			mask = 0;
			break;
		case HAVE_REPS:
		case HAVE_REPS | HAVE_STEP:
			begin = BEGIN_DEF;
			mask |= HAVE_BEGIN;
			break;
		case HAVE_REPS | HAVE_ENDER:
			s = STEP_DEF;
			mask = HAVE_REPS | HAVE_ENDER | HAVE_STEP;
			break;
		case HAVE_REPS | HAVE_ENDER | HAVE_STEP:
			if (randomize)
				begin = BEGIN_DEF;
			else if (reps == 0)
				errx(1, "must specify begin if reps == 0");
			begin = ender - reps * s + s;
			mask = 0;
			break;
		case HAVE_REPS | HAVE_BEGIN:
			s = STEP_DEF;
			mask = HAVE_REPS | HAVE_BEGIN | HAVE_STEP;
			break;
		case HAVE_REPS | HAVE_BEGIN | HAVE_STEP:
			if (randomize)
				ender = ENDER_DEF;
			else
				ender = begin + reps * s - s;
			mask = 0;
			break;
		case HAVE_REPS | HAVE_BEGIN | HAVE_ENDER:
			if (reps == 0)
				errx(1, "infinite sequences cannot be bounded");
			else if (reps == 1)
				s = 0.0;
			else
				s = (ender - begin) / (reps - 1);
			mask = 0;
			break;
		case HAVE_REPS | HAVE_BEGIN | HAVE_ENDER | HAVE_STEP:
			/* if reps given and implied, */
			if (!randomize && s != 0.0) {
				long t = (ender - begin + s) / s;
				if (t <= 0)
					errx(1, "impossible stepsize");
				if (t < reps)		/* take lesser */
					reps = t;
			}
			mask = 0;
			break;
		default:
			errx(1, "bad mask");
		}
	if (reps == 0)
		infinity = true;
	if (randomize) {
		if (use_random) {
			srandom((unsigned long)s);
			divisor = (double)INT32_MAX + 1;
		} else
			divisor = (double)UINT32_MAX + 1;

		/*
		 * Attempt to DWIM when the user has specified an
		 * integer range within that of the random number
		 * generator: distribute the numbers equally in
		 * the range [begin .. ender].  Jot's default %.0f
		 * format would make the appearance of the first and
		 * last specified value half as likely as the rest.
		 */
		if (!have_format && prec == 0 &&
		    begin >= 0 && begin < divisor &&
		    ender >= 0 && ender < divisor) {
			if (begin <= ender)
				ender += 1;
			else
				begin += 1;
			nosign = true;
			intdata = true;
			(void)strlcpy(format,
			    chardata ? "%c" : "%u", sizeof(format));
		}
		x = ender - begin;
		for (i = 1; i <= reps || infinity; i++) {
			if (use_random)
				y = random() / divisor;
			else
				y = arc4random() / divisor;
			if (putdata(y * x + begin, !(reps - i)))
				errx(1, "range error in conversion");
		}
	} else
		for (i = 1, x = begin; i <= reps || infinity; i++, x += s)
			if (putdata(x, !(reps - i)))
				errx(1, "range error in conversion");
	if (!nofinalnl)
		putchar('\n');
	exit(0);
}
示例#29
0
文件: elfdump.c 项目: coyizumi/cs111
int
main(int ac, char **av)
{
    cap_rights_t rights;
    u_int64_t phoff;
    u_int64_t shoff;
    u_int64_t phentsize;
    u_int64_t phnum;
    u_int64_t shentsize;
    u_int64_t shnum;
    u_int64_t shstrndx;
    u_int64_t offset;
    u_int64_t name;
    u_int64_t type;
    struct stat sb;
    u_int flags;
    Elf32_Ehdr *e;
    void *p;
    void *sh;
    void *v;
    int fd;
    int ch;
    int i;

    out = stdout;
    flags = 0;
    while ((ch = getopt(ac, av, "acdeiGhnprsw:")) != -1)
        switch (ch) {
        case 'a':
            flags = ED_ALL;
            break;
        case 'c':
            flags |= ED_SHDR;
            break;
        case 'd':
            flags |= ED_DYN;
            break;
        case 'e':
            flags |= ED_EHDR;
            break;
        case 'i':
            flags |= ED_INTERP;
            break;
        case 'G':
            flags |= ED_GOT;
            break;
        case 'h':
            flags |= ED_HASH;
            break;
        case 'n':
            flags |= ED_NOTE;
            break;
        case 'p':
            flags |= ED_PHDR;
            break;
        case 'r':
            flags |= ED_REL;
            break;
        case 's':
            flags |= ED_SYMTAB;
            break;
        case 'w':
            if ((out = fopen(optarg, "w")) == NULL)
                err(1, "%s", optarg);
            cap_rights_init(&rights, CAP_FSTAT, CAP_WRITE);
            if (cap_rights_limit(fileno(out), &rights) < 0 && errno != ENOSYS)
                err(1, "unable to limit rights for %s", optarg);
            break;
        case '?':
        default:
            usage();
        }
    ac -= optind;
    av += optind;
    if (ac == 0 || flags == 0)
        usage();
    if ((fd = open(*av, O_RDONLY)) < 0 ||
            fstat(fd, &sb) < 0)
        err(1, "%s", *av);
    cap_rights_init(&rights, CAP_MMAP_R);
    if (cap_rights_limit(fd, &rights) < 0 && errno != ENOSYS)
        err(1, "unable to limit rights for %s", *av);
    close(STDIN_FILENO);
    cap_rights_init(&rights, CAP_WRITE);
    if (cap_rights_limit(STDOUT_FILENO, &rights) < 0 && errno != ENOSYS)
        err(1, "unable to limit rights for stdout");
    if (cap_rights_limit(STDERR_FILENO, &rights) < 0 && errno != ENOSYS)
        err(1, "unable to limit rights for stderr");
    if (cap_enter() < 0 && errno != ENOSYS)
        err(1, "unable to enter capability mode");
    e = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, fd, 0);
    if (e == MAP_FAILED)
        err(1, NULL);
    if (!IS_ELF(*(Elf32_Ehdr *)e))
        errx(1, "not an elf file");
    phoff = elf_get_off(e, e, E_PHOFF);
    shoff = elf_get_off(e, e, E_SHOFF);
    phentsize = elf_get_quarter(e, e, E_PHENTSIZE);
    phnum = elf_get_quarter(e, e, E_PHNUM);
    shentsize = elf_get_quarter(e, e, E_SHENTSIZE);
    p = (char *)e + phoff;
    if (shoff > 0) {
        sh = (char *)e + shoff;
        shnum = elf_get_shnum(e, sh);
        shstrndx = elf_get_shstrndx(e, sh);
        offset = elf_get_off(e, (char *)sh + shstrndx * shentsize,
                             SH_OFFSET);
        shstrtab = (char *)e + offset;
    } else {
        sh = NULL;
        shnum = 0;
        shstrndx = 0;
        shstrtab = NULL;
    }
    for (i = 0; (u_int64_t)i < shnum; i++) {
        name = elf_get_word(e, (char *)sh + i * shentsize, SH_NAME);
        offset = elf_get_off(e, (char *)sh + i * shentsize, SH_OFFSET);
        if (strcmp(shstrtab + name, ".strtab") == 0)
            strtab = (char *)e + offset;
        if (strcmp(shstrtab + name, ".dynstr") == 0)
            dynstr = (char *)e + offset;
    }
    if (flags & ED_EHDR)
        elf_print_ehdr(e, sh);
    if (flags & ED_PHDR)
        elf_print_phdr(e, p);
    if (flags & ED_SHDR)
        elf_print_shdr(e, sh);
    for (i = 0; (u_int64_t)i < phnum; i++) {
        v = (char *)p + i * phentsize;
        type = elf_get_word(e, v, P_TYPE);
        switch (type) {
        case PT_INTERP:
            if (flags & ED_INTERP)
                elf_print_interp(e, v);
            break;
        case PT_NULL:
        case PT_LOAD:
        case PT_DYNAMIC:
        case PT_NOTE:
        case PT_SHLIB:
        case PT_PHDR:
            break;
        }
    }
    for (i = 0; (u_int64_t)i < shnum; i++) {
        v = (char *)sh + i * shentsize;
        type = elf_get_word(e, v, SH_TYPE);
        switch (type) {
        case SHT_SYMTAB:
            if (flags & ED_SYMTAB)
                elf_print_symtab(e, v, strtab);
            break;
        case SHT_DYNAMIC:
            if (flags & ED_DYN)
                elf_print_dynamic(e, v);
            break;
        case SHT_RELA:
            if (flags & ED_REL)
                elf_print_rela(e, v);
            break;
        case SHT_REL:
            if (flags & ED_REL)
                elf_print_rel(e, v);
            break;
        case SHT_NOTE:
            name = elf_get_word(e, v, SH_NAME);
            if (flags & ED_NOTE &&
                    strcmp(shstrtab + name, ".note.ABI-tag") == 0)
                elf_print_note(e, v);
            break;
        case SHT_DYNSYM:
            if (flags & ED_SYMTAB)
                elf_print_symtab(e, v, dynstr);
            break;
        case SHT_PROGBITS:
            name = elf_get_word(e, v, SH_NAME);
            if (flags & ED_GOT &&
                    strcmp(shstrtab + name, ".got") == 0)
                elf_print_got(e, v);
            break;
        case SHT_HASH:
            if (flags & ED_HASH)
                elf_print_hash(e, v);
            break;
        case SHT_NULL:
        case SHT_STRTAB:
        case SHT_NOBITS:
        case SHT_SHLIB:
            break;
        }
    }

    return 0;
}
示例#30
0
文件: event.c 项目: dotike/pkg
static int
event_sandboxed_get_string(pkg_sandbox_cb func, char **result, int64_t *len,
		void *ud)
{
	pid_t pid;
	int	status, ret = EPKG_OK;
	int pair[2], r, allocated_len = 0, off = 0;
	char *buf = NULL;

	if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) {
		warn("socketpair failed");
		return (EPKG_FATAL);
	}

	pid = fork();

	switch(pid) {
	case -1:
		warn("fork failed");
		return (EPKG_FATAL);
		break;
	case 0:
		break;
	default:
		/* Parent process */
		close(pair[0]);
		/*
		 * We use blocking IO here as if the child is terminated we would have
		 * EINTR here
		 */
		buf = malloc(BUFSIZ);
		if (buf == NULL) {
			warn("malloc failed");
			return (EPKG_FATAL);
		}
		allocated_len = BUFSIZ;
		do {
			if (off >= allocated_len) {
				allocated_len *= 2;
				buf = realloc(buf, allocated_len);
				if (buf == NULL) {
					warn("realloc failed");
					return (EPKG_FATAL);
				}
			}

			r = read(pair[1], buf + off, allocated_len - off);
			if (r == -1 && errno != EINTR) {
				free(buf);
				warn("read failed");
				return (EPKG_FATAL);
			}
			else if (r > 0) {
				off += r;
			}
		} while (r > 0);

		/* Fill the result buffer */
		*len = off;
		*result = buf;
		if (*result == NULL) {
			warn("malloc failed");
			kill(pid, SIGTERM);
			ret = EPKG_FATAL;
		}
		while (waitpid(pid, &status, 0) == -1) {
			if (errno != EINTR) {
				warn("Sandboxed process pid=%d", (int)pid);
				ret = -1;
				break;
			}
		}

		if (WIFEXITED(status)) {
			ret = WEXITSTATUS(status);
		}
		if (WIFSIGNALED(status)) {
			/* Process got some terminating signal, hence stop the loop */
			fprintf(stderr, "Sandboxed process pid=%d terminated abnormally by signal: %d\n",
					(int)pid, WTERMSIG(status));
			ret = -1;
		}
		return (ret);
	}

	/* Here comes child process */
	close(pair[1]);

#ifdef HAVE_CAPSICUM
	if (cap_enter() < 0 && errno != ENOSYS) {
		warn("cap_enter() failed");
		return (EPKG_FATAL);
	}
#endif

	/*
	 * XXX: if capsicum is not enabled we basically have no idea of how to
	 * make a sandbox
	 */
	ret = func(pair[0], ud);

	close(pair[0]);

	_exit(ret);
}