/* Support routines for terminal I/O. This module defines the following Fortran-callable routines: GROTER, GRCTER, GRWTER, GRPTER. */ #include #include #include #include #include #include #include #ifdef PG_PPU #define GROTER groter_ #define GRWTER grwter_ #define GRCTER grcter_ #define GRPTER grpter_ #define GRKTER grkter_ #define GRETER greter_ #else #define GROTER groter #define GRWTER grwter #define GRCTER grcter #define GRPTER grpter #define GRKTER grkter #define GRETER greter #endif /* Open a channel to the device specified by 'cdev'. * * cdev I The name of the device to be opened * ldev I Number of valid characters in cdev * groter O The open channel number (-1 indicates an error) */ int GROTER(cdev, ldev, cdev_len) char *cdev; int *ldev; int cdev_len; { int fd; /* The returned file descriptor */ char name[64]; /* A copy of the given terminal device name */ /* * Make a copy of the given file if there is sufficient room in name[]. */ if(*ldev <= sizeof(name)-1) { strncpy(name, cdev, *ldev); name[*ldev] = '\0'; } else { fprintf(stderr, "groter: Terminal file name too long.\n"); return -1; }; /* * Open the terminal. */ if((fd = open(name, 2)) == -1) { perror(name); return -1; }; return fd; } /* Close a previously opened channel. * * fd I The channel number to be closed */ void GRCTER(fd) int *fd; { close(*fd); return; } /* Write lbuf bytes from cbuf to the channel fd. Data is written without * any formating. * * fd I The channel number * cbuf I Character array of data to be written * lbuf I/O The number of bytes to write, set to zero on return */ void GRWTER(fd, cbuf, lbuf, cbuf_len) int *fd; char *cbuf; int *lbuf; int cbuf_len; { int nwritten = write (*fd, cbuf, *lbuf); if (nwritten != *lbuf) perror("Error writing to graphics device"); *lbuf = 0; return; } /* Write prompt string on terminal and then read response. This version * will try to read lbuf characters. * * fd I The channel number * cprom I An optional prompt string * lprom I Number of valid characters in cprom * cbuf O Character array of data read * lbuf I/O The number of bytes to read, on return number read */ void GRPTER(fd, cprom, lprom, cbuf, lbuf, cprom_len, cbuf_len) int *fd; char *cprom; int *lprom; char *cbuf; int *lbuf; int cprom_len; int cbuf_len; { char *buff = cbuf; /* C pointer to FORTRAN string */ int ndone=0; /* The number of characters read */ struct termios term; /* Terminal mode flags */ /* * Get the current set of terminal mode flags. */ if(tcgetattr(*fd, &term)==0) { struct termios saveterm; /* Saved terminal attributes */ int ntry; /* The number of characters still to be read */ int nread; /* The number of characters read in one iteration */ /* * Save the existing terminal mode flags to be restored later. */ saveterm = term; /* * Enable raw single character input. */ term.c_lflag &= ~ICANON; term.c_cc[VMIN] = 1; /* * Install the new terminal flags after first waiting for all pending * output to be delivered to the terminal and after discarding any * lingering input. */ tcsetattr(*fd, TCSAFLUSH, &term); /* * Prompt for input. */ if(*lprom>0) write(*fd, cprom, *lprom); /* * Read up to 'ntry' characters from the terminal. */ ndone = 0; ntry = *lbuf; do { nread = read(*fd, &buff[ndone], ntry); ndone += nread; ntry -= nread; } while(nread>0 && ntry>0); /* * Restore the previous terminal mode flags. */ tcsetattr(*fd, TCSAFLUSH, &saveterm); }; *lbuf=ndone; return; } static struct termios saved_attr; static struct termios term; /* Terminal mode flags */ static int saved_fd=-1; static int exit_handler=1; /* * Restore the previous terminal mode. */ void GRETER(void) { if (saved_fd >= 0) { tcsetattr(saved_fd, TCSAFLUSH, &saved_attr); saved_fd = -1; }; return; } /* Read one character from the terminal (with timeout), * and set terminal to no canonical, no echo mode. * * fd I The channel number * tmo I Timeout in tenths of a second * cbuf O Character array of data read */ void GRKTER(fd, tmo, cbuf, cbuf_len) int *fd; int *tmo; char *cbuf; int cbuf_len; { int nread; /* * Get the current set of terminal mode flags. */ *cbuf='\0'; if (*fd != saved_fd) { if (saved_fd >= 0) { tcsetattr(saved_fd, TCSAFLUSH, &saved_attr); saved_fd = -1; } if(tcgetattr(*fd, &term)!=0) return; /* * Save the existing terminal mode flags to be restored later. */ saved_attr = term; /* * Enable raw single character input. */ term.c_lflag &= ~(ICANON) & ~(ECHO); term.c_cc[VMIN] = 1; term.c_cc[VTIME] = 0; /* * Install the new terminal flags after first waiting for all pending * output to be delivered to the terminal and after discarding any * lingering input. */ tcsetattr(*fd, TCSAFLUSH, &term); if (exit_handler) { atexit(GRETER); exit_handler=0; } saved_fd = *fd; } if (*tmo != 0) { term.c_cc[VMIN] = (*tmo == 0); term.c_cc[VTIME] = *tmo; tcsetattr(*fd, TCSANOW, &term); } /* * Read one character from the terminal. */ nread = read(*fd, cbuf, 1); if (nread!=1) *cbuf='\0'; if (*tmo != 0) { term.c_cc[VMIN] = 1; term.c_cc[VTIME] = 0; tcsetattr(*fd, TCSANOW, &term); } return; }