/* FILE: console.c */ /* By Vassilis Papadimos -- vpapad at theseas.ntua.gr and Spiros Ioannou -- sivann at theseas.ntua.gr */ #include #include #include #include #include #include /* Fix ISC brain damage. When using gcc fdopen isn't declared in . */ #if defined(SYSV) && defined(SYSV386) && defined(__STDC__) && defined(ISC) extern FILE *fdopen(int, char const *); #endif static FILE *input = 0; #ifdef ultrix #define USE_FILE #define FILE_NAME "/dev/xcons" #endif #ifndef USE_FILE #include #ifdef SVR4 #include #include /* for I_PUSH */ #endif #ifdef TIOCCONS #define USE_PTY static int tty_fd, pty_fd; static char ttydev[64], ptydev[64]; #endif #endif #if defined(SYSV) && defined(SYSV386) #define USE_OSM #endif static OpenConsole () { struct stat sbuf; /* must be owner and have read/write permission */ if (!stat("/dev/console", &sbuf) && (sbuf.st_uid == getuid()) && !access("/dev/console", R_OK|W_OK)) { #ifdef USE_FILE input = fopen (FILE_NAME, "r"); #endif #ifdef USE_PTY int on = 1; if (get_pty (&pty_fd, &tty_fd, ttydev, ptydev) == 0 && ioctl (tty_fd, TIOCCONS, (char *) &on) != -1) { input = fdopen (pty_fd, "r"); } #endif } #ifdef USE_OSM /* Don't have to be owner of /dev/console when using /dev/osm. */ input = fdopen(osm_pipe(), "r"); #endif if (!input) printf("Couldn't open /dev/console!\n"); } static CloseConsole () { if (input) fclose (input); #ifdef USE_PTY close (tty_fd); #endif } static void stripNonprint (b) char *b; { char *c; c = b; while (*b) { if (isprint (*b) || isspace (*b) && *b != '\r') { if (c != b) *c = *b; ++c; } ++b; } *c = '\0'; } main() { int mode=1; int n,pty, buf, nbytes; char buffer[100]; if (get_pty (&pty_fd, &tty_fd, ttydev, ptydev) != 0) { perror();} printf("pty:%s\n",ptydev); printf("tty:%s\n",ttydev); while(1){ n = read (pty_fd, buffer, 1000); printf("S:%s",buffer); } return 0; } #ifdef USE_PTY /* This function opens up a pty master and stuffs it's value into pty. * If it finds one, it returns a value of 0. If it does not find one, * it returns a value of !0. This routine is designed to be re-entrant, * so that if a pty master is found and later, we find that the slave * has problems, we can re-enter this function and get another one. */ #ifndef PTYCHAR1 #ifdef hpux #define PTYCHAR1 "zyxwvutsrqp" #else /* !hpux */ #define PTYCHAR1 "pqrstuvwxyzPQRSTUVWXYZ" #endif /* !hpux */ #endif /* !PTYCHAR1 */ #ifndef PTYCHAR2 #ifdef hpux #define PTYCHAR2 "fedcba9876543210" #else /* !hpux */ #define PTYCHAR2 "0123456789abcdef" #endif /* !hpux */ #endif /* !PTYCHAR2 */ get_pty (pty, tty, ttydev, ptydev) int *pty, *tty; char *ttydev, *ptydev; { #ifdef SVR4 if ((*pty = open ("/dev/ptmx", O_RDWR)) < 0) { return 1; } grantpt(*pty); unlockpt(*pty); strcpy(ttydev, ptsname(*pty)); if ((*tty = open(ttydev, O_RDWR)) >= 0) { (void)ioctl(*tty, I_PUSH, "ttcompat"); return 0; } if (*pty >= 0) close (*pty); #else /* !SVR4, need lots of code */ #ifdef USE_GET_PSEUDOTTY if ((*pty = getpseudotty (&ttydev, &ptydev)) >= 0 && (*tty = open (ttydev, O_RDWR)) >= 0) return 0; if (*pty >= 0) close (*pty); #else static int devindex, letter = 0; #if defined(umips) && defined (SYSTYPE_SYSV) struct stat fstat_buf; *pty = open ("/dev/ptc", O_RDWR); if (*pty < 0 || (fstat (*pty, &fstat_buf)) < 0) { return(1); } sprintf (ttydev, "/dev/ttyq%d", minor(fstat_buf.st_rdev)); sprintf (ptydev, "/dev/ptyq%d", minor(fstat_buf.st_rdev)); if ((*tty = open (ttydev, O_RDWR)) >= 0) { /* got one! */ return(0); } close (*pty); #else /* not (umips && SYSTYPE_SYSV) */ #ifdef CRAY for (; devindex < 256; devindex++) { sprintf (ttydev, "/dev/ttyp%03d", devindex); sprintf (ptydev, "/dev/pty/%03d", devindex); if ((*pty = open (ptydev, O_RDWR)) >= 0 && (*tty = open (ttydev, O_RDWR)) >= 0) { /* We need to set things up for our next entry * into this function! */ (void) devindex++; return(0); } if (*pty >= 0) close (*pty); } #else /* !CRAY */ strcpy (ttydev, "/dev/ttyxx"); strcpy (ptydev, "/dev/ptyxx"); while (PTYCHAR1[letter]) { ttydev [strlen(ttydev) - 2] = ptydev [strlen(ptydev) - 2] = PTYCHAR1 [letter]; while (PTYCHAR2[devindex]) { ttydev [strlen(ttydev) - 1] = ptydev [strlen(ptydev) - 1] = PTYCHAR2 [devindex]; if ((*pty = open (ptydev, O_RDWR)) >= 0 && (*tty = open (ttydev, O_RDWR)) >= 0) { /* We need to set things up for our next entry * into this function! */ (void) devindex++; return(0); } if (*pty >= 0) close (*pty); devindex++; } devindex = 0; (void) letter++; } #endif /* CRAY else not CRAY */ #endif /* umips && SYSTYPE_SYSV */ #endif /* USE_GET_PSEUDOTTY */ #endif /* SVR4 */ /* We were unable to allocate a pty master! Return an error * condition and let our caller terminate cleanly. */ return(1); } #endif #ifdef USE_OSM /* * On SYSV386 there is a special device, /dev/osm, where system messages * are sent. Problem is that we can't perform a select(2) on this device. * So this routine creates a streams-pty where one end reads the device and * sends the output to xconsole. */ osm_pipe() { int tty, pid; char ttydev[64]; if ((tty = open("/dev/ptmx", O_RDWR)) < 0) return -1; grantpt(tty); unlockpt(tty); strcpy(ttydev, (char *)ptsname(tty)); if ((pid = fork()) == 0) { int pty, osm, buf, nbytes; pty = open(ttydev, O_RDWR); osm = open("/dev/osm", O_RDWR); while ((nbytes = read(osm, &buf, sizeof(buf))) >= 0) write(pty, &buf, nbytes); } return tty; } #endif /* USE_OSM */ /*autorespond_main() { xconsole_main(); } */