1#!/bin/sh 2 3set -u 4prog=$(basename "$0" .sh) 5cat > /tmp/$prog.c <<EOF 6/* \$Id: pddupfd.c,v 1.6 2026/07/04 17:48:47 kostik Exp kostik $ */ 7 8#include <sys/types.h> 9#include <sys/fcntl.h> 10#include <sys/mman.h> 11#include <sys/procdesc.h> 12#include <sys/resource.h> 13#include <sys/wait.h> 14#include <machine/atomic.h> 15#include <err.h> 16#include <signal.h> 17#include <stdio.h> 18#include <stdlib.h> 19#include <unistd.h> 20 21#define MY_SYS_pdopenpid 603 22#define MY_SYS_pddupfd 604 23 24static int 25my_pdopenpid(pid_t pid, int flags) 26{ 27 return (syscall(MY_SYS_pdopenpid, pid, flags)); 28} 29 30static int 31my_pddupfd(pid_t pid, int remote_fd, int flags) 32{ 33 return (syscall(MY_SYS_pddupfd, pid, remote_fd, flags)); 34} 35 36static void 37check(int fd, int child, int *comm) 38{ 39 struct __wrusage wu; 40 struct __siginfo si; 41 int error, f, pp, rfd, status, workfd; 42 char cmd[128]; 43 44 error = pdgetpid(fd, &pp); 45 if (error == -1) 46 err(1, "pgdetpid"); 47 printf("child pid %d %d\n", child, pp); 48 49 while ((rfd = (int)atomic_load_int(comm)) == -1) 50 ; 51 if (rfd == -2) 52 errx(1, "open in child failed"); 53 workfd = my_pddupfd(fd, rfd, 0); 54 if (workfd == -1) 55 err(1, "pddupfd"); 56 57 f = fcntl(workfd, F_GETFD); 58 if (f == -1) 59 err(1, "F_GETFD %d", workfd); 60 f &= ~FD_CLOEXEC; 61 error = fcntl(workfd, F_SETFD, f); 62 if (error == -1) 63 err(1, "F_SETFD %d", workfd); 64 65 snprintf(cmd, sizeof(cmd), "cat 0<&%d", workfd); 66 system(cmd); 67 close(workfd); 68 69 atomic_store_int(comm, -1); 70 71 error = pdwait(fd, &status, WEXITED, &wu, &si); 72 if (error == -1) 73 err(1, "pdwait"); 74 printf("exited pid %d status %#x si.si_status %#x si.si_code %#x\n", 75 pp, status, si.si_status, si.si_code); 76} 77 78int 79main(void) 80{ 81 int *comm; 82 pid_t child; 83 int fd, workfd; 84 85 comm = mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED | 86 MAP_ANONYMOUS, -1, 0); 87 if (comm == MAP_FAILED) 88 err(1, "mmap"); 89 atomic_store_int(comm, -1); 90 91 child = fork(); 92 if (child == -1) 93 err(1, "fork"); 94 if (child == 0) { 95 workfd = open("/etc/passwd", O_RDONLY); 96 if (workfd == -1) { 97 atomic_store_int(comm, -2); 98 err(1, "open"); 99 } 100 atomic_store_int(comm, workfd); 101 while ((int)atomic_load_int(comm) >= 0) 102 sleep(1); 103 _exit(0x123); 104 } 105 106 fd = my_pdopenpid(child, 0); 107 if (fd == -1) 108 err(1, "pdopenpid"); 109 110 check(fd, child, comm); 111 close(fd); 112} 113EOF 114 115cc -o /tmp/$prog -Wall -Wextra -g -O0 /tmp/$prog.c || exit 1 116 117../testcases/swap/swap -t 2m -i 20 & 118sleep 2 119 120cd /tmp 121s=0 122start=`date +%s` 123while [ $((`date +%s`- start)) -lt 120 ]; do 124 ./$prog > /dev/null ; s=$? 125done 126[ $s -eq 124 ] && s=0 127while pkill swap; do :; done 128wait 129cd - 130 131rm /tmp/$prog /tmp/$prog.c 132exit $s 133