123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194 |
- #include <assert.h>
- #include <errno.h>
- #include <grp.h>
- #include <limits.h>
- #include <stdlib.h>
- #include <string.h>
- #include <sys/resource.h>
- #include <sys/stat.h>
- #include <sys/types.h>
- #include <sys/wait.h>
- #include <unistd.h>
- #include "pty-private.h"
- static int
- pts_name (int fd, char **pts, size_t buf_len)
- {
- int rv;
- char *buf = *pts;
- for (;;)
- {
- char *new_buf;
- if (buf_len)
- {
- rv = ptsname_r (fd, buf, buf_len);
- if (rv != 0 || memchr (buf, '\0', buf_len))
-
- break;
-
- buf_len += buf_len;
- }
- else
-
- buf_len = 128;
- if (buf != *pts)
-
- new_buf = realloc (buf, buf_len);
- else
- new_buf = malloc (buf_len);
- if (! new_buf)
- {
- rv = -1;
-
- break;
- }
- buf = new_buf;
- }
- if (rv == 0)
- *pts = buf;
- else if (buf != *pts)
- free (buf);
- return rv;
- }
- int
- grantpt (int fd)
- {
- int retval = -1;
- #ifdef PATH_MAX
- char _buf[PATH_MAX];
- #else
- char _buf[512];
- #endif
- char *buf = _buf;
- struct stat st;
- uid_t uid;
- gid_t gid;
- pid_t pid;
- if (pts_name (fd, &buf, sizeof (_buf)))
- return -1;
- if (stat(buf, &st) < 0)
- goto cleanup;
-
- uid = getuid ();
- if (st.st_uid != uid)
- {
- if (chown (buf, uid, st.st_gid) < 0)
- goto helper;
- }
- gid = getgid ();
-
- if (st.st_gid != gid)
- {
- if (chown (buf, uid, gid) < 0)
- goto helper;
- }
-
- if ((st.st_mode & ACCESSPERMS) != (S_IRUSR|S_IWUSR|S_IWGRP))
- {
- if (chmod (buf, S_IRUSR|S_IWUSR|S_IWGRP) < 0)
- goto helper;
- }
- retval = 0;
- goto cleanup;
-
- helper:
- pid = vfork ();
- if (pid == -1)
- goto cleanup;
- else if (pid == 0)
- {
-
- struct rlimit rl = { 0, 0 };
- setrlimit (RLIMIT_CORE, &rl);
-
- if (fd != PTY_FILENO)
- if (dup2 (fd, PTY_FILENO) < 0)
- _exit (FAIL_EBADF);
- execle (_PATH_PT_CHOWN, _PATH_PT_CHOWN, NULL, NULL);
- _exit (FAIL_EXEC);
- }
- else
- {
- int w;
- if (waitpid (pid, &w, 0) == -1)
- goto cleanup;
- if (!WIFEXITED (w))
- errno = ENOEXEC;
- else
- switch (WEXITSTATUS(w))
- {
- case 0:
- retval = 0;
- break;
- case FAIL_EBADF:
- errno = EBADF;
- break;
- case FAIL_EINVAL:
- errno = EINVAL;
- break;
- case FAIL_EACCES:
- errno = EACCES;
- break;
- case FAIL_EXEC:
- errno = ENOEXEC;
- break;
- default:
- assert(! "getpt: internal error: invalid exit code from pt_chown");
- }
- }
- cleanup:
- if (buf != _buf)
- free (buf);
- return retval;
- }
|