1 /* $OpenBSD: dup2_self.c,v 1.3 2003/07/31 21:48:08 deraadt Exp $ */ 2 /* 3 * Written by Artur Grabowski <art@openbsd.org> 2002 Public Domain. 4 */ 5 #include <stdio.h> 6 #include <stdlib.h> 7 #include <unistd.h> 8 #include <err.h> 9 #include <fcntl.h> 10 11 /* 12 * We're testing a small tweak in dup2 semantics. Normally dup and dup2 13 * will clear the close-on-exec flag on the new fd (which appears to be 14 * an implementation mistake from start and not some planned behavior). 15 * In todays implementations of dup and dup2 we have to make an effort 16 * to really clear that flag. But all tested implementations of dup2 have 17 * another tweak. If we dup2(old, new) when old == new, the syscall 18 * short-circuits and returns early (because there is no need to do all 19 * the work (and there is a risk for serious mistakes)). So although the 20 * docs say that dup2 should "take 'old', close 'new' perform a dup(2) of 21 * 'old' into 'new'" the docs are not really followed because close-on-exec 22 * is not cleared on 'new'. 23 * 24 * Since everyone has this bug, we pretend that this is the way it is 25 * supposed to be and test here that it really works that way. 26 * 27 * This is a fine example on where two separate implementation fuckups 28 * take out each other and make the end-result the way it was meant to be. 29 */ 30 31 int 32 main(int argc, char *argv[]) 33 { 34 int orgfd, fd1, fd2; 35 char temp[] = "/tmp/dup2XXXXXXXXX"; 36 37 if ((orgfd = mkstemp(temp)) < 0) 38 err(1, "mkstemp"); 39 remove(temp); 40 41 if (ftruncate(orgfd, 1024) != 0) 42 err(1, "ftruncate"); 43 44 if ((fd1 = dup(orgfd)) < 0) 45 err(1, "dup"); 46 47 /* Set close-on-exec */ 48 if (fcntl(fd1, F_SETFD, 1) != 0) 49 err(1, "fcntl(F_SETFD)"); 50 51 if ((fd2 = dup2(fd1, fd1)) < 0) 52 err(1, "dup2"); 53 54 /* Test 1: Do we get the right fd? */ 55 if (fd2 != fd1) 56 errx(1, "dup2 didn't give us the right fd"); 57 58 /* Test 2: Was close-on-exec cleared? */ 59 if (fcntl(fd2, F_GETFD) == 0) 60 errx(1, "dup2 cleared close-on-exec"); 61 62 return 0; 63 } 64