File:  [Public anonymous repository] / mmondor / mmsoftware / util / tty-loopback.c
Revision 1.2: download - view: text, annotated - select for diffs - revision graph
Wed Oct 17 20:17:57 2007 UTC (6 years, 6 months ago) by mmondor
Branches: MAIN
CVS tags: HEAD
Now uses posix_openpty(3) and ptsname(3) instead of a custom pty(4)
allocator function.  Also uses grantpt(3) and unlockpt(3).

    1:	/*
    2:	 * Copyright (c) 2005, Matthew Mondor
    3:	 * ALL RIGHTS RESERVED.
    4:	 */
    5:	
    6:	/*
    7:	 * Allocates two pty(4) devices and links them together.
    8:	 * Supplies to stdout the two tty(4) devices which may be used for loopback.
    9:	 */
   10:	
   11:	
   12:	
   13:	#include <sys/types.h>
   14:	#include <poll.h>
   15:	#include <fcntl.h>
   16:	#include <unistd.h>
   17:	
   18:	#include <stdlib.h>
   19:	#include <stdio.h>
   20:	#include <string.h>
   21:	
   22:	
   23:	
   24:	int			main(void);
   25:	
   26:	
   27:	
   28:	#define	DBUFSIZ		65536
   29:	
   30:	
   31:	
   32:	int
   33:	main(void)
   34:	{
   35:		char		*dbuf;
   36:		struct pollfd	fds[2];
   37:	
   38:		if ((dbuf = malloc(DBUFSIZ)) == NULL) {
   39:			(void) fprintf(stderr,
   40:			    "Couldn't allocate %d bytes of heap memory\n", DBUFSIZ);
   41:			return EXIT_FAILURE;
   42:		}
   43:	
   44:		if ((fds[0].fd = posix_openpt(O_RDWR)) == -1 ||
   45:		    (fds[1].fd = posix_openpt(O_RDWR)) == -1) {
   46:			(void) fprintf(stderr,
   47:			    "Couldn't allocate two pty(4) devices\n");
   48:			return EXIT_FAILURE;
   49:		}
   50:	
   51:		if (grantpt(fds[0].fd) == -1 || grantpt(fds[1].fd) == -1) {
   52:			(void) fprintf(stderr,
   53:			    "Couldn't grant permissions on tty(4) devices\n");
   54:			return EXIT_FAILURE;
   55:		}
   56:	
   57:		/*
   58:		 * Output ttys we handle
   59:		 */
   60:		(void) printf("%s\n", ptsname(fds[0].fd));
   61:		(void) printf("%s\n", ptsname(fds[1].fd));
   62:		(void) fflush(stdout);
   63:	
   64:		/*
   65:		 * Now redirect any input from any terminal to the other pair.
   66:		 * This basically provides two connected ttys, a sort of loopback
   67:		 * tty system, useful for debugging some applications.
   68:		 */
   69:		fds[0].events = fds[1].events = POLLIN;
   70:		fds[0].revents = fds[1].revents = 0;
   71:		for (;;) {
   72:			int	ret, i;
   73:	
   74:			if ((ret = poll(fds, 2, -1)) == -1)
   75:				break;
   76:			if (ret == 0)
   77:				continue;
   78:			for (i = 0; i < 2; i++) {
   79:				if ((fds[i].revents & POLLHUP) != 0 ||
   80:				    (fds[i].revents & POLLERR) != 0)
   81:					goto end;
   82:				if ((fds[i].revents & POLLIN) != 0) {
   83:					size_t	len;
   84:	
   85:					if ((len = read(fds[i].fd, dbuf, DBUFSIZ))
   86:					    == -1)
   87:						goto end;
   88:					if (len > 0) {
   89:						if (write(fds[!i].fd, dbuf, len) == -1)
   90:							goto end;
   91:					}
   92:				}
   93:			}
   94:		}
   95:	
   96:	end:
   97:		free(dbuf);
   98:		(void) unlockpt(fds[0].fd);
   99:		(void) close(fds[0].fd);
  100:		(void) unlockpt(fds[1].fd);
  101:		(void) close(fds[1].fd);
  102:	
  103:		return EXIT_SUCCESS;
  104:	}