unit posix_tty_tcsetattr(cerr er, int fd, int action, ptr_t termiorep, string cc) { struct termios termios; int e = termioset(&termios,termiorep,cc); if(e) send_errno(er,e); else if(tcsetattr(fd, action, &termios) == -1) send_errno(er,errno); return empty_record; }
unit posix_io_fcntl_sfl(cerr er, int fd, word flags) { if(fcntl(fd, F_SETFL, flags) == -1) send_errno(er,errno); return empty_record; }
unit posix_tty_tcflow(cerr er, int fd, int action) { if(tcflow(fd, action) == -1) send_errno(er,errno); return empty_record; }
unit posix_io_fcntl_sfd(cerr er, int fd, word flag) { if(fcntl(fd, F_SETFD, flag) == -1) /* mask with FD_CLOEXEC? */ send_errno(er,errno); return empty_record; }
unit posix_io_dup2(cerr er, int oldfd, int newfd) { if(dup2(oldfd,newfd)==-1) send_errno(er,errno); return empty_record; }
unit posix_tty_tcsendbreak(cerr er, int fd, int duration) { if(tcsendbreak(fd, duration) == -1) send_errno(er,errno); return empty_record; }
unit posix_io_close(cerr er, int fd) { if(close(fd)==-1) send_errno(er,errno); return empty_record; }
unit posix_tty_tcsetpgrp(cerr er, int fd, int pgid) { if(tcsetpgrp(fd, (pid_t) pgid) == -1) send_errno(er,errno); return empty_record; }
unit posix_tty_tcdrain(cerr er, int fd) { if(tcdrain(fd) == -1) send_errno(er,errno); return empty_record; }
unit posix_tty_tcflush(cerr er, int fd, int queue_selector) { if(tcflush(fd, queue_selector) == -1) send_errno(er,errno); return empty_record; }
unit posix_io_fsync(cerr er, int fd) { if(fsync(fd) == -1) send_errno(er,errno); return empty_record; }
void handle_request(char *request, const struct ucred *src) { char *buff; int omode; if ((buff = strdup(request)) == NULL) { perror("strdup(3) couldn't allocate memory"); return; } if (sscanf(request, "open %s %d", buff, &omode) != 2) { fprintf(stderr, "Invalid request: %s\n", request); goto outbuff; } if (!can_access(buff, src)) { errno = EACCES; if (send_errno(STDOUT_FILENO) < 0) { fprintf(stderr, "send_errno() failed attempting to notify client: %s\n", strerror(errno)); fprintf(stderr, "Note: Permission denied for pid %ld to open %s (euid = %ld, egid = %ld)\n", (long) src->pid, buff, (long) src->uid, (long) src->gid); } goto outbuff; } int fd = open(buff, omode); if (fd < 0) { int open_error = errno; if (send_errno(STDOUT_FILENO) < 0) { fprintf(stderr, "send_errno() failed attempting to notify client: %s\n", strerror(errno)); fprintf(stderr, "Note: couldn't open %s: %s\n", buff, strerror(open_error)); } goto outbuff; } if (send_fd(STDOUT_FILENO, fd) < 0) { fprintf(stderr, "send_fd() failed attempting to send fd for %s: %s\n", buff, strerror(errno)); goto outclose; } outclose: close(fd); outbuff: free(buff); }
int posix_tty_tcgetpgrp(cerr er, int fd) { pid_t pid = tcgetpgrp(fd); if(pid == (pid_t)-1) send_errno(er,errno); return (int)pid; }
ptr_t posix_io_fcntl_l(cerr er, int fd, int cmd, ptr_t flockrep) { struct flock flock; if(fcntl(fd, cmd, flockset(&flock, flockrep)) == -1) send_errno(er,errno); return Flockrep(&flock); }
uct posix_tty_tcgetattr(cerr er, int fd) { struct termios* termios = enew_atomic(struct termios); if(tcgetattr(fd, termios) == -1) send_errno(er,errno); return (uct)termios; }
int posix_io_fcntl_d(cerr er, int fd, int basefd) { int newfd = fcntl(fd, F_DUPFD, basefd); if(newfd == -1) send_errno(er,errno); return newfd; }
int posix_io_writebuf(cerr er, int fd, word8array buf, int len, int start) { int written = write(fd, (stringbuf(buf)) + start, len); if(written == -1) send_errno(er,errno); return written; }
word posix_io_fcntl_gfd(cerr er, int fd) { int r = fcntl(fd, F_GETFD); if(r == -1) send_errno(er,errno); return r; /* mask with FD_CLOEXEC? */ }
int posix_io_dup(cerr er, int fd) { int newfd = dup(fd); if(newfd == -1) send_errno(er,errno); return newfd; }
int posix_io_lseek(cerr er, int filedes, int argoffset, int whence) { off_t offset = lseek(filedes, argoffset, whence); if(offset == (off_t)-1) send_errno(er,errno); return offset; }
int posix_io_readbuf(cerr er, int fd, word8array buf, int len, int start) { int bytes_read = read(fd, (stringbuf(buf)) + start, len); if(bytes_read == -1) send_errno(er,errno); return bytes_read; }
intpair posix_io_pipe(cerr er, unit unused) { int fds[2]; ptr_t pair; if(pipe(fds) == -1) send_errno(er, errno); pair = alloc_intint(fds[0], fds[1]); return pair; }
string posix_io_read(cerr er, int fd, int size) { char* buf = NULL; string vec = alloc_uninit_string(size,&buf); int bytes_read = read(fd,buf,size); if(bytes_read==-1) send_errno(er,errno); else adjust_stringlen(vec,bytes_read); return vec; }
wordpair posix_io_fcntl_gfl(cerr er, int fd) { int r = fcntl(fd, F_GETFL); word flags; word mode; ptr_t pair; if(r == -1) send_errno(er,errno); flags = r & (~O_ACCMODE); mode = r & O_ACCMODE; pair = alloc_intint(flags, mode); return pair; }
void handle_client_request(int clientfd) { static char req_buff[2048]; struct iovec iov; iov.iov_base = req_buff; iov.iov_len = sizeof(req_buff)-1; unsigned char cmsg_buff[CMSG_SPACE(sizeof(struct ucred))]; struct msghdr msg; msg.msg_name = NULL; msg.msg_namelen = 0; msg.msg_iov = &iov; msg.msg_iovlen = 1; msg.msg_control = cmsg_buff; msg.msg_controllen = sizeof(cmsg_buff); msg.msg_flags = 0; ssize_t n; n = recvmsg(clientfd, &msg, 0); if (n == 0) { syslog(LOG_INFO, "Ignoring empty message from client.\n"); return; } else if (n < 0) { syslog(LOG_ERR, "Error retrieving message from client: %s\n", strerror(errno)); return; } if (msg.msg_controllen != sizeof(cmsg_buff)) { errno = EINVAL; if (send_errno(clientfd) < 0) { syslog(LOG_ERR, "send_errno() failed when attempting to notify client of invalid or non-existent cmsg: %s\n", strerror(errno)); } } else { struct ucred *ucredptr; ucredptr = (struct ucred *) CMSG_DATA((struct cmsghdr *) cmsg_buff); serve_client_request(clientfd, req_buff, ucredptr); } }
string os_filesys_tmpname(cerr er) { #ifdef AVOID_TMPNAM char buf[] = "/tmp/tnXXXXXX"; int fd = mkstemp(buf); if(fd == -1){ send_errno(er,errno); *buf = 0; } else close(fd); return cstring2mlstring_alloc(buf); #else char* buf; string res = alloc_uninit_string(L_tmpnam,&buf); char *result = tmpnam(buf); assert(result == buf); adjust_stringlen(res,strlen(buf)); return res; #endif }
int main(void) { struct stat statbuf; if (fstat(STDIN_FILENO, &statbuf) < 0) { perror("fstat(2) failed for stdin"); exit(EXIT_FAILURE); } if (!S_ISSOCK(statbuf.st_mode)) { fprintf(stderr, "Fatal: stdin is not a socket\n"); exit(EXIT_FAILURE); } if (fstat(STDOUT_FILENO, &statbuf) < 0) { perror("fstat(2) failed for stdout"); exit(EXIT_FAILURE); } if (!S_ISSOCK(statbuf.st_mode)) { fprintf(stderr, "Fatal: stdout is not a socket\n"); exit(EXIT_FAILURE); } int optval = 1; if (setsockopt(STDOUT_FILENO, SOL_SOCKET, SO_PASSCRED, &optval, sizeof(optval)) < 0) { perror("setsockopt(2) failed when trying to set SO_PASSCRED"); exit(EXIT_FAILURE); } static char linebuff[LINE_MAX]; ssize_t msg_len; unsigned char cmsg_buff[CMSG_SPACE(sizeof(struct ucred))]; struct iovec iov; iov.iov_base = linebuff; iov.iov_len = sizeof(linebuff)-1; struct msghdr msg; msg.msg_name = NULL; msg.msg_namelen = 0; msg.msg_iov = &iov; msg.msg_iovlen = 1; msg.msg_control = cmsg_buff; msg.msg_controllen = CMSG_LEN(sizeof(struct ucred)); msg.msg_flags = 0; while ((msg_len = recvmsg(STDIN_FILENO, &msg, 0)) > 0) { char *request = iov.iov_base; if (request[msg_len-1] == '\n') request[--msg_len] = '\0'; if (msg.msg_controllen != CMSG_LEN(sizeof(struct ucred))) { errno = EINVAL; if (send_errno(STDOUT_FILENO) < 0) { fprintf(stderr, "send_errno() failed when attempting to notify client of invalid or non-existent cmsg: %s\n", strerror(errno)); } } else { struct ucred *ucredptr; ucredptr = (struct ucred *) CMSG_DATA((struct cmsghdr *) cmsg_buff); handle_request(request, ucredptr); } iov.iov_base = linebuff; iov.iov_len = sizeof(linebuff)-1; msg.msg_name = NULL; msg.msg_namelen = 0; msg.msg_iov = &iov; msg.msg_iovlen = 1; msg.msg_control = cmsg_buff; msg.msg_controllen = CMSG_LEN(sizeof(struct ucred)); msg.msg_flags = 0; } if (msg_len < 0) { perror("recvmsg(2) error"); exit(EXIT_FAILURE); } return 0; }