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; }
/* * 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"); }
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; }
/* * 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); }
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); }
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); }
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); }
// 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; }
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__); }
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"); }
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); }
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; }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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; }
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); }
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); });
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); }
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 */ }
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); }
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; }
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); }