Example.No.1:
通过socketpair打开两个连接起来的Unix套接字,一个用于进程本身读取内容,并输出到进程本身的标准输出,另一个则用于子进程传递通过Unix套接字发送excel的一个进程打开的文件描述符,通过sendmsg的辅助数据传递
进程本身代码:
- #include <stdio.h>
- #include <stdlib.h>
- #include <sys/socket.h>
- #include <unistd.h>
- #include <string.h>
- #include <errno.h>
- #include <sys/wait.h>
- #include <fcntl.h>
-
- #define BUFSIZE 4096
-
-
- int read_fd(int fd,void* ptr,size_t nbytes,int* recvfd ) {
- struct msghdr msg;
- struct iovec iov[1];
- ssize_t n;
- union {
- struct cmsghdr cm;
- char control[CMSG_SPACE(sizeof(int))];
- }control_un;
-
- msg.msg_control = control_un.control;
- msg.msg_controllen = sizeof(control_un.control);
- msg.msg_name = NULL;
- msg.msg_namelen = 0;
- iov[0].iov_base = ptr;
- iov[0].iov_len = nbytes;
- msg.msg_iov = iov;
- msg.msg_iovlen = 1;
- if ((n = recvmsg(fd,&msg,0)) <= 0) {
- return n;
- }
- struct cmsghdr* cmptr;
- if ((cmptr = CMSG_FIRSTHDR(&msg)) != NULL && cmptr->cmsg_len == CMSG_LEN(sizeof(int))) {
- if (cmptr->cmsg_level != SOL_SOCKET) {
- printf("control level != SOL_SOCKET\n");
- exit(1);
- }
-
- if (cmptr->cmsg_type != SCM_RIGHTS) {
- printf("control level != SCM_RIGHTS\n");
- exit(1);
- }
- *recvfd = *(int*)CMSG_DATA(cmptr);
- }else {
- *recvfd = -1;
- }
- }
- int my_open(char* pathname,int mode) {
- int fd,sockfd[2],status;
- char c;
- if (socketpair(AF_LOCAL,SOCK_STREAM,0,sockfd) < 0) {
- printf("setsockpair error: %s\n",strerror(errno));
- exit(1);
- }
- int childpid;
- if ((childpid = fork()) < 0) {
- printf("fork error: %s\n",strerror(errno));
- exit(1);
- }else if (childpid == 0) {
- char argsockfd[10],argmode[10];
- snprintf(argsockfd,sizeof(argsockfd),"%d",sockfd[1]);
- snprintf(argmode,sizeof(argmode),mode);
- execl("./openfile","openfile",argsockfd,pathname,argmode,(char*)NULL);
- }
- close(sockfd[1]);
- if (waitpid(childpid,&status,0) < 0) {
- printf("waitpid error: %s\n",strerror(errno));
- exit(1);
- }
- if (WIFEXITED(status) == 0) {
- printf("child process did not terminate\n");
- exit(1);
- }
-
- if ((status = WEXITSTATUS(status)) == 0) {
- if (read_fd(sockfd[0],&c,1,&fd) < 0) {
- printf("read_fd error\n");
- exit(1);
- }
- }else {
- errno = status;
- fd = -1;
- }
- close(sockfd[0]);
- return fd;
- }
- int main(int argc,char** argv) {
- if (argc != 2) {
- printf("please add <pathname>\n");
- exit(1);
- }
-
- int fd;
- if ((fd = my_open(argv[1],O_RDONLY)) < 0) {
- printf("can't open %s\n",argv[1]);
- exit(1);
- }
- char buf[BUFSIZE];
- int n;
- while ((n = read(fd,buf,BUFSIZE)) > 0) {
- if (write(STDOUT_FILENO,n) != n) {
- printf("write error: %s\n",strerror(errno));
- exit(1);
- }
- }
- return 0;
- }
openfile进程代码:
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <sys/socket.h>
- #include <fcntl.h>
- #include <string.h>
- #include <errno.h>
-
- int write_fd(int fd,int sendfd) {
- struct msghdr msg;
- struct iovec iov[1];
-
- union {
- struct cmsghdr cmsg;
- char controls[CMSG_SPACE(sizeof(int))];
- }control_un;
-
- msg.msg_name = NULL;
- msg.msg_namelen = 0;
- msg.msg_control = control_un.controls;
- msg.msg_controllen = sizeof(control_un.controls);
- struct cmsghdr* cmptr;
- cmptr = CMSG_FIRSTHDR(&msg);
- cmptr->cmsg_len = CMSG_LEN(sizeof(int));
- cmptr->cmsg_level = SOL_SOCKET;
- cmptr->cmsg_type = SCM_RIGHTS;
- *(int*)(CMSG_DATA(cmptr)) = sendfd;
- iov[0].iov_base = ptr;
- iov[0].iov_len = nbytes;
- msg.msg_iov = iov;
- msg.msg_iovlen = 1;
- return sendmsg(fd,0);
- }
-
- int main(int argc,char** argv) {
- if (argc != 4) {
- printf("please check your input-arguments\n");
- exit(1);
- }
-
- int fd;
- if ((fd = open(argv[2],atoi(argv[3]))) < 0) {
- printf("open %s fail: error reason: %s\n",argv[2],strerror(errno));
- exit(1);
- }
-
- int n;
- if ((n = write_fd(atoi(argv[1]),"",fd)) < 0) {
- exit(n);
- }
- exit(0);
- }