/* gcc -std=gnu99 -g -ggdb -Wall -pedantic -o test_kill_proc_with_pty test_kill_proc_with_pty.c -lutil */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* the string the child writes */ char orig_string[] = "hello, world\n"; /* the string we expect to read back in the parent */ char result_string[] = "hello, world\r\n"; void hexify (size_t bytes, const void *data) { const char *p; size_t i; int add_space = 0; i = bytes; p = (const char *)data; while (i) { fprintf(stderr, "%02x", *p); i--;p++; add_space++; if ((add_space % 2) == 0) { fputc(' ', stderr); } } fputc('\n', stderr); add_space = 0; i = bytes; p = (const char *)data; while (i) { switch (*p) { case '\n': fprintf(stderr, "\\n"); break; case '\r': fprintf(stderr, "\\r"); break; default: fprintf(stderr, "%c", *p); } i--;p++; add_space++; } fputc('\n', stderr); } void run_test (void) { int pty_master; pid_t pid; pid = forkpty (&pty_master, NULL, NULL, NULL); if (pid < 0) { perror ("forkpty"); exit (EXIT_FAILURE); } else if (pid) { int status; char buffer[1024]; ssize_t ret; int nfds; fd_set readfds; fd_set exceptfds; FD_ZERO (&readfds); FD_ZERO (&exceptfds); FD_SET (pty_master, &readfds); /* Parent */ nfds = pty_master+1; assert (select (nfds, &readfds, NULL, &exceptfds, NULL) == 1); assert (FD_ISSET (pty_master, &readfds)); assert (! kill (-pid, SIGKILL)); assert (waitpid (pid, &status, 0) == pid); memset (buffer, '\0', sizeof (buffer)); ret = read (pty_master, buffer, sizeof (buffer)); assert (ret > 0); if (strcmp (buffer, result_string)) { fprintf (stderr, "ERROR: incorrect output: result_string='%s', buffer='%s'\n", result_string, buffer); fprintf(stderr, "result_string:\n"); hexify (strlen (result_string), result_string); fprintf(stderr, "buffer:\n"); hexify (strlen (buffer), buffer); exit (EXIT_FAILURE); } close (pty_master); } else { /* Child */ #if 0 (void)write (STDOUT_FILENO, orig_string, strlen (orig_string)); /*fprintf(stdout, "%s", orig_string);*/ #else /* force a shell */ /* This seems to make the problem easier to hit */ system ("echo hello, world;sleep 999"); #endif exit (0); } } int main(int argc, char *argv[]) { int i; int count = 100; if (argc == 2) count = atol (argv[1]); fprintf(stderr, "Running tests\n"); for (i = 0; i < count; i++) { fprintf (stderr, "loop %d of %d\n", 1+i, count); run_test (); } fprintf(stderr, "Ran tests\n"); }