/* * Program to test for possible misbehaviour upon accessing /dev/tty * when the `real' ctty device isn't open. * * Run this with a tty device pathname as an argument. For the test to * be valid, the tty device must be one nothing else has open. */ #include #include #include #include #include #include #include #include #include #include extern const char *__progname; static const char *ttydev; static int ttyfd; static int devttyfd; static void forkchild(void) { pid_t kid; int status; fflush(0); kid = fork(); if (kid == 0) return; wait(&status); if (WIFEXITED(status)) { if (WEXITSTATUS(status) == 0) exit(0); printf("exit %d\n",(int)WEXITSTATUS(status)); exit(1); } if (WIFSIGNALED(status)) { printf("signal %d (%s)%s\n",WTERMSIG(status),(WTERMSIG(status)>=NSIG)?"unknown":sys_siglist[WTERMSIG(status)],WCOREDUMP(status)?" - core dumped":""); exit(1); } printf("incomprehensible exit status %d (%#x)\n",status,status); exit(1); } int main(int, char **); int main(int ac, char **av) { int n; if (ac != 2) { fprintf(stderr,"Usage: %s tty-device\n",__progname); exit(1); } ttydev = av[1]; // setsid() is defined to fail for process group leaders (why?!) if (getpgrp() == getpid()) forkchild(); // Make us session leader of a new session if (setsid() < 0) { fprintf(stderr,"%s: setsid() failed: %s\n",__progname,strerror(errno)); exit(1); } // We want to be able to print stuff even if stdout is a tty... signal(SIGTTOU,SIG_IGN); // Open the specified tty device. ttyfd = open(ttydev,O_RDWR|O_NONBLOCK,0); if (ttyfd < 0) { fprintf(stderr,"%s: can't open %s: %s\n",__progname,ttydev,strerror(errno)); exit(1); } // Make it our ctty if (ioctl(ttyfd,TIOCSCTTY,0) < 0) { fprintf(stderr,"%s: TIOCSCTTY failed: %s\n",__progname,strerror(errno)); exit(1); } // Open /dev/tty devttyfd = open("/dev/tty",O_RDWR|O_NONBLOCK,0); if (ttyfd < 0) { fprintf(stderr,"%s: can't open /dev/tty: %s\n",__progname,strerror(errno)); exit(1); } // Close the real ctty close(ttyfd); // Test: try to access it via /dev/tty n = write(devttyfd,"hello\r\n",7); if (n < 0) { fprintf(stderr,"%s: test write failed: %s\n",__progname,strerror(errno)); exit(1); } if (n != 7) { fprintf(stderr,"%s: test write returned %d, not 7\n",__progname,n); exit(1); } fprintf(stderr,"%s: test write worked\n",__progname); exit(0); }