X-Git-Url: http://ncurses.scripts.mit.edu/?a=blobdiff_plain;f=progs%2Freset_cmd.c;h=50bfd2cd0630d3a5be4e59000ef6c914712db9f8;hb=HEAD;hp=09dba5e5bb8bad1a4699c460e94b0c45c408450f;hpb=e2e9c09c48b19b24979cafb2d4864f538b5ddd1c;p=ncurses.git diff --git a/progs/reset_cmd.c b/progs/reset_cmd.c index 09dba5e5..6ae3b673 100644 --- a/progs/reset_cmd.c +++ b/progs/reset_cmd.c @@ -1,5 +1,6 @@ /**************************************************************************** - * Copyright (c) 2016 Free Software Foundation, Inc. * + * Copyright 2019-2023,2024 Thomas E. Dickey * + * Copyright 2016,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -31,6 +32,7 @@ ****************************************************************************/ #include +#include #include #include @@ -45,13 +47,13 @@ #endif #if NEED_PTEM_H -/* they neglected to define struct winsize in termios.h -- it's only +/* they neglected to define struct winsize in termios.h -- it is only in termio.h */ #include #include #endif -MODULE_ID("$Id: reset_cmd.c,v 1.7 2016/09/10 20:49:10 tom Exp $") +MODULE_ID("$Id: reset_cmd.c,v 1.37 2024/04/08 17:29:34 tom Exp $") /* * SCO defines TIOCGSIZE and the corresponding struct. Other systems (SunOS, @@ -73,48 +75,27 @@ MODULE_ID("$Id: reset_cmd.c,v 1.7 2016/09/10 20:49:10 tom Exp $") # endif #endif -static int my_fd; +#define set_flags(target, mask) target |= mask +#define clear_flags(target, mask) target &= ~((unsigned)(mask)) + static FILE *my_file; -static TTY original_settings; -static bool can_restore = FALSE; static bool use_reset = FALSE; /* invoked as reset */ static bool use_init = FALSE; /* invoked as init */ -static void -exit_error(void) +static GCC_NORETURN void +failed(const char *msg) { + int code = errno; + + (void) fprintf(stderr, "%s: %s: %s\n", _nc_progname, msg, strerror(code)); restore_tty_settings(); (void) fprintf(my_file, "\n"); fflush(my_file); - ExitProgram(EXIT_FAILURE); - /* NOTREACHED */ -} - -static void -failed(const char *msg) -{ - char temp[BUFSIZ]; - - _nc_STRCPY(temp, _nc_progname, sizeof(temp)); - _nc_STRCAT(temp, ": ", sizeof(temp)); - _nc_STRNCAT(temp, msg, sizeof(temp), sizeof(temp) - strlen(temp) - 2); - perror(temp); - exit_error(); + ExitProgram(ErrSystem(code)); /* NOTREACHED */ } -static bool -get_tty_settings(int fd, TTY * tty_settings) -{ - bool success = TRUE; - my_fd = fd; - if (fd < 0 || GET_TTY(my_fd, tty_settings) < 0) { - success = FALSE; - } - return success; -} - static bool cat_file(char *file) { @@ -124,7 +105,7 @@ cat_file(char *file) bool sent = FALSE; if (file != 0) { - if ((fp = fopen(file, "r")) == 0) + if ((fp = safe_fopen(file, "r")) == 0) failed(file); while ((nr = fread(buf, sizeof(char), sizeof(buf), fp)) != 0) { @@ -210,25 +191,102 @@ out_char(int c) #define reset_char(item, value) \ tty_settings->c_cc[item] = CHK(tty_settings->c_cc[item], value) +/* + * Simplify ifdefs + */ +#ifndef BSDLY +#define BSDLY 0 +#endif +#ifndef CRDLY +#define CRDLY 0 +#endif +#ifndef ECHOCTL +#define ECHOCTL 0 +#endif +#ifndef ECHOKE +#define ECHOKE 0 +#endif +#ifndef ECHOPRT +#define ECHOPRT 0 +#endif +#ifndef FFDLY +#define FFDLY 0 +#endif +#ifndef IMAXBEL +#define IMAXBEL 0 +#endif +#ifndef IUCLC +#define IUCLC 0 +#endif +#ifndef IXANY +#define IXANY 0 +#endif +#ifndef NLDLY +#define NLDLY 0 +#endif +#ifndef OCRNL +#define OCRNL 0 +#endif +#ifndef OFDEL +#define OFDEL 0 +#endif +#ifndef OFILL +#define OFILL 0 +#endif +#ifndef OLCUC +#define OLCUC 0 +#endif +#ifndef ONLCR +#define ONLCR 0 +#endif +#ifndef ONLRET +#define ONLRET 0 +#endif +#ifndef ONOCR +#define ONOCR 0 +#endif +#ifndef OXTABS +#define OXTABS 0 +#endif +#ifndef TAB3 +#define TAB3 0 +#endif +#ifndef TABDLY +#define TABDLY 0 +#endif +#ifndef TOSTOP +#define TOSTOP 0 +#endif +#ifndef VTDLY +#define VTDLY 0 +#endif +#ifndef XCASE +#define XCASE 0 +#endif + /* * Reset the terminal mode bits to a sensible state. Very useful after * a child program dies in raw mode. */ void -reset_tty_settings(TTY * tty_settings) +reset_tty_settings(int fd, TTY * tty_settings, int noset) { -#ifdef TERMIOS - tcgetattr(my_fd, tty_settings); -#else - stty(my_fd, tty_settings); + unsigned mask; +#ifdef TIOCMGET + int modem_bits; #endif + GET_TTY(fd, tty_settings); + #ifdef TERMIOS #if defined(VDISCARD) && defined(CDISCARD) reset_char(VDISCARD, CDISCARD); #endif reset_char(VEOF, CEOF); reset_char(VERASE, CERASE); +#if defined(VERASE2) && defined(CERASE2) + reset_char(VERASE2, CERASE2); +#endif #if defined(VFLUSH) && defined(CFLUSH) reset_char(VFLUSH, CFLUSH); #endif @@ -254,108 +312,69 @@ reset_tty_settings(TTY * tty_settings) reset_char(VWERASE, CWERASE); #endif - tty_settings->c_iflag &= ~((unsigned) (IGNBRK - | PARMRK - | INPCK - | ISTRIP - | INLCR - | IGNCR -#ifdef IUCLC - | IUCLC -#endif -#ifdef IXANY - | IXANY -#endif - | IXOFF)); - - tty_settings->c_iflag |= (BRKINT - | IGNPAR - | ICRNL - | IXON -#ifdef IMAXBEL - | IMAXBEL -#endif - ); - - tty_settings->c_oflag &= ~((unsigned) (0 -#ifdef OLCUC - | OLCUC -#endif -#ifdef OCRNL - | OCRNL -#endif -#ifdef ONOCR - | ONOCR -#endif -#ifdef ONLRET - | ONLRET -#endif -#ifdef OFILL - | OFILL -#endif -#ifdef OFDEL - | OFDEL -#endif -#ifdef NLDLY - | NLDLY -#endif -#ifdef CRDLY - | CRDLY -#endif -#ifdef TABDLY - | TABDLY -#endif -#ifdef BSDLY - | BSDLY -#endif -#ifdef VTDLY - | VTDLY -#endif -#ifdef FFDLY - | FFDLY -#endif - )); - - tty_settings->c_oflag |= (OPOST -#ifdef ONLCR - | ONLCR -#endif - ); - - tty_settings->c_cflag &= ~((unsigned) (CSIZE - | CSTOPB - | PARENB - | PARODD - | CLOCAL)); - tty_settings->c_cflag |= (CS8 | CREAD); - tty_settings->c_lflag &= ~((unsigned) (ECHONL - | NOFLSH -#ifdef TOSTOP - | TOSTOP -#endif -#ifdef ECHOPTR - | ECHOPRT -#endif -#ifdef XCASE - | XCASE -#endif - )); - - tty_settings->c_lflag |= (ISIG - | ICANON - | ECHO - | ECHOE - | ECHOK -#ifdef ECHOCTL - | ECHOCTL -#endif -#ifdef ECHOKE - | ECHOKE -#endif - ); -#endif - - SET_TTY(my_fd, tty_settings); + clear_flags(tty_settings->c_iflag, (IGNBRK + | PARMRK + | INPCK + | ISTRIP + | INLCR + | IGNCR + | IUCLC + | IXANY + | IXOFF)); + + set_flags(tty_settings->c_iflag, (BRKINT + | IGNPAR + | ICRNL + | IXON + | IMAXBEL)); + + clear_flags(tty_settings->c_oflag, (0 + | OLCUC + | OCRNL + | ONOCR + | ONLRET + | OFILL + | OFDEL + | NLDLY + | CRDLY + | TABDLY + | BSDLY + | VTDLY + | FFDLY)); + + set_flags(tty_settings->c_oflag, (OPOST + | ONLCR)); + + mask = (CSIZE | CSTOPB | PARENB | PARODD); +#ifdef TIOCMGET + /* leave clocal alone if this appears to use a modem */ + if (ioctl(fd, TIOCMGET, &modem_bits) == -1) + mask |= CLOCAL; +#else + /* cannot check - use the behavior from tset */ + mask |= CLOCAL; +#endif + clear_flags(tty_settings->c_cflag, mask); + + set_flags(tty_settings->c_cflag, (CS8 | CREAD)); + clear_flags(tty_settings->c_lflag, (ECHONL + | NOFLSH + | TOSTOP + | ECHOPRT + | XCASE)); + + set_flags(tty_settings->c_lflag, (ISIG + | ICANON + | ECHO + | ECHOE + | ECHOK + | ECHOCTL + | ECHOKE)); +#endif /* TERMIOS */ + + if (!noset) { + SET_TTY(fd, tty_settings); + } } /* @@ -368,7 +387,7 @@ default_erase(void) int result; if (over_strike - && key_backspace != 0 + && VALID_STRING(key_backspace) && strlen(key_backspace) == 1) { result = key_backspace[0]; } else { @@ -389,6 +408,13 @@ default_erase(void) void set_control_chars(TTY * tty_settings, int my_erase, int my_intr, int my_kill) { +#if defined(EXP_WIN32_DRIVER) + /* noop */ + (void) tty_settings; + (void) my_erase; + (void) my_intr; + (void) my_kill; +#else if (DISABLED(tty_settings->c_cc[VERASE]) || my_erase >= 0) { tty_settings->c_cc[VERASE] = UChar((my_erase >= 0) ? my_erase @@ -406,6 +432,7 @@ set_control_chars(TTY * tty_settings, int my_erase, int my_intr, int my_kill) ? my_kill : CKILL); } +#endif } /* @@ -415,29 +442,49 @@ set_control_chars(TTY * tty_settings, int my_erase, int my_intr, int my_kill) void set_conversions(TTY * tty_settings) { -#ifdef ONLCR - tty_settings->c_oflag |= ONLCR; -#endif - tty_settings->c_iflag |= ICRNL; - tty_settings->c_lflag |= ECHO; -#ifdef OXTABS - tty_settings->c_oflag |= OXTABS; -#endif /* OXTABS */ +#if defined(EXP_WIN32_DRIVER) + /* FIXME */ +#else + set_flags(tty_settings->c_oflag, ONLCR); + set_flags(tty_settings->c_iflag, ICRNL); + set_flags(tty_settings->c_lflag, ECHO); + set_flags(tty_settings->c_oflag, OXTABS); /* test used to be tgetflag("NL") */ - if (newline != (char *) 0 && newline[0] == '\n' && !newline[1]) { + if (VALID_STRING(newline) && newline[0] == '\n' && !newline[1]) { /* Newline, not linefeed. */ -#ifdef ONLCR - tty_settings->c_oflag &= ~((unsigned) ONLCR); -#endif - tty_settings->c_iflag &= ~((unsigned) ICRNL); + clear_flags(tty_settings->c_oflag, ONLCR); + clear_flags(tty_settings->c_iflag, ICRNL); } -#ifdef OXTABS +#if OXTABS /* test used to be tgetflag("pt") */ - if (has_hardware_tabs) /* Print tabs. */ - tty_settings->c_oflag &= ~OXTABS; + if (VALID_STRING(set_tab) && VALID_STRING(clear_all_tabs)) + clear_flags(tty_settings->c_oflag, OXTABS); #endif /* OXTABS */ - tty_settings->c_lflag |= (ECHOE | ECHOK); + set_flags(tty_settings->c_lflag, (ECHOE | ECHOK)); +#endif +} + +static bool +sent_string(const char *s) +{ + bool sent = FALSE; + if (VALID_STRING(s)) { + tputs(s, 0, out_char); + sent = TRUE; + } + return sent; +} + +static bool +to_left_margin(void) +{ + if (VALID_STRING(carriage_return)) { + sent_string(carriage_return); + } else { + out_char('\r'); + } + return TRUE; } /* @@ -450,58 +497,45 @@ set_conversions(TTY * tty_settings) static bool reset_tabstops(int wide) { - if ((init_tabs != 8) && (set_tab && clear_all_tabs)) { + if ((init_tabs != 8) + && VALID_NUMERIC(init_tabs) + && VALID_STRING(set_tab) + && VALID_STRING(clear_all_tabs)) { int c; - (void) putc('\r', my_file); /* Force to left margin. */ + to_left_margin(); tputs(clear_all_tabs, 0, out_char); - - for (c = 8; c < wide; c += 8) { - /* Get to the right column. In BSD tset, this used to try a bunch - * of half-clever things with cup and hpa, for an average saving of - * somewhat less than two character times per tab stop, less than - * .01 sec at 2400cps. We lost all this cruft because it seemed to - * be introducing some odd bugs. - * -----------12345678----------- */ - (void) fputs(" ", my_file); - tputs(set_tab, 0, out_char); + if (init_tabs > 1) { + if (init_tabs > wide) + init_tabs = (short) wide; + for (c = init_tabs; c < wide; c += init_tabs) { + fprintf(my_file, "%*s", init_tabs, " "); + tputs(set_tab, 0, out_char); + } + to_left_margin(); } - putc('\r', my_file); return (TRUE); } return (FALSE); } -static bool -sent_string(const char *s) -{ - bool sent = FALSE; - if (s != 0) { - tputs(s, 0, out_char); - sent = TRUE; - } - return sent; -} - -#define PUTCHAR(c) fputc(c, my_file) - /* Output startup string. */ bool -send_init_strings(TTY * old_settings) +send_init_strings(int fd GCC_UNUSED, TTY * old_settings) { int i; bool need_flush = FALSE; (void) old_settings; -#ifdef TAB3 +#if TAB3 if (old_settings != 0 && old_settings->c_oflag & (TAB3 | ONLCR | OCRNL | ONLRET)) { old_settings->c_oflag &= (TAB3 | ONLCR | OCRNL | ONLRET); - SET_TTY(my_fd, old_settings); + SET_TTY(fd, old_settings); } #endif if (use_reset || use_init) { - if (init_prog != 0) { + if (VALID_STRING(init_prog)) { IGNORE_RC(system(init_prog)); } @@ -513,38 +547,37 @@ send_init_strings(TTY * old_settings) ? reset_2string : init_2string); - if (set_lr_margin != 0) { - need_flush |= sent_string(TPARM_2(set_lr_margin, 0, - columns - 1)); - } else if (set_left_margin_parm != 0 - && set_right_margin_parm != 0) { - need_flush |= sent_string(TPARM_1(set_left_margin_parm, 0)); - need_flush |= sent_string(TPARM_1(set_right_margin_parm, - columns - 1)); - } else if (clear_margins != 0 - && set_left_margin != 0 - && set_right_margin != 0) { + if (VALID_STRING(clear_margins)) { need_flush |= sent_string(clear_margins); - if (carriage_return != 0) { - need_flush |= sent_string(carriage_return); - } else { - PUTCHAR('\r'); - } + } +#if defined(set_lr_margin) + else if (VALID_STRING(set_lr_margin)) { + need_flush |= sent_string(TIPARM_2(set_lr_margin, 0, columns - 1)); + } +#endif +#if defined(set_left_margin_parm) && defined(set_right_margin_parm) + else if (VALID_STRING(set_left_margin_parm) + && VALID_STRING(set_right_margin_parm)) { + need_flush |= sent_string(TIPARM_1(set_left_margin_parm, 0)); + need_flush |= sent_string(TIPARM_1(set_right_margin_parm, + columns - 1)); + } +#endif + else if (VALID_STRING(set_left_margin) + && VALID_STRING(set_right_margin)) { + need_flush |= to_left_margin(); need_flush |= sent_string(set_left_margin); - if (parm_right_cursor) { - need_flush |= sent_string(TPARM_1(parm_right_cursor, - columns - 1)); + if (VALID_STRING(parm_right_cursor)) { + need_flush |= sent_string(TIPARM_1(parm_right_cursor, + columns - 1)); } else { for (i = 0; i < columns - 1; i++) { - PUTCHAR(' '); + out_char(' '); + need_flush = TRUE; } } need_flush |= sent_string(set_right_margin); - if (carriage_return != 0) { - need_flush |= sent_string(carriage_return); - } else { - PUTCHAR('\r'); - } + need_flush |= to_left_margin(); } need_flush |= reset_tabstops(columns); @@ -569,15 +602,23 @@ show_tty_change(TTY * old_settings, int which, unsigned def) { - unsigned older, newer; + unsigned older = 0, newer = 0; char *p; +#if defined(EXP_WIN32_DRIVER) + /* noop */ + (void) old_settings; + (void) new_settings; + (void) name; + (void) which; + (void) def; +#else newer = new_settings->c_cc[which]; older = old_settings->c_cc[which]; if (older == newer && older == def) return; - +#endif (void) fprintf(stderr, "%s %s ", name, older == newer ? "is" : "set to"); if (DISABLED(newer)) { @@ -621,58 +662,36 @@ reset_flush(void) void print_tty_chars(TTY * old_settings, TTY * new_settings) { +#if defined(EXP_WIN32_DRIVER) + /* noop */ +#else show_tty_change(old_settings, new_settings, "Erase", VERASE, CERASE); show_tty_change(old_settings, new_settings, "Kill", VKILL, CKILL); show_tty_change(old_settings, new_settings, "Interrupt", VINTR, CINTR); +#endif } +#if HAVE_SIZECHANGE /* - * Open a file descriptor on the current terminal, to obtain its settings. - * stderr is less likely to be redirected than stdout; try that first. + * Set window size if not set already, but update our copy of the values if the + * size was set. */ -int -save_tty_settings(TTY * tty_settings) -{ - if (!get_tty_settings(STDERR_FILENO, tty_settings) && - !get_tty_settings(STDOUT_FILENO, tty_settings) && - !get_tty_settings(STDIN_FILENO, tty_settings) && - !get_tty_settings(open("/dev/tty", O_RDWR), tty_settings)) { - failed("terminal attributes"); - } - can_restore = TRUE; - original_settings = *tty_settings; - return my_fd; -} - void -restore_tty_settings(void) -{ - if (can_restore) - SET_TTY(my_fd, &original_settings); -} - -/* Set the modes if they've changed. */ -void -update_tty_settings(TTY * old_settings, TTY * new_settings) -{ - if (memcmp(new_settings, old_settings, sizeof(TTY))) { - SET_TTY(my_fd, new_settings); - } -} - -#if HAVE_SIZECHANGE -/* Set window size if not set already */ -void -set_window_size(int fd, int high, int wide) +set_window_size(int fd, NCURSES_INT2 *high, NCURSES_INT2 *wide) { STRUCT_WINSIZE win; (void) ioctl(fd, IOCTL_GET_WINSIZE, &win); if (WINSIZE_ROWS(win) == 0 && - WINSIZE_COLS(win) == 0 && - high > 0 && wide > 0) { - WINSIZE_ROWS(win) = (unsigned short) high; - WINSIZE_COLS(win) = (unsigned short) wide; - (void) ioctl(fd, IOCTL_SET_WINSIZE, &win); + WINSIZE_COLS(win) == 0) { + if (*high > 0 && *wide > 0) { + WINSIZE_ROWS(win) = (unsigned short) *high; + WINSIZE_COLS(win) = (unsigned short) *wide; + (void) ioctl(fd, IOCTL_SET_WINSIZE, &win); + } + } else if (WINSIZE_ROWS(win) > 0 && + WINSIZE_COLS(win) > 0) { + *high = (short) WINSIZE_ROWS(win); + *wide = (short) WINSIZE_COLS(win); } } #endif