--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Makefile Sat Jun 09 18:01:31 2007 +0200
@@ -0,0 +1,2 @@
+tcpscript: tcpscript.o
+ $(CC) -o $@ $^ -lutil
--- a/script.c Sat Jun 09 18:01:03 2007 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,433 +0,0 @@
-/*
- * Copyright (c) 1980 Regents of the University of California.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-/*
- * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL>
- * - added Native Language Support
- *
- * 2000-07-30 Per Andreas Buer <per@linpro.no> - added "q"-option
- */
-
-/*
- * script
- */
-#include <stdio.h>
-#include <stdlib.h>
-#include <paths.h>
-#include <time.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <termios.h>
-#include <sys/ioctl.h>
-#include <sys/time.h>
-#include <sys/file.h>
-#include <sys/signal.h>
-#include "nls.h"
-
-#ifdef __linux__
-#include <unistd.h>
-#include <string.h>
-#endif
-
-#include "../defines.h"
-#ifdef HAVE_openpty
-#include <pty.h>
-#endif
-
-void finish(int);
-void done(void);
-void fail(void);
-void resize(int);
-void fixtty(void);
-void getmaster(void);
-void getslave(void);
-void doinput(void);
-void dooutput(void);
-void doshell(void);
-
-char *shell;
-FILE *fscript;
-int master;
-int slave;
-int child;
-int subchild;
-char *fname;
-
-struct termios tt;
-struct winsize win;
-int lb;
-int l;
-#ifndef HAVE_openpty
-char line[] = "/dev/ptyXX";
-#endif
-int aflg = 0;
-char *cflg = NULL;
-int fflg = 0;
-int qflg = 0;
-int tflg = 0;
-
-static char *progname;
-
-static void
-die_if_link(char *fn) {
- struct stat s;
-
- if (lstat(fn, &s) == 0 && (S_ISLNK(s.st_mode) || s.st_nlink > 1)) {
- fprintf(stderr,
- _("Warning: `%s' is a link.\n"
- "Use `%s [options] %s' if you really "
- "want to use it.\n"
- "Script not started.\n"),
- fn, progname, fn);
- exit(1);
- }
-}
-
-/*
- * script -t prints time delays as floating point numbers
- * The example program (scriptreplay) that we provide to handle this
- * timing output is a perl script, and does not handle numbers in
- * locale format (not even when "use locale;" is added).
- * So, since these numbers are not for human consumption, it seems
- * easiest to set LC_NUMERIC here.
- */
-
-int
-main(int argc, char **argv) {
- extern int optind;
- char *p;
- int ch;
-
- progname = argv[0];
- if ((p = strrchr(progname, '/')) != NULL)
- progname = p+1;
-
-
- setlocale(LC_ALL, "");
- setlocale(LC_NUMERIC, "C"); /* see comment above */
- bindtextdomain(PACKAGE, LOCALEDIR);
- textdomain(PACKAGE);
-
- if (argc == 2) {
- if (!strcmp(argv[1], "-V") || !strcmp(argv[1], "--version")) {
- printf(_("%s from %s\n"),
- progname, util_linux_version);
- return 0;
- }
- }
-
- while ((ch = getopt(argc, argv, "ac:fqt")) != -1)
- switch((char)ch) {
- case 'a':
- aflg++;
- break;
- case 'c':
- cflg = optarg;
- break;
- case 'f':
- fflg++;
- break;
- case 'q':
- qflg++;
- break;
- case 't':
- tflg++;
- break;
- case '?':
- default:
- fprintf(stderr,
- _("usage: script [-a] [-f] [-q] [-t] [file]\n"));
- exit(1);
- }
- argc -= optind;
- argv += optind;
-
- if (argc > 0)
- fname = argv[0];
- else {
- fname = "typescript";
- die_if_link(fname);
- }
- if ((fscript = fopen(fname, aflg ? "a" : "w")) == NULL) {
- perror(fname);
- fail();
- }
-
- shell = getenv("SHELL");
- if (shell == NULL)
- shell = _PATH_BSHELL;
-
- getmaster();
- if (!qflg)
- printf(_("Script started, file is %s\n"), fname);
- fixtty();
-
- (void) signal(SIGCHLD, finish);
- child = fork();
- if (child < 0) {
- perror("fork");
- fail();
- }
- if (child == 0) {
- subchild = child = fork();
- if (child < 0) {
- perror("fork");
- fail();
- }
- if (child)
- dooutput();
- else
- doshell();
- } else
- (void) signal(SIGWINCH, resize);
- doinput();
-
- return 0;
-}
-
-void
-doinput() {
- register int cc;
- char ibuf[BUFSIZ];
-
- (void) fclose(fscript);
-
- while ((cc = read(0, ibuf, BUFSIZ)) > 0)
- (void) write(master, ibuf, cc);
- done();
-}
-
-#include <sys/wait.h>
-
-void
-finish(int dummy) {
- int status;
- register int pid;
- register int die = 0;
-
- while ((pid = wait3(&status, WNOHANG, 0)) > 0)
- if (pid == child)
- die = 1;
-
- if (die)
- done();
-}
-
-void
-resize(int dummy) {
- /* transmit window change information to the child */
- (void) ioctl(0, TIOCGWINSZ, (char *)&win);
- (void) ioctl(slave, TIOCSWINSZ, (char *)&win);
-
- kill(child, SIGWINCH);
-}
-
-/*
- * Stop extremely silly gcc complaint on %c:
- * warning: `%c' yields only last 2 digits of year in some locales
- */
-static void
-my_strftime(char *buf, size_t len, const char *fmt, const struct tm *tm) {
- strftime(buf, len, fmt, tm);
-}
-
-void
-dooutput() {
- register int cc;
- time_t tvec;
- char obuf[BUFSIZ];
- struct timeval tv;
- double oldtime=time(NULL), newtime;
-
- (void) close(0);
-#ifdef HAVE_openpty
- (void) close(slave);
-#endif
- tvec = time((time_t *)NULL);
- my_strftime(obuf, sizeof obuf, "%c\n", localtime(&tvec));
- fprintf(fscript, _("Script started on %s"), obuf);
-
- for (;;) {
- if (tflg)
- gettimeofday(&tv, NULL);
- cc = read(master, obuf, sizeof (obuf));
- if (cc <= 0)
- break;
- if (tflg) {
- newtime = tv.tv_sec + (double) tv.tv_usec / 1000000;
- fprintf(stderr, "%f %i\n", newtime - oldtime, cc);
- oldtime = newtime;
- }
- (void) write(1, obuf, cc);
- (void) fwrite(obuf, 1, cc, fscript);
- if (fflg)
- (void) fflush(fscript);
- }
- done();
-}
-
-void
-doshell() {
- char *shname;
-
-#if 0
- int t;
-
- t = open(_PATH_TTY, O_RDWR);
- if (t >= 0) {
- (void) ioctl(t, TIOCNOTTY, (char *)0);
- (void) close(t);
- }
-#endif
-
- getslave();
- (void) close(master);
- (void) fclose(fscript);
- (void) dup2(slave, 0);
- (void) dup2(slave, 1);
- (void) dup2(slave, 2);
- (void) close(slave);
-
- shname = strrchr(shell, '/');
- if (shname)
- shname++;
- else
- shname = shell;
-
- if (cflg)
- execl(shell, shname, "-c", cflg, 0);
- else
- execl(shell, shname, "-i", 0);
-
- perror(shell);
- fail();
-}
-
-void
-fixtty() {
- struct termios rtt;
-
- rtt = tt;
- cfmakeraw(&rtt);
- rtt.c_lflag &= ~ECHO;
- (void) tcsetattr(0, TCSAFLUSH, &rtt);
-}
-
-void
-fail() {
-
- (void) kill(0, SIGTERM);
- done();
-}
-
-void
-done() {
- time_t tvec;
-
- if (subchild) {
- if (!qflg) {
- char buf[BUFSIZ];
- tvec = time((time_t *)NULL);
- my_strftime(buf, sizeof buf, "%c\n", localtime(&tvec));
- fprintf(fscript, _("\nScript done on %s"), buf);
- }
- (void) fclose(fscript);
- (void) close(master);
- } else {
- (void) tcsetattr(0, TCSAFLUSH, &tt);
- if (!qflg)
- printf(_("Script done, file is %s\n"), fname);
- }
- exit(0);
-}
-
-void
-getmaster() {
-#ifdef HAVE_openpty
- (void) tcgetattr(0, &tt);
- (void) ioctl(0, TIOCGWINSZ, (char *)&win);
- if (openpty(&master, &slave, NULL, &tt, &win) < 0) {
- fprintf(stderr, _("openpty failed\n"));
- fail();
- }
-#else
- char *pty, *bank, *cp;
- struct stat stb;
-
- pty = &line[strlen("/dev/ptyp")];
- for (bank = "pqrs"; *bank; bank++) {
- line[strlen("/dev/pty")] = *bank;
- *pty = '0';
- if (stat(line, &stb) < 0)
- break;
- for (cp = "0123456789abcdef"; *cp; cp++) {
- *pty = *cp;
- master = open(line, O_RDWR);
- if (master >= 0) {
- char *tp = &line[strlen("/dev/")];
- int ok;
-
- /* verify slave side is usable */
- *tp = 't';
- ok = access(line, R_OK|W_OK) == 0;
- *tp = 'p';
- if (ok) {
- (void) tcgetattr(0, &tt);
- (void) ioctl(0, TIOCGWINSZ,
- (char *)&win);
- return;
- }
- (void) close(master);
- }
- }
- }
- fprintf(stderr, _("Out of pty's\n"));
- fail();
-#endif /* not HAVE_openpty */
-}
-
-void
-getslave() {
-#ifndef HAVE_openpty
- line[strlen("/dev/")] = 't';
- slave = open(line, O_RDWR);
- if (slave < 0) {
- perror(line);
- fail();
- }
- (void) tcsetattr(slave, TCSAFLUSH, &tt);
- (void) ioctl(slave, TIOCSWINSZ, (char *)&win);
-#endif
- (void) setsid();
- (void) ioctl(slave, TIOCSCTTY, 0);
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tcpscript.c Sat Jun 09 18:01:31 2007 +0200
@@ -0,0 +1,504 @@
+/*
+ * Copyright (c) 1980 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL>
+ * - added Native Language Support
+ *
+ * 2000-07-30 Per Andreas Buer <per@linpro.no> - added "q"-option
+ */
+
+/*
+ * script
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <termios.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <sys/file.h>
+#include <sys/signal.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#ifdef __linux__
+#include <unistd.h>
+#include <string.h>
+#endif
+
+#define HAVE_openpty
+#define _PATH_BSHELL "/bin/sh"
+#ifdef HAVE_openpty
+#include <pty.h>
+#endif
+
+void finish(int);
+void done(void);
+void fail(void);
+void resize(int);
+void fixtty(void);
+void getmaster(void);
+void getslave(void);
+void doinput(void);
+void dooutput(void);
+void doshell(void);
+
+char *shell;
+int master;
+int slave;
+int child;
+int subchild;
+char *fname;
+
+struct termios tt;
+struct winsize win;
+int lb;
+int l;
+#ifndef HAVE_openpty
+char line[] = "/dev/ptyXX";
+#endif
+int aflg = 0;
+char *cflg = NULL;
+int fflg = 0;
+int qflg = 0;
+int tflg = 0;
+int tcp_port = 4000;
+
+enum {
+ MAXCONNS = 10
+};
+
+static char *progname;
+
+static void
+die_if_link(char *fn) {
+ struct stat s;
+
+ if (lstat(fn, &s) == 0 && (S_ISLNK(s.st_mode) || s.st_nlink > 1)) {
+ fprintf(stderr,
+ "Warning: `%s' is a link.\n"
+ "Use `%s [options] %s' if you really "
+ "want to use it.\n"
+ "Script not started.\n",
+ fn, progname, fn);
+ exit(1);
+ }
+}
+
+/*
+ * script -t prints time delays as floating point numbers
+ * The example program (scriptreplay) that we provide to handle this
+ * timing output is a perl script, and does not handle numbers in
+ * locale format (not even when "use locale;" is added).
+ * So, since these numbers are not for human consumption, it seems
+ * easiest to set LC_NUMERIC here.
+ */
+
+int
+main(int argc, char **argv) {
+ extern int optind;
+ char *p;
+ int ch;
+
+ progname = argv[0];
+ if ((p = strrchr(progname, '/')) != NULL)
+ progname = p+1;
+
+
+ if (argc == 2) {
+ if (!strcmp(argv[1], "-V") || !strcmp(argv[1], "--version")) {
+ printf("%s from %s\n",
+ progname, "viric 2007");
+ return 0;
+ }
+ }
+
+ while ((ch = getopt(argc, argv, "ac:fqtp:")) != -1)
+ switch((char)ch) {
+ case 'a':
+ aflg++;
+ break;
+ case 'c':
+ cflg = optarg;
+ break;
+ case 'p':
+ tcp_port = atoi(optarg);
+ break;
+ case 'f':
+ fflg++;
+ break;
+ case 'q':
+ qflg++;
+ break;
+ case 't':
+ tflg++;
+ break;
+ case '?':
+ default:
+ fprintf(stderr,
+ "usage: script [-a] [-f] [-q] [-t] [file]\n");
+ exit(1);
+ }
+ argc -= optind;
+ argv += optind;
+
+ shell = getenv("SHELL");
+ if (shell == NULL)
+ shell = _PATH_BSHELL;
+
+ getmaster();
+ if (!qflg)
+ printf("Script started, file is %s\n", fname);
+ fixtty();
+
+ (void) signal(SIGCHLD, finish);
+ child = fork();
+ if (child < 0) {
+ perror("fork");
+ fail();
+ }
+ if (child == 0) {
+ subchild = child = fork();
+ if (child < 0) {
+ perror("fork");
+ fail();
+ }
+ if (child)
+ dooutput();
+ else
+ doshell();
+ } else
+ (void) signal(SIGWINCH, resize);
+ doinput();
+
+ return 0;
+}
+
+void
+doinput() {
+ register int cc;
+ char ibuf[BUFSIZ];
+
+ while ((cc = read(0, ibuf, BUFSIZ)) > 0)
+ (void) write(master, ibuf, cc);
+ done();
+}
+
+#include <sys/wait.h>
+
+void
+finish(int dummy) {
+ int status;
+ register int pid;
+ register int die = 0;
+
+ while ((pid = wait3(&status, WNOHANG, 0)) > 0)
+ if (pid == child)
+ die = 1;
+
+ if (die)
+ done();
+}
+
+void
+resize(int dummy) {
+ /* transmit window change information to the child */
+ (void) ioctl(0, TIOCGWINSZ, (char *)&win);
+ (void) ioctl(slave, TIOCSWINSZ, (char *)&win);
+
+ kill(child, SIGWINCH);
+}
+
+/*
+ * Stop extremely silly gcc complaint on %c:
+ * warning: `%c' yields only last 2 digits of year in some locales
+ */
+static void
+my_strftime(char *buf, size_t len, const char *fmt, const struct tm *tm) {
+ strftime(buf, len, fmt, tm);
+}
+
+void fatal()
+{
+ exit(-1);
+}
+
+int listen_tcp()
+{
+ int s;
+ struct sockaddr_in addr;
+ int res;
+
+ s = socket(PF_INET, SOCK_STREAM, 0);
+ if (s == -1)
+ perror("Failed socket()"), fatal();
+
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(tcp_port);
+ addr.sin_addr.s_addr = INADDR_ANY;
+ res = bind(s, (struct sockaddr *) &addr, sizeof(addr));
+ if (s != 0)
+ perror("Failed bind()"), fatal();
+
+ res = listen(s, 1);
+ if (s != 0)
+ perror("Failed listen()"), fatal();
+
+ printf("Listening on port %i\n", tcp_port);
+ return s;
+}
+
+void remove_element(int index, int *array, int total)
+{
+ int i;
+ for (i = index; i < (total - 1); ++i)
+ array[i] = array[i+1];
+}
+
+void
+dooutput() {
+ int cc;
+ char obuf[BUFSIZ];
+ int accept_socket;
+ int conns[MAXCONNS];
+ int nconns;
+ int i;
+
+ (void) close(0);
+#ifdef HAVE_openpty
+ (void) close(slave);
+#endif
+ fd_set read_set;
+ fd_set should_read_set;
+ fd_set tcp_set;
+
+ accept_socket = listen_tcp();
+ FD_ZERO(&should_read_set);
+ FD_SET(accept_socket, &should_read_set);
+ FD_SET(master, &should_read_set);
+
+ nconns = 0;
+ for (;;) {
+ int max;
+ read_set = should_read_set;
+
+ /* Calculate max fd */
+ max = accept_socket;
+ if (master > max)
+ max = master;
+ for (i = 0; i < nconns; ++i)
+ if (conns[i] > max)
+ max = conns[i];
+
+ select(max + 1, &read_set, 0, 0, 0);
+
+ if (FD_ISSET(master, &read_set))
+ {
+ cc = read(master, obuf, sizeof (obuf));
+ if (cc <= 0)
+ break;
+ /* Write to the terminal output */
+ (void) write(1, obuf, cc);
+ /* Broadcast messages */
+ for (i = 0; i < nconns; ++i)
+ (void) write(conns[i], obuf, cc);
+ }
+ for (i = 0; i < nconns; ++i)
+ {
+ if (FD_ISSET(conns[i], &read_set))
+ {
+ int size;
+ size = read(conns[i], obuf, sizeof(obuf));
+ if (size == 0)
+ {
+ close(conns[i]);
+ FD_CLR(conns[i], &should_read_set);
+ remove_element(i, conns, nconns);
+ nconns--;
+ }
+ }
+ }
+ if (FD_ISSET(accept_socket, &read_set))
+ {
+ int s;
+ s = accept(accept_socket, 0, 0);
+ if (s == -1)
+ {
+ perror("accept() failed");
+ break;
+ }
+ if (nconns < (MAXCONNS - 1))
+ {
+ FD_SET(s, &should_read_set);
+ conns[nconns] = s;
+ nconns++;
+ } else
+ close(s);
+ }
+ }
+
+ close(accept_socket);
+ for (i = 0; i < nconns; ++i)
+ close(conns[i]);
+
+ done();
+}
+
+void
+doshell() {
+ char *shname;
+
+#if 0
+ int t;
+
+ t = open(_PATH_TTY, O_RDWR);
+ if (t >= 0) {
+ (void) ioctl(t, TIOCNOTTY, (char *)0);
+ (void) close(t);
+ }
+#endif
+
+ getslave();
+ (void) close(master);
+ (void) dup2(slave, 0);
+ (void) dup2(slave, 1);
+ (void) dup2(slave, 2);
+ (void) close(slave);
+
+ shname = strrchr(shell, '/');
+ if (shname)
+ shname++;
+ else
+ shname = shell;
+
+ if (cflg)
+ execl(shell, shname, "-c", cflg, 0);
+ else
+ execl(shell, shname, "-i", 0);
+
+ perror(shell);
+ fail();
+}
+
+void
+fixtty() {
+ struct termios rtt;
+
+ rtt = tt;
+ cfmakeraw(&rtt);
+ rtt.c_lflag &= ~ECHO;
+ (void) tcsetattr(0, TCSAFLUSH, &rtt);
+}
+
+void
+fail() {
+
+ (void) kill(0, SIGTERM);
+ done();
+}
+
+void
+done() {
+ time_t tvec;
+
+ if (subchild) {
+ (void) close(master);
+ } else {
+ (void) tcsetattr(0, TCSAFLUSH, &tt);
+ }
+ exit(0);
+}
+
+void
+getmaster() {
+#ifdef HAVE_openpty
+ (void) tcgetattr(0, &tt);
+ (void) ioctl(0, TIOCGWINSZ, (char *)&win);
+ if (openpty(&master, &slave, NULL, &tt, &win) < 0) {
+ fprintf(stderr, "openpty failed\n");
+ fail();
+ }
+#else
+ char *pty, *bank, *cp;
+ struct stat stb;
+
+ pty = &line[strlen("/dev/ptyp")];
+ for (bank = "pqrs"; *bank; bank++) {
+ line[strlen("/dev/pty")] = *bank;
+ *pty = '0';
+ if (stat(line, &stb) < 0)
+ break;
+ for (cp = "0123456789abcdef"; *cp; cp++) {
+ *pty = *cp;
+ master = open(line, O_RDWR);
+ if (master >= 0) {
+ char *tp = &line[strlen("/dev/")];
+ int ok;
+
+ /* verify slave side is usable */
+ *tp = 't';
+ ok = access(line, R_OK|W_OK) == 0;
+ *tp = 'p';
+ if (ok) {
+ (void) tcgetattr(0, &tt);
+ (void) ioctl(0, TIOCGWINSZ,
+ (char *)&win);
+ return;
+ }
+ (void) close(master);
+ }
+ }
+ }
+ fprintf(stderr, "Out of pty's\n");
+ fail();
+#endif /* not HAVE_openpty */
+}
+
+void
+getslave() {
+#ifndef HAVE_openpty
+ line[strlen("/dev/")] = 't';
+ slave = open(line, O_RDWR);
+ if (slave < 0) {
+ perror(line);
+ fail();
+ }
+ (void) tcsetattr(slave, TCSAFLUSH, &tt);
+ (void) ioctl(slave, TIOCSWINSZ, (char *)&win);
+#endif
+ (void) setsid();
+ (void) ioctl(slave, TIOCSCTTY, 0);
+}