1f08c3bdfSopenharmony_ci/* 2f08c3bdfSopenharmony_ci * 3f08c3bdfSopenharmony_ci * Copyright (c) International Business Machines Corp., 2002 4f08c3bdfSopenharmony_ci * 5f08c3bdfSopenharmony_ci * This program is free software; you can redistribute it and/or modify 6f08c3bdfSopenharmony_ci * it under the terms of the GNU General Public License as published by 7f08c3bdfSopenharmony_ci * the Free Software Foundation; either version 2 of the License, or 8f08c3bdfSopenharmony_ci * (at your option) any later version. 9f08c3bdfSopenharmony_ci * 10f08c3bdfSopenharmony_ci * This program is distributed in the hope that it will be useful, 11f08c3bdfSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 12f08c3bdfSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 13f08c3bdfSopenharmony_ci * the GNU General Public License for more details. 14f08c3bdfSopenharmony_ci * 15f08c3bdfSopenharmony_ci * You should have received a copy of the GNU General Public License 16f08c3bdfSopenharmony_ci * along with this program; if not, write to the Free Software 17f08c3bdfSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18f08c3bdfSopenharmony_ci */ 19f08c3bdfSopenharmony_ci 20f08c3bdfSopenharmony_ci/* 12/24/2002 Port to LTP robbiew@us.ibm.com */ 21f08c3bdfSopenharmony_ci/* 06/30/2001 Port to Linux nsharoff@us.ibm.com */ 22f08c3bdfSopenharmony_ci 23f08c3bdfSopenharmony_ci#define _GNU_SOURCE 24f08c3bdfSopenharmony_ci#include <stdio.h> 25f08c3bdfSopenharmony_ci#include <stdlib.h> 26f08c3bdfSopenharmony_ci#include <unistd.h> 27f08c3bdfSopenharmony_ci#include <errno.h> 28f08c3bdfSopenharmony_ci#include <signal.h> 29f08c3bdfSopenharmony_ci#include <fcntl.h> 30f08c3bdfSopenharmony_ci#include <sys/wait.h> 31f08c3bdfSopenharmony_ci#include <sys/poll.h> 32f08c3bdfSopenharmony_ci 33f08c3bdfSopenharmony_ci/** LTP Port **/ 34f08c3bdfSopenharmony_ci#include "test.h" 35f08c3bdfSopenharmony_ci#include "safe_macros.h" 36f08c3bdfSopenharmony_ci 37f08c3bdfSopenharmony_cichar *TCID = "hangup01"; /* Test program identifier. */ 38f08c3bdfSopenharmony_ciint TST_TOTAL = 5; /* Total number of test cases. */ 39f08c3bdfSopenharmony_ci/**************/ 40f08c3bdfSopenharmony_ci 41f08c3bdfSopenharmony_ci/* 42f08c3bdfSopenharmony_ci * pty master clone device 43f08c3bdfSopenharmony_ci */ 44f08c3bdfSopenharmony_ci#define MASTERCLONE "/dev/ptmx" 45f08c3bdfSopenharmony_ci 46f08c3bdfSopenharmony_ci#define MESSAGE1 "I love Linux!" 47f08c3bdfSopenharmony_ci#define MESSAGE2 "Use the LTP for all your Linux testing needs." 48f08c3bdfSopenharmony_ci#define MESSAGE3 "For the latest version of the LTP tests, visit http://ltp.sourceforge.net" 49f08c3bdfSopenharmony_ci 50f08c3bdfSopenharmony_ci#define NUMMESSAGES 3 51f08c3bdfSopenharmony_ci 52f08c3bdfSopenharmony_ci#define BUFSZ 4096 53f08c3bdfSopenharmony_ci 54f08c3bdfSopenharmony_civoid cleanup(void); 55f08c3bdfSopenharmony_ci 56f08c3bdfSopenharmony_cipid_t childpid; 57f08c3bdfSopenharmony_ci 58f08c3bdfSopenharmony_civoid cleanup(void) 59f08c3bdfSopenharmony_ci{ 60f08c3bdfSopenharmony_ci 61f08c3bdfSopenharmony_ci int status; 62f08c3bdfSopenharmony_ci 63f08c3bdfSopenharmony_ci if (0 < childpid) { 64f08c3bdfSopenharmony_ci 65f08c3bdfSopenharmony_ci /* If the PID is still alive... */ 66f08c3bdfSopenharmony_ci if (kill(childpid, 0) == 0 || errno == ESRCH) { 67f08c3bdfSopenharmony_ci 68f08c3bdfSopenharmony_ci /* KILL IT! */ 69f08c3bdfSopenharmony_ci (void)kill(childpid, 15); 70f08c3bdfSopenharmony_ci 71f08c3bdfSopenharmony_ci /* And take care of any leftover zombies. */ 72f08c3bdfSopenharmony_ci if (waitpid(childpid, &status, WNOHANG) < 0) { 73f08c3bdfSopenharmony_ci tst_resm(TWARN | TERRNO, 74f08c3bdfSopenharmony_ci "waitpid(%d, ...) failed", childpid); 75f08c3bdfSopenharmony_ci } 76f08c3bdfSopenharmony_ci 77f08c3bdfSopenharmony_ci } 78f08c3bdfSopenharmony_ci 79f08c3bdfSopenharmony_ci } 80f08c3bdfSopenharmony_ci 81f08c3bdfSopenharmony_ci} 82f08c3bdfSopenharmony_ci 83f08c3bdfSopenharmony_ci/* 84f08c3bdfSopenharmony_ci * parent process for hangup test 85f08c3bdfSopenharmony_ci */ 86f08c3bdfSopenharmony_civoid parent(int masterfd, int childpid) 87f08c3bdfSopenharmony_ci{ 88f08c3bdfSopenharmony_ci char buf[BUFSZ]; 89f08c3bdfSopenharmony_ci struct pollfd pollfds[1]; 90f08c3bdfSopenharmony_ci size_t len = strlen(MESSAGE1); 91f08c3bdfSopenharmony_ci int hangupcount = 0; 92f08c3bdfSopenharmony_ci int datacount = 0; 93f08c3bdfSopenharmony_ci int status; 94f08c3bdfSopenharmony_ci int i; 95f08c3bdfSopenharmony_ci 96f08c3bdfSopenharmony_ci pollfds[0].fd = masterfd; 97f08c3bdfSopenharmony_ci pollfds[0].events = POLLIN; 98f08c3bdfSopenharmony_ci 99f08c3bdfSopenharmony_ci sleep(1); 100f08c3bdfSopenharmony_ci 101f08c3bdfSopenharmony_ci while ((i = poll(pollfds, 1, -1)) == 1) { 102f08c3bdfSopenharmony_ci if (read(masterfd, buf, len) == -1) { 103f08c3bdfSopenharmony_ci ++hangupcount; 104f08c3bdfSopenharmony_ci#ifdef DEBUG 105f08c3bdfSopenharmony_ci tst_resm(TINFO, "hangup %d", hangupcount); 106f08c3bdfSopenharmony_ci#endif 107f08c3bdfSopenharmony_ci if (hangupcount == NUMMESSAGES) { 108f08c3bdfSopenharmony_ci break; 109f08c3bdfSopenharmony_ci } 110f08c3bdfSopenharmony_ci } else { 111f08c3bdfSopenharmony_ci ++datacount; 112f08c3bdfSopenharmony_ci switch (datacount) { 113f08c3bdfSopenharmony_ci case 1: 114f08c3bdfSopenharmony_ci if (strncmp(buf, MESSAGE1, 115f08c3bdfSopenharmony_ci strlen(MESSAGE1)) != 0) { 116f08c3bdfSopenharmony_ci tst_brkm(TFAIL, cleanup, 117f08c3bdfSopenharmony_ci "unexpected message 1"); 118f08c3bdfSopenharmony_ci } 119f08c3bdfSopenharmony_ci len = strlen(MESSAGE2); 120f08c3bdfSopenharmony_ci break; 121f08c3bdfSopenharmony_ci case 2: 122f08c3bdfSopenharmony_ci if (strncmp(buf, MESSAGE2, 123f08c3bdfSopenharmony_ci strlen(MESSAGE2)) != 0) { 124f08c3bdfSopenharmony_ci tst_brkm(TFAIL, cleanup, 125f08c3bdfSopenharmony_ci "unexpected message 2"); 126f08c3bdfSopenharmony_ci } 127f08c3bdfSopenharmony_ci len = strlen(MESSAGE3); 128f08c3bdfSopenharmony_ci break; 129f08c3bdfSopenharmony_ci case 3: 130f08c3bdfSopenharmony_ci if (strncmp(buf, MESSAGE3, 131f08c3bdfSopenharmony_ci strlen(MESSAGE3)) != 0) { 132f08c3bdfSopenharmony_ci tst_brkm(TFAIL, cleanup, 133f08c3bdfSopenharmony_ci "unexpected message 3"); 134f08c3bdfSopenharmony_ci } 135f08c3bdfSopenharmony_ci break; 136f08c3bdfSopenharmony_ci default: 137f08c3bdfSopenharmony_ci tst_brkm(TFAIL, cleanup, 138f08c3bdfSopenharmony_ci "unexpected data message"); 139f08c3bdfSopenharmony_ci 140f08c3bdfSopenharmony_ci } 141f08c3bdfSopenharmony_ci } 142f08c3bdfSopenharmony_ci } 143f08c3bdfSopenharmony_ci if (i != 1) { 144f08c3bdfSopenharmony_ci tst_brkm(TFAIL, cleanup, "poll"); 145f08c3bdfSopenharmony_ci } 146f08c3bdfSopenharmony_ci while (waitpid(childpid, &status, WNOHANG) < 0 && errno != ESRCH) ; 147f08c3bdfSopenharmony_ci 148f08c3bdfSopenharmony_ci tst_resm((status == 0 ? TPASS : TFAIL), 149f08c3bdfSopenharmony_ci "child process exited with status %d", status); 150f08c3bdfSopenharmony_ci} 151f08c3bdfSopenharmony_ci 152f08c3bdfSopenharmony_ci/* 153f08c3bdfSopenharmony_ci * Child process for hangup test. Write three messages to the slave 154f08c3bdfSopenharmony_ci * pty, with a hangup after each. 155f08c3bdfSopenharmony_ci */ 156f08c3bdfSopenharmony_ciint child(int masterfd) 157f08c3bdfSopenharmony_ci{ 158f08c3bdfSopenharmony_ci int slavefd; 159f08c3bdfSopenharmony_ci char *slavename; 160f08c3bdfSopenharmony_ci 161f08c3bdfSopenharmony_ci if ((slavename = ptsname(masterfd)) == NULL) { 162f08c3bdfSopenharmony_ci printf("ptsname[child] failed: %s\n", strerror(errno)); 163f08c3bdfSopenharmony_ci return 1; 164f08c3bdfSopenharmony_ci } 165f08c3bdfSopenharmony_ci if ((slavefd = open(slavename, O_RDWR)) < 0) { 166f08c3bdfSopenharmony_ci printf("open[1] failed: %s\n", strerror(errno)); 167f08c3bdfSopenharmony_ci return 1; 168f08c3bdfSopenharmony_ci } 169f08c3bdfSopenharmony_ci if (write(slavefd, MESSAGE1, strlen(MESSAGE1)) != strlen(MESSAGE1)) { 170f08c3bdfSopenharmony_ci printf("write failed: %s\n", strerror(errno)); 171f08c3bdfSopenharmony_ci return 1; 172f08c3bdfSopenharmony_ci } 173f08c3bdfSopenharmony_ci if (close(slavefd) != 0) { 174f08c3bdfSopenharmony_ci printf("close[1] failed: %s\n", strerror(errno)); 175f08c3bdfSopenharmony_ci return 1; 176f08c3bdfSopenharmony_ci } 177f08c3bdfSopenharmony_ci if ((slavefd = open(slavename, O_RDWR)) < 0) { 178f08c3bdfSopenharmony_ci printf("open[2] failed: %s\n", strerror(errno)); 179f08c3bdfSopenharmony_ci return 1; 180f08c3bdfSopenharmony_ci } 181f08c3bdfSopenharmony_ci if (write(slavefd, MESSAGE2, strlen(MESSAGE2)) != strlen(MESSAGE2)) { 182f08c3bdfSopenharmony_ci printf("write[2] failed: %s\n", strerror(errno)); 183f08c3bdfSopenharmony_ci return 1; 184f08c3bdfSopenharmony_ci } 185f08c3bdfSopenharmony_ci if (close(slavefd) != 0) { 186f08c3bdfSopenharmony_ci printf("close[2] failed: %s\n", strerror(errno)); 187f08c3bdfSopenharmony_ci return 1; 188f08c3bdfSopenharmony_ci } 189f08c3bdfSopenharmony_ci if ((slavefd = open(slavename, O_RDWR)) < 0) { 190f08c3bdfSopenharmony_ci printf("open[3] failed: %s\n", strerror(errno)); 191f08c3bdfSopenharmony_ci return 1; 192f08c3bdfSopenharmony_ci } 193f08c3bdfSopenharmony_ci if (write(slavefd, MESSAGE3, strlen(MESSAGE3)) != strlen(MESSAGE3)) { 194f08c3bdfSopenharmony_ci printf("write[3] failed: %s\n", strerror(errno)); 195f08c3bdfSopenharmony_ci return 1; 196f08c3bdfSopenharmony_ci } 197f08c3bdfSopenharmony_ci if (close(slavefd) != 0) { 198f08c3bdfSopenharmony_ci printf("close[3] failed: %s\n", strerror(errno)); 199f08c3bdfSopenharmony_ci return 1; 200f08c3bdfSopenharmony_ci } 201f08c3bdfSopenharmony_ci return 0; 202f08c3bdfSopenharmony_ci} 203f08c3bdfSopenharmony_ci 204f08c3bdfSopenharmony_ci/* 205f08c3bdfSopenharmony_ci * main test driver 206f08c3bdfSopenharmony_ci */ 207f08c3bdfSopenharmony_ciint main(void) 208f08c3bdfSopenharmony_ci{ 209f08c3bdfSopenharmony_ci int masterfd; /* master pty fd */ 210f08c3bdfSopenharmony_ci char *slavename; 211f08c3bdfSopenharmony_ci pid_t childpid; 212f08c3bdfSopenharmony_ci 213f08c3bdfSopenharmony_ci/*--------------------------------------------------------------------*/ 214f08c3bdfSopenharmony_ci masterfd = SAFE_OPEN(NULL, MASTERCLONE, O_RDWR); 215f08c3bdfSopenharmony_ci 216f08c3bdfSopenharmony_ci slavename = ptsname(masterfd); 217f08c3bdfSopenharmony_ci if (slavename == NULL) 218f08c3bdfSopenharmony_ci tst_brkm(TBROK | TERRNO, NULL, "ptsname"); 219f08c3bdfSopenharmony_ci 220f08c3bdfSopenharmony_ci if (grantpt(masterfd) != 0) 221f08c3bdfSopenharmony_ci tst_brkm(TBROK | TERRNO, NULL, "grantpt"); 222f08c3bdfSopenharmony_ci 223f08c3bdfSopenharmony_ci if (unlockpt(masterfd) != 0) 224f08c3bdfSopenharmony_ci tst_brkm(TBROK | TERRNO, NULL, "unlockpt"); 225f08c3bdfSopenharmony_ci 226f08c3bdfSopenharmony_ci childpid = fork(); 227f08c3bdfSopenharmony_ci if (childpid == -1) 228f08c3bdfSopenharmony_ci tst_brkm(TBROK | TERRNO, NULL, "fork"); 229f08c3bdfSopenharmony_ci else if (childpid == 0) 230f08c3bdfSopenharmony_ci exit(child(masterfd)); 231f08c3bdfSopenharmony_ci else 232f08c3bdfSopenharmony_ci parent(masterfd, childpid); 233f08c3bdfSopenharmony_ci/*--------------------------------------------------------------------*/ 234f08c3bdfSopenharmony_ci cleanup(); 235f08c3bdfSopenharmony_ci 236f08c3bdfSopenharmony_ci tst_exit(); 237f08c3bdfSopenharmony_ci} 238