/* * sysdep2.c System dependent routines * * getrowcols - get number of columns and rows. * setcbreak - set tty mode to raw, cbreak or normal. * enab_sig - enable / disable tty driver signals. * strtok - for systems that don't have it. * dup2 - for ancient systems like SVR2. * * This file is part of the minicom communications package, * Copyright 1991-1995 Miquel van Smoorenburg. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifdef HAVE_CONFIG_H #include #endif #include "port.h" #include "sysdep.h" #ifdef POSIX_TERMIOS static struct termios savetty; #else static struct sgttyb savetty; static struct tchars savetty2; #endif /* Get the number of rows and columns for this screen. */ void getrowcols(int *rows, int *cols) { char *p; #ifdef TIOCGWINSZ struct winsize ws; if (ioctl(0, TIOCGWINSZ, &ws) >= 0) { *rows = ws.ws_row; *cols = ws.ws_col; } #else # ifdef TIOCGSIZE struct ttysize ws; if (ioctl(0, TIOCGSIZE, &ws) >= 0) { *rows = ws.ts_lines; *cols = ws.ts_cols; } # endif #endif /* An extra check here because eg. SCO does have TIOCGWINSZ * defined but the support is not in the kernel (ioctl * returns -1. Yeah :-( */ if (*rows == 0 && (p = getenv("LINES")) != NULL) *rows = atoi(p); if (*cols == 0 && (p = getenv("COLUMNS")) != NULL) *cols = atoi(p); } /* * Set cbreak mode. * Mode 0 = normal. * Mode 1 = cbreak, no echo * Mode 2 = raw, no echo. * Mode 3 = only return erasechar (for wkeys.c) * * Returns: the current erase character. */ int setcbreak(int mode) { #ifdef POSIX_TERMIOS struct termios tty; static int init = 0; static int erasechar; #ifndef XCASE # ifdef _XCASE # define XCASE _XCASE # else # define XCASE 0 # endif #endif if (init == 0) { tcgetattr(0, &savetty); erasechar = savetty.c_cc[VERASE]; init++; } if (mode == 3) return erasechar; /* Always return to default settings first */ tcsetattr(0, TCSADRAIN, &savetty); if (mode == 0) { return erasechar; } tcgetattr(0, &tty); if (mode == 1) { tty.c_oflag &= ~OPOST; tty.c_lflag &= ~(XCASE|ECHONL|NOFLSH); tty.c_lflag &= ~(ICANON | ISIG | ECHO); tty.c_iflag &= ~(ICRNL|INLCR); tty.c_cflag |= CREAD; tty.c_cc[VTIME] = 5; tty.c_cc[VMIN] = 1; } if (mode == 2) { /* raw */ tty.c_iflag &= ~(IGNBRK | IGNCR | INLCR | ICRNL | IUCLC | IXANY | IXON | IXOFF | INPCK | ISTRIP); tty.c_iflag |= (BRKINT | IGNPAR); tty.c_oflag &= ~OPOST; tty.c_lflag &= ~(XCASE|ECHONL|NOFLSH); tty.c_lflag &= ~(ICANON | ISIG | ECHO); tty.c_cflag |= CREAD; tty.c_cc[VTIME] = 5; tty.c_cc[VMIN] = 1; } tcsetattr(0, TCSADRAIN, &tty); return erasechar; #else struct sgttyb args; static int init = 0; static int erasechar; #ifdef _BSD43 static struct ltchars ltchars; #endif if (init == 0) { ioctl(0, TIOCGETP, &savetty); ioctl(0, TIOCGETC, &savetty2); #ifdef _BSD43 ioctl(0, TIOCGLTC, <chars); #endif erasechar = savetty.sg_erase; init++; } if (mode == 3) return erasechar; if (mode == 0) { ioctl(0, TIOCSETP, &savetty); ioctl(0, TIOCSETC, &savetty2); #ifdef _BSD43 ioctl(0, TIOCSLTC, <chars); #endif return erasechar; } ioctl(0, TIOCGETP, &args); if (mode == 1) { args.sg_flags |= CBREAK; args.sg_flags &= ~(ECHO|RAW); } if (mode == 2) { args.sg_flags |= RAW; args.sg_flags &= ~(ECHO|CBREAK); } ioctl(0, TIOCSETP, &args); return erasechar; #endif } /* Enable / disable signals from tty driver */ void enab_sig(int onoff, int intchar) { #ifdef POSIX_TERMIOS struct termios tty; tcgetattr(0, &tty); if (onoff) tty.c_lflag |= ISIG; else tty.c_lflag &= ~ISIG; /* Set interrupt etc. characters: Zmodem support. */ if (onoff && intchar) { tty.c_cc[VINTR] = intchar; tty.c_cc[VQUIT] = -1; #ifdef VSUSP tty.c_cc[VSUSP] = -1; #endif } tcsetattr(0, TCSADRAIN, &tty); #endif #ifdef _V7 struct tchars tch; struct sgttyb sg; ioctl(0, TIOCGETP, &sg); ioctl(0, TIOCGETC, &tch); if (onoff) { sg.sg_flags &= ~RAW; sg.sg_flags |= CBREAK; } else { sg.sg_flags &= ~CBREAK; sg.sg_flags |= RAW; } if (onoff && intchar) { tch.t_intrc = intchar; tch.t_quitc = -1; } ioctl(0, TIOCSETP, &sg); ioctl(0, TIOCSETC, &tch); #endif } #ifdef _SVR2 /* Fake the dup2() system call */ int dup2(int from, int to) { int files[20]; int n, f, exstat = -1; /* Ignore if the same */ if (from == to) return to; /* Initialize file descriptor table */ for (f = 0; f < 20; f++) files[f] = 0; /* Close "to" file descriptor, if open */ close(to); /* Keep opening files until we reach "to" */ while ((n = open("/dev/null", 0)) < to && n >= 0) { if (n == from) break; files[n] = 1; } if (n == to) { /* Close "to" again, and perform dup() */ close(n); exstat = dup(from); } else { /* We failed. Set exit status and errno. */ if (n > 0) close(n); exstat = -1; errno = EBADF; } /* Close all temporarily opened file descriptors */ for (f = 0; f < 20; f++) if (files[f]) close(f); /* We're done. */ return exstat; } #endif