From 3cea43ccbe0bbc16b139caa0586d32d75fed060c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 5 Oct 2012 11:01:47 -0700 Subject: [PATCH] Split out I/O functions to separate file Signed-off-by: Keith Packard --- Makefile | 6 +- fdpass.c | 116 ++++++++++++++++++++++++++++++++++++++ fdpass.h | 35 ++++++++++++ fdpassing.c | 157 +++++++++++++++++----------------------------------- 4 files changed, 206 insertions(+), 108 deletions(-) create mode 100644 fdpass.c create mode 100644 fdpass.h diff --git a/Makefile b/Makefile index e208bc1..81ea87d 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,6 @@ CFLAGS=-O0 -g -fdpassing: fdpassing.o - $(CC) -o $@ fdpassing.o \ No newline at end of file +all: fdpassing + +fdpassing: fdpassing.o fdpass.o + $(CC) -o $@ fdpassing.o fdpass.o diff --git a/fdpass.c b/fdpass.c new file mode 100644 index 0000000..ed67713 --- /dev/null +++ b/fdpass.c @@ -0,0 +1,116 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "fdpass.h" + +int +sock_fd_read(int sock, void *buf, ssize_t bufsize, int *fd) +{ + ssize_t size; + struct msghdr msg; + struct iovec iov; + union { + struct cmsghdr cmsghdr; + char control[CMSG_SPACE(sizeof (int))]; + } cmsgu; + struct cmsghdr *cmsg; + + iov.iov_base = buf; + iov.iov_len = bufsize; + + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + if (fd) { + msg.msg_control = cmsgu.control; + msg.msg_controllen = sizeof(cmsgu.control); + size = recvmsg (sock, &msg, 0); + } else { + size = read (sock, buf, bufsize); + } + + if (size < 0) { + perror("recvmsg"); + exit(1); + } + + + if (fd && (cmsg = CMSG_FIRSTHDR(&msg)) && + cmsg->cmsg_len == CMSG_LEN(sizeof(int))) { + if (cmsg->cmsg_level != SOL_SOCKET) { + fprintf (stderr, "invalid cmsg_level %d\n", + cmsg->cmsg_level); + exit(1); + } + if (cmsg->cmsg_type != SCM_RIGHTS) { + fprintf (stderr, "invalid cmsg_type %d\n", + cmsg->cmsg_type); + exit(1); + } + + *fd = *((int *) CMSG_DATA(cmsg)); + printf ("received fd %d\n", *fd); + } else if (fd) { + *fd = -1; + } + return size; +} + +ssize_t +sock_fd_write(int sock, void *buf, ssize_t buflen, int fd) +{ + ssize_t size; + struct msghdr msg; + struct iovec iov; + union { + struct cmsghdr cmsghdr; + char control[CMSG_SPACE(sizeof (int))]; + } cmsgu; + struct cmsghdr *cmsg; + + iov.iov_base = buf; + iov.iov_len = buflen; + + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + + if (fd != -1) { + msg.msg_control = cmsgu.control; + msg.msg_controllen = sizeof(cmsgu.control); + + cmsg = CMSG_FIRSTHDR(&msg); + cmsg->cmsg_len = CMSG_LEN(sizeof (int)); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + + printf ("passing fd %d\n", fd); + *((int *) CMSG_DATA(cmsg)) = fd; + } else { + msg.msg_control = NULL; + msg.msg_controllen = 0; + printf ("not passing fd\n"); + } + + size = sendmsg(sock, &msg, 0); + + if (size < 0) + perror ("sendmsg"); + return size; +} diff --git a/fdpass.h b/fdpass.h new file mode 100644 index 0000000..e3cc915 --- /dev/null +++ b/fdpass.h @@ -0,0 +1,35 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _FDPASS_H_ +#define _FDPASS_H_ + +#include +#include +#include +#include +#include +#include +#include + +int +sock_fd_read(int sock, void *buf, ssize_t bufsize, int *fd); + +ssize_t +sock_fd_write(int sock, void *buf, ssize_t buflen, int fd); + +#endif diff --git a/fdpassing.c b/fdpassing.c index 59941cb..53642ab 100644 --- a/fdpassing.c +++ b/fdpassing.c @@ -15,129 +15,73 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#include -#include -#include -#include -#include -#include +#include "fdpass.h" -int -sock_fd_read(int sock, void *buf, ssize_t bufsize, int *fd) +char * +itoa(int i, char *buf) { - ssize_t size; - struct msghdr msg; - struct iovec iov; - union { - struct cmsghdr cmsghdr; - char control[CMSG_SPACE(sizeof (int))]; - } cmsgu; - struct cmsghdr *cmsg; + buf += 10; + *--buf = '\0'; + do { + *--buf = '0' + i % 10; + } while ((i /= 10)); + return buf; +} - iov.iov_base = buf; - iov.iov_len = bufsize; - - msg.msg_name = NULL; - msg.msg_namelen = 0; - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - msg.msg_control = cmsgu.control; - msg.msg_controllen = sizeof(cmsgu.control); - - size = recvmsg (sock, &msg, 0); - if (size < 0) { - perror("recvmsg"); - exit(1); - } - - cmsg = CMSG_FIRSTHDR(&msg); - if (cmsg && - cmsg->cmsg_len == CMSG_LEN(sizeof(int))) { - if (cmsg->cmsg_level != SOL_SOCKET) { - fprintf (stderr, "invalid cmsg_level %d\n", - cmsg->cmsg_level); - exit(1); - } - if (cmsg->cmsg_type != SCM_RIGHTS) { - fprintf (stderr, "invalid cmsg_type %d\n", - cmsg->cmsg_type); - exit(1); - } - - *fd = *((int *) CMSG_DATA(cmsg)); - printf ("received fd %d\n", *fd); - } else { - *fd = -1; - } - return size; +void +handler(int i) +{ + char buf[12]; + char *b = itoa(i, buf); + + write (2, "signal ", 7); + write (2, b, strlen(b)); + write (2, "\n", 1); + _exit(1); } void child(int sock) { - int fd; + int fd, *fdp; char buf[16]; ssize_t size; + int i = 0; - size = sock_fd_read(sock, buf, sizeof(buf), &fd); - if (size == 0) - return; - printf ("read %d\n", size); - if (fd != -1) - write(fd, "hello, world\n", 13); -} - -ssize_t -sock_fd_write(int sock, void *buf, ssize_t buflen, int fd) -{ - ssize_t size; - struct msghdr msg; - struct iovec iov; - union { - struct cmsghdr cmsghdr; - char control[CMSG_SPACE(sizeof (int))]; - } cmsgu; - struct cmsghdr *cmsg; - - iov.iov_base = buf; - iov.iov_len = buflen; - - msg.msg_name = NULL; - msg.msg_namelen = 0; - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - - if (fd != -1) { - msg.msg_control = cmsgu.control; - msg.msg_controllen = sizeof(cmsgu.control); - - cmsg = CMSG_FIRSTHDR(&msg); - cmsg->cmsg_len = CMSG_LEN(sizeof (int)); - cmsg->cmsg_level = SOL_SOCKET; - cmsg->cmsg_type = SCM_RIGHTS; - - printf ("passing fd %d\n", fd); - *((int *) CMSG_DATA(cmsg)) = fd; - } else { - msg.msg_control = NULL; - msg.msg_controllen = 0; - printf ("not passing fd\n"); + signal(SIGSEGV, handler); + sleep(1); + for (;;) { + if (!(i & 1)) + fdp = NULL; + else + fdp = &fd; + size = sock_fd_read(sock, buf, sizeof(buf), fdp); + if (size == 0) + break; + printf ("read %d\n", size); + if (fdp && fd != -1) + write(fd, "hello, world\n", 13); + i++; } - - size = sendmsg(sock, &msg, 0); - - if (size < 0) - perror ("sendmsg"); - return size; + printf ("child done\n"); } void parent(int sock) { ssize_t size; - size = sock_fd_write(sock, "1", 1, 1); + int i; + int fd; - printf ("wrote %d\n", size); + for (i = 0; i < 8; i++) { + if ((i & 1)) + fd = -1; + else + fd = 1; + size = sock_fd_write(sock, "1", 1, fd); + printf ("wrote %d\n", size); + } + close(sock); } int @@ -152,15 +96,16 @@ main(int argc, char **argv) } switch ((pid = fork())) { case 0: + close(sv[0]); child(sv[1]); break; case -1: perror("fork"); exit(1); default: + close(sv[1]); parent(sv[0]); - sleep(1); - kill(pid, SIGTERM); break; } + return 0; }