diff --git a/sys/include/posix.h b/sys/include/posix.h index c2b2a47..5de90cc 100644 --- a/sys/include/posix.h +++ b/sys/include/posix.h @@ -143,6 +143,7 @@ extern unsigned int POSIX_sleep(unsigned int seconds); extern int POSIX_pipe(int *errnop, int fildes[2]); extern int POSIX_umask(int *errnop, int mask); +extern int POSIX_getpgrp(int *errnop); extern int POSIX_getuid(int *errnop); extern int POSIX_geteuid(int *errnop); extern int POSIX_setuid(int *errnop, int uid); diff --git a/sys/src/lib/posix/ids.c b/sys/src/lib/posix/ids.c index d130064..2a30d25 100644 --- a/sys/src/lib/posix/ids.c +++ b/sys/src/lib/posix/ids.c @@ -21,6 +21,61 @@ #include #include "internal.h" +int __libposix_session_leader = -1; + +static int +get_noteid(int *errnop, int pid) +{ + int n, f; + char buf[30]; + + sprint(buf, "/proc/%d/noteid", pid); + f = open(buf, 0); + if(f < 0){ + *errnop = __libposix_get_errno(PosixEPERM); + return -1; + } + n = read(f, buf, sizeof(buf) - 1); + if(n < 0){ + *errnop = __libposix_get_errno(PosixEPERM); + return -1; + } + buf[n] = '\0'; + n = atoi(buf); + close(f); + + return n; +} + +static int +set_noteid(int *errnop, int pid, int noteid) +{ + int n, f; + char buf[30]; + + if(pid == 0) + pid = getpid(); + if(noteid == 0){ + noteid = get_noteid(errnop, pid); + if(noteid < 0) + return noteid; + } + sprint(buf, "/proc/%d/noteid", pid); + f = open(buf, 1); + if(f < 0) { + *errnop = __libposix_get_errno(PosixESRCH); + return -1; + } + n = sprint(buf, "%d", noteid); + n = write(f, buf, n); + if(n < 0){ + *errnop = __libposix_get_errno(PosixEPERM); + return -1; + } + close(f); + return 0; +} + int POSIX_getuid(int *errnop) { @@ -81,22 +136,58 @@ POSIX_setregid(int *errnop, int rgid, int egid) return 0; } +int +POSIX_getpgrp(int *errnop) +{ + int pid = getpid(); + return get_noteid(errnop, pid); +} + int POSIX_setpgid(int *errnop, int pid, int pgid) { - return 0; + if(pid < 0 || pgid < 0){ + *errnop = __libposix_get_errno(PosixEINVAL); + return -1; + } + return set_noteid(errnop, pid, pgid); } int POSIX_getsid(int *errnop, int pid) { - return 0; + int reqnoteid, mynoteid; + + if(pid < 0){ + *errnop = __libposix_get_errno(PosixESRCH); + return -1; + } + if(pid == 0) + pid = getpid(); + else if(pid == getpid()) + return __libposix_session_leader; + reqnoteid = get_noteid(errnop, pid); + if(reqnoteid < 0) + return reqnoteid; + if(__libposix_session_leader < 0) + return reqnoteid; + mynoteid = POSIX_getpgrp(errnop); + if(mynoteid == reqnoteid){ + /* if it share our pgrp (aka noteid), it shares + * our session leader + */ + return __libposix_session_leader; + } + return reqnoteid; } int POSIX_setsid(int *errnop) { - *errnop = __libposix_get_errno(PosixEPERM); - return 0; + if(rfork(RFNAMEG|RFNOTEG) < 0){ + *errnop = __libposix_get_errno(PosixEPERM); + return -1; + } + __libposix_session_leader = POSIX_getpgrp(errnop); + return __libposix_session_leader; } -