int parse_proc_stat(int statfd, struct proc_stat *out) { char buf[1024]; int n; unsigned dev; lseek(statfd, 0, SEEK_SET); if (read(statfd, buf, sizeof buf) < 0) return assert_nonzero(errno); n = sscanf(buf, "%d (%16[^)]) %c %d %d %d %u", &out->pid, out->comm, &out->state, &out->ppid, &out->pgid, &out->sid, &dev); if (n == EOF) return assert_nonzero(errno); if (n != 7) { return EINVAL; } out->ctty = dev; struct stat st; if (fstat(statfd, &st) != 0) return assert_nonzero(errno); out->uid = st.st_uid; out->gid = st.st_gid; return 0; }
int *get_child_tty_fds(struct ptrace_child *child, int statfd, int *count) { struct proc_stat child_status; struct stat tty_st, console_st, st; char buf[PATH_MAX]; struct fd_array fds = {}; DIR *dir; struct dirent *d; debug("Looking up fds for tty in child."); if ((child->error = parse_proc_stat(statfd, &child_status))) return NULL; debug("Resolved child tty: %x", (unsigned)child_status.ctty); if (stat("/dev/tty", &tty_st) < 0) { child->error = assert_nonzero(errno); error("Unable to stat /dev/tty"); return NULL; } if (stat("/dev/console", &console_st) < 0) { child->error = errno; error("Unable to stat /dev/console"); return NULL; } snprintf(buf, sizeof buf, "/proc/%d/fd/", child->pid); if ((dir = opendir(buf)) == NULL) return NULL; while ((d = readdir(dir)) != NULL) { if (d->d_name[0] == '.') continue; snprintf(buf, sizeof buf, "/proc/%d/fd/%s", child->pid, d->d_name); if (stat(buf, &st) < 0) continue; if (st.st_rdev == child_status.ctty || st.st_rdev == tty_st.st_rdev || st.st_rdev == console_st.st_rdev) { debug("Found an alias for the tty: %s", d->d_name); if (fd_array_push(&fds, atoi(d->d_name)) != 0) { child->error = assert_nonzero(errno); error("Unable to allocate memory for fd array."); goto out; } } } out: *count = fds.n; closedir(dir); return fds.fds; }
int get_process_tty_termios(pid_t pid, struct termios *tio) { int err = EINVAL; char buf[PATH_MAX]; int i; int fd; for (i = 0; i < 3 && err; i++) { err = 0; snprintf(buf, sizeof buf, "/proc/%d/fd/%d", pid, i); if ((fd = open(buf, O_RDONLY)) < 0) { err = -fd; continue; } if (!isatty(fd)) { err = ENOTTY; goto retry; } if (tcgetattr(fd, tio) < 0) { err = -assert_nonzero(errno); } retry: close(fd); } return err; }
int copy_tty_state(pid_t pid, const char *pty) { int fd, err = EINVAL; struct termios tio; err = get_process_tty_termios(pid, &tio); if (err) return err; if ((fd = open(pty, O_RDONLY)) < 0) return -assert_nonzero(errno); if (tcsetattr(fd, TCSANOW, &tio) < 0) err = assert_nonzero(errno); close(fd); return -err; }
void test_newWithBits_size0(void) { BitStream *bstream; testStart("New with bits (size = 0)"); bstream = BitStream_newWithBits(0, NULL); assert_equal(bstream->length, 0, "Internal bit length is incorrect.\n"); assert_nonzero(bstream->datasize, "Internal buffer size is incorrect.\n"); assert_nonnull(bstream->data, "Internal buffer not allocated.\n"); testFinish(); }
int copy_tty_state(pid_t pid, const char *pty) { char buf[PATH_MAX]; int fd, err = EINVAL; struct termios tio; int i; for (i = 0; i < 3 && err; i++) { err = 0; snprintf(buf, sizeof buf, "/proc/%d/fd/%d", pid, i); if ((fd = open(buf, O_RDONLY)) < 0) { err = -fd; continue; } if (!isatty(fd)) { err = ENOTTY; goto retry; } if (tcgetattr(fd, &tio) < 0) { err = -assert_nonzero(errno); } retry: close(fd); } if (err) return err; if ((fd = open(pty, O_RDONLY)) < 0) return -assert_nonzero(errno); if (tcsetattr(fd, TCSANOW, &tio) < 0) err = assert_nonzero(errno); close(fd); return -err; }
void test_ECIinvalid(void) { QRinput *stream; int ret; testStart("Appending invalid ECI header"); stream = QRinput_new(); ret = QRinput_appendECIheader(stream, 999999); assert_zero(ret, "Valid ECI header rejected."); ret = QRinput_appendECIheader(stream, 1000000); assert_nonzero(ret, "Invalid ECI header accepted."); QRinput_free(stream); testFinish(); }
int check_pgroup(pid_t target) { pid_t pg; DIR *dir; struct dirent *d; pid_t pid; char *p; int err = 0; struct proc_stat pid_stat; debug("Checking for problematic process group members..."); pg = getpgid(target); if (pg < 0) { error("Unable to get pgid for pid %d", (int)target); return errno; } if ((dir = opendir("/proc/")) == NULL) return assert_nonzero(errno); while ((d = readdir(dir)) != NULL) { if (d->d_name[0] == '.') continue; pid = strtol(d->d_name, &p, 10); if (*p) continue; if (pid == target) continue; if (getpgid(pid) == pg) { /* * We are actually being somewhat overly-conservative here * -- if pid is a child of target, and has not yet called * execve(), reptyr's setpgid() strategy may suffice. That * is a fairly rare case, and annoying to check for, so * for now let's just bail out. */ if ((err = read_proc_stat(pid, &pid_stat))) { memcpy(pid_stat.comm, "???", 4); } error("Process %d (%.*s) shares %d's process group. Unable to attach.\n" "(This most commonly means that %d has suprocesses).", (int)pid, TASK_COMM_LENGTH, pid_stat.comm, (int)target, (int)target); err = EINVAL; goto out; } } out: closedir(dir); return err; }
int get_process_tty_termios(pid_t pid, struct termios *tio) { int err = EINVAL; struct kinfo_proc *kp; unsigned int cnt; struct filestat_list *head; struct filestat *fst; struct procstat *procstat; int fd = -1; head = get_procfiles(pid, &kp, &procstat, &cnt); STAILQ_FOREACH(fst, head, next) { if (fst->fs_type == PS_FST_TYPE_VNODE) { if (fst->fs_path) { fd = open(fst->fs_path, O_RDONLY); if (fd >= 0 && isatty(fd)) { if (tcgetattr(fd, tio) < 0) { err = -assert_nonzero(errno); } else { close(fd); err = 0; goto done; } } close(fd); } } } done: procstat_freefiles(procstat, head); procstat_freeprocs(procstat, kp); procstat_close(procstat); return err; }