t_ttyio.c revision 272343
1272343Sngie/* $NetBSD: t_ttyio.c,v 1.2 2011/04/19 20:07:53 martin Exp $ */ 2272343Sngie 3272343Sngie/* 4272343Sngie * Copyright (c) 2001, 2008 The NetBSD Foundation, Inc. 5272343Sngie * All rights reserved. 6272343Sngie * 7272343Sngie * This code is derived from software contributed to The NetBSD Foundation 8272343Sngie * by Andrew Brown. 9272343Sngie * 10272343Sngie * Redistribution and use in source and binary forms, with or without 11272343Sngie * modification, are permitted provided that the following conditions 12272343Sngie * are met: 13272343Sngie * 1. Redistributions of source code must retain the above copyright 14272343Sngie * notice, this list of conditions and the following disclaimer. 15272343Sngie * 2. Redistributions in binary form must reproduce the above copyright 16272343Sngie * notice, this list of conditions and the following disclaimer in the 17272343Sngie * documentation and/or other materials provided with the distribution. 18272343Sngie * 19272343Sngie * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20272343Sngie * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21272343Sngie * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22272343Sngie * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23272343Sngie * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24272343Sngie * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25272343Sngie * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26272343Sngie * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27272343Sngie * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28272343Sngie * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29272343Sngie * POSSIBILITY OF SUCH DAMAGE. 30272343Sngie */ 31272343Sngie 32272343Sngie#include <sys/cdefs.h> 33272343Sngie__COPYRIGHT("@(#) Copyright (c) 2008\ 34272343Sngie The NetBSD Foundation, inc. All rights reserved."); 35272343Sngie__RCSID("$NetBSD: t_ttyio.c,v 1.2 2011/04/19 20:07:53 martin Exp $"); 36272343Sngie 37272343Sngie#include <sys/types.h> 38272343Sngie#include <sys/wait.h> 39272343Sngie 40272343Sngie#include <err.h> 41272343Sngie#include <errno.h> 42272343Sngie#include <signal.h> 43272343Sngie#include <stdio.h> 44272343Sngie#include <stdlib.h> 45272343Sngie#include <string.h> 46272343Sngie#include <termios.h> 47272343Sngie#include <unistd.h> 48272343Sngie 49272343Sngie#if defined(__NetBSD__) 50272343Sngie#include <util.h> 51272343Sngie#elif defined(__bsdi__) 52272343Sngieint openpty(int *, int *, char *, struct termios *, struct winsize *); 53272343Sngie#elif defined(__FreeBSD__) 54272343Sngie#include <libutil.h> 55272343Sngie#else 56272343Sngie#error where openpty? 57272343Sngie#endif 58272343Sngie 59272343Sngie#include <atf-c.h> 60272343Sngie 61272343Sngie#define REQUIRE_ERRNO(x, v) ATF_REQUIRE_MSG(x != v, "%s: %s", #x, strerror(errno)) 62272343Sngie 63272343SngieATF_TC(ioctl); 64272343SngieATF_TC_HEAD(ioctl, tc) 65272343Sngie{ 66272343Sngie atf_tc_set_md_var(tc, "descr", 67272343Sngie "Checks that ioctl calls are restarted " 68272343Sngie "properly after being interrupted"); 69272343Sngie} 70272343Sngie 71272343Sngie/* ARGSUSED */ 72272343Sngiestatic void 73272343Sngiesigchld(int nsig) 74272343Sngie{ 75272343Sngie REQUIRE_ERRNO(wait(NULL), -1); 76272343Sngie} 77272343Sngie 78272343SngieATF_TC_BODY(ioctl, tc) 79272343Sngie{ 80272343Sngie int m, s, rc; 81272343Sngie char name[128], buf[128]; 82272343Sngie struct termios term; 83272343Sngie struct sigaction sa; 84272343Sngie 85272343Sngie /* unbuffer stdout */ 86272343Sngie setbuf(stdout, NULL); 87272343Sngie 88272343Sngie /* 89272343Sngie * Create default termios settings for later use 90272343Sngie */ 91272343Sngie memset(&term, 0, sizeof(term)); 92272343Sngie term.c_iflag = TTYDEF_IFLAG; 93272343Sngie term.c_oflag = TTYDEF_OFLAG; 94272343Sngie term.c_cflag = TTYDEF_CFLAG; 95272343Sngie term.c_lflag = TTYDEF_LFLAG; 96272343Sngie cfsetspeed(&term, TTYDEF_SPEED); 97272343Sngie 98272343Sngie /* get a tty */ 99272343Sngie REQUIRE_ERRNO(openpty(&m, &s, name, &term, NULL), -1); 100272343Sngie 101272343Sngie switch (fork()) { 102272343Sngie case -1: 103272343Sngie atf_tc_fail("fork(): %s", strerror(errno)); 104272343Sngie /* NOTREACHED */ 105272343Sngie case 0: 106272343Sngie /* wait for parent to get set up */ 107272343Sngie (void)sleep(1); 108272343Sngie (void)printf("child1: exiting\n"); 109272343Sngie exit(0); 110272343Sngie /* NOTREACHED */ 111272343Sngie default: 112272343Sngie (void)printf("parent: spawned child1\n"); 113272343Sngie break; 114272343Sngie } 115272343Sngie 116272343Sngie switch (fork()) { 117272343Sngie case -1: 118272343Sngie atf_tc_fail("fork(): %s", strerror(errno)); 119272343Sngie /* NOTREACHED */ 120272343Sngie case 0: 121272343Sngie /* wait for parent to get upset */ 122272343Sngie (void)sleep(2); 123272343Sngie /* drain the tty q */ 124272343Sngie if (read(m, buf, sizeof(buf)) == -1) 125272343Sngie err(1, "read"); 126272343Sngie (void)printf("child2: exiting\n"); 127272343Sngie exit(0); 128272343Sngie /* NOTREACHED */ 129272343Sngie default: 130272343Sngie (void)printf("parent: spawned child2\n"); 131272343Sngie break; 132272343Sngie } 133272343Sngie 134272343Sngie /* set up a restarting signal handler */ 135272343Sngie (void)sigemptyset(&sa.sa_mask); 136272343Sngie sa.sa_handler = sigchld; 137272343Sngie sa.sa_flags = SA_RESTART; 138272343Sngie REQUIRE_ERRNO(sigaction(SIGCHLD, &sa, NULL), -1); 139272343Sngie 140272343Sngie /* put something in the output q */ 141272343Sngie REQUIRE_ERRNO(write(s, "Hello world\n", 12), -1); 142272343Sngie 143272343Sngie /* ask for output to drain but don't drain it */ 144272343Sngie rc = 0; 145272343Sngie if (tcsetattr(s, TCSADRAIN, &term) == -1) { 146272343Sngie (void)printf("parent: tcsetattr: %s\n", strerror(errno)); 147272343Sngie rc = 1; 148272343Sngie } 149272343Sngie 150272343Sngie /* wait for last child */ 151272343Sngie sa.sa_handler = SIG_DFL; 152272343Sngie REQUIRE_ERRNO(sigaction(SIGCHLD, &sa, NULL), -1); 153272343Sngie (void) wait(NULL); 154272343Sngie 155272343Sngie ATF_REQUIRE_EQ(rc, 0); 156272343Sngie} 157272343Sngie 158272343SngieATF_TP_ADD_TCS(tp) 159272343Sngie{ 160272343Sngie ATF_TP_ADD_TC(tp, ioctl); 161272343Sngie 162272343Sngie return atf_no_error(); 163272343Sngie} 164