diff -ur screen.orig/ansi.c screen/ansi.c --- screen.orig/ansi.c 2023-06-01 14:58:17.230665007 +0300 +++ screen/ansi.c 2022-01-28 17:06:02.666611503 +0300 @@ -727,8 +727,8 @@ break; } # ifdef DW_CHARS - if (curr->w_encoding == UTF8 && utf8_isdouble(c)) - curr->w_mbcs = 0xff; + if (curr->w_encoding == UTF8 && utf8_isdouble(c)) + curr->w_mbcs = 0xff; # endif font = curr->w_rend.font; # endif @@ -3027,7 +3027,7 @@ WMsg(p, err, str) struct win *p; int err; -const char *str; +char *str; { extern struct layer *flayer; struct layer *oldflayer = flayer; diff -ur screen.orig/attacher.c screen/attacher.c --- screen.orig/attacher.c 2023-06-01 14:58:17.231665009 +0300 +++ screen/attacher.c 2022-01-28 17:06:02.666611503 +0300 @@ -33,14 +33,9 @@ #include #include #include -#include #include "screen.h" #include "extern.h" -#ifdef USE_PAM -#include -#endif - #include static int WriteMessage __P((int, struct msg *)); @@ -59,7 +54,7 @@ #endif static sigret_t AttachSigCont __P(SIGPROTOARG); -extern int real_uid, real_gid, eff_uid, eff_gid, init_eff_gid; +extern int real_uid, real_gid, eff_uid, eff_gid; extern int ServerSocket; extern struct display *displays; extern char *SockName, *SockMatch, SockPath[]; @@ -704,7 +699,7 @@ /* ADDED by Rainer Pruy 10/15/87 */ /* POLISHED by mls. 03/10/91 */ -static const char LockEnd[] = "Welcome back to screen !!\n"; +static char LockEnd[] = "Welcome back to screen !!\n"; static sigret_t LockHup SIGDEFARG @@ -741,7 +736,6 @@ { signal(SIGCHLD, SIG_DFL); debug1("lockterminal: '%s' seems executable, execl it!\n", prg); - fflush(NULL); if ((pid = fork()) == 0) { /* Child */ @@ -821,7 +815,6 @@ #ifdef USE_PAM -#if 0 /* * PAM support by Pablo Averbuj */ @@ -876,13 +869,8 @@ &PAM_conv, NULL }; -#endif -static pam_userpass_t userpass; -static struct pam_conv conv = { - &pam_userpass_conv, - &userpass -}; + #endif /* -- original copyright by Luigi Cannelloni 1985 (luigi@faui70.UUCP) -- */ @@ -891,10 +879,9 @@ { char fullname[100], *cp1, message[100 + 100]; #ifdef USE_PAM - int status; - pam_handle_t *pamh = NULL; -#else - char *pass, mypass[16 + 1], salt[3]; + pam_handle_t *pamh = 0; + int pam_error; + char *tty_name; #endif char *pass = 0, mypass[16 + 1], salt[3]; int using_pam = 1; @@ -976,35 +963,23 @@ if (using_pam) { #ifdef USE_PAM - userpass.user = ppp->pw_name; - userpass.pass = cp1; - - openlog("screen", LOG_PID, LOG_AUTH); - status = pam_start("screen", ppp->pw_name, &conv, &pamh); - - if (status == PAM_SUCCESS) - { - /* Let the PAM modules make use of our SGID privileges. */ - xsetegid(init_eff_gid); - if ((status = pam_authenticate(pamh, 0)) != PAM_SUCCESS) - { - xsetegid(real_gid); - pam_end(pamh, status); - continue; - } - xsetegid(real_gid); + PAM_conversation.appdata_ptr = cp1; + pam_error = pam_start("screen", ppp->pw_name, &PAM_conversation, &pamh); + if (pam_error != PAM_SUCCESS) + AttacherFinit(SIGARG); /* goodbye */ - status = pam_end(pamh, PAM_SUCCESS); - if (status == PAM_SUCCESS) - { - memset(cp1, 0, strlen(cp1)); - userpass.pass = NULL; - break; - } - } - -#else - if (!strncmp(crypt(cp1, pass), pass, strlen(pass))) + if (strncmp(attach_tty, "/dev/", 5) == 0) + tty_name = attach_tty + 5; + else + tty_name = attach_tty; + pam_error = pam_set_item(pamh, PAM_TTY, tty_name); + if (pam_error != PAM_SUCCESS) + AttacherFinit(SIGARG); /* goodbye */ + + pam_error = pam_authenticate(pamh, 0); + pam_end(pamh, pam_error); + PAM_conversation.appdata_ptr = 0; + if (pam_error == PAM_SUCCESS) break; #endif } diff -ur screen.orig/autogen.sh screen/autogen.sh --- screen.orig/autogen.sh 2023-06-01 14:58:17.231665009 +0300 +++ screen/autogen.sh 2022-01-28 17:06:02.666611503 +0300 @@ -1,2 +1,2 @@ #!/bin/sh -exec autoreconf +autoreconf -i diff -ur screen.orig/braille_tsi.c screen/braille_tsi.c --- screen.orig/braille_tsi.c 2023-06-01 14:58:17.231665009 +0300 +++ screen/braille_tsi.c 2022-01-28 17:06:02.670611602 +0300 @@ -6,7 +6,7 @@ * Bill Barry barryb@dots.physics.orst.edu * * Copyright (c) 1995 by Science Access Project, Oregon State University. - * + * * * 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 @@ -36,21 +36,20 @@ extern struct display *display; struct key2rc { - int key; - int nr; - char *arg1; - char *arg2; + int key; + int nr; + char *arg1; + char *arg2; }; +static int tsi_ctype = 1; /* cursor type, 0,1,2 */ -static int tsi_ctype = 1; /* cursor type, 0,1,2 */ - -static int tsi_line_type; /* indicates number of cells on powerbraille - display 01=20 cells 02=40 cells 03=80 cells */ +static int tsi_line_type; /* indicates number of cells on powerbraille + display 01=20 cells 02=40 cells 03=80 cells */ static int display_status_tsi __P((void)); -static int write_line_tsi __P((char *, int, int)); -static void buttonpress_tsi __P((struct key2rc *)); +static int write_line_tsi __P((char*, int, int)); +static void buttonpress_tsi __P((structkey2rc*)); static void buttonpress_navigator_40 __P((void)); static void buttonpress_powerbraille_40 __P((void)); static void buttonpress_powerbraille_80 __P((void)); @@ -58,262 +57,258 @@ int bd_init_powerbraille_40() { - bd.write_line_braille = write_line_tsi; - bd.buttonpress = buttonpress_powerbraille_40; - bd.bd_response_test = display_status_tsi; - bd.bd_ncells = 40; - tsi_line_type = 2; - return 0; + bd.write_line_braille = write_line_tsi; + bd.buttonpress = buttonpress_powerbraille_40; + bd.bd_response_test = display_status_tsi; + bd.bd_ncells = 40; + tsi_line_type = 2; + return 0; } int bd_init_powerbraille_80() { - bd.write_line_braille = write_line_tsi; - bd.buttonpress = buttonpress_powerbraille_80; - bd.bd_response_test = display_status_tsi; - bd.bd_ncells = 80; - tsi_line_type = 3; - return 0; + bd.write_line_braille = write_line_tsi; + bd.buttonpress = buttonpress_powerbraille_80; + bd.bd_response_test = display_status_tsi; + bd.bd_ncells = 80; + tsi_line_type = 3; + return 0; } int bd_init_navigator_40() { - bd.write_line_braille = write_line_tsi; - bd.buttonpress = buttonpress_navigator_40; - bd.bd_response_test = display_status_tsi; - bd.bd_ncells = 40; - tsi_line_type = 2; - return 0; + bd.write_line_braille = write_line_tsi; + bd.buttonpress = buttonpress_navigator_40; + bd.bd_response_test = display_status_tsi; + bd.bd_ncells = 40; + tsi_line_type = 2; + return 0; } -static int +static int display_status_tsi() { - char obuf[3],ibuf[20]; - int r; + char obuf[3], ibuf[20]; + int r; - obuf[0] = 0xff; - obuf[1] = 0xff; - obuf[2] = 0x0a; - r = read(bd.bd_fd, ibuf, 20); /* flush the input port */ - r = write(bd.bd_fd, obuf, 3); - if (r != 3) - return -1; + obuf[0] = 0xff; + obuf[1] = 0xff; + obuf[2] = 0x0a; + r = read(bd.bd_fd, ibuf, 20); /* flush the input port */ + r = write(bd.bd_fd, obuf, 3); + if (r != 3) + return -1; /* we have written to the display asking for a response - we wait 1 second for the response, read it and if no + we wait 1 second for the response, read it and if no response we wait 2 seconds, if still no response, return -1 to indicate no braille display available */ - sleep(1); - r = read(bd.bd_fd, ibuf, 2); - if (r == -1) - { - sleep(2); - r = read(bd.bd_fd, ibuf, 2); - } - debug2("first chars from braille display %d %d\n",ibuf[0],ibuf[1]); - if (r != 2 || ibuf[0] != 0 || ibuf[1] != 5) - return -1; - - r= read(bd.bd_fd,ibuf,2); - if (r != 2) - return -1; - debug2("braille display size:%d dots:%d\n", ibuf[0], ibuf[1]); - bd.bd_ncells = (unsigned char)ibuf[0]; - if (bd.bd_ncells <= 1) - return -1; - r = read(bd.bd_fd,ibuf,1); - if (r != 1) - return -1; - if (ibuf[0] == 'V') - r = read(bd.bd_fd, ibuf, 3); - else - r = read(bd.bd_fd, ibuf + 1, 2) + 1; - if (r != 3) - return -1; - ibuf[3] = 0; - debug1("braille display version %s\n", ibuf); - bd.bd_version = atof(ibuf); - return 0; + + sleep(1); + r = read(bd.bd_fd, ibuf, 2); + if (r == -1) { + sleep(2); + r = read(bd.bd_fd, ibuf, 2); + } + + debug2("first chars from braille display %d %d\n", ibuf[0], ibuf[1]); + if (r != 2 || ibuf[0] != 0 || ibuf[1] != 5) + return -1; + + r = read(bd.bd_fd, ibuf, 2); + if (r != 2) + return -1; + + debug2("braille display size:%d dots:%d\n", ibuf[0], ibuf[1]); + bd.bd_ncells = (unsigned char)ibuf[0]; + if (bd.bd_ncells <= 1) + return -1; + + r = read(bd.bd_fd, ibuf, 1); + if (r != 1) + return -1; + + if (ibuf[0] == 'V') + r = read(bd.bd_fd, ibuf, 3); + else + r = read(bd.bd_fd, ibuf + 1, 2) + 1; + + if (r != 3) + return -1; + + ibuf[3] = 0; + debug1("braille display version %s\n", ibuf); + bd.bd_version = atof(ibuf); + return 0; } - -static int -write_line_tsi (bstr,line_length, cursor_pos) -char *bstr; -int line_length, cursor_pos; +static int +write_line_tsi(char *bstr, int line_length, int cursor_pos) { - int obp, i; - bd.bd_obuf[0] = 0xff; - bd.bd_obuf[1] = 0xff; - bd.bd_obuf[2] = tsi_line_type; - bd.bd_obuf[3] = 0x07; - bd.bd_obuf[4] = cursor_pos; - bd.bd_obuf[5] = tsi_ctype; - obp=6; - - for (i=0; i < line_length; i++) - { - bd.bd_obuf[2*i+obp] = 0; - bd.bd_obuf[2*i+1+obp] = bd.bd_btable[(int)(unsigned char)bstr[i]]; - } - for (i=line_length; i < bd.bd_ncells; i++) - { - bd.bd_obuf[2*i+obp] = 0; - bd.bd_obuf[2*i+1+obp] = bd.bd_btable[(int)' ']; - } + int obp, i; + bd.bd_obuf[0] = 0xff; + bd.bd_obuf[1] = 0xff; + bd.bd_obuf[2] = tsi_line_type; + bd.bd_obuf[3] = 0x07; + bd.bd_obuf[4] = cursor_pos; + bd.bd_obuf[5] = tsi_ctype; + obp = 6; + + for (i = 0; i < line_length; i++) { + bd.bd_obuf[2*i + obp] = 0; + bd.bd_obuf[2*i + 1 + obp] = bd.bd_btable[(int)(unsigned char)bstr[i]]; + } + for (i = line_length; i < bd.bd_ncells; i++) { + bd.bd_obuf[2*i + obp] = 0; + bd.bd_obuf[2*i + 1 + obp] = bd.bd_btable[(int)' ']; + } - bd.bd_obuflen = 2*bd.bd_ncells + obp ; - return 0; + bd.bd_obuflen = 2*bd.bd_ncells + obp; + return 0; } static struct key2rc keys_navigator_40[] = { - {0x4000000, RC_STUFF, "-k", "kl"}, /* 1 */ - {0x10000000, RC_STUFF, "-k", "kr"}, /* 3 */ - {0x8000000, RC_STUFF, "-k", "ku"}, /* 2 */ - {0x20000000, RC_STUFF, "-k", "kd"}, /* 4 */ - {0x2000, RC_BD_BC_LEFT, 0, 0}, /* 6 */ - {0x8000, RC_BD_BC_RIGHT, 0, 0}, /* 8 */ - {0x4000, RC_BD_BC_UP, 0, 0}, /* 7 */ - {0x10000, RC_BD_BC_DOWN, 0, 0}, /* 9 */ - {0x6000, RC_BD_UPPER_LEFT, 0, 0}, /* 6, 7 */ - {0xc000, RC_BD_UPPER_RIGHT, 0, 0}, /* 7, 8 */ - {0x12000, RC_BD_LOWER_LEFT, 0, 0}, /* 6, 9 */ - {0x18000, RC_BD_LOWER_RIGHT, 0, 0}, /* 8, 9 */ - {0xa000, RC_BD_INFO, "1032", 0}, /* bc 6, 8 */ - {0x14000000, RC_BD_INFO, "2301", 0}, /* sc 1, 3 */ - {0x4008000, RC_BD_INFO, "3330", 0}, /* bc+sc 1, 8 */ - {0x8010000, RC_BD_BELL, 0, 0}, /* 2, 9 */ - {0x8004000, RC_BD_EIGHTDOT, 0, 0}, /* 2, 7 */ - {0x40000000, RC_STUFF, "\015", 0}, /* 5 */ - {0x20000, RC_BD_LINK, 0, 0}, /* 10 */ - {0x10002000, RC_BD_SCROLL, 0, 0}, /* 3, 6 */ - {0x20010000, RC_BD_NCRC, "+", 0}, /* 4, 9 */ - {0x14000, RC_BD_SKIP, 0, 0}, /* 7, 9*/ - {-1, RC_ILLEGAL, 0, 0} + {0x4000000, RC_STUFF, "-k", "kl"}, /* 1 */ + {0x10000000, RC_STUFF, "-k", "kr"}, /* 3 */ + {0x8000000, RC_STUFF, "-k", "ku"}, /* 2 */ + {0x20000000, RC_STUFF, "-k", "kd"}, /* 4 */ + {0x2000, RC_BD_BC_LEFT, 0, 0}, /* 6 */ + {0x8000, RC_BD_BC_RIGHT, 0, 0}, /* 8 */ + {0x4000, RC_BD_BC_UP, 0, 0}, /* 7 */ + {0x10000, RC_BD_BC_DOWN, 0, 0}, /* 9 */ + {0x6000, RC_BD_UPPER_LEFT, 0, 0}, /* 6, 7 */ + {0xc000, RC_BD_UPPER_RIGHT, 0, 0}, /* 7, 8 */ + {0x12000, RC_BD_LOWER_LEFT, 0, 0}, /* 6, 9 */ + {0x18000, RC_BD_LOWER_RIGHT, 0, 0}, /* 8, 9 */ + {0xa000, RC_BD_INFO, "1032", 0}, /* bc 6, 8 */ + {0x14000000, RC_BD_INFO, "2301", 0}, /* sc 1, 3 */ + {0x4008000, RC_BD_INFO, "3330", 0}, /* bc+sc 1, 8 */ + {0x8010000, RC_BD_BELL, 0, 0}, /* 2, 9 */ + {0x8004000, RC_BD_EIGHTDOT, 0, 0}, /* 2, 7 */ + {0x40000000, RC_STUFF, "\015", 0}, /* 5 */ + {0x20000, RC_BD_LINK, 0, 0}, /* 10 */ + {0x10002000, RC_BD_SCROLL, 0, 0}, /* 3, 6 */ + {0x20010000, RC_BD_NCRC, "+", 0}, /* 4, 9 */ + {0x14000, RC_BD_SKIP, 0, 0}, /* 7, 9*/ + {-1, RC_ILLEGAL, 0, 0} }; static struct key2rc keys_powerbraille_40[] = { - {0x4000000, RC_STUFF, "-k", "kl"}, /* 1 */ - {0x10000000, RC_STUFF, "-k", "kr"}, /* 3 */ - {0x8000000, RC_STUFF, "-k", "ku"}, /* 2 */ - {0x20000000, RC_STUFF, "-k", "kd"}, /* 4 */ - {0x2000, RC_BD_BC_LEFT, 0, 0}, /* 6 */ - {0x8000, RC_BD_BC_RIGHT, 0, 0}, /* 8 */ - {0x4000, RC_BD_BC_UP, 0, 0}, /* 7 */ - {0x10000, RC_BD_BC_DOWN, 0, 0}, /* 9 */ - {0x8002000, RC_BD_UPPER_LEFT, 0, 0}, /* 2, 6 */ - {0xc000, RC_BD_UPPER_RIGHT, 0, 0}, /* 7, 8 */ - {0x20002000, RC_BD_LOWER_LEFT, 0, 0}, /* 3, 6 */ - {0x18000, RC_BD_LOWER_RIGHT, 0, 0}, /* 8, 9 */ - {0x8008000, RC_BD_INFO, "1032", 0}, /* bc 2, 8 */ - {0x6000, RC_BD_INFO, "2301", 0}, /* 6, 7 */ - {0x8004000, RC_BD_INFO, "3330", 0}, /* bc+sc 2, 7 */ - {0x8010000, RC_BD_BELL, 0, 0}, /* 2, 9 */ - {0x20008000, RC_BD_EIGHTDOT, 0, 0}, /* 4, 6 */ - {0x40000000, RC_STUFF, "\015", 0}, /* 5 */ - {0x20000, RC_BD_LINK, 0, 0}, /* 10 */ - {0xa000, RC_BD_SCROLL, 0, 0}, /* 6, 8 */ - {0x20010000, RC_BD_NCRC, "+", 0}, /* 4, 9 */ - {0x20004000, RC_BD_SKIP, 0, 0}, /* 4, 7 */ - {-1, RC_ILLEGAL, 0, 0} + {0x4000000, RC_STUFF, "-k", "kl"}, /* 1 */ + {0x10000000, RC_STUFF, "-k", "kr"}, /* 3 */ + {0x8000000, RC_STUFF, "-k", "ku"}, /* 2 */ + {0x20000000, RC_STUFF, "-k", "kd"}, /* 4 */ + {0x2000, RC_BD_BC_LEFT, 0, 0}, /* 6 */ + {0x8000, RC_BD_BC_RIGHT, 0, 0}, /* 8 */ + {0x4000, RC_BD_BC_UP, 0, 0}, /* 7 */ + {0x10000, RC_BD_BC_DOWN, 0, 0}, /* 9 */ + {0x8002000, RC_BD_UPPER_LEFT, 0, 0}, /* 2, 6 */ + {0xc000, RC_BD_UPPER_RIGHT, 0, 0}, /* 7, 8 */ + {0x20002000, RC_BD_LOWER_LEFT, 0, 0}, /* 3, 6 */ + {0x18000, RC_BD_LOWER_RIGHT, 0, 0}, /* 8, 9 */ + {0x8008000, RC_BD_INFO, "1032", 0}, /* bc 2, 8 */ + {0x6000, RC_BD_INFO, "2301", 0}, /* 6, 7 */ + {0x8004000, RC_BD_INFO, "3330", 0}, /* bc+sc 2, 7 */ + {0x8010000, RC_BD_BELL, 0, 0}, /* 2, 9 */ + {0x20008000, RC_BD_EIGHTDOT, 0, 0}, /* 4, 6 */ + {0x40000000, RC_STUFF, "\015", 0}, /* 5 */ + {0x20000, RC_BD_LINK, 0, 0}, /* 10 */ + {0xa000, RC_BD_SCROLL, 0, 0}, /* 6, 8 */ + {0x20010000, RC_BD_NCRC, "+", 0}, /* 4, 9 */ + {0x20004000, RC_BD_SKIP, 0, 0}, /* 4, 7 */ + {-1, RC_ILLEGAL, 0, 0} }; - static struct key2rc keys_powerbraille_80[] = { - {0x4000000, RC_STUFF, "-k", "kl"}, /* 1 */ - {0x10000000, RC_STUFF, "-k", "kr"}, /* 3 */ - {0x8000000, RC_STUFF, "-k", "ku"}, /* 2 */ - {0x20000000, RC_STUFF, "-k", "kd"}, /* 4 */ - {0x40000, RC_BD_BC_LEFT, 0, 0}, /* 6 */ - {0x100000, RC_BD_BC_RIGHT, 0, 0}, /* 8 */ - {0x4000, RC_BD_BC_UP, 0, 0}, /* 7 */ - {0x10000, RC_BD_BC_DOWN, 0, 0}, /* 9 */ - {0x44000, RC_BD_UPPER_LEFT, 0, 0}, /* 6, 7 */ - {0x104000, RC_BD_UPPER_RIGHT, 0, 0}, /* 7, 8 */ - {0x50000, RC_BD_LOWER_LEFT, 0, 0}, /* 6, 9 */ - {0x110000, RC_BD_LOWER_RIGHT, 0, 0}, /* 8, 9 */ - {0x8100000, RC_BD_INFO, "1032", 0}, /* 2, 8 */ - {0x8040000, RC_BD_INFO, "2301", 0}, /* 2, 6 */ - {0x140000, RC_BD_INFO, "3330", 0}, /* 6, 8 */ - {0x8010000, RC_BD_BELL, 0, 0}, /* 2, 9 */ - {0x8004000, RC_BD_EIGHTDOT, 0, 0}, /* 2, 7 */ - {0x40000000, RC_STUFF, "\015", 0}, /* 5 */ - {0x20000, RC_BD_LINK, 0, 0}, /* 10 */ - {0x20004000, RC_BD_SCROLL, 0, 0}, /* 4, 7 */ - {0x20010000, RC_BD_NCRC, "+", 0}, /* 4, 9 */ - {0x40010000, RC_BD_SKIP, 0, 0}, /* 5, 9 */ - {-1, RC_ILLEGAL, 0, 0} + {0x4000000, RC_STUFF, "-k", "kl"}, /* 1 */ + {0x10000000, RC_STUFF, "-k", "kr"}, /* 3 */ + {0x8000000, RC_STUFF, "-k", "ku"}, /* 2 */ + {0x20000000, RC_STUFF, "-k", "kd"}, /* 4 */ + {0x40000, RC_BD_BC_LEFT, 0, 0}, /* 6 */ + {0x100000, RC_BD_BC_RIGHT, 0, 0}, /* 8 */ + {0x4000, RC_BD_BC_UP, 0, 0}, /* 7 */ + {0x10000, RC_BD_BC_DOWN, 0, 0}, /* 9 */ + {0x44000, RC_BD_UPPER_LEFT, 0, 0}, /* 6, 7 */ + {0x104000, RC_BD_UPPER_RIGHT, 0, 0}, /* 7, 8 */ + {0x50000, RC_BD_LOWER_LEFT, 0, 0}, /* 6, 9 */ + {0x110000, RC_BD_LOWER_RIGHT, 0, 0}, /* 8, 9 */ + {0x8100000, RC_BD_INFO, "1032", 0}, /* 2, 8 */ + {0x8040000, RC_BD_INFO, "2301", 0}, /* 2, 6 */ + {0x140000, RC_BD_INFO, "3330", 0}, /* 6, 8 */ + {0x8010000, RC_BD_BELL, 0, 0}, /* 2, 9 */ + {0x8004000, RC_BD_EIGHTDOT, 0, 0}, /* 2, 7 */ + {0x40000000, RC_STUFF, "\015", 0}, /* 5 */ + {0x20000, RC_BD_LINK, 0, 0}, /* 10 */ + {0x20004000, RC_BD_SCROLL, 0, 0}, /* 4, 7 */ + {0x20010000, RC_BD_NCRC, "+", 0}, /* 4, 9 */ + {0x40010000, RC_BD_SKIP, 0, 0}, /* 5, 9 */ + {-1, RC_ILLEGAL, 0, 0} }; static void -buttonpress_tsi(tab) -struct key2rc *tab; +buttonpress_tsi(struct key2rc *tab) { - int i, nb; - int bkeys; - unsigned char buf[10]; - nb = read(bd.bd_fd, buf, 10); - debug1("buttonpress_tsi: read %d bytes\n", nb); - for (i=0, bkeys=0; i < nb; i++) - { - switch (buf[i] & 0xE0) - { - case 0x00: bkeys += ((int)(buf[i] & 0x1f) ); break; - case 0x20: bkeys += ((int)(buf[i] & 0x1f) << 5 ); break; - case 0x40: bkeys += ((int)(buf[i] & 0x1f) << 9 ); break; - case 0x60: bkeys += ((int)(buf[i] & 0x1f) << 13 ); break; - case 0xA0: bkeys += ((int)(buf[i] & 0x1f) << 18 ); break; - case 0xC0: bkeys += ((int)(buf[i] & 0x1f) << 22 ); break; - case 0xE0: bkeys += ((int)(buf[i] & 0x1f) << 26 ); break; - default: break; + int i, nb; + int bkeys; + unsigned char buf[10]; + nb = read(bd.bd_fd, buf, 10); + debug1("buttonpress_tsi: read %d bytes\n", nb); + for (i = 0, bkeys = 0; i < nb; i++) { + switch (buf[i] & 0xE0) { + case 0x00: bkeys += ((int)(buf[i] & 0x1f)); break; + case 0x20: bkeys += ((int)(buf[i] & 0x1f) << 5); break; + case 0x40: bkeys += ((int)(buf[i] & 0x1f) << 9); break; + case 0x60: bkeys += ((int)(buf[i] & 0x1f) << 13); break; + case 0xA0: bkeys += ((int)(buf[i] & 0x1f) << 18); break; + case 0xC0: bkeys += ((int)(buf[i] & 0x1f) << 22); break; + case 0xE0: bkeys += ((int)(buf[i] & 0x1f) << 26); break; + default: break; + } } - } - debug1("bkeys %x\n", bkeys); - for (i = 0; tab[i].key != -1; i++) - if (bkeys == tab[i].key) - break; - debug1("bkey index %d\n", i); - if (tab[i].key != -1 && tab[i].nr != RC_ILLEGAL) - { - char *args[3]; - int argl[2]; - - struct action act; - args[0] = tab[i].arg1; - args[1] = tab[i].arg2; - args[2] = 0; - argl[0] = args[0] ? strlen(args[0]) : 0; - argl[1] = args[1] ? strlen(args[1]) : 0; - act.nr = tab[i].nr; - act.args = args; - act.argl = argl; - display = bd.bd_dpy; - DoAction(&act, -2); - } -} + debug1("bkeys %x\n", bkeys); + for (i = 0; tab[i].key != -1; i++) + if (bkeys == tab[i].key) + break; + + debug1("bkey index %d\n", i); + + if (tab[i].key != -1 && tab[i].nr != RC_ILLEGAL) { + char *args[3]; + int argl[2]; + + struct action act; + args[0] = tab[i].arg1; + args[1] = tab[i].arg2; + args[2] = 0; + argl[0] = args[0] ? strlen(args[0]) : 0; + argl[1] = args[1] ? strlen(args[1]) : 0; + act.nr = tab[i].nr; + act.args = args; + act.argl = argl; + display = bd.bd_dpy; + DoAction(&act, -2); + } +} static void buttonpress_navigator_40() { - buttonpress_tsi(keys_navigator_40); + buttonpress_tsi(keys_navigator_40); } static void buttonpress_powerbraille_40() { - buttonpress_tsi(keys_powerbraille_40); + buttonpress_tsi(keys_powerbraille_40); } static void buttonpress_powerbraille_80() { - buttonpress_tsi(keys_powerbraille_80); + buttonpress_tsi(keys_powerbraille_80); } #endif /* HAVE_BRAILLE */ - - diff -ur screen.orig/ChangeLog screen/ChangeLog --- screen.orig/ChangeLog 2023-06-01 14:58:17.228665002 +0300 +++ screen/ChangeLog 2022-01-28 17:06:02.662611403 +0300 @@ -1,18 +1,28 @@ -Version 4.8.0 (05/02/2020) +Version 4.9.0 (30/01/2022): + * Hardstatus option for used encoding (escape string '%e') + * OpenBSD uses native openpty() from its utils.h + * Fixes: + - fix combining char handling that could lead to a segfault + - CVE-2021-26937: possible denial of service via a crafted UTF-8 character sequence (bug #60030) + - make screen exit code be 0 when checking --help + - session names limit is 80 symbols (bug #61534) + - option -X ignores specified user in multiuser env (bug #37437) + - a lot of reformations/fixes/cleanups (man page and source code) + +Version 4.8.0 (05/02/2020): * Improve startup time by only polling for files to close - Fixes: + * Fixes: - Fix for segfault if termcap doesn't have Km entry - Make screen exit code be 0 when checking --version - Fix potential memory corruption when using OSC 49 - -Version 4.7.0 (02/10/2019) +Version 4.7.0 (02/10/2019): * Add support for SGR (1006) mouse mode * Add support for OSC 11 * Update Unicode ambiguous and wide tables to 12.1.0 * Fixes: - - cross-compilation support (bug #43223) - - a lot of manpage fixes and cleanups + - cross-compilation support (bug #43223) + - a lot of manpage fixes and cleanups Version 4.6.2 (23/10/2017): * Fixes: @@ -62,12 +72,11 @@ * Introduce Xx string escape showing the executed command of a window * Implement dead/zombie window polling, allowing for auto reconnecting * Allow setting hardstatus on first line - - New Commands: - * 'sort' command sorting windows by title - * 'bumpleft', 'bumpright' - manually move windows on window list - * 'collapse' removing numbering 'gaps' between windows, by renumbering - * 'windows' command now accepts arguments for use with querying + * New Commands: + - 'sort' command sorting windows by title + - 'bumpleft', 'bumpright' - manually move windows on window list + - 'collapse' removing numbering 'gaps' between windows, by renumbering + - 'windows' command now accepts arguments for use with querying Version 4.2.1 (28/04/2014): * allow for terminal with long $TERM (up to 32 characters) @@ -79,8 +88,7 @@ New Commands: * 'unbindall' to unbind all commands * 'up', 'down', 'left', 'right' sub-commands for 'focus' - * 'rendition' to specify rendition to use in caption/hardstatus for - window-names that have bell/monitor/silence/so turned on. + * 'rendition' to specify rendition to use in caption/hardstatus for window-names that have bell/monitor/silence/so turned on. * 'layout', with the following sub-commands - 'title' - 'number' @@ -372,8 +380,8 @@ ======================= .screenrc: - screen now only opens the windows you explicitly ask for. if you - specify none, you still get one window, of course. + screen now only opens the windows you explicitly ask for. + If you specify none, you still get one window, of course. screen 3.0. Patchlevel 5 ======================== @@ -391,7 +399,7 @@ by a colon. Oldchar and newchar are either single ascii characters, or the two character sequence ^x, where x is an ascii character, or a 3 digit octal value prepended with '\'. the string "\040=.:^M=q" - rebinds '.' to set marks, and the return rey will abort copy mode. + rebinds '.' to set marks, and the return key will abort copy mode. set scrollback 100 resizes the scrollback history buffer to 100 lines. a default of 50 @@ -426,7 +434,7 @@ ^A : set vbell_msg "Wuff Wuff" -Thousand enhancements: help resizible, copy'n'paste in main +Thousand enhancements: help resizable, copy'n'paste in main socket loop, and no more '\0' hackin'. :WS=\E8;%d;%dt: screen can now resize windows under sunview. @@ -454,12 +462,12 @@ bind 'O' set login off is valid in your .screenrc as well as typed at the ':' prompt. a bonus is ":set all" which is synonym to ":help". - At the Colon prompt also KeyNames can be entered, alothough that makes + At the Colon prompt also KeyNames can be entered, although that makes not always sense. ^A x uses a builtin lockprg, if a) we don't find our lockprg, or - b) user supplies us with the environmet variable LOCKPRG set to "builtin" + b) user supplies us with the environment variable LOCKPRG set to "builtin" the builtin locks until your login password is typed. on systems using "shadow password files" you are prompted for a password. @@ -480,7 +488,7 @@ rare markroutine bug fixed. -we dont open every file the attacher tells us. +we don't open every file the attacher tells us. we have now our wonderful "Wuff, Wuff" visual_bell diff -ur screen.orig/configure.ac screen/configure.ac --- screen.orig/configure.ac 2023-06-01 14:58:17.232665011 +0300 +++ screen/configure.ac 2022-01-28 17:06:02.670611602 +0300 @@ -172,6 +172,40 @@ #include #include ], [int x = SIGCHLD | FNDELAY;], , AC_DEFINE(SYSV)) +AC_CHECKING(for sequent/ptx) +AC_EGREP_CPP(YES_IS_DEFINED, +[#ifdef _SEQUENT_ + YES_IS_DEFINED; +#endif +], LIBS="$LIBS -lsocket -linet";seqptx=1) + +AC_CHECKING(SVR4) +AC_EGREP_CPP(yes, +[main () { +#if defined(SVR4) || defined(__SVR4) + yes; +#endif +], AC_NOTE(- you have a SVR4 system) AC_DEFINE(SVR4) svr4=1) +if test -n "$svr4" ; then +oldlibs="$LIBS" +LIBS="$LIBS -lelf" +AC_CHECKING(SVR4) +AC_TRY_LINK([#include +],, +[AC_CHECK_HEADER(dwarf.h, AC_DEFINE(BUGGYGETLOGIN), +[AC_CHECK_HEADER(elf.h, AC_DEFINE(BUGGYGETLOGIN))])] +,LIBS="$oldlibs") +fi + +AC_CHECK_HEADERS([stropts.h string.h strings.h]) + +AC_CHECKING(for Solaris 2.x) +AC_EGREP_CPP(YES_IS_DEFINED, +[#if defined(SVR4) && defined(sun) + YES_IS_DEFINED; +#endif +], LIBS="$LIBS -lsocket -lnsl -lkstat") + dnl dnl **** typedefs **** dnl @@ -280,7 +314,7 @@ #define S_IFIFO 0010000 #endif -char *fin = "conftest$$"; +char *fin = "/tmp/conftest$$"; main() { @@ -328,7 +362,7 @@ ], AC_NOTE(- your fifos are usable) fifo=1, AC_NOTE(- your fifos are not usable), AC_NOTE(- skipping check because we are cross compiling; assuming fifos are usable) fifo=1) -rm -f conftest* +rm -f /tmp/conftest* if test -n "$fifo"; then AC_CHECKING(for broken fifo implementation) @@ -351,7 +385,7 @@ #define S_IFIFO 0010000 #endif -char *fin = "conftest$$"; +char *fin = "/tmp/conftest$$"; main() { @@ -377,7 +411,7 @@ ], AC_NOTE(- your implementation is ok), AC_NOTE(- you have a broken implementation) AC_DEFINE(BROKEN_PIPE) fifobr=1, AC_NOTE(- skipping check because we are cross compiling; assuming fifo implementation is ok)) -rm -f conftest* +rm -f /tmp/conftest* fi dnl @@ -401,7 +435,7 @@ #include #include -char *son = "conftest$$"; +char *son = "/tmp/conftest$$"; main() { @@ -440,7 +474,7 @@ ], AC_NOTE(- your sockets are usable) sock=1, AC_NOTE(- your sockets are not usable), AC_NOTE(- skipping check because we are cross compiling; assuming sockets are usable) sock=1) -rm -f conftest* +rm -f /tmp/conftest* if test -n "$sock"; then AC_CHECKING(socket implementation) @@ -457,7 +491,7 @@ #include #include -char *son = "conftest$$"; +char *son = "/tmp/conftest$$"; main() { @@ -480,7 +514,7 @@ AC_NOTE(- unix domain sockets are not kept in the filesystem) AC_DEFINE(SOCK_NOT_IN_FS) socknofs=1, AC_NOTE(- skipping check because we are cross compiling; assuming sockets are normal)) -rm -f conftest* +rm -f /tmp/conftest* fi @@ -502,7 +536,7 @@ #include #include -char *nam = "conftest$$"; +char *nam = "/tmp/conftest$$"; #ifdef NAMEDPIPE @@ -601,7 +635,7 @@ tgetent((char *)0, (char *)0); #endif ],, -LIBS="-ltinfo $olibs" +LIBS="-ltermcap $olibs" AC_CHECKING(libtermcap) AC_TRY_LINK(,tgetent((char *)0, (char *)0);,, LIBS="-ltermlib $olibs" @@ -622,9 +656,6 @@ AC_MSG_ERROR(!!! no tgetent - no screen))))))))) AC_TRY_RUN([ - -extern char *tgoto(char *,int,int); - main() { exit(strcmp(tgoto("%p1%d", 0, 1), "1") ? 0 : 1); @@ -638,11 +669,20 @@ dnl **** PTY specific things **** dnl if test "$cross_compiling" = no ; then +AC_CHECKING(for /dev/ptc) +if test -r /dev/ptc; then +AC_DEFINE(HAVE_DEV_PTC) +fi +fi + +if test "$cross_compiling" = no ; then AC_CHECKING(for SVR4 ptys) sysvr4ptys= +if test -c /dev/ptmx ; then AC_TRY_LINK([],[ptsname(0);grantpt(0);unlockpt(0);],[AC_DEFINE(HAVE_SVR4_PTYS) sysvr4ptys=1]) fi +fi AC_CHECK_FUNCS(getpt) @@ -824,6 +864,11 @@ dnl dnl **** loadav **** dnl +if test "$cross_compiling" = no ; then +AC_CHECKING(for libutil(s)) +test -f /usr/lib/libutils.a && LIBS="$LIBS -lutils" +test -f /usr/lib/libutil.a && LIBS="$LIBS -lutil" +fi AC_CHECKING(getloadavg) AC_TRY_LINK(,[getloadavg((double *)0, 0);], @@ -1053,6 +1098,11 @@ LIBS="$LIBS -lcrypt" AC_CHECKING(crypt) AC_TRY_LINK(,,,LIBS="$oldlibs") +if test "$cross_compiling" = no ; then +test -f /lib/libsec.a || test -f /usr/lib/libsec.a && LIBS="$LIBS -lsec" +test -f /lib/libshadow.a || test -f /usr/lib/libshadow.a && LIBS="$LIBS -lshadow" +fi + oldlibs="$LIBS" LIBS="$LIBS -lsun" AC_CHECKING(IRIX sun library) @@ -1194,26 +1244,17 @@ AC_CHECK_FUNCS(rename fchmod fchown strerror lstat _exit utimes vsnprintf getcwd setlocale strftime) -AC_CHECK_LIB(dl, dlopen) - AC_ARG_ENABLE(pam, [ --enable-pam enable PAM support]) if test "$enable_pam" = "yes"; then AC_MSG_CHECKING(for PAM support) oldlibs="$LIBS" - cf_result=no - - AC_CHECK_LIB(pam, pam_start, LIBS="$LIBS -lpam";cf_result=yes, cf_result=no) - - if test "$cf_result" = yes; then - AC_CHECK_LIB(pam_userpass, pam_userpass_conv, LIBS="$LIBS -lpam_userpass";cf_result=yes, cf_result=no) - fi - - if test "$cf_result" = yes; then - AC_DEFINE(USE_PAM) - else - LIBS="$oldlibs" - fi - AC_MSG_RESULT($cf_result); + LIBS="$LIBS -lpam" + AC_TRY_LINK([#include ], [ + pam_start(0, 0, 0, 0); + pam_authenticate(0, 0); + pam_end(0,0); + ], AC_MSG_RESULT(yes);AC_DEFINE(USE_PAM), + AC_MSG_RESULT(no);LIBS="$oldlibs") fi AC_ARG_ENABLE(use-locale, diff -ur screen.orig/display.c screen/display.c --- screen.orig/display.c 2023-06-01 14:58:17.233665014 +0300 +++ screen/display.c 2022-01-28 17:06:02.674611701 +0300 @@ -28,7 +28,6 @@ #include #include -#include #include #ifndef sun # include @@ -327,17 +326,6 @@ return display; } -static sigjmp_buf alarm_jump; - -static sigret_t -FlushSigAlarm SIGDEFARG -{ -#ifdef DEBUG - debug("FlushSigAlarm\n"); -#endif - siglongjmp (alarm_jump, 1); -} - void FreeDisplay() @@ -358,12 +346,7 @@ Flush(3); if (!display) return; - if (sigsetjmp(alarm_jump,1)==0) { - signal(SIGALRM, FlushSigAlarm); - alarm(10); - SetTTY(D_userfd, &D_OldMode); - alarm(0); - } + SetTTY(D_userfd, &D_OldMode); fcntl(D_userfd, F_SETFL, 0); } freetty(); @@ -2332,7 +2315,7 @@ { char *buf; #ifdef UTF8 - int extrabytes = strlen(hstatusstring) - strlen_onscreen(hstatusstring, NULL); + int extrabytes = strlen(hstatusstring) - strlen_onscreen((unsigned char *)hstatusstring, NULL); #else int extrabytes = 0; #endif @@ -2435,7 +2418,7 @@ if (y == cv->c_ye + 1 && from >= cv->c_xs && from <= cv->c_xe) { #ifdef UTF8 - int extrabytes = strlen(captionstring) - strlen_onscreen(captionstring, NULL); + int extrabytes = strlen(captionstring) - strlen_onscreen((unsigned char *)captionstring, NULL); #else int extrabytes = 0; #endif @@ -3040,7 +3023,6 @@ AddChar(' '); } - void Flush(progress) int progress; @@ -3092,15 +3074,7 @@ break; } } - if (sigsetjmp (alarm_jump,1) == 0) { - signal(SIGALRM, FlushSigAlarm); - alarm(10); - wr = write(D_userfd, p, l); - alarm(0); - } else { - debug1("Warning: We spent too long in flush: %d\n", errno); - return; - } + wr = write(D_userfd, p, l); if (wr <= 0) { if (errno == EINTR) @@ -3208,8 +3182,7 @@ { debug("display activity stopped sleep\n"); if (eat) - if (read(D_userfd, &buf, 1) < 1) - ; + read(D_userfd, &buf, 1); } debug2("DisplaySleep(%d) ending, eat was %d\n", n, eat); } @@ -3432,7 +3405,7 @@ */ int size; char bufspace[MAX_MOUSE_SEQUENCE + IOSIZE]; - unsigned char *buf = bufspace + MAX_MOUSE_SEQUENCE; + unsigned char *buf = (unsigned char*)bufspace + MAX_MOUSE_SEQUENCE; struct canvas *cv; @@ -3507,7 +3480,7 @@ if (p->w_zdisplay == display) { flayer = &p->w_layer; - bufp = buf; + bufp = (char *)buf; while (size > 0) LayProcess(&bufp, &size); return; @@ -3790,7 +3763,7 @@ return; } #endif - (*D_processinput)(buf, size); + (*D_processinput)((char *)buf, size); } static void @@ -4015,7 +3988,6 @@ } } #endif - fflush(NULL); switch (pid = (int)fork()) { case -1: @@ -4063,19 +4035,13 @@ } debug1("=== RunBlanker: pid %d\n", (int)getpid()); #endif - { - int fd = open(m, O_RDWR); - if (fd < 0) - Panic(errno, "Cannot open %s", m); - if (dup2(fd, 0) < 0) - Panic(errno, "Cannot redirect %s to %s", "stdin", m); - if (dup2(fd, 1) < 0) - Panic(errno, "Cannot redirect %s to %s", "stdout", m); - if (dup2(fd, 2) < 0) - Panic(errno, "Cannot redirect %s to %s", "stderr", m); - if (fd > 2) - close(fd); - } + close(0); + close(1); + close(2); + if (open(m, O_RDWR)) + Panic(errno, "Cannot open %s", m); + dup(0); + dup(0); close(D_blankerev.fd); if (slave != -1) close(slave); diff -ur screen.orig/display.h screen/display.h --- screen.orig/display.h 2023-06-01 14:58:17.233665014 +0300 +++ screen/display.h 2022-01-28 17:06:02.674611701 +0300 @@ -61,7 +61,7 @@ struct mouse_parse { char sgrmode; /* non-zero if parsing an SGR sequence */ - char state; /* current state of parsing */ + int state; /* current state of parsing */ int params[3]; /* parsed params: button, x, y */ }; @@ -112,7 +112,7 @@ int d_mousetrack; /* set when user wants to use mouse even when the window does not */ #ifdef RXVT_OSC - int d_xtermosc[4]; /* osc used */ + int d_xtermosc[5]; /* osc used */ #endif struct mchar d_lpchar; /* missing char */ struct timeval d_status_time; /* time of status display */ diff -ur screen.orig/doc/FAQ screen/doc/FAQ --- screen.orig/doc/FAQ 2023-06-01 14:58:17.233665014 +0300 +++ screen/doc/FAQ 2022-01-28 17:06:02.674611701 +0300 @@ -191,7 +191,7 @@ Q: The "talk" command does not work when Screen is active. A: Talk and several other programs rely on entries in the Utmp- - Database (/var/run/utmp). On some systems this Database is world + Database (/etc/utmp). On some systems this Database is world writable, on others it is not. If it is not, screen must be installed with the appropriate permissions (user or group s-bit) just like any program that uses PTYs (rlogin, xterm, ...). When diff -ur screen.orig/doc/screen.1 screen/doc/screen.1 --- screen.orig/doc/screen.1 2023-06-01 14:58:17.236665021 +0300 +++ screen/doc/screen.1 2022-01-28 17:06:02.678611800 +0300 @@ -1,10 +1,7 @@ .\" vi:set wm=5 -.TH SCREEN 1 "Feb 2020" -.if n .ds Q \&" -.if n .ds U \&" -.if t .ds Q `` -.if t .ds U '' -.UC 4 +.TH SCREEN 1 "2022 Jan 30" "GNU Screen 4.9.0" +. +. .SH NAME screen \- screen manager with VT100/ANSI terminal emulation @@ -80,14 +77,14 @@ .I Screen will also print out control characters in caret notation. .PP -The standard way to create a new window is to type \*QC-a c\*U. +The standard way to create a new window is to type \fBC-a c\fP. This creates a new window running a shell and switches to that window immediately, regardless of the state of the process running in the current window. Similarly, you can create a new window with a custom command in it by first binding the command to a keystroke (in your .screenrc file or at the -\*QC-a :\*U command line) and -then using it just like the \*QC-a c\*U command. +\fBC-a :\fP command line) and +then using it just like the \fBC-a c\fP command. In addition, new windows can be created by running a command like: .IP screen emacs prog.c @@ -103,7 +100,7 @@ the invoking shell to the application (emacs in this case), because it is forked from the parent screen process, not from the invoking shell. .PP -If \*Q/var/run/utmp\*U is writable by +If \*Q/etc/utmp\*U is writable by .IR screen , an appropriate record will be written to this file for each window, and removed when the window is terminated. @@ -121,11 +118,11 @@ you'll need to make sure you have correctly selected your terminal type, just as you would for any other termcap/terminfo program. (You can do this by using -.IR tset +.IR test for example.) .PP If you're impatient and want to get started without doing a lot more reading, -you should remember this one command: \*QC-a ?\*U. +you should remember this one command: \fBC-a ?\fP. Typing these two characters will display a list of the available .I screen commands and their bindings. Each keystroke is discussed in @@ -232,7 +229,7 @@ The use of this option is discouraged. .TP 5 .BR \-l " and " \-ln -turns login mode on or off (for /var/run/utmp updating). +turns login mode on or off (for /etc/utmp updating). This can also be defined through the \*Qdeflogin\*U .screenrc command. .TP 5 .BR \-ls " [" \fImatch ] @@ -257,12 +254,6 @@ Sessions marked as `dead' should be thoroughly checked and removed. Ask your system administrator if you are not sure. Remove sessions with the \fB-wipe\fP option. -.IP "" 5 -Note: - If sockets are missing (and because of this, your sessions are not -listed), you may send a SIGCHLD to its `SCREEN' -process and the process will re-establish the socket (think of -someone cleaning /tmp thoroughly). .TP 5 .B \-L tells @@ -378,7 +369,8 @@ When creating a new session, this option can be used to specify a meaningful name for the session. This name identifies the session for \*Qscreen \-list\*U and \*Qscreen \-r\*U actions. It substitutes the -default [\fItty.host\fP] suffix. +default [\fItty.host\fP] suffix. This name should not be longer +then 80 symbols. .TP 5 .BI "\-t " name sets the title (a.\|k.\|a.) for the default shell or specified program. @@ -788,7 +780,7 @@ When .I screen is invoked, it executes initialization commands from the files -\*Q/etc/screenrc\*U and +\*Q/usr/local/etc/screenrc\*U and \*Q.screenrc\*U in the user's home directory. These are the \*Qprogrammer's defaults\*U that can be overridden in the following ways: for the global screenrc file @@ -930,14 +922,16 @@ and each occurrence of `^G' is replaced by the definition for bell in your termcap (usually an audible bell). The default message is -.sp +.PP +.nf 'Activity in window %n' -.sp +.fi +.PP Note that monitoring is off for all windows by default, but can be altered by use of the \*Qmonitor\*U command (C-a M). .RE .TP -.BR "allpartial on" | off +.BR "allpartial [ on | off ]" .RS 0 .PP If set to on, only the current cursor line is refreshed on window change. @@ -948,7 +942,7 @@ default redraw behavior of newly created windows. .RE .TP -.BR "altscreen on" | off +.BR "altscreen [ on | off ]" .RS 0 .PP If set to on, "alternate screen" support is enabled in virtual terminals, @@ -1021,7 +1015,7 @@ Make bright colored text also bold. .RE .TP -.BR "autodetach on" | off +.BR "autodetach [ on | off ]" .RS 0 .PP Sets whether @@ -1035,7 +1029,7 @@ and all the processes it contains. Autodetach is on by default. .RE .TP -.BR "autonuke on" | off +.BR "autonuke [ on | off ]" .RS 0 .PP Sets whether a clear screen sequence should nuke all the output @@ -1069,7 +1063,7 @@ with the numerical id \fIid\fP. .RE .TP -.BR "bce " [ on | off ] +.BR "bce [ on | off ]" .RS 0 .PP Change background-color-erase setting. If \*Qbce\*U is set to on, all @@ -1090,11 +1084,11 @@ and each occurrence of `^G' is replaced by the definition for bell in your termcap (usually an audible bell). The default message is -.sp -.RS +.PP +.nf 'Bell in window %n' -.RE -.sp +.fi +.PP An empty message can be supplied to the \*Qbell_msg\*U command to suppress output of a message line (bell_msg ""). Without parameter, the current message is shown. @@ -1248,7 +1242,7 @@ escape (besides ^A). .RE .TP -.BR break [ \fIduration\fR ] +.BR "break " [ \fIduration\fR ] .RS 0 .PP Send a break signal for \fIduration\fP*0.25 seconds to this window. @@ -1318,10 +1312,10 @@ Swaps window with next one on window list. .RE .TP -.BR "c1 " [ on | off ] +.BR "c1 [ on | off ]" .RS 0 .PP -Change c1 code processing. \*QC1 on\*U tells screen to treat +Change c1 code processing. \fBC1 on\fP tells screen to treat the input characters between 128 and 159 as control functions. Such an 8-bit code is normally the same as ESC followed by the corresponding 7-bit code. The default setting is to process c1 @@ -1426,7 +1420,7 @@ you may regard \*QC-a esc\*U (copy mode) as its `Vi command mode'. .RE .TP -.BR "command " [ \-c " \fIclass\fP" ] +.BR "command [ \-c " \fIclass\fP" ]" .RS 0 .PP This command has the same effect as typing the screen escape @@ -1435,14 +1429,14 @@ class. See also \*Qbind\*U and \*Qbindkey\*U. .RE .TP -.BR "compacthist " [ on | off ] +.BR "compacthist [ on | off ]" .RS 0 .PP This tells screen whether to suppress trailing blank lines when scrolling up text into the history buffer. .RE .TP -.BR "console " [ on | off ] +.BR "console [ on | off ]" .RS 0 .PP Grabs or un-grabs the machines console output to a window. @@ -1517,7 +1511,7 @@ \fBB\fP, \fBE\fP@move the cursor WORD by WORD (as in vi). _ \fBf/F\fP, \fBt/T\fP@T{ -move the cursor forward/backward to the next occurence of the +move the cursor forward/backward to the next occurrence of the target. (eg, '3fy' will move the cursor to the 3rd 'y' to the right.) T} _ @@ -1539,7 +1533,7 @@ _ .TE .\"\fBf\fP,\fBt\fP, \fBF\fP, \fBT\fP@T{ -.\"move the cursor forward/backward to the next occurence of the target. +.\"move the cursor forward/backward to the next occurrence of the target. .\"T} .PP @@ -1571,7 +1565,7 @@ Example: \*QC-a C-[ H 10 j 5 Y\*U will copy lines 11 to 15 into the paste buffer. .PP -The folllowing search keys are defined: +The following search keys are defined: .IP \fB/\fP \fIVi\fP-like search forward. .IP @@ -1652,7 +1646,7 @@ No longer exists, use \*Qreadreg\*U instead. .RE .TP -.BR "crlf " [ on | off ] +.BR "crlf [ on | off ]" .RS 0 .PP This affects the copying of text regions with the `C-a [' command. If it is set @@ -1661,7 +1655,7 @@ When no parameter is given, the state is toggled. .RE .TP -.BR "debug on" | off +.BR "debug [ on | off ]" .RS 0 .PP Turns runtime debugging on or off. If @@ -1672,14 +1666,14 @@ be turned off once and forever. .RE .TP -.BR "defc1 on" | off +.BR "defc1 [ on | off ]" .RS 0 .PP Same as the \fBc1\fP command except that the default setting for new windows is changed. Initial setting is `on'. .RE .TP -.BR "defautonuke on" | off +.BR "defautonuke [ on | off ]" .RS 0 .PP Same as the \fBautonuke\fP command except that the default setting for new displays is changed. Initial setting is `off'. @@ -1687,7 +1681,7 @@ want to have a dependency on the terminal type. .RE .TP -.BR "defbce on" | off +.BR "defbce [ on | off ]" .RS 0 .PP Same as the \fBbce\fP command except that the default setting for new @@ -1721,7 +1715,7 @@ argument. .RE .TP -.BR "defdynamictitle on" | off +.BR "defdynamictitle [ on | off ]" .RS 0 .PP Set default behaviour for new windows regarding if screen should change window @@ -1739,18 +1733,18 @@ characters for users that will be added later. .RE .TP -.BR "defflow " on | off | "auto " [ interrupt ] +.BR "defflow [ on | off | auto [ interrupt ]] .RS 0 .PP Same as the \fBflow\fP command except that the default setting for new windows is changed. Initial setting is `auto'. -Specifying \*Qdefflow auto interrupt\*U is the same as the command-line options +Specifying \fBdefflow auto interrupt\fP is the same as the command-line options .B \-fa and .BR \-i . .RE .TP -.BR "defgr on" | off +.BR "defgr [ on | off ]" .RS 0 .PP Same as the \fBgr\fP command except that the default setting for new @@ -1783,14 +1777,14 @@ terminal. .RE .TP -.BR "deflog on" | off +.BR "deflog [ on | off ]" .RS 0 .PP Same as the \fBlog\fP command except that the default setting for new windows is changed. Initial setting is `off'. .RE .TP -.BR "deflogin on" | off +.BR "deflogin [ on | off ]" .RS 0 .PP Same as the \fBlogin\fP command except that the default setting for new windows @@ -1805,21 +1799,21 @@ When no \*Qdefmode\*U command is given, mode 0622 is used. .RE .TP -.BR "defmonitor on" | off +.BR "defmonitor [ on | off]" .RS 0 .PP Same as the \fBmonitor\fP command except that the default setting for new windows is changed. Initial setting is `off'. .RE .TP -.BR "defmousetrack on" | off +.BR "defmousetrack [ on | off ]" .RS 0 .PP Same as the \fBmousetrack\fP command except that the default setting for new windows is changed. Initial setting is `off'. .RE .TP -.BR "defnonblock on" | off | \fInumsecs\fP +.BR "defnonblock [ on | off | \fInumsecs\fP] .RS 0 .PP Same as the \fBnonblock\fP command except that the default setting for @@ -1847,7 +1841,7 @@ Synonym to the \fBshell\fP .screenrc command. See there. .RE .TP -.BR "defsilence on" | off +.BR "defsilence [ on | off ]" .RS 0 .PP Same as the \fBsilence\fP command except that the default setting for new @@ -1861,7 +1855,7 @@ windows is changed. Initial setting is 0 milliseconds, meaning `off'. .RE .TP -.BR "defutf8 on" | off +.BR "defutf8 [ on | off ]" .RS 0 .PP Same as the \fButf8\fP command except that the default setting for new @@ -1869,7 +1863,7 @@ \*Q\-U\*U, otherwise `off'. .RE .TP -.BR "defwrap on" | off +.BR "defwrap [ on | off ]" .RS 0 .PP Same as the \fBwrap\fP command except that the default setting for new @@ -1877,7 +1871,7 @@ \*Qwrap\*U command (\*QC-a r\*U) or by means of "C-a : wrap on|off". .RE .TP -.BR "defwritelock on" | off | auto +.BR "defwritelock [ on | off | auto ]" .RS 0 .PP Same as the \fBwritelock\fP command except that the default setting for new @@ -2043,7 +2037,7 @@ .IR tic . .RE .TP -.BR "dynamictitle on" | off +.BR "dynamictitle [ on | off ]" .RS 0 .PP Change behaviour for windows regarding if screen should change window title @@ -2056,7 +2050,7 @@ The echo command may be used to annoy .I screen users with a 'message of the -day'. Typically installed in a global /etc/screenrc. +day'. Typically installed in a global /local/etc/screenrc. The option \*Q\-n\*U may be used to suppress the line feed. See also \*Qsleep\*U. Echo is also useful for online checking of environment variables. @@ -2201,8 +2195,7 @@ automatically if the window is displayed more than once. .RE .TP -.B flow -.RB [ on | off | "auto\fR]\fP" +.BR "flow [ on | off | auto]" .RS 0 .PP Sets the flow-control mode for this window. @@ -2213,7 +2206,7 @@ Default is set by `defflow'. .RE .TP -.BR "focus " [ next|prev|up|down|left|right|top|bottom ] +.BR "focus [ next | prev | up | down | left | right | top | bottom ]" .RS 0 .PP Move the input focus to the next region. This is done in a cyclic @@ -2264,7 +2257,7 @@ This forces any currently selected region to be automatically resized at least a certain \fIwidth\fP and \fIheight\fP. All other surrounding regions will be resized in order to accommodate. -This constraint follows everytime the \*Qfocus\*U command is +This constraint follows every time the \*Qfocus\*U command is used. The \*Qresize\*U command can be used to increase either dimension of a region, but never below what is set with \*Qfocusminsize\*U. The underscore `_' is a synonym for @@ -2273,7 +2266,7 @@ Without any parameters, the minimum width and height is shown. .RE .TP -.BR "gr " [ on | off ] +.BR "gr [ on | off ]" .RS 0 .PP Turn GR charset switching on/off. Whenever screen sees an input @@ -2303,7 +2296,7 @@ scrollback buffer. .RE .TP -.BR "hardcopy_append on" | off +.BR "hardcopy_append [ on | off ]" .RS 0 .PP If set to "on", @@ -2322,11 +2315,11 @@ current working directory. .RE .TP -.BR "hardstatus " [ on | off ] +.BR "hardstatus [ on | off ]" .TP -.BR "hardstatus \fR[\fBalways\fR]\fBfirstline" | lastline | message | ignore [ \fIstring\fR ] +.BR "hardstatus [ always ] firstline | lastline | message | ignore [ string ]" .TP -.BR "hardstatus string" [ \fIstring\fR ] +.BR "hardstatus string [ string ]" .RS 0 .PP This command configures the use and emulation of the terminal's @@ -2386,8 +2379,7 @@ .BR help [ \fIclass\fP ] .RS 0 .PP -Not really a online help, but -displays a help +Not really a online help, but displays a help .I screen showing you all the key bindings. The first pages list all the internal commands followed by their current @@ -2432,7 +2424,7 @@ If no arguments are given, the current settings are displayed. .RE .TP -.BR "ignorecase " [ on | off ] +.BR "ignorecase [ on | off ]" .RS 0 .PP Tell screen to ignore the case of characters in searches. Default is @@ -2492,8 +2484,7 @@ (shell) running in the window receives a HANGUP condition, the window structure is removed and .I screen -(your display) switches to another -window. When the last window is destroyed, +(your display) switches to another window. When the last window is destroyed, .I screen exits. After a kill @@ -2613,7 +2604,7 @@ \fBlayout autosave\fP command. .RE .TP -.BR "layout autosave " [\fBon|off\fP] +.BR "layout autosave [ on | off]" .RS 0 .PP Change or display the status of automatcally saving layouts. The @@ -2652,7 +2643,7 @@ Display the disclaimer page. This is done whenever .I screen is started without options, which should be often enough. See also -the \*Qstartup_message\*U command. +the \fBstartup_message\fP command. .RE .TP .B lockscreen @@ -2674,7 +2665,7 @@ shell. This feature should rather be called `lockterminal'. .RE .TP -.BR "log " [ on | off ] +.BR "log [ on | off ]" .RS 0 .PP Start/stop writing output of the current window to a file @@ -2699,7 +2690,7 @@ default value is 10 seconds. .RE .TP -.BR "login " [ on | off ] +.BR "login [ on | off ]" .RS 0 .PP Adds or removes the entry in the utmp database file for the current window. @@ -2798,7 +2789,7 @@ Insert the command character (C-a) in the current window's input stream. .RE .TP -.BR "monitor " [ on | off ] +.BR "monitor [ on | off ]" .RS 0 .PP Toggles activity monitoring of windows. @@ -2809,7 +2800,7 @@ Monitoring is initially off for all windows. .RE .TP -.BR "mousetrack " [ on | off ] +.BR "mousetrack [ on | off ]" .RS 0 .PP This command determines whether @@ -2819,7 +2810,7 @@ been split in various ways can be selected by pointing to them with a mouse and left-clicking them. Without specifying \fBon\fP or \fBoff\fP, the current state is displayed. The default state -is determined by the \*Qdefmousetrack\*U command. +is determined by the \fBdefmousetrack\fP command. .RE .TP .BI "msgminwait " sec @@ -2839,7 +2830,7 @@ is not disturbed by other activity. The default is 5 seconds. .RE .TP -.BR "multiuser on" | off +.BR "multiuser [ on | off ]" .RS 0 .PP Switch between singleuser and multiuser mode. Standard @@ -2851,7 +2842,7 @@ session. .RE .TP -.BR "nethack on" | off +.BR "nethack [ on | off ]" .RS 0 .PP Changes the kind of error messages used by @@ -2861,8 +2852,7 @@ much funnier to read. Anyway, standard messages often tend to be unclear as well. .br -This option is only -available if +This option is only available if .I screen was compiled with the NETHACK flag defined. The default setting is then determined by the presence of the environment @@ -2877,8 +2867,7 @@ This command can be used repeatedly to cycle through the list of windows. .RE .PP -.B nonblock -.RB [ on | off | \fInumsecs ] +.BR "nonblock [ on | off | numsecs ]" .RS 0 .PP Tell screen how to deal with user interfaces (displays) that cease to @@ -2925,7 +2914,7 @@ \fIother\fP has the same effect as \fInext\fP. .RE .TP -.BR "partial on" | off +.BR "partial [ on | off ]" .RS 0 .PP Defines whether the display should be refreshed (as with \fIredisplay\fP) after @@ -2940,9 +2929,8 @@ .PP Present a crypted password in your \*Q.screenrc\*U file and .I screen -will ask -for it, whenever someone attempts to resume a detached. This is useful -if you have privileged programs running under +will ask for it, whenever someone attempts to resume a detached. +This is useful if you have privileged programs running under .I screen and you want to protect your session from reattach attempts by another user masquerading as your uid (i.e. any superuser.) @@ -2960,22 +2948,22 @@ of the current window. The register '.' is treated as the paste buffer. If no parameter is given the user is prompted for a single register to paste. -The paste buffer can be filled with the \fIcopy\fP, \fIhistory\fP and -\fIreadbuf\fP commands. -Other registers can be filled with the \fIregister\fP, \fIreadreg\fP and -\fIpaste\fP commands. -If \fIpaste\fP is called with a second argument, the contents of the specified -registers is pasted into the named destination register rather than +The paste buffer can be filled with the \fBcopy\fP, \fBhistory\fP and +\fBreadbuf\fP commands. +Other registers can be filled with the \fBregister\fP, \fBreadreg\fP and +\fBpaste\fP commands. +If \fBpaste\fP is called with a second argument, the contents of the specified +registers is pasted into the named destination register rather than the window. If '.' is used as the second argument, the displays paste buffer is the destination. -Note, that \*Qpaste\*U uses a wide variety of resources: Whenever a second +Note, that \fBpaste\fP uses a wide variety of resources: Whenever a second argument is specified no current window is needed. When the source specification -only contains registers (not the paste buffer) then there need not be a current -display (terminal attached), as the registers are a global resource. The +only contains registers (not the paste buffer) then there need not be a current +display (terminal attached), as the registers are a global resource. The paste buffer exists once for every user. .RE .TP -.BR "pastefont " [ on | off ] +.BR "pastefont [ on | off ]" .RS 0 .PP Tell @@ -3070,7 +3058,7 @@ Reads the contents of the specified file into the paste buffer. You can tell screen the encoding of the file via the \fB\-e\fP option. If no file is specified, the screen-exchange filename is used. -See also \*Qbufferfile\*U command. +See also \fBbufferfile\fP command. .RE .TP .IR "\fBreadreg\fP " [ encoding "] [" register " [" filename ]] @@ -3117,17 +3105,21 @@ .B "removebuf" .RS 0 .PP -Unlinks the screen-exchange file used by the commands \*Qwritebuf\*U and -\*Qreadbuf\*U. +Unlinks the screen-exchange file used by the commands +\fBwritebuf\fP and \fBreadbuf\fP. .RE .TP -.B "rendition bell" | monitor | silence | so " \fIattr\fR " \fR[\fP \fIcolor\fP \fR]\fP +.B "rendition [ bell | monitor | silence | so ] attr [ color ]" .RS 0 .PP Change the way .I screen -renders the titles of windows that have monitor or bell flags set in caption or hardstatus or windowlist. See the \*QSTRING ESCAPES\*U chapter for the syntax of the modifiers. -The default for monitor is currently \*Q=b \*U (bold, active colors), for bell \*Q=ub \*U (underline, bold and active colors), and \*Q=u \*U for silence. +renders the titles of windows that have monitor or bell flags set in +caption or hardstatus or windowlist. See the \*QSTRING ESCAPES\*U +chapter for the syntax of the modifiers. +The default for monitor is currently \*Q=b \*U (bold, active colors), +for bell \*Q=ub \*U (underline, bold and active colors), and \*Q=u \*U +for silence. .RE .TP .B "reset" @@ -3197,7 +3189,7 @@ .I screen will prompt for how you would like to resize the current region. -See \*Qfocusminsize\*U if you want to restrict the minimun size a region +See \*Qfocusminsize\*U if you want to restrict the minimum size a region can have. .RE .RE @@ -3294,7 +3286,7 @@ and value. The environment is inherited by all subsequently forked shells. .RE .TP -.BR "setsid " [ on | off ] +.BR "setsid [ on | off ]" .RS 0 .PP Normally screen uses different sessions and process groups for @@ -3326,7 +3318,7 @@ entitled \*QTITLES (naming windows)\*U. .RE .TP -.BR "silence " [ on | off "|\fIsec\fP]" +.BR "silence [ on | off | sec ]" .RS 0 .PP Toggles silence monitoring of windows. @@ -3414,18 +3406,17 @@ With this current implementation of screen, scrolling data will appear much slower in a vertically split region than one that is not. This should be taken into consideration if you need -to use system commands such as \*Qcat\*U or \*Qtail -f\*U. +to use system commands such as \fBcat\fP or \fBtail -f\fP. .RE .TP -.B "startup_message on\fP|\fBoff" +.B "startup_message [ on | off ]" .RS 0 .PP Select whether you want to see the copyright notice during startup. Default is `on', as you probably noticed. .RE .PP -.BR "status " [ top | up | down | bottom ] -.RB [ left | right ] +.BR "status [ top | up | down | bottom ] [ left | right ]" .RS 0 .PP The status window by default is in bottom-left corner. This command can move @@ -3630,7 +3621,7 @@ Unset an environment variable. .RE .TP -.BR "utf8 " [ on | off [ on | off ]] +.BR "utf8 [ on | off [ on | off ]]" .RS 0 .PP Change the encoding used in the current window. If utf8 is enabled, the @@ -3642,7 +3633,7 @@ window. .RE .TP -.BR "vbell " [ on | off ] +.BR "vbell [ on | off ]" .RS 0 .PP Sets the visual bell setting for this window. Omitting the parameter @@ -3674,7 +3665,7 @@ visual bell message. The default is 1 second. .RE .TP -.BR "verbose " [ on | off ] +.BR "verbose [ on | off ]" .RS 0 .PP If verbose is switched on, the command name is echoed, whenever a window @@ -3711,7 +3702,7 @@ vice versa. .RE .TP -.BR "windowlist " [ \-b "] [" \-m "] [" \-g ] +.BR "windowlist [ \-b ] [ \-m ] [ \-g ]" .TP .IR "\fBwindowlist string\fR " [ string ] .TP @@ -3819,7 +3810,7 @@ The default command without any parameter is limited to a size of 1024 bytes. .RE .TP -.BR "wrap " [ on | off ] +.BR "wrap [ on | off ]" .RS 0 .PP Sets the line-wrap setting for the current window. @@ -3842,7 +3833,7 @@ command and defaults to \*Q/tmp/screen\-exchange\*U. .RE .TP -.BR "writelock " [ on | "off\fR|\fBauto\fR]" +.BR "writelock [ on | off | auto]" .RS 0 .PP In addition to access control lists, not all users may be able to write to @@ -3864,7 +3855,7 @@ current window. .RE .TP -.BR "zmodem " [ off\fR|\fPauto\fR|\fPcatch\fR|\fPpass ] +.BR "zmodem [ off | auto | catch | pass ]" .TP .IR "\fBzmodem sendcmd\fR " [ string ] .TP @@ -4068,6 +4059,8 @@ the escape character itself .IP E sets %? to true if the escape character has been pressed. +.IP e +encoding .IP f flags of the window, see \*Qwindows\*U for meanings of the various flags .IP F @@ -4163,7 +4156,7 @@ .IP r reverse .IP s -standout +/standout .IP B blinking .PD @@ -4347,9 +4340,11 @@ history recall commands. .PP Here's some .screenrc examples: -.IP -screen \-t top 2 nice top -.PP +.sp +.nf + screen \-t top 2 nice top +.fi +.sp Adding this line to your .screenrc would start a nice-d version of the \*Qtop\*U command in window 2 named \*Qtop\*U rather than \*Qnice\*U. .sp @@ -4361,15 +4356,19 @@ These commands would start a shell with the given shelltitle. The title specified is an auto-title that would expect the prompt and the typed command to look something like the following: -.IP -/usr/joe/src/dir> trn -.PP +.sp +.nf + /usr/joe/src/dir> trn +.fi +.sp (it looks after the '> ' for the command name). The window status would show the name \*Qtrn\*U while the command was running, and revert to \*Qcsh\*U upon completion. -.IP -bind R screen \-t '% |root:' su -.PP +.sp +.nf + bind R screen \-t '% |root:' su +.fi +.sp Having this command in your .screenrc would bind the key sequence \*QC-a R\*U to the \*Qsu\*U command and give it an auto-title name of \*Qroot:\*U. @@ -4404,17 +4403,21 @@ If these invisible characters aren't a multiple of 8 then backspacing over a tab will result in an incorrect display. One way to get around this is to use a prompt like this: -.IP -set prompt='^[[0000m^[k^[\e% ' -.PP +.sp +.nf + set prompt='^[[0000m^[k^[\e% ' +.fi +.sp The escape-sequence \*Q[0000m\*U not only normalizes the character attributes, but all the zeros round the length of the invisible characters up to 8. Bash users will probably want to echo the escape sequence in the PROMPT_COMMAND: -.IP -PROMPT_COMMAND='printf "\e033k\e033\e134"' -.PP +.sp +.nf + PROMPT_COMMAND='printf "\e033k\e033\e134"' +.fi +.sp (I used \*Q\e134\*U to output a `\e' because of a bug in bash v1.04). @@ -5202,12 +5205,12 @@ .I screen distribution package for private and global initialization files. .IP $SYSSCREENRC -.IP /etc/screenrc +.IP /usr/local/etc/screenrc .I screen initialization commands .IP $SCREENRC .IP $HOME/.screenrc -Read in after /etc/screenrc +Read in after /usr/local/etc/screenrc .IP $SCREENDIR/S\- .IP /local/screens/S\- Socket directories (default) @@ -5228,16 +5231,11 @@ or .IP /etc/termcap Terminal capability databases -.IP /var/run/utmp +.IP /etc/utmp Login records .IP $LOCKPRG Program that locks a terminal. - -.SH "SEE ALSO" -termcap(5), utmp(5), vi(1), captoinfo(1), tic(1) - - .SH AUTHORS Originally created by Oliver Laumann. For a long time maintained and developed by Juergen Weigert, Michael Schroeder, Micah Cowan @@ -5247,7 +5245,7 @@ .SH COPYLEFT .nf -Copyright (c) 2018-2020 +Copyright (c) 2018-2022 Alexander Naumov Amadeusz Slawinski Copyright (c) 2015-2017 @@ -5267,6 +5265,7 @@ Michael Schroeder Copyright (C) 1987 Oliver Laumann .fi + .PP 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 @@ -5324,10 +5323,12 @@ .I screen available via anonymous ftp from ftp.gnu.org/gnu/screen/ or any other .I GNU -distribution site. The home site of +distribution site. The home page of .I screen -is savannah.gnu.org/projects/screen/. If you want to help, send a note to -screen-devel@gnu.org. +is https://savannah.gnu.org/projects/screen/ and the git repo +is https://git.savannah.gnu.org/cgit/screen.git. +If you want to help, send a note to +.BR screen-devel@gnu.org. .SH BUGS .PD @@ -5355,9 +5356,9 @@ must be installed as set-uid with owner root on most systems in order to be able to correctly change the owner of the tty device file for each window. -Special permission may also be required to write the file \*Q/var/run/utmp\*U. +Special permission may also be required to write the file \*Q/etc/utmp\*U. .IP \(bu -Entries in \*Q/var/run/utmp\*U are not removed when +Entries in \*Q/etc/utmp\*U are not removed when .I screen is killed with SIGKILL. This will cause some programs (like "w" or "rwho") @@ -5387,7 +5388,15 @@ file from which the session is booted, or have to be changed manually. .IP \(bu A weird imagination is most useful to gain full advantage of all the features. -.IP \(bu +.PP Send bug-reports, fixes, enhancements, t-shirts, money, beer & pizza to .BR screen-devel@gnu.org . +.SH "SEE ALSO" +.BR termcap(5), +.BR utmp(5), +.BR vi(1), +.BR captoinfo(1), +.BR tic(1), +.BR tty(4), +.BR pty(7) diff -ur screen.orig/doc/screen.texinfo screen/doc/screen.texinfo --- screen.orig/doc/screen.texinfo 2023-06-01 14:58:17.238665025 +0300 +++ screen/doc/screen.texinfo 2022-01-28 17:06:02.682611899 +0300 @@ -4,14 +4,14 @@ @documentencoding ISO-8859-15 @setfilename screen.info @settitle Screen User's Manual -@dircategory Terminals +@dircategory General Commands @finalout @setchapternewpage odd @c %**end of header -@set version 4.8.0 +@set version 4.9.0 @direntry -* Screen: (screen). The virtual terminal manager. +* Screen: (screen). Full-screen window manager. @end direntry @c For examples, use a literal escape in info. @@ -25,7 +25,7 @@ @ifinfo This file documents the @code{Screen} virtual terminal manager. -Copyright (c) 1993-2018 Free Software Foundation, Inc. +Copyright (c) 1993-2022 Free Software Foundation, Inc. Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice @@ -53,11 +53,11 @@ @title Screen @subtitle The virtual terminal manager @subtitle for Version @value{version} -@subtitle Feb 2020 +@subtitle Jan 2022 @page @vskip 0pt plus 1filll -Copyright @copyright{} 1993-2018 Free Software Foundation, Inc. +Copyright @copyright{} 1993-2022 Free Software Foundation, Inc. Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice @@ -185,7 +185,7 @@ the invoking shell to the application (emacs in this case), because it is forked from the parent screen process, not from the invoking shell. -If @file{/var/run/utmp} is writable by @code{screen}, an appropriate record +If @file{/etc/utmp} is writable by @code{screen}, an appropriate record will be written to this file for each window, and removed when the window is closed. This is useful for working with @code{talk}, @code{script}, @code{shutdown}, @code{rsend}, @code{sccs} and other @@ -314,7 +314,7 @@ @item -l @itemx -ln -Turn login mode on or off (for @file{/var/run/utmp} updating). This option +Turn login mode on or off (for @file{/etc/utmp} updating). This option is equivalent to the @code{deflogin} command (@pxref{Login}). @item -ls [@var{match}] @@ -333,13 +333,6 @@ Ask your system administrator if you are not sure. Remove sessions with the @samp{-wipe} option. -@emph{Note}: - If sockets are missing (and because of this, your sessions are not - listed), you may send a @code{SIGCHLD} to its `SCREEN' - process and the process will re-establish the socket (think of - someone cleaning @file{/tmp} thoroughly). - - @item -L Tell @code{screen} to turn on automatic output logging for the windows. @@ -504,14 +497,14 @@ @cindex screenrc When @code{screen} is invoked, it executes initialization commands from the files @file{.screenrc} in the user's home directory and -@file{/etc/screenrc}. These defaults can be overridden in the +@file{/usr/local/etc/screenrc}. These defaults can be overridden in the following ways: For the global screenrc file @code{screen} searches for the environment variable @code{$SYSSCREENRC} (this override feature may be disabled at compile-time). The user specific screenrc file is searched for in @code{$SCREENRC}, then @file{@code{$HOME}/.screenrc}. The command line option @samp{-c} -specifies which file to use (@pxref{Invoking Screen}. Commands in these +specifies which file to use (@pxref{Invoking Screen}). Commands in these files are used to set options, bind commands to keys, and to automatically establish one or more windows at the beginning of your @code{screen} session. Commands are listed one per line, with @@ -1096,7 +1089,7 @@ @item logfile @var{filename} Place where to collect logfiles. @xref{Log}. @item login [@var{state}] -Log the window in @file{/var/run/utmp}. @xref{Login}. +Log the window in @file{/etc/utmp}. @xref{Login}. @item logtstamp [@var{state}] Configure logfile time-stamps. @xref{Log}. @item mapdefault @@ -2219,7 +2212,7 @@ Without any arguments, @code{screen} will prompt for how you would like to resize the current region. -See @code{focusminsize} if you want to restrict the minimun size a region can have. +See @code{focusminsize} if you want to restrict the minimum size a region can have. @end deffn @@ -2412,7 +2405,7 @@ * Naming Windows:: Control the name of the window * Console:: See the host's console messages * Kill:: Destroy an unwanted window -* Login:: Control @file{/var/run/utmp} logging +* Login:: Control @file{/etc/utmp} logging * Mode:: Control the file mode of the pty * Monitor:: Watch for activity or inactivity in a window * Windows:: List the active windows @@ -2621,7 +2614,7 @@ @kindex L @deffn Command login [state] (@kbd{C-a L})@* -Adds or removes the entry in @file{/var/run/utmp} for the current window. +Adds or removes the entry in @file{/etc/utmp} for the current window. This controls whether or not the window is @dfn{logged in}. In addition to this toggle, it is convenient to have ``log in'' and ``log out'' keys. For instance, @code{bind I login on} and @code{bind O @@ -3696,7 +3689,7 @@ @noindent @kbd{f}/@kbd{F}, @kbd{t}/@kbd{T} move the cursor forward/backward to the -next occurence of the target. (eg, '3fy' will move the cursor to the 3rd +next occurrence of the target. (eg, '3fy' will move the cursor to the 3rd 'y' to the right.) @noindent @@ -3877,7 +3870,7 @@ (none)@* Stuff the string @var{string} in the input buffer of the current window. This is like the @code{paste} command, but with much less overhead. -Without a paramter, @code{screen} will prompt for a string to stuff. +Without a parameter, @code{screen} will prompt for a string to stuff. You cannot paste large buffers with the @code{stuff} command. It is most useful for key bindings. @xref{Bindkey}. @end deffn @@ -5328,7 +5321,8 @@ load averages over 1, 5, and 15 minutes (if this is available on your system). For window-specific information use @code{info} (@pxref{Info}). If a @var{string} is specified, it changes the format of the time report -like it is described in the string escapes chapter (@pxref{String Escapes}). Screen uses a default of @samp{%c:%s %M %d %H%? %l%?}. +like it is described in the string escapes chapter (@pxref{String Escapes}). +Screen uses a default of @samp{%c:%s %M %d %H%? %l%?}. @end deffn @node Verbose, Version, Time, Miscellaneous @@ -5578,6 +5572,8 @@ weekday name @item E sets %? to true if the escape character has been pressed. +@item e +encoding @item f flags of the window. @xref{Windows}, for meanings of the various flags. @item F @@ -5809,13 +5805,13 @@ global initialization files. @item @code{$SYSSCREENRC} -@itemx /etc/screenrc +@itemx /local/etc/screenrc @code{screen} initialization commands @item @code{$SCREENRC} @itemx @code{$HOME}/.iscreenrc @itemx @code{$HOME}/.screenrc -Read in after /etc/screenrc +Read in after /local/etc/screenrc @item @code{$SCREENDIR}/S-@var{login} @@ -5842,7 +5838,7 @@ @itemx /etc/termcap Terminal capability databases -@item /var/run/utmp +@item /etc/utmp Login records @item @code{$LOCKPRG} @@ -5954,10 +5950,10 @@ in order to be able to correctly change the owner of the tty device file for each window. Special permission may also be required to write the file -@file{/var/run/utmp}. +@file{/etc/utmp}. @item -Entries in @file{/var/run/utmp} are not removed when @code{screen} is killed +Entries in @file{/etc/utmp} are not removed when @code{screen} is killed with SIGKILL. This will cause some programs (like "w" or "rwho") to advertise that a user is logged on who really isn't. @@ -5995,7 +5991,7 @@ @section Reporting Bugs @cindex bug report -If you find a bug in @code{Screen}, please send electronic mail to +If you find a bug in @code{Screen}, please send mail to @w{@samp{screen-devel@@gnu.org}}. Include the version number of @code{Screen} which you are using. Also include in your message the hardware and operating system, the compiler used to compile, a diff -ur screen.orig/encoding.c screen/encoding.c --- screen.orig/encoding.c 2023-06-01 14:58:17.239665027 +0300 +++ screen/encoding.c 2022-01-28 17:06:02.682611899 +0300 @@ -1264,7 +1264,7 @@ }; if (c >= 0xdf00 && c <= 0xdfff) - return 1; /* dw combining sequence */ + return 1; /* dw combining sequence */ return ((bisearch(c, wide, sizeof(wide) / sizeof(struct interval) - 1)) || (cjkwidth && bisearch(c, ambiguous, diff -ur screen.orig/etc/etcscreenrc screen/etc/etcscreenrc --- screen.orig/etc/etcscreenrc 2023-06-01 14:58:17.239665027 +0300 +++ screen/etc/etcscreenrc 2022-01-28 17:05:57.346479760 +0300 @@ -1,6 +1,6 @@ # # This is an example for the global screenrc file. -# You may want to install this file as /etc/screenrc. +# You may want to install this file as /usr/local/etc/screenrc. # Check config.h for the exact location. # # Flaws of termcap and standard settings are done here. @@ -92,10 +92,3 @@ bind O login off bind } history -# Red Hat Hack^H^H^H^HPatch -# This makes screen treat backspaces '^?' as -# deletes. There should be a fix in the code -# for the way termcap inheritance works, -# but I dont know where to put it, and this works. -bindkey -d -k kb stuff \010 -# /Red Hat Patch diff -ur screen.orig/etc/screenrc screen/etc/screenrc --- screen.orig/etc/screenrc 2023-06-01 14:58:17.239665027 +0300 +++ screen/etc/screenrc 2022-01-28 17:06:02.682611899 +0300 @@ -130,15 +130,6 @@ register ] "\033:se ai\015a" bind ^] paste [.] -# Red Hat Hack^H^H^H^HPatch -# This makes screen treat backspaces '^?' as -# deletes. There should be a fix in the code -# for the way termcap inheritance works, -# but I dont know where to put it, and this works. -bindkey -d -k kb stuff \010 -# /Red Hat Patch - - ################ # # default windows diff -ur screen.orig/extern.h screen/extern.h --- screen.orig/extern.h 2023-06-01 14:58:17.240665030 +0300 +++ screen/extern.h 2022-01-28 17:06:02.682611899 +0300 @@ -75,7 +75,7 @@ extern int GetAnsiStatus __P((struct win *, char *)); extern void WNewAutoFlow __P((struct win *, int)); extern void WBell __P((struct win *, int)); -extern void WMsg __P((struct win *, int, const char *)); +extern void WMsg __P((struct win *, int, char *)); extern void WChangeSize __P((struct win *, int, int)); extern void WindowChanged __P((struct win *, int)); extern int MFindUsedLine __P((struct win *, int, int)); diff -ur screen.orig/FAQ screen/FAQ --- screen.orig/FAQ 2023-06-01 14:58:17.233665014 +0300 +++ screen/FAQ 2022-01-28 17:06:02.674611701 +0300 @@ -191,7 +191,7 @@ Q: The "talk" command does not work when Screen is active. A: Talk and several other programs rely on entries in the Utmp- - Database (/var/run/utmp). On some systems this Database is world + Database (/etc/utmp). On some systems this Database is world writable, on others it is not. If it is not, screen must be installed with the appropriate permissions (user or group s-bit) just like any program that uses PTYs (rlogin, xterm, ...). When diff -ur screen.orig/fileio.c screen/fileio.c --- screen.orig/fileio.c 2023-06-01 14:58:17.240665030 +0300 +++ screen/fileio.c 2022-01-28 17:06:02.682611899 +0300 @@ -42,109 +42,108 @@ extern struct display *display, *displays; extern struct win *fore; extern struct layer *flayer; -extern int ServerSocket; -extern int real_uid, eff_uid; -extern int real_gid, eff_gid; -extern char *extra_incap, *extra_outcap; -extern char *home, *RcFileName; -extern char SockPath[], *SockName; +extern int ServerSocket; +extern int real_uid, eff_uid; +extern int real_gid, eff_gid; +extern char *extra_incap, *extra_outcap; +extern char *home, *RcFileName; +extern char SockPath[], *SockName; #ifdef COPY_PASTE -extern char *BufferFile; +extern char *BufferFile; #endif -extern int hardcopy_append; -extern char *hardcopydir; - -static char *CatExtra __P((char *, char *)); -static char *findrcfile __P((char *)); +extern int hardcopy_append; +extern char *hardcopydir; +static char *CatExtra __P((char *, char *)); +static char *findrcfile __P((char *)); char *rc_name = ""; int rc_recursion = 0; -static char * CatExtra(register char *str1, register char *str2) { - register char *cp; - register int len1, len2, add_colon; - - len1 = strlen(str1); - if (len1 == 0) - return str2; - add_colon = (str1[len1 - 1] != ':'); - if (str2) { - len2 = strlen(str2); - if ((cp = realloc(str2, (unsigned) len1 + len2 + add_colon + 1)) == NULL) - Panic(0, "%s", strnomem); - bcopy(cp, cp + len1 + add_colon, len2 + 1); - } - else { - if ((cp = malloc((unsigned) len1 + add_colon + 1)) == NULL) - Panic(0, "%s", strnomem); - cp[len1 + add_colon] = '\0'; - } - bcopy(str1, cp, len1); - if (add_colon) - cp[len1] = ':'; - return cp; -} - -static char *findrcfile(char *rcfile) { - char buf[256]; - char *p; - - /* Tilde prefix support courtesy , - * taken from a Debian patch. */ - if (rcfile && *rcfile == '~') { - static char rcfilename_tilde_exp[MAXPATHLEN+1]; - char *slash_position = strchr(rcfile, '/'); - - if (slash_position == rcfile+1) { - char *home = getenv("HOME"); - if (!home) { - Msg(0, "%s: source: tilde expansion failed", rc_name); - return NULL; - } - snprintf(rcfilename_tilde_exp, MAXPATHLEN, "%s/%s", home, rcfile+2); - } - else if (slash_position) { - struct passwd *p; - *slash_position = 0; - p = getpwnam(rcfile+1); - if (!p){ - Msg(0, "%s: source: tilde expansion failed for user %s", rc_name, rcfile+1); - return NULL; - } - snprintf(rcfilename_tilde_exp, MAXPATHLEN, "%s/%s", p->pw_dir, slash_position+1); - } - else { - Msg(0, "%s: source: illegal tilde expression.", rc_name); - return NULL; - } - rcfile = rcfilename_tilde_exp; - } - - if (rcfile) { - char *rcend = rindex(rc_name, '/'); - if (*rcfile != '/' && rcend && (rcend - rc_name) + strlen(rcfile) + 2 < sizeof(buf)) { - strncpy(buf, rc_name, rcend - rc_name + 1); - strcpy(buf + (rcend - rc_name) + 1, rcfile); - if (access(buf, R_OK) == 0) - return SaveStr(buf); - } - debug1("findrcfile: you specified '%s'\n", rcfile); - return SaveStr(rcfile); - } - - debug("findrcfile: you specified nothing...\n"); - if ((p = getenv("SCREENRC")) != NULL && *p != '\0') { - debug1(" $SCREENRC has: '%s'\n", p); - return SaveStr(p); - } - else { - debug(" ...nothing in $SCREENRC, defaulting $HOME/.screenrc\n"); - if (strlen(home) > sizeof(buf) - 12) - Panic(0, "Rc: home too large"); - sprintf(buf, "%s/.screenrc", home); - return SaveStr(buf); - } +static char * +CatExtra(register char *str1, register char *str2) +{ + register char *cp; + register int len1, len2, add_colon; + + len1 = strlen(str1); + if (len1 == 0) + return str2; + add_colon = (str1[len1 - 1] != ':'); + if (str2) { + len2 = strlen(str2); + if ((cp = realloc(str2, (unsigned)len1 + len2 + add_colon + 1)) == NULL) + Panic(0, "%s", strnomem); + bcopy(cp, cp + len1 + add_colon, len2 + 1); + } else { + if ((cp = malloc((unsigned)len1 + add_colon + 1)) == NULL) + Panic(0, "%s", strnomem); + cp[len1 + add_colon] = '\0'; + } + bcopy(str1, cp, len1); + if (add_colon) + cp[len1] = ':'; + return cp; +} + +static char * +findrcfile(char *rcfile) +{ + char buf[256]; + char *p; + + /* Tilde prefix support courtesy , + * taken from a Debian patch. */ + if (rcfile && *rcfile == '~') { + static char rcfilename_tilde_exp[MAXPATHLEN + 1]; + char *slash_position = strchr(rcfile, '/'); + + if (slash_position == rcfile + 1) { + char *home = getenv("HOME"); + if (!home) { + Msg(0, "%s: source: tilde expansion failed", rc_name); + return NULL; + } + snprintf(rcfilename_tilde_exp, MAXPATHLEN, "%s/%s", home, rcfile + 2); + } else if (slash_position) { + struct passwd *p; + *slash_position = 0; + p = getpwnam(rcfile + 1); + if (!p) { + Msg(0, "%s: source: tilde expansion failed for user %s", rc_name, rcfile + 1); + return NULL; + } + snprintf(rcfilename_tilde_exp, MAXPATHLEN, "%s/%s", p->pw_dir, slash_position + 1); + } else { + Msg(0, "%s: source: illegal tilde expression.", rc_name); + return NULL; + } + rcfile = rcfilename_tilde_exp; + } + + if (rcfile) { + char *rcend = rindex(rc_name, '/'); + if (*rcfile != '/' && rcend && (rcend - rc_name) + strlen(rcfile) + 2 < sizeof(buf)) { + strncpy(buf, rc_name, rcend - rc_name + 1); + strcpy(buf + (rcend - rc_name) + 1, rcfile); + if (access(buf, R_OK) == 0) + return SaveStr(buf); + } + debug1("findrcfile: you specified '%s'\n", rcfile); + return SaveStr(rcfile); + } + + debug("findrcfile: you specified nothing...\n"); + if ((p = getenv("SCREENRC")) != NULL && *p != '\0') { + debug1(" $SCREENRC has: '%s'\n", p); + return SaveStr(p); + } else { + debug(" ...nothing in $SCREENRC, defaulting $HOME/.screenrc\n"); + if (strlen(home) > sizeof(buf) - 12) + Panic(0, "Rc: home too large"); + sprintf(buf, "%s/.screenrc", home); + return SaveStr(buf); + } } /* @@ -152,630 +151,638 @@ * 1) rcfilename = "/etc/screenrc" * 2) rcfilename = RcFileName */ -int StartRc(char *rcfilename, int nopanic) { - register int argc, len; - register char *p, *cp; - char buf[2048]; - char *args[MAXARGS]; - int argl[MAXARGS]; - FILE *fp; - char *oldrc_name = rc_name; - - /* always fix termcap/info capabilities */ - extra_incap = CatExtra("TF", extra_incap); - - /* Special settings for vt100 and others */ - if (display && (!strncmp(D_termname, "vt", 2) || !strncmp(D_termname, "xterm", 5))) - extra_incap = CatExtra("xn:f0=\033Op:f1=\033Oq:f2=\033Or:f3=\033Os:f4=\033Ot:f5=\033Ou:f6=\033Ov:f7=\033Ow:f8=\033Ox:f9=\033Oy:f.=\033On:f,=\033Ol:fe=\033OM:f+=\033Ok:f-=\033Om:f*=\033Oj:f/=\033Oo:fq=\033OX", extra_incap); - - rc_name = findrcfile(rcfilename); - if (rc_name == NULL || (fp = secfopen(rc_name, "r")) == NULL) { - const char *rc_nonnull = rc_name ? rc_name : rcfilename; - if (!rc_recursion && RcFileName && !strcmp(RcFileName, rc_nonnull)) { - /* - * User explicitly gave us that name, - * this is the only case, where we get angry, if we can't read - * the file. - */ - debug3("StartRc: '%s','%s', '%s'\n", RcFileName, rc_name ? rc_name : "(null)", rcfilename); - if (!nopanic) Panic(0, "Unable to open \"%s\".", rc_nonnull); - /* possibly NOTREACHED */ - } - - debug1("StartRc: '%s' no good. ignored\n", rc_nonnull); - if (rc_name) - Free(rc_name); - rc_name = oldrc_name; - return 1; - } - while (fgets(buf, sizeof buf, fp) != NULL) { - if ((p = rindex(buf, '\n')) != NULL) - *p = '\0'; - - if ((argc = Parse(buf, sizeof buf, args, argl)) == 0) - continue; - - if (strcmp(args[0], "echo") == 0) { - if (!display) - continue; - if (argc < 2 || (argc == 3 && strcmp(args[1], "-n")) || argc > 3) { - Msg(0, "%s: 'echo [-n] \"string\"' expected.", rc_name); - continue; - } - AddStr(args[argc - 1]); - if (argc != 3) { - AddStr("\r\n"); - Flush(0); - } - } - - else if (strcmp(args[0], "sleep") == 0) { - if (!display) - continue; - debug("sleeeeeeep\n"); - if (argc != 2) { - Msg(0, "%s: sleep: one numeric argument expected.", rc_name); - continue; - } - DisplaySleep1000(1000 * atoi(args[1]), 1); - } +int +StartRc(char *rcfilename, int nopanic) +{ + register int argc, len; + register char *p, *cp; + char buf[2048]; + char *args[MAXARGS]; + int argl[MAXARGS]; + FILE *fp; + char *oldrc_name = rc_name; + + /* always fix termcap/info capabilities */ + extra_incap = CatExtra("TF", extra_incap); + + /* Special settings for vt100 and others */ + if (display && (!strncmp(D_termname, "vt", 2) || !strncmp(D_termname, "xterm", 5))) + extra_incap = CatExtra("xn:f0=\033Op:f1=\033Oq:f2=\033Or:f3=\033Os:f4=\033Ot:f5=\033Ou:f6=\033Ov:f7=\033Ow:f8=\033Ox:f9=\033Oy:f.=\033On:f,=\033Ol:fe=\033OM:f+=\033Ok:f-=\033Om:f*=\033Oj:f/=\033Oo:fq=\033OX", extra_incap); + + rc_name = findrcfile(rcfilename); + if (rc_name == NULL || (fp = secfopen(rc_name, "r")) == NULL) { + const char *rc_nonnull = rc_name ? rc_name : rcfilename; + if (!rc_recursion && RcFileName && !strcmp(RcFileName, rc_nonnull)) { + /* + * User explicitly gave us that name, + * this is the only case, where we get angry, if we can't read + * the file. + */ + debug3("StartRc: '%s','%s', '%s'\n", RcFileName, rc_name ? rc_name : "(null)", rcfilename); + if (!nopanic) + Panic(0, "Unable to open \"%s\".", rc_nonnull); + /* possibly NOTREACHED */ + } + + debug1("StartRc: '%s' no good. ignored\n", rc_nonnull); + if (rc_name) + Free(rc_name); + rc_name = oldrc_name; + return 1; + } + while (fgets(buf, sizeof buf, fp) != NULL) { + if ((p = rindex(buf, '\n')) != NULL) + *p = '\0'; + + if ((argc = Parse(buf, sizeof buf, args, argl)) == 0) + continue; + + if (strcmp(args[0], "echo") == 0) { + if (!display) + continue; + if (argc < 2 || (argc == 3 && strcmp(args[1], "-n")) || argc > 3) { + Msg(0, "%s: 'echo [-n] \"string\"' expected.", rc_name); + continue; + } + AddStr(args[argc - 1]); + if (argc != 3) { + AddStr("\r\n"); + Flush(0); + } + } else if (strcmp(args[0], "sleep") == 0) { + if (!display) + continue; + debug("sleeeeeeep\n"); + if (argc != 2) { + Msg(0, "%s: sleep: one numeric argument expected.", rc_name); + continue; + } + DisplaySleep1000(1000 * atoi(args[1]), 1); + } #ifdef TERMINFO else if (!strcmp(args[0], "termcapinfo") || !strcmp(args[0], "terminfo")) { #else - else if (!strcmp(args[0], "termcapinfo") || !strcmp(args[0], "termcap")) { + else if (!strcmp(args[0], "termcapinfo") || !strcmp(args[0], "termcap")) { #endif - if (!display) - continue; - if (argc < 3 || argc > 4) { - Msg(0, "%s: %s: incorrect number of arguments.", rc_name, args[0]); - continue; - } - - for (p = args[1]; p && *p; p = cp) { - if ((cp = index(p, '|')) != 0) - *cp++ = '\0'; - len = strlen(p); - if (p[len - 1] == '*') { - if (!(len - 1) || !strncmp(p, D_termname, len - 1)) - break; - } - else if (!strcmp(p, D_termname)) - break; - } - if (!(p && *p)) - continue; - extra_incap = CatExtra(args[2], extra_incap); - if (argc == 4) - extra_outcap = CatExtra(args[3], extra_outcap); - } - else if (!strcmp(args[0], "source")) { - if (rc_recursion <= 10) { - rc_recursion++; - (void)StartRc(args[1], 0); - rc_recursion--; - } - } - } - fclose(fp); - Free(rc_name); - rc_name = oldrc_name; - return 0; -} - -void FinishRc(char *rcfilename) { - char buf[2048]; - FILE *fp; - char *oldrc_name = rc_name; - - rc_name = findrcfile(rcfilename); - - if (rc_name == NULL || (fp = secfopen(rc_name, "r")) == NULL) { - const char *rc_nonnull = rc_name ? rc_name : rcfilename; - if (rc_recursion) - Msg(errno, "%s: source %s", oldrc_name, rc_nonnull); - else if (RcFileName && !strcmp(RcFileName, rc_nonnull)) { + if (!display) + continue; + if (argc < 3 || argc > 4) { + Msg(0, "%s: %s: incorrect number of arguments.", rc_name, args[0]); + continue; + } + + for (p = args[1]; p && *p; p = cp) { + if ((cp = index(p, '|')) != 0) + *cp++ = '\0'; + len = strlen(p); + if (p[len - 1] == '*') { + if (!(len - 1) || !strncmp(p, D_termname, len - 1)) + break; + } else if (!strcmp(p, D_termname)) + break; + } + if (!(p && *p)) + continue; + extra_incap = CatExtra(args[2], extra_incap); + if (argc == 4) + extra_outcap = CatExtra(args[3], extra_outcap); + } else if (!strcmp(args[0], "source")) { + if (rc_recursion <= 10) { + rc_recursion++; + (void)StartRc(args[1], 0); + rc_recursion--; + } + } + } + fclose(fp); + Free(rc_name); + rc_name = oldrc_name; + return 0; +} + +void +FinishRc(char *rcfilename) +{ + char buf[2048]; + FILE *fp; + char *oldrc_name = rc_name; + + rc_name = findrcfile(rcfilename); + + if (rc_name == NULL || (fp = secfopen(rc_name, "r")) == NULL) { + const char *rc_nonnull = rc_name ? rc_name : rcfilename; + if (rc_recursion) + Msg(errno, "%s: source %s", oldrc_name, rc_nonnull); + else if (RcFileName && !strcmp(RcFileName, rc_nonnull)) { /* * User explicitly gave us that name, * this is the only case, where we get angry, if we can't read * the file. */ - debug3("FinishRc:'%s','%s','%s'\n", RcFileName, rc_name ? rc_name : "(null)", rcfilename); - Panic(0, "Unable to open \"%s\".", rc_nonnull); - /* NOTREACHED */ - } - debug1("FinishRc: '%s' no good. ignored\n", rc_nonnull); - if (rc_name) - Free(rc_name); - rc_name = oldrc_name; - return; - } - - debug("finishrc is going...\n"); - while (fgets(buf, sizeof buf, fp) != NULL) - RcLine(buf, sizeof buf); - (void) fclose(fp); - Free(rc_name); - rc_name = oldrc_name; -} - -void do_source(char *rcfilename) { - if (rc_recursion > 10) { - Msg(0, "%s: source: recursion limit reached", rc_name); - return; - } - rc_recursion++; - FinishRc(rcfilename); - rc_recursion--; + debug3("FinishRc:'%s','%s','%s'\n", RcFileName, rc_name ? rc_name : "(null)", rcfilename); + Panic(0, "Unable to open \"%s\".", rc_nonnull); + /* NOTREACHED */ + } + debug1("FinishRc: '%s' no good. ignored\n", rc_nonnull); + if (rc_name) + Free(rc_name); + rc_name = oldrc_name; + return; + } + + debug("finishrc is going...\n"); + while (fgets(buf, sizeof buf, fp) != NULL) + RcLine(buf, sizeof buf); + (void)fclose(fp); + Free(rc_name); + rc_name = oldrc_name; +} + +void +do_source(char *rcfilename) +{ + if (rc_recursion > 10) { + Msg(0, "%s: source: recursion limit reached", rc_name); + return; + } + rc_recursion++; + FinishRc(rcfilename); + rc_recursion--; } - /* * Running a Command Line in the environment determined by the display. * The fore window is taken from the display as well as the user. * This is bad when we run detached. */ -void RcLine(char *ubuf, int ubufl) { - char *args[MAXARGS]; - int argl[MAXARGS]; +void +RcLine(char *ubuf, int ubufl) +{ + char *args[MAXARGS]; + int argl[MAXARGS]; #ifdef MULTIUSER - extern struct acluser *EffectiveAclUser; /* acl.c */ - extern struct acluser *users; /* acl.c */ + extern struct acluser *EffectiveAclUser; /* acl.c */ + extern struct acluser *users; /* acl.c */ #endif - if (display) { - fore = D_fore; - flayer = D_forecv->c_layer; - } - else - flayer = fore ? fore->w_savelayer : 0; - if (Parse(ubuf, ubufl, args, argl) <= 0) - return; + if (display) { + fore = D_fore; + flayer = D_forecv->c_layer; + } else + flayer = fore ? fore->w_savelayer : 0; + if (Parse(ubuf, ubufl, args, argl) <= 0) + return; #ifdef MULTIUSER - if (!display) { + if (!display) { /* the session owner does it, when there is no display here */ - EffectiveAclUser = users; - debug("RcLine: WARNING, no display no user! Session owner executes command\n"); - } + EffectiveAclUser = users; + debug("RcLine: WARNING, no display no user! Session owner executes command\n"); + } #endif - DoCommand(args, argl); + DoCommand(args, argl); #ifdef MULTIUSER - EffectiveAclUser = 0; + EffectiveAclUser = 0; #endif } /* needs display for copybuffer access and termcap dumping */ -void WriteFile(struct acluser *user, char *fn, int dump) { +void +WriteFile(struct acluser *user, char *fn, int dump) +{ /* dump==0: create .termcap, * dump==1: hardcopy, * #ifdef COPY_PASTE * dump==2: BUFFERFILE - * #endif COPY_PASTE + * #endif COPY_PASTE * dump==1: scrollback, */ - register int i, j, k; - register char *p; - register FILE *f; - char fnbuf[1024]; - char *mode = "w"; + register int i, j, k; + register char *p; + register FILE *f; + char fnbuf[1024]; + char *mode = "w"; #ifdef COPY_PASTE - int public = 0; + int public = 0; # ifdef HAVE_LSTAT - struct stat stb, stb2; - int fd, exists = 0; + struct stat stb, stb2; + int fd, exists = 0; # endif #endif - switch (dump) { - case DUMP_TERMCAP: - if (fn == 0) { - i = SockName - SockPath; - if (i > (int)sizeof(fnbuf) - 9) - i = 0; - strncpy(fnbuf, SockPath, i); - strcpy(fnbuf + i, ".termcap"); - fn = fnbuf; - } - break; - - case DUMP_HARDCOPY: - case DUMP_SCROLLBACK: - if (fn == 0) { - if (fore == 0) - return; - if (hardcopydir && *hardcopydir && strlen(hardcopydir) < sizeof(fnbuf) - 21) - sprintf(fnbuf, "%s/hardcopy.%d", hardcopydir, fore->w_number); - else - sprintf(fnbuf, "hardcopy.%d", fore->w_number); - fn = fnbuf; - } - if (hardcopy_append && !access(fn, W_OK)) - mode = "a"; - break; + switch (dump) { + case DUMP_TERMCAP: + if (fn == 0) { + i = SockName - SockPath; + if (i > (int)sizeof(fnbuf) - 9) + i = 0; + strncpy(fnbuf, SockPath, i); + strcpy(fnbuf + i, ".termcap"); + fn = fnbuf; + } + break; + + case DUMP_HARDCOPY: + case DUMP_SCROLLBACK: + if (fn == 0) { + if (fore == 0) + return; + if (hardcopydir && *hardcopydir && strlen(hardcopydir) < sizeof(fnbuf) - 21) + sprintf(fnbuf, "%s/hardcopy.%d", hardcopydir, fore->w_number); + else + sprintf(fnbuf, "hardcopy.%d", fore->w_number); + fn = fnbuf; + } + if (hardcopy_append && !access(fn, W_OK)) + mode = "a"; + break; #ifdef COPY_PASTE - case DUMP_EXCHANGE: - if (fn == 0) { - strncpy(fnbuf, BufferFile, sizeof(fnbuf) - 1); - fnbuf[sizeof(fnbuf) - 1] = 0; - fn = fnbuf; - } - public = !strcmp(fn, bufferfile); + case DUMP_EXCHANGE: + if (fn == 0) { + strncpy(fnbuf, BufferFile, sizeof(fnbuf) - 1); + fnbuf[sizeof(fnbuf) - 1] = 0; + fn = fnbuf; + } + public = !strcmp(fn, DEFAULT_BUFFERFILE); # ifdef HAVE_LSTAT - exists = !lstat(fn, &stb); - if (public && exists && (S_ISLNK(stb.st_mode) || stb.st_nlink > 1)) { - Msg(0, "No write to links, please."); - return; - } + exists = !lstat(fn, &stb); + if (public && exists && (S_ISLNK(stb.st_mode) || stb.st_nlink > 1)) { + Msg(0, "No write to links, please."); + return; + } # endif - break; + break; #endif - } + } - debug2("WriteFile(%d) %s\n", dump, fn); - if (UserContext() > 0) { - debug("Writefile: usercontext\n"); + debug2("WriteFile(%d) %s\n", dump, fn); + if (UserContext() > 0) { + debug("Writefile: usercontext\n"); #ifdef COPY_PASTE - if (dump == DUMP_EXCHANGE && public) { + if (dump == DUMP_EXCHANGE && public) { # ifdef HAVE_LSTAT - if (exists) { - if ((fd = open(fn, O_WRONLY, 0666)) >= 0) { - if (fstat(fd, &stb2) == 0 && stb.st_dev == stb2.st_dev && stb.st_ino == stb2.st_ino) - if (ftruncate(fd, 0) < 0) { - close(fd); - fd = -1; - } - else { - close(fd); - fd = -1; - } - } - } - else - fd = open(fn, O_WRONLY|O_CREAT|O_EXCL, 0666); - f = fd >= 0 ? fdopen(fd, mode) : 0; + if (exists) { + if ((fd = open(fn, O_WRONLY, 0666)) >= 0) { + if (fstat(fd, &stb2) == 0 && stb.st_dev == stb2.st_dev && stb.st_ino == stb2.st_ino) + ftruncate(fd, 0); + else { + close(fd); + fd = -1; + } + } + } else + fd = open(fn, O_WRONLY|O_CREAT|O_EXCL, 0666); + f = fd >= 0 ? fdopen(fd, mode) : 0; # else - f = fopen(fn, mode); + f = fopen(fn, mode); # endif - } - else + } else #endif /* COPY_PASTE */ - f = fopen(fn, mode); - if (f == NULL) { - debug2("WriteFile: fopen(%s,\"%s\") failed\n", fn, mode); - UserReturn(0); - } - else { - switch (dump) { - case DUMP_HARDCOPY: - case DUMP_SCROLLBACK: - if (!fore) - break; - if (*mode == 'a') { - putc('>', f); - for (j = fore->w_width - 2; j > 0; j--) - putc('=', f); - fputs("<\n", f); - } - if (dump == DUMP_SCROLLBACK) { + f = fopen(fn, mode); + if (f == NULL) { + debug2("WriteFile: fopen(%s,\"%s\") failed\n", fn, mode); + UserReturn(0); + } else { + switch (dump) { + case DUMP_HARDCOPY: + case DUMP_SCROLLBACK: + if (!fore) + break; + if (*mode == 'a') { + putc('>', f); + for (j = fore->w_width - 2; j > 0; j--) + putc('=', f); + fputs("<\n", f); + } + if (dump == DUMP_SCROLLBACK) { #ifdef COPY_PASTE - for (i = fore->w_histheight - fore->w_scrollback_height; i < fore->w_histheight; i++) { - p = (char *)(WIN(i)->image); - for (k = fore->w_width - 1; k >= 0 && p[k] == ' '; k--) - ; - for (j = 0; j <= k; j++) - putc(p[j], f); - putc('\n', f); - } -#endif - } - for (i = 0; i < fore->w_height; i++) { - p = (char *)fore->w_mlines[i].image; - for (k = fore->w_width - 1; k >= 0 && p[k] == ' '; k--) - ; - for (j = 0; j <= k; j++) - putc(p[j], f); - putc('\n', f); - } - break; - - case DUMP_TERMCAP: - DumpTermcap(fore->w_aflag, f); - break; + for (i = fore->w_histheight - fore->w_scrollback_height; i < fore->w_histheight; i++) { + p = (char *)(WIN(i)->image); + for (k = fore->w_width - 1; + k >= 0 && p[k] == ' '; k--) + ; + for (j = 0; j <= k; j++) + putc(p[j], f); + putc('\n', f); + } +#endif + } + for (i = 0; i < fore->w_height; i++) { + p = (char *)fore->w_mlines[i].image; + for (k = fore->w_width - 1; + k >= 0 && p[k] == ' '; k--) + ; + for (j = 0; j <= k; j++) + putc(p[j], f); + putc('\n', f); + } + break; + + case DUMP_TERMCAP: + DumpTermcap(fore->w_aflag, f); + break; #ifdef COPY_PASTE - case DUMP_EXCHANGE: - p = user->u_plop.buf; - for (i = user->u_plop.len; i-- > 0; p++) - if (*p == '\r' && (i == 0 || p[1] != '\n')) - putc('\n', f); - else - putc(*p, f); - break; -#endif - } - (void) fclose(f); - UserReturn(1); - } - } - if (UserStatus() <= 0) - Msg(0, "Cannot open \"%s\"", fn); - else if (display && !*rc_name) { - switch (dump) { - case DUMP_TERMCAP: - Msg(0, "Termcap entry written to \"%s\".", fn); - break; - case DUMP_HARDCOPY: - case DUMP_SCROLLBACK: - Msg(0, "Screen image %s to \"%s\".", (*mode == 'a') ? "appended" : "written", fn); - break; + case DUMP_EXCHANGE: + p = user->u_plop.buf; + for (i = user->u_plop.len; i-- > 0; p++) + if (*p == '\r' && (i == 0 || p[1] != '\n')) + putc('\n', f); + else + putc(*p, f); + break; +#endif + } + (void)fclose(f); + UserReturn(1); + } + } + if (UserStatus() <= 0) + Msg(0, "Cannot open \"%s\"", fn); + else if (display && !*rc_name) { + switch (dump) { + case DUMP_TERMCAP: + Msg(0, "Termcap entry written to \"%s\".", fn); + break; + case DUMP_HARDCOPY: + case DUMP_SCROLLBACK: + Msg(0, "Screen image %s to \"%s\".", (*mode == 'a') ? "appended" : "written", fn); + break; #ifdef COPY_PASTE - case DUMP_EXCHANGE: - Msg(0, "Copybuffer written to \"%s\".", fn); + case DUMP_EXCHANGE: + Msg(0, "Copybuffer written to \"%s\".", fn); #endif - } - } + } + } } #ifdef COPY_PASTE /* * returns an allocated buffer which holds a copy of the file named fn. - * lenp (if nonzero) points to a location, where the buffer size should be + * lenp (if nonzero) points to a location, where the buffer size should be * stored. */ -char *ReadFile(char *fn, int *lenp) { - int i, l, size; - char c, *bp, *buf; - struct stat stb; - - ASSERT(lenp); - debug1("ReadFile(%s)\n", fn); - - if ((i = secopen(fn, O_RDONLY, 0)) < 0) { - Msg(errno, "no %s -- no slurp", fn); - return NULL; - } - - if (fstat(i, &stb)) { - Msg(errno, "no good %s -- no slurp", fn); - close(i); - return NULL; - } - size = stb.st_size; - - if ((buf = malloc(size)) == NULL) { - close(i); - Msg(0, "%s", strnomem); - return NULL; - } - errno = 0; - - if ((l = read(i, buf, size)) != size) { - if (l < 0) - l = 0; - Msg(errno, "Got only %d bytes from %s", l, fn); - } - else { - if (read(i, &c, 1) > 0) - Msg(0, "Slurped only %d characters (of %d) into buffer - try again", l, size); - else - Msg(0, "Slurped %d characters into buffer", l); - } - close(i); - *lenp = l; - for (bp = buf; l-- > 0; bp++) - if (*bp == '\n' && (bp == buf || bp[-1] != '\r')) - *bp = '\r'; - return buf; -} - -void KillBuffers() { - if (UserContext() > 0) - UserReturn(unlink(BufferFile) ? errno : 0); - errno = UserStatus(); - Msg(errno, "%s %sremoved", BufferFile, errno ? "not " : ""); +char * +ReadFile(char *fn, int *lenp) +{ + int i, l, size; + char c, *bp, *buf; + struct stat stb; + + ASSERT(lenp); + debug1("ReadFile(%s)\n", fn); + + if ((i = secopen(fn, O_RDONLY, 0)) < 0) { + Msg(errno, "no %s -- no slurp", fn); + return NULL; + } + + if (fstat(i, &stb)) { + Msg(errno, "no good %s -- no slurp", fn); + close(i); + return NULL; + } + size = stb.st_size; + + if ((buf = malloc(size)) == NULL) { + close(i); + Msg(0, "%s", strnomem); + return NULL; + } + errno = 0; + + if ((l = read(i, buf, size)) != size) { + if (l < 0) + l = 0; + Msg(errno, "Got only %d bytes from %s", l, fn); + } else { + if (read(i, &c, 1) > 0) + Msg(0, "Slurped only %d characters (of %d) into buffer - try again", l, size); + else + Msg(0, "Slurped %d characters into buffer", l); + } + close(i); + *lenp = l; + for (bp = buf; l-- > 0; bp++) + if (*bp == '\n' && (bp == buf || bp[-1] != '\r')) + *bp = '\r'; + return buf; +} + +void +KillBuffers() +{ + if (UserContext() > 0) + UserReturn(unlink(BufferFile) ? errno : 0); + errno = UserStatus(); + Msg(errno, "%s %sremoved", BufferFile, errno ? "not " : ""); } #endif /* COPY_PASTE */ /* (Almost) secure open and fopen... */ -FILE *secfopen(char *name, char *mode) { - FILE *fi; +FILE * +secfopen(char *name, char *mode) +{ + FILE *fi; #ifndef USE_SETEUID - int flags, fd; + int flags, fd; #endif - debug2("secfopen(%s, %s)\n", name, mode); + debug2("secfopen(%s, %s)\n", name, mode); #ifdef USE_SETEUID - xseteuid(real_uid); - xsetegid(real_gid); - fi = fopen(name, mode); - xseteuid(eff_uid); - xsetegid(eff_gid); - return fi; - + xseteuid(real_uid); + xsetegid(real_gid); + fi = fopen(name, mode); + xseteuid(eff_uid); + xsetegid(eff_gid); + return fi; #else - if (eff_uid == real_uid) - return fopen(name, mode); - if (mode[0] && mode[1] == '+') - flags = O_RDWR; - else - flags = (mode[0] == 'r') ? O_RDONLY : O_WRONLY; - if (mode[0] == 'w') - flags |= O_CREAT | O_TRUNC; - else if (mode[0] == 'a') - flags |= O_CREAT | O_APPEND; - else if (mode[0] != 'r') { - errno = EINVAL; - return 0; - } - if ((fd = secopen(name, flags, 0666)) < 0) - return 0; - if ((fi = fdopen(fd, mode)) == 0) { - close(fd); - return 0; - } - return fi; + if (eff_uid == real_uid) + return fopen(name, mode); + if (mode[0] && mode[1] == '+') + flags = O_RDWR; + else + flags = (mode[0] == 'r') ? O_RDONLY : O_WRONLY; + if (mode[0] == 'w') + flags |= O_CREAT | O_TRUNC; + else if (mode[0] == 'a') + flags |= O_CREAT | O_APPEND; + else if (mode[0] != 'r') { + errno = EINVAL; + return 0; + } + if ((fd = secopen(name, flags, 0666)) < 0) + return 0; + if ((fi = fdopen(fd, mode)) == 0) { + close(fd); + return 0; + } + return fi; #endif } - -int secopen(char *name, int flags, int mode) { - int fd; +int +secopen(char *name, int flags, int mode) +{ + int fd; #ifndef USE_SETEUID - int q; - struct stat stb; + int q; + struct stat stb; #endif - debug3("secopen(%s, 0x%x, 0%03o)\n", name, flags, mode); + debug3("secopen(%s, 0x%x, 0%03o)\n", name, flags, mode); #ifdef USE_SETEUID - xseteuid(real_uid); - xsetegid(real_gid); - fd = open(name, flags, mode); - xseteuid(eff_uid); - xsetegid(eff_gid); - return fd; + xseteuid(real_uid); + xsetegid(real_gid); + fd = open(name, flags, mode); + xseteuid(eff_uid); + xsetegid(eff_gid); + return fd; #else - if (eff_uid == real_uid) - return open(name, flags, mode); - /* Truncation/creation is done in UserContext */ - if ((flags & O_TRUNC) || ((flags & O_CREAT) && access(name, F_OK))) { - if (UserContext() > 0) { - if ((fd = open(name, flags, mode)) >= 0) { - close(fd); - UserReturn(0); - } - if (errno == 0) - errno = EACCES; - UserReturn(errno); - } - if ((q = UserStatus())) { - if (q > 0) - errno = q; - return -1; - } - } - if (access(name, F_OK)) - return -1; - if ((fd = open(name, flags & ~(O_TRUNC | O_CREAT), 0)) < 0) - return -1; - debug("open successful\n"); - if (fstat(fd, &stb)) { - close(fd); - return -1; - } - debug("fstat successful\n"); - if (stb.st_uid != real_uid) { - switch (flags & (O_RDONLY | O_WRONLY | O_RDWR)) { - case O_RDONLY: - q = 0004; - break; - case O_WRONLY: - q = 0002; - break; - default: - q = 0006; - break; - } - if ((stb.st_mode & q) != q) { - debug1("secopen: permission denied (%03o)\n", stb.st_mode & 07777); - close(fd); - errno = EACCES; - return -1; - } - } - debug1("secopen ok - returning %d\n", fd); - return fd; -#endif -} - - -int printpipe(struct win *p, char *cmd) { - int pi[2]; - if (pipe(pi)) { - WMsg(p, errno, "printing pipe"); - return -1; - } - fflush(NULL); - switch (fork()) { - case -1: - WMsg(p, errno, "printing fork"); - return -1; - case 0: - display = p->w_pdisplay; - displays = 0; - ServerSocket = -1; + if (eff_uid == real_uid) + return open(name, flags, mode); + + /* Truncation/creation is done in UserContext */ + if ((flags & O_TRUNC) || ((flags & O_CREAT) && access(name, F_OK))) { + if (UserContext() > 0) { + if ((fd = open(name, flags, mode)) >= 0) { + close(fd); + UserReturn(0); + } + if (errno == 0) + errno = EACCES; + UserReturn(errno); + } + if ((q = UserStatus())) { + if (q > 0) + errno = q; + return -1; + } + } + if (access(name, F_OK)) + return -1; + if ((fd = open(name, flags & ~(O_TRUNC | O_CREAT), 0)) < 0) + return -1; + debug("open successful\n"); + if (fstat(fd, &stb)) { + close(fd); + return -1; + } + debug("fstat successful\n"); + if (stb.st_uid != real_uid) { + switch (flags & (O_RDONLY | O_WRONLY | O_RDWR)) { + case O_RDONLY: + q = 0004; + break; + case O_WRONLY: + q = 0002; + break; + default: + q = 0006; + break; + } + if ((stb.st_mode & q) != q) { + debug1("secopen: permission denied (%03o)\n", stb.st_mode & 07777); + close(fd); + errno = EACCES; + return -1; + } + } + debug1("secopen ok - returning %d\n", fd); + return fd; +#endif +} + +int +printpipe(struct win *p, char *cmd) +{ + int pi[2]; + if (pipe(pi)) { + WMsg(p, errno, "printing pipe"); + return -1; + } + switch (fork()) { + case -1: + WMsg(p, errno, "printing fork"); + return -1; + case 0: + display = p->w_pdisplay; + displays = 0; + ServerSocket = -1; #ifdef DEBUG - if (dfp && dfp != stderr) - fclose(dfp); + if (dfp && dfp != stderr) + fclose(dfp); #endif - if (dup2(pi[0], 0) < 0) - Panic(errno, "printpipe dup2"); - closeallfiles(0); - if (setgid(real_gid) || setuid(real_uid)) - Panic(errno, "printpipe setuid"); - eff_uid = real_uid; - eff_gid = real_gid; + close(0); + dup(pi[0]); + closeallfiles(0); + if (setgid(real_gid) || setuid(real_uid)) + Panic(errno, "printpipe setuid"); + eff_uid = real_uid; + eff_gid = real_gid; #ifdef SIGPIPE - signal(SIGPIPE, SIG_DFL); + signal(SIGPIPE, SIG_DFL); #endif - execl("/bin/sh", "sh", "-c", cmd, NULL); - Panic(errno, "/bin/sh"); - default: - break; - } - close(pi[0]); - return pi[1]; -} - -int readpipe(char **cmdv) { - int pi[2]; - - if (pipe(pi)) { - Msg(errno, "pipe"); - return -1; - } - - fflush(NULL); - switch (fork()) { - case -1: - Msg(errno, "fork"); - return -1; - case 0: - displays = 0; - ServerSocket = -1; + execl("/bin/sh", "sh", "-c", cmd, (char *)0); + Panic(errno, "/bin/sh"); + default: + break; + } + close(pi[0]); + return pi[1]; +} + +int +readpipe(char **cmdv) +{ + int pi[2]; + + if (pipe(pi)) { + Msg(errno, "pipe"); + return -1; + } + + switch (fork()) { + case -1: + Msg(errno, "fork"); + return -1; + case 0: + displays = 0; + ServerSocket = -1; #ifdef DEBUG - if (dfp && dfp != stderr) - fclose(dfp); + if (dfp && dfp != stderr) + fclose(dfp); #endif - close(1); - if (dup(pi[1]) != 1) { - close(pi[1]); - Panic(0, "dup"); - } - closeallfiles(1); - - if (setgid(real_gid) || setuid(real_uid)) { - close(1); - Panic(errno, "setuid/setgid"); - } - eff_uid = real_uid; - eff_gid = real_gid; + close(1); + if (dup(pi[1]) != 1) { + close(pi[1]); + Panic(0, "dup"); + } + closeallfiles(1); + + if (setgid(real_gid) || setuid(real_uid)) { + close(1); + Panic(errno, "setuid/setgid"); + } + eff_uid = real_uid; + eff_gid = real_gid; #ifdef SIGPIPE - signal(SIGPIPE, SIG_DFL); + signal(SIGPIPE, SIG_DFL); #endif - execvp(*cmdv, cmdv); - close(1); - Panic(errno, "%s", *cmdv); - default: - break; - } - close(pi[1]); - return pi[0]; + execvp(*cmdv, cmdv); + close(1); + Panic(errno, "%s", *cmdv); + default: + break; + } + close(pi[1]); + return pi[0]; } diff -ur screen.orig/HACKING screen/HACKING --- screen.orig/HACKING 2023-06-01 14:58:17.228665002 +0300 +++ screen/HACKING 2022-01-28 17:06:02.662611403 +0300 @@ -4,7 +4,7 @@ The local variable nr is set to an integer value representing the command to be evaluated; for every command `foo', there is an integer value RC_FOO for use as nr's value to represent it. Find - the matching case label to follow procesing of the command. + the matching case label to follow processing of the command. The RC_FOO values are defined in comm.h, which is automatically generated by comm.sh, based on the names of the commands diff -ur screen.orig/help.c screen/help.c --- screen.orig/help.c 2023-06-01 14:58:17.240665030 +0300 +++ screen/help.c 2022-01-28 17:06:02.686611998 +0300 @@ -111,8 +111,9 @@ printf("\nError: "); printf(message, arg); printf("\n"); + exit(1); } - exit(1); + exit(0); } /* Here come the help page routines */ diff -ur screen.orig/INSTALL screen/INSTALL --- screen.orig/INSTALL 2023-06-01 14:58:17.228665002 +0300 +++ screen/INSTALL 2022-01-28 17:06:02.662611403 +0300 @@ -40,7 +40,7 @@ not. At least it must be on a filesystem that supports sockets/fifos. SOCKDIR must not point into an AFS (Andrew File System) mounted directory. If you are uncertain about your NFS implementation, use a UFS directory for -SOCKDIR. Personally, I favour a users home directory and recommend the the +SOCKDIR. Personally, I favour a user's home directory and recommend the the /tmp/ area. The path for ETCSCREENRC may also need to be adapted. @@ -58,7 +58,7 @@ -------------------- You may well run screen from your private binary directory and with a private socket directory like $HOME/.screen. But to have a full featured -screen and (from a users point of view) more secure pty's you should +screen and (from a user's point of view) more secure pty's you should consult a system administrator and discuss installing screen setuid-root in some globally accessible directory like /usr/local/bin. @@ -94,7 +94,7 @@ The files screenrc and etc/etcscreenrc are instructive samples that demonstrate what can/should be done from your private .screenrc and from $ETCSCREENRC -- do not just copy them. Read them. Look through the -etcscreenrc file for system wide defaults that you like to set. e.g. +etcscreenrc file for system wide defaults that you like to set, e.g. autodetach off, startup_message off, vbell on, ... Since version 3.2.15 the screenrc file syntax changed slightly. All rc files from previous versions should be run through the 'newsyntax' script that comes diff -ur screen.orig/.iscreenrc screen/.iscreenrc --- screen.orig/.iscreenrc 2023-06-01 14:58:17.227665000 +0300 +++ screen/.iscreenrc 2022-01-28 17:06:02.662611403 +0300 @@ -17,7 +17,7 @@ echo -n "booting screen" # let it flash, not horn! -#vbell on # "vbell" don't work any longer, sorry. +#vbell on # "vbell" doesn't work any longer, sorry. #vbell_msg " Wuff, Wuff!! " # this is the default message #bell "Bimmmel No. %" # sounds the bell and shows a message @@ -45,11 +45,11 @@ # Printing in the leftmost column is not save. We express that fact as :LP@: # # Emacs tends to smear it's highlighted status bar across the screen, producing -# ugly areas of bright background, if termcap is'nt perfectly sober. +# ugly areas of bright background, if termcap isn't perfectly sober. # Give a little :ms@: in the termcap, this may help. # # And who invented the initialisation for facit terminals? We tell him that -# we non't like smooth scroll, by specifying :ti=\E[?l:. +# we don't like smooth scroll, by specifying :ti=\E[?l:. # \E[?3l 80 Zeichen # \E[?3h 132 Zeichen # LP Last column Printable @@ -92,11 +92,11 @@ # ICL 6402 testing: termcap icl* G0:S0=\E$[start]:E0=\E%[end]:C0=j9kx5 GS=\E(0^O:GE=\E(B^O:G1=k:G2=l:G3=m:G4=j:GV=x:GH=q:GR=u:GL=t:GU=w:GD=v:GC=n -# Flowcontrol produces trouble. ^S und ^Q will never reach screen, as our +# Flow control produces trouble. ^S und ^Q will never reach screen, as our # terminals catch them locally. Who can explain that to me?: #flow on|off|auto [interrupt] -# Long Lines get wrapped around (the back of your terminal). This is the +# Long lines get wrapped around (the back of your terminal). This is the # default for vt100. But now programs make different asumptions about your # terminal. You may find two linefeeds where you'd expect one, or you may # be confronted with a truncated line. Currently there is no fix, but pressing @@ -106,10 +106,10 @@ # the autoaka allows you to see the currently executing shell command in the # window name field. To use that, your shell prompt must contain ^[k^[\ or # you will see the string "(init)" as a name. -# in my .cshrc I may use this for a wonderfull tcsh-prompt: +# in my .cshrc I may use this for a wonderful tcsh-prompt: # set prompt="%{^[k^[\\%}%h %c2(%m)%# " # -# defining a shellaka that contains a pipe-symbol (|) activites the +# defining a shellaka that contains a pipe-symbol (|) activates the # autoaka feature. To the left of that | you specify a constant part of # your prompt as a trigger, to the right you may place a default string # as in @@ -121,8 +121,8 @@ # ... now a little bit of key bindings # In case we don't have write permission for /etc/utmp (no s-bit) # we create even local windows via rlogin. -> Et voila: a utmp-slot -# utmp-slots are strongly recomended to keep sccs and talk happy. -# (thus we have ^A# or. ^Ac for windowcreation with or without utmp-slot.) +# utmp-slots are strongly recommended to keep sccs and talk happy. +# (thus we have ^A# or. ^Ac for window creation with or without utmp-slot.) # but if we run suid-root, we produce all the rlogins with -ln, # as nobody shall refer to these pty's. bind '!' screen -ln -k faui41 rlogin faui41 @@ -151,7 +151,7 @@ # What happens, when you 'think emacs' and want to erase a whole # line? You type ^A^K right? Under screen it should be ^Aa^K. But... # killing the window would be a real punishment for a little mistyping. -bind k #wow! I even amange to type ^Ak by accident. +bind k #wow! I even mange to type ^Ak by accident. #bind ^k #bind K kill diff -ur screen.orig/layer.c screen/layer.c --- screen.orig/layer.c 2023-06-01 14:58:17.241665032 +0300 +++ screen/layer.c 2022-01-28 17:06:02.686611998 +0300 @@ -876,26 +876,22 @@ { VA_LIST(ap) char buf[MAXPATHLEN*2]; - ssize_t len; - const int errlen = err ? 100 : 0; + char *p = buf; struct canvas *cv; VA_START(ap, fmt); fmt = DoNLS(fmt); - len = vsnprintf(buf, sizeof(buf) - errlen, fmt, VA_ARGS(ap)); + (void)vsnprintf(p, sizeof(buf) - 100, fmt, VA_ARGS(ap)); VA_END(ap); - if (len < 0) { - strncpy(buf, fmt, sizeof(buf) - errlen); - buf[sizeof(buf) - errlen - 1] = 0; - } if (err) { - const char *strerr = strerror(err); - if (strerr) { - strncat(buf, ": ", 2); - strncat(buf, strerr, errlen - 3); - } + p += strlen(p); + *p++ = ':'; + *p++ = ' '; + strncpy(p, strerror(err), buf + sizeof(buf) - p - 1); + buf[sizeof(buf) - 1] = 0; } + debug2("LMsg('%s') (%#x);\n", buf, (unsigned int)flayer); for (display = displays; display; display = display->d_next) { for (cv = D_cvlist; cv; cv = cv->c_next) @@ -943,7 +939,7 @@ for (l = lay; l; l = l->l_next) { if (l->l_layfn == &WinLf || l->l_layfn == &BlankLf) break; - debug1("- killing %p\n", l); + debug1("- killing %#x\n", l); if (oldflayer == l) oldflayer = 0; for (cv = l->l_cvlist; cv; cv = ncv) { @@ -977,7 +973,7 @@ Msg(0, "No memory for layer struct"); return -1; } - debug2("Entering new layer on top of %p: %p\n", (unsigned int)flayer, newlay); + debug2("Entering new layer on top of %#x: %#x\n", (unsigned int)flayer, newlay); data = 0; if (datasize) { if ((data = calloc(1, datasize)) == 0) { diff -ur screen.orig/layer.h screen/layer.h --- screen.orig/layer.h 2023-06-01 14:58:17.241665032 +0300 +++ screen/layer.h 2022-01-28 17:06:02.686611998 +0300 @@ -106,7 +106,7 @@ debug("LayCallUp\n"); \ flayer = flayer->l_next; \ oldcvlist = flayer->l_cvlist; \ - debug1("oldcvlist: %p\n", oldcvlist); \ + debug1("oldcvlist: %x\n", oldcvlist); \ flayer->l_cvlist = oldlay->l_cvlist; \ for (cv = flayer->l_cvlist; cv; cv = cv->c_lnext) \ cv->c_layer = flayer; \ diff -ur screen.orig/list_window.c screen/list_window.c --- screen.orig/list_window.c 2023-06-01 14:58:17.242665034 +0300 +++ screen/list_window.c 2022-01-28 17:06:02.686611998 +0300 @@ -515,7 +515,7 @@ if (onblank) { - debug3("flayer %p %d %x\n", flayer, flayer->l_width, flayer->l_height); + debug3("flayer %x %d %x\n", flayer, flayer->l_width, flayer->l_height); if (!display) { LMsg(0, "windowlist -b: display required"); diff -ur screen.orig/loadav.c screen/loadav.c --- screen.orig/loadav.c 2023-06-01 14:58:17.242665034 +0300 +++ screen/loadav.c 2022-01-28 17:06:02.686611998 +0300 @@ -85,13 +85,13 @@ if ((fp = secfopen("/proc/loadavg", "r")) == NULL) return 0; - s = fgets(buf, sizeof(buf), fp); + *buf = 0; + fgets(buf, sizeof(buf), fp); fclose(fp); - if (s == NULL) - return 0; /* can't use fscanf because the decimal point symbol depends on * the locale but the kernel uses always '.'. */ + s = buf; for (i = 0; i < (LOADAV_NUM > 3 ? 3 : LOADAV_NUM); i++) { d = e = 0; diff -ur screen.orig/Makefile.in screen/Makefile.in --- screen.orig/Makefile.in 2023-06-01 14:58:17.228665002 +0300 +++ screen/Makefile.in 2022-01-28 17:06:02.662611403 +0300 @@ -67,7 +67,7 @@ sched.c teln.c nethack.c encoding.c canvas.c layout.c viewport.c \ list_display.c list_generic.c list_window.c OFILES= screen.o ansi.o fileio.o mark.o misc.o resize.o socket.o \ - search.o tty.o term.o window.o utmp.o loadav.o help.o \ + search.o tty.o term.o window.o utmp.o loadav.o putenv.o help.o \ termcap.o input.o attacher.o pty.o process.o display.o comm.o \ kmapdef.o acls.o braille.o braille_tsi.o logfile.o layer.o \ list_generic.o list_display.o list_window.o \ @@ -91,15 +91,15 @@ -if [ -f $(DESTDIR)$(bindir)/screen ] && [ ! -f $(DESTDIR)$(bindir)/screen.old ]; then mv $(DESTDIR)$(bindir)/screen $(DESTDIR)$(bindir)/screen.old; fi rm -f $(DESTDIR)$(bindir)/screen (cd $(DESTDIR)$(bindir) && ln -f -s $(SCREEN) screen) - cp $(srcdir)/utf8encodings/?? $(RPM_BUILD_ROOT)$(SCREENENCODINGS) + cp $(srcdir)/utf8encodings/?? $(DESTDIR)$(SCREENENCODINGS) ############################################################################### install: installdirs install_bin - pushd doc ; $(MAKE) install; popd - -(export TERMINFO="$(DESTDIR)$(datadir)/terminfo"; if [ -d "$$TERMINFO" ]; then \ - tic ${srcdir}/terminfo/screeninfo.src; \ - chmod 644 "$$TERMINFO"/s/screen*; \ - fi) + cd doc ; $(MAKE) install + -if [ -d $(DESTDIR)/usr/lib/terminfo ]; then \ + PATH="$$PATH:/usr/5bin" tic ${srcdir}/terminfo/screeninfo.src; \ + chmod 644 $(DESTDIR)/usr/lib/terminfo/s/screen*; \ + fi # Better do this by hand. E.g. under RCS... # cat ${srcdir}/terminfo/screencap >> /etc/termcap @echo "termcap entry (${srcdir}/terminfo/screencap) should be installed manually." @@ -107,7 +107,7 @@ installdirs: # Path leading to ETCSCREENRC and Socketdirectory not checked. - $(srcdir)/etc/mkinstalldirs $(DESTDIR)$(bindir) $(RPM_BUILD_ROOT)$(SCREENENCODINGS) + $(srcdir)/etc/mkinstalldirs $(DESTDIR)$(bindir) $(DESTDIR)$(SCREENENCODINGS) cd doc ; $(MAKE) installdirs uninstall: .version diff -ur screen.orig/mark.c screen/mark.c --- screen.orig/mark.c 2023-06-01 14:58:17.242665034 +0300 +++ screen/mark.c 2022-01-28 17:06:02.690612097 +0300 @@ -45,12 +45,12 @@ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ -static int is_letter __P((int)); +static int is_letter __P((char)); static void nextword __P((int *, int *, int, int)); static int linestart __P((int)); static int lineend __P((int)); -static int rem __P((int, int , int , int , int , char *, int)); -static int eq __P((int, int )); +static int rem __P((int, int, int, int, int, char *, int)); +static int eq __P((int, int)); static int MarkScrollDownDisplay __P((int)); static int MarkScrollUpDisplay __P((int)); @@ -69,76 +69,72 @@ int pastefont = 1; #endif -struct LayFuncs MarkLf = -{ - MarkProcess, - MarkAbort, - MarkRedisplayLine, - DefClearLine, - MarkRewrite, - DefResize, - DefRestore, - 0 +struct LayFuncs MarkLf = { + MarkProcess, + MarkAbort, + MarkRedisplayLine, + DefClearLine, + MarkRewrite, + DefResize, + DefRestore, + 0 }; -int join_with_cr = 0; +int join_with_cr = 0; int compacthist = 0; unsigned char mark_key_tab[256]; /* this array must be initialised first! */ static struct markdata *markdata; - /* * VI like is_letter: 0 - whitespace * 1 - letter - * 2 - other + * 2 - other */ -static int is_letter(c) -char c; +static int +is_letter(char c) { - if ((c >= 'a' && c <= 'z') || - (c >= 'A' && c <= 'Z') || - (c >= '0' && c <= '9') || - c == '_' || c == '.' || - c == '@' || c == ':' || - c == '%' || c == '!' || - c == '-' || c == '+') + if ((c >= 'a' && c <= 'z') || + (c >= 'A' && c <= 'Z') || + (c >= '0' && c <= '9') || + c == '_' || c == '.' || + c == '@' || c == ':' || + c == '%' || c == '!' || + c == '-' || c == '+') /* thus we can catch email-addresses as a word :-) */ - return 1; - else if (c != ' ') - return 2; - return 0; + return 1; + else if (c != ' ') + return 2; + return 0; } static int -linestart(y) -int y; +linestart(int y) { - register int x; - register unsigned char *i; + register int x; + register unsigned char *i; - for (x = markdata->left_mar, i = WIN(y)->image + x; x < fore->w_width - 1; x++) - if (*i++ != ' ') - break; - if (x == fore->w_width - 1) - x = markdata->left_mar; - return x; + for (x = markdata->left_mar, i = WIN(y)->image + x; x < fore->w_width - 1; x++) + if (*i++ != ' ') + break; + if (x == fore->w_width - 1) + x = markdata->left_mar; + return x; } static int -lineend(y) -int y; +lineend(int y) { - register int x; - register unsigned char *i; + register int x; + register unsigned char *i; - for (x = markdata->right_mar, i = WIN(y)->image + x; x >= 0; x--) - if (*i-- != ' ') - break; - if (x < 0) - x = markdata->left_mar; - return x; + for (x = markdata->right_mar, i = WIN(y)->image + x; x >= 0; x--) + if (*i-- != ' ') + break; + if (x < 0) + x = markdata->left_mar; + return x; } /* @@ -149,50 +145,50 @@ static int nextchar(int *xp, int *yp, int direction, char target, int num) { - int width; /* width of the current window. */ - int x; /* x coordinate of the current cursor position. */ - int step; /* amount to increment x (+1 or -1) */ - int adjust; /* Final adjustment of cursor position. */ - char *displayed_line; /* Line in which search takes place. */ - - debug("nextchar\n"); - - x = *xp; - step = 1; - adjust = 0; - width = fore->w_width; - displayed_line = (char *)WIN(*yp) -> image; - - switch(direction) { - case 't': - adjust = -1; /* fall through */ - case 'f': - step = 1; - break; - case 'T': - adjust = 1; /* fall through */ - case 'F': - step = -1; - break; - default: - ASSERT(0); - } - - x += step; - - debug1("ml->image = %s\n", displayed_line); - debug2("num = %d, width = %d\n",num, width); - debug2("x = %d target = %c\n", x, target ); - - for ( ;x>=0 && x <= width; x += step) { - if (displayed_line[x] == target) { - if (--num == 0) { - *xp = x + adjust; - return 0; - } - } - } - return -1; + int width; /* width of the current window. */ + int x; /* x coordinate of the current cursor position. */ + int step; /* amount to increment x (+1 or -1) */ + int adjust; /* Final adjustment of cursor position. */ + char *displayed_line; /* Line in which search takes place. */ + + debug("nextchar\n"); + + x = *xp; + step = 1; + adjust = 0; + width = fore->w_width; + displayed_line = (char *)WIN(*yp)->image; + + switch (direction) { + case 't': + adjust = -1; /* fall through */ + case 'f': + step = 1; + break; + case 'T': + adjust = 1; /* fall through */ + case 'F': + step = -1; + break; + default: + ASSERT(0); + } + + x += step; + + debug1("ml->image = %s\n", displayed_line); + debug2("num = %d, width = %d\n", num, width); + debug2("x = %d target = %c\n", x, target); + + for (; x >= 0 && x <= width; x += step) { + if (displayed_line[x] == target) { + if (--num == 0) { + *xp = x + adjust; + return 0; + } + } + } + return -1; } /* @@ -204,222 +200,201 @@ * NW_BIG: match WORDs not words */ -#define NW_BACK (1<<0) -#define NW_ENDOFWORD (1<<1) -#define NW_MUSTMOVE (1<<2) -#define NW_BIG (1<<3) - - +#define NW_BACK (1<<0) +#define NW_ENDOFWORD (1<<1) +#define NW_MUSTMOVE (1<<2) +#define NW_BIG (1<<3) static void -nextword(xp, yp, flags, num) -int *xp, *yp, flags, num; +nextword(int *xp, int *yp, int flags, int num) { - int xx = fore->w_width, yy = fore->w_histheight + fore->w_height; - register int sx, oq, q, x, y; - struct mline *ml; - - x = *xp; - y = *yp; - sx = (flags & NW_BACK) ? -1 : 1; - if ((flags & NW_ENDOFWORD) && (flags & NW_MUSTMOVE)) - x += sx; - ml = WIN(y); - for (oq = -1; ; x += sx, oq = q) - { - if (x >= xx || x < 0) - q = 0; - else if (flags & NW_BIG) - q = ml->image[x] == ' '; - else - q = is_letter(ml->image[x]); - if (oq >= 0 && oq != q) - { - if (oq == 0 || !(flags & NW_ENDOFWORD)) - *xp = x; - else - *xp = x-sx; - *yp = y; - if ((!(flags & NW_ENDOFWORD) && q) || - ((flags & NW_ENDOFWORD) && oq)) - { - if (--num <= 0) - return; - } - } - if (x == xx) - { - x = -1; - if (++y >= yy) - return; - ml = WIN(y); - } - else if (x < 0) - { - x = xx; - if (--y < 0) - return; - ml = WIN(y); + int xx = fore->w_width, yy = fore->w_histheight + fore->w_height; + register int sx, oq, q, x, y; + struct mline *ml; + + x = *xp; + y = *yp; + sx = (flags & NW_BACK) ? -1 : 1; + if ((flags & NW_ENDOFWORD) && (flags & NW_MUSTMOVE)) + x += sx; + ml = WIN(y); + for (oq = -1;; x += sx, oq = q) { + if (x >= xx || x < 0) + q = 0; + else if (flags & NW_BIG) + q = ml->image[x] == ' '; + else + q = is_letter(ml->image[x]); + + if (oq >= 0 && oq != q) { + if (oq == 0 || !(flags & NW_ENDOFWORD)) + *xp = x; + else + *xp = x - sx; + *yp = y; + + if ((!(flags & NW_ENDOFWORD) && q) || ((flags & NW_ENDOFWORD) && oq)) { + if (--num <= 0) + return; + } + } + + if (x == xx) { + x = -1; + if (++y >= yy) + return; + ml = WIN(y); + } else if (x < 0) { + x = xx; + if (--y < 0) + return; + ml = WIN(y); + } } - } } - /* * y1, y2 are WIN coordinates * - * redisplay: 0 - just copy - * 1 - redisplay + copy - * 2 - count + copy, don't redisplay + * redisplay: 0 - just copy + * 1 - redisplay + copy + * 2 - count + copy, don't redisplay */ static int -rem(x1, y1, x2, y2, redisplay, pt, yend) -int x1, y1, x2, y2, redisplay, yend; -char *pt; +rem(int x1, int y1, int x2, int y2, int redisplay, char *pt, int yend) { - int i, j, from, to, ry, c; - int l = 0; - unsigned char *im; - struct mline *ml; + int i, j, from, to, ry, c; + int l = 0; + unsigned char *im; + struct mline *ml; #ifdef FONT - int cf, cfx, font; - unsigned char *fo, *fox; + int cf, cfx, font; + unsigned char *fo, *fox; #endif - markdata->second = 0; - if (y2 < y1 || ((y2 == y1) && (x2 < x1))) - { - i = y2; - y2 = y1; - y1 = i; - i = x2; - x2 = x1; - x1 = i; - } - ry = y1 - markdata->hist_offset; - - i = y1; - if (redisplay != 2 && pt == 0 && ry <0) - { - i -= ry; - ry = 0; - } - for (; i <= y2; i++, ry++) - { - if (redisplay != 2 && pt == 0 && ry > yend) - break; - ml = WIN(i); - from = (i == y1) ? x1 : 0; - if (from < markdata->left_mar) - from = markdata->left_mar; - for (to = fore->w_width, im = ml->image + to; to >= 0; to--) - if (*im-- != ' ') - break; - if (i == y2 && x2 < to) - to = x2; - if (to > markdata->right_mar) - to = markdata->right_mar; - if (redisplay == 1 && from <= to && ry >=0 && ry <= yend) - MarkRedisplayLine(ry, from, to, 0); - if (redisplay != 2 && pt == 0) /* don't count/copy */ - continue; - j = from; + markdata->second = 0; + if (y2 < y1 || ((y2 == y1) && (x2 < x1))) { + i = y2; + y2 = y1; + y1 = i; + i = x2; + x2 = x1; + x1 = i; + } + ry = y1 - markdata->hist_offset; + + i = y1; + if (redisplay != 2 && pt == 0 && ry < 0) { + i -= ry; + ry = 0; + } + for (; i <= y2; i++, ry++) { + if (redisplay != 2 && pt == 0 && ry > yend) + break; + ml = WIN(i); + from = (i == y1) ? x1 : 0; + + if (from < markdata->left_mar) + from = markdata->left_mar; + for (to = fore->w_width, im = ml->image + to; to >= 0; to--) + if (*im-- != ' ') + break; + if (i == y2 && x2 < to) + to = x2; + if (to > markdata->right_mar) + to = markdata->right_mar; + if (redisplay == 1 && from <= to && ry >= 0 && ry <= yend) + MarkRedisplayLine(ry, from, to, 0); + if (redisplay != 2 && pt == 0) /* don't count/copy */ + continue; + j = from; #ifdef DW_CHARS - if (dw_right(ml, j, fore->w_encoding)) - j--; + if (dw_right(ml, j, fore->w_encoding)) + j--; #endif - im = ml->image + j; + im = ml->image + j; #ifdef FONT - fo = ml->font + j; - fox = ml->fontx + j; - font = ASCII; + fo = ml->font + j; + fox = ml->fontx + j; + font = ASCII; #endif - for (; j <= to; j++) - { - c = (unsigned char)*im++; + for (; j <= to; j++) { + c = (unsigned char)*im++; #ifdef FONT - cf = (unsigned char)*fo++; - cfx = (unsigned char)*fox++; + cf = (unsigned char)*fo++; + cfx = (unsigned char)*fox++; # ifdef UTF8 - if (fore->w_encoding == UTF8) - { - c |= cf << 8 | cfx << 16; - if (c == UCS_HIDDEN) - continue; - c = ToUtf8_comb(pt, c); - l += c; - if (pt) - pt += c; - continue; - } + if (fore->w_encoding == UTF8) { + c |= cf << 8 | cfx << 16; + if (c == UCS_HIDDEN) + continue; + c = ToUtf8_comb(pt, c); + l += c; + if (pt) + pt += c; + continue; + } # endif # ifdef DW_CHARS - if (is_dw_font(cf)) - { - c = c << 8 | (unsigned char)*im++; - fo++; - j++; - } + if (is_dw_font(cf)) { + c = c << 8 | (unsigned char)*im++; + fo++; + j++; + } # endif - if (pastefont) - { - c = EncodeChar(pt, c | cf << 16, fore->w_encoding, &font); - l += c; - if (pt) - pt += c; - continue; - } + if (pastefont) { + c = EncodeChar(pt, c | cf << 16, fore->w_encoding, &font); + l += c; + if (pt) + pt += c; + continue; + } #endif /* FONT */ - if (pt) - *pt++ = c; - l++; - } + if (pt) + *pt++ = c; + l++; + } #ifdef FONT - if (pastefont && font != ASCII) - { - if (pt) - { - strcpy(pt, "\033(B"); - pt += 3; - } - l += 3; - } + if (pastefont && font != ASCII) { + if (pt) { + strcpy(pt, "\033(B"); + pt += 3; + } + l += 3; + } #endif - if (i != y2 && (to != fore->w_width - 1 || ml->image[to + 1] == ' ')) - { - /* - * this code defines, what glues lines together - */ - switch (markdata->nonl) - { - case 0: /* lines separated by newlines */ - if (pt) - *pt++ = '\r'; - l++; - if (join_with_cr) - { - if (pt) - *pt++ = '\n'; - l++; + if (i != y2 && (to != fore->w_width - 1 || ml->image[to + 1] == ' ')) { + /* + * this code defines, what glues lines together + */ + switch (markdata->nonl) { + case 0: /* lines separated by newlines */ + if (pt) + *pt++ = '\r'; + l++; + if (join_with_cr) { + if (pt) + *pt++ = '\n'; + l++; + } + break; + case 1: /* nothing to separate lines */ + break; + case 2: /* lines separated by blanks */ + if (pt) + *pt++ = ' '; + l++; + break; + case 3: /* seperate by comma, for csh junkies */ + if (pt) + *pt++ = ','; + l++; + break; + } } - break; - case 1: /* nothing to separate lines */ - break; - case 2: /* lines separated by blanks */ - if (pt) - *pt++ = ' '; - l++; - break; - case 3: /* seperate by comma, for csh junkies */ - if (pt) - *pt++ = ','; - l++; - break; - } } - } - return l; + return l; } /* Check if two chars are identical. All digits are treated @@ -427,67 +402,63 @@ */ static int -eq(a, b) -int a, b; +eq(int a, int b) { - if (a == b) - return 1; - if (a == 0 || b == 0) - return 1; - if (a <= '9' && a >= '0' && b <= '9' && b >= '0') - return 1; - return 0; + if (a == b) + return 1; + if (a == 0 || b == 0) + return 1; + if (a <= '9' && a >= '0' && b <= '9' && b >= '0') + return 1; + return 0; } - /**********************************************************************/ int GetHistory() /* return value 1 if copybuffer changed */ { - int i = 0, q = 0, xx, yy, x, y; - unsigned char *linep; - struct mline *ml; - - ASSERT(display && fore); - x = fore->w_x; - if (x >= fore->w_width) - x = fore->w_width - 1; - y = fore->w_y + fore->w_histheight; - debug2("cursor is at x=%d, y=%d\n", x, y); - ml = WIN(y); - for (xx = x - 1, linep = ml->image + xx; xx >= 0; xx--) - if ((q = *linep--) != ' ' ) - break; - debug3("%c at (%d,%d)\n", q, xx, y); - for (yy = y - 1; yy >= 0; yy--) - { - ml = WIN(yy); - linep = ml->image; - if (xx < 0 || eq(linep[xx], q)) - { /* line is matching... */ - for (i = fore->w_width - 1, linep += i; i >= x; i--) - if (*linep-- != ' ') - break; - if (i >= x) - break; - } - } - if (yy < 0) - return 0; - if (D_user->u_plop.buf) - UserFreeCopyBuffer(D_user); - if ((D_user->u_plop.buf = (char *)malloc((unsigned) (i - x + 2))) == NULL) - { - LMsg(0, "Not enough memory... Sorry."); - return 0; - } - bcopy((char *)linep - i + x + 1, D_user->u_plop.buf, i - x + 1); - D_user->u_plop.len = i - x + 1; + int i = 0, q = 0, xx, yy, x, y; + unsigned char *linep; + struct mline *ml; + + ASSERT(display && fore); + x = fore->w_x; + if (x >= fore->w_width) + x = fore->w_width - 1; + y = fore->w_y + fore->w_histheight; + debug2("cursor is at x=%d, y=%d\n", x, y); + ml = WIN(y); + for (xx = x - 1, linep = ml->image + xx; xx >= 0; xx--) + if ((q = *linep--) != ' ') + break; + debug3("%c at (%d,%d)\n", q, xx, y); + for (yy = y - 1; yy >= 0; yy--) { + ml = WIN(yy); + linep = ml->image; + if (xx < 0 || eq(linep[xx], q)) { /* line is matching... */ + for (i = fore->w_width - 1, linep += i; i >= x; i--) + if (*linep-- != ' ') + break; + if (i >= x) + break; + } + } + if (yy < 0) + return 0; + if (D_user->u_plop.buf) + UserFreeCopyBuffer(D_user); + if ((D_user->u_plop.buf = (char *)malloc((unsigned)(i - x + 2))) == + NULL) { + LMsg(0, "Not enough memory... Sorry."); + return 0; + } + bcopy((char *)linep - i + x + 1, D_user->u_plop.buf, i - x + 1); + D_user->u_plop.len = i - x + 1; #ifdef ENCODINGS - D_user->u_plop.enc = fore->w_encoding; + D_user->u_plop.enc = fore->w_encoding; #endif - return 1; + return 1; } /**********************************************************************/ @@ -496,98 +467,88 @@ void MarkRoutine() { - int x, y; + int x, y; - ASSERT(fore && display && D_user); + ASSERT(fore && display && D_user); - debug2("MarkRoutine called: fore nr %d, display %s\n", - fore->w_number, D_usertty); + debug2("MarkRoutine called: fore nr %d, display %s\n", fore->w_number, D_usertty); - if (InitOverlayPage(sizeof(*markdata), &MarkLf, 1)) - return; - flayer->l_encoding = fore->w_encoding; - flayer->l_mode = 1; - markdata = (struct markdata *)flayer->l_data; - markdata->md_user = D_user; /* XXX: Correct? */ - markdata->md_window = fore; - markdata->second = 0; - markdata->rep_cnt = 0; - markdata->append_mode = 0; - markdata->write_buffer = 0; - markdata->nonl = 0; - markdata->left_mar = 0; - markdata->right_mar = fore->w_width - 1; - markdata->hist_offset = fore->w_histheight; - x = fore->w_x; - y = D2W(fore->w_y); - if (x >= fore->w_width) - x = fore->w_width - 1; - - LGotoPos(flayer, x, W2D(y)); - LMsg(0, "Copy mode - Column %d Line %d(+%d) (%d,%d)", - x + 1, W2D(y + 1), fore->w_histheight, fore->w_width, fore->w_height); - markdata->cx = markdata->x1 = x; - markdata->cy = markdata->y1 = y; - flayer->l_x = x; - flayer->l_y = W2D(y); + if (InitOverlayPage(sizeof(*markdata), &MarkLf, 1)) + return; + flayer->l_encoding = fore->w_encoding; + flayer->l_mode = 1; + markdata = (struct markdata *)flayer->l_data; + markdata->md_user = D_user; /* XXX: Correct? */ + markdata->md_window = fore; + markdata->second = 0; + markdata->rep_cnt = 0; + markdata->append_mode = 0; + markdata->write_buffer = 0; + markdata->nonl = 0; + markdata->left_mar = 0; + markdata->right_mar = fore->w_width - 1; + markdata->hist_offset = fore->w_histheight; + x = fore->w_x; + y = D2W(fore->w_y); + if (x >= fore->w_width) + x = fore->w_width - 1; + + LGotoPos(flayer, x, W2D(y)); + LMsg(0, "Copy mode - Column %d Line %d(+%d) (%d,%d)", x + 1, W2D(y + 1), fore->w_histheight, fore->w_width, fore->w_height); + markdata->cx = markdata->x1 = x; + markdata->cy = markdata->y1 = y; + flayer->l_x = x; + flayer->l_y = W2D(y); } static void -MarkProcess(inbufp,inlenp) -char **inbufp; -int *inlenp; +MarkProcess(char **inbufp, int *inlenp) { - char *inbuf, *pt; - int inlen; - int cx, cy, x2, y2, j, yend; - int newcopylen = 0, od; - int in_mark; - int rep_cnt; - struct acluser *md_user; + char *inbuf, *pt; + int inlen; + int cx, cy, x2, y2, j, yend; + int newcopylen = 0, od; + int in_mark; + int rep_cnt; + struct acluser *md_user; /* char *extrap = 0, extrabuf[100]; */ - markdata = (struct markdata *)flayer->l_data; - fore = markdata->md_window; - md_user = markdata->md_user; - if (inbufp == 0) - { - MarkAbort(); - return; - } - - LGotoPos(flayer, markdata->cx, W2D(markdata->cy)); - inbuf= *inbufp; - inlen= *inlenp; - pt = inbuf; - in_mark = 1; - while (in_mark && (inlen /* || extrap */)) - { - unsigned char ch = (unsigned char )*pt++; - inlen--; - if (flayer->l_mouseevent.start) - { - int r = LayProcessMouse(flayer, ch); - if (r == -1) - LayProcessMouseSwitch(flayer, 0); - else - { - if (r) - ch = 0222; - else - continue; - } - } - od = mark_key_tab[(int)ch]; - rep_cnt = markdata->rep_cnt; - if (od >= '0' && od <= '9' && !markdata->f_cmd.flag) - { - if (rep_cnt < 1001 && (od != '0' || rep_cnt != 0)) - { - markdata->rep_cnt = 10 * rep_cnt + od - '0'; - continue; + markdata = (struct markdata *)flayer->l_data; + fore = markdata->md_window; + md_user = markdata->md_user; + if (inbufp == 0) { + MarkAbort(); + return; + } + + LGotoPos(flayer, markdata->cx, W2D(markdata->cy)); + inbuf = *inbufp; + inlen = *inlenp; + pt = inbuf; + in_mark = 1; + while (in_mark && (inlen /* || extrap */)) { + unsigned char ch = (unsigned char)*pt++; + inlen--; + if (flayer->l_mouseevent.start) { + int r = LayProcessMouse(flayer, ch); + if (r == -1) + LayProcessMouseSwitch(flayer, 0); + else { + if (r) + ch = 0222; + else + continue; + } + } + od = mark_key_tab[(int)ch]; + rep_cnt = markdata->rep_cnt; + if (od >= '0' && od <= '9' && !markdata->f_cmd.flag) { + if (rep_cnt < 1001 && (od != '0' || rep_cnt != 0)) { + markdata->rep_cnt = 10 * rep_cnt + od - '0'; + continue; /* * Now what is that 1001 here? Well, we have a screen with * 25 * 80 = 2000 characters. Movement is at most across the full @@ -598,32 +559,31 @@ * words, as they should be more advanced. jw. * Oh, wrong. We still give even the experienced user a factor of ten. */ - } - } - cx = markdata->cx; - cy = markdata->cy; + } + } + cx = markdata->cx; + cy = markdata->cy; - if (markdata -> f_cmd.flag) { - debug2("searching for %c:%d\n",od,rep_cnt); - markdata->f_cmd.flag = 0; - markdata->rep_cnt = 0; - - if (isgraph (od)) { - markdata->f_cmd.target = od; - rep_cnt = (rep_cnt) ? rep_cnt : 1; - nextchar(&cx, &cy, markdata->f_cmd.direction, od, rep_cnt ); - revto(cx, cy); - continue; - } - } + if (markdata->f_cmd.flag) { + debug2("searching for %c:%d\n", od, rep_cnt); + markdata->f_cmd.flag = 0; + markdata->rep_cnt = 0; + + if (isgraph(od)) { + markdata->f_cmd.target = od; + rep_cnt = (rep_cnt) ? rep_cnt : 1; + nextchar(&cx, &cy, markdata->f_cmd.direction, od, rep_cnt); + revto(cx, cy); + continue; + } + } processchar: - switch (od) - { - case 'f': /* fall through */ - case 'F': /* fall through */ - case 't': /* fall through */ - case 'T': /* fall through */ + switch (od) { + case 'f': /* fall through */ + case 'F': /* fall through */ + case 't': /* fall through */ + case 'T': /* fall through */ /* * Set f_cmd to do a search on the next key stroke. * If we break, rep_cnt will be reset, so we @@ -632,905 +592,857 @@ * break here so later followon code will be * hit. */ - markdata->f_cmd.flag = 1; - markdata->f_cmd.direction = od; - debug("entering char search\n"); - continue; - case ';': - case ',': - if (!markdata->f_cmd.target) - break; - if (!rep_cnt) - rep_cnt = 1; - nextchar(&cx, &cy, - od == ';' ? markdata->f_cmd.direction : (markdata->f_cmd.direction ^ 0x20), - markdata->f_cmd.target, rep_cnt ); - revto(cx, cy); - break; - case 'o': - case 'x': - if (!markdata->second) - break; - markdata->cx = markdata->x1; - markdata->cy = markdata->y1; - markdata->x1 = cx; - markdata->y1 = cy; - revto(markdata->cx, markdata->cy); - break; - case '\014': /* CTRL-L Redisplay */ - Redisplay(0); - LGotoPos(flayer, cx, W2D(cy)); - break; - case 0202: /* M-C-b */ - case '\010': /* CTRL-H Backspace */ - case 'h': - if (rep_cnt == 0) - rep_cnt = 1; - revto(cx - rep_cnt, cy); - break; - case 0216: /* M-C-p */ - case '\016': /* CTRL-N */ - case 'j': - if (rep_cnt == 0) - rep_cnt = 1; - revto(cx, cy + rep_cnt); - break; - case '+': - if (rep_cnt == 0) - rep_cnt = 1; - j = cy + rep_cnt; - if (j > fore->w_histheight + fore->w_height - 1) - j = fore->w_histheight + fore->w_height - 1; - revto(linestart(j), j); - break; - case '-': - if (rep_cnt == 0) - rep_cnt = 1; - cy -= rep_cnt; - if (cy < 0) - cy = 0; - revto(linestart(cy), cy); - break; - case '^': - revto(linestart(cy), cy); - break; - case '\n': - revto(markdata->left_mar, cy + 1); - break; - case 0220: /* M-C-p */ - case '\020': /* CTRL-P */ - case 'k': - if (rep_cnt == 0) - rep_cnt = 1; - revto(cx, cy - rep_cnt); - break; - case 0206: /* M-C-f */ - case 'l': - if (rep_cnt == 0) - rep_cnt = 1; - revto(cx + rep_cnt, cy); - break; - case '\001': /* CTRL-A from tcsh/emacs */ - case '0': - revto(markdata->left_mar, cy); - break; - case '\004': /* CTRL-D down half screen */ - if (rep_cnt == 0) - rep_cnt = (fore->w_height + 1) >> 1; - revto_line(cx, cy + rep_cnt, W2D(cy)); - break; - case '$': - revto(lineend(cy), cy); - break; - case '\022': /* CTRL-R emacs style backwards search */ - ISearch(-1); - in_mark = 0; - break; - case '\023': /* CTRL-S emacs style search */ - ISearch(1); - in_mark = 0; - break; - case '\025': /* CTRL-U up half screen */ - if (rep_cnt == 0) - rep_cnt = (fore->w_height + 1) >> 1; - revto_line(cx, cy - rep_cnt, W2D(cy)); - break; - case '\007': /* CTRL-G show cursorpos */ - if (markdata->left_mar == 0 && markdata->right_mar == fore->w_width - 1) - LMsg(0, "Column %d Line %d(+%d)", cx+1, W2D(cy)+1, - markdata->hist_offset); - else - LMsg(0, "Column %d(%d..%d) Line %d(+%d)", cx+1, - markdata->left_mar+1, markdata->right_mar+1, W2D(cy)+1, markdata->hist_offset); - break; - case '\002': /* CTRL-B back one page */ - if (rep_cnt == 0) - rep_cnt = 1; - rep_cnt *= fore->w_height; - revto(cx, cy - rep_cnt); - break; - case '\006': /* CTRL-F forward one page */ - if (rep_cnt == 0) - rep_cnt = 1; - rep_cnt *= fore->w_height; - revto(cx, cy + rep_cnt); - break; - case '\005': /* CTRL-E scroll up */ - if (rep_cnt == 0) - rep_cnt = 1; - rep_cnt = MarkScrollUpDisplay(rep_cnt); - if (cy < D2W(0)) - revto(cx, D2W(0)); - else - LGotoPos(flayer, cx, W2D(cy)); - break; - case '\031': /* CTRL-Y scroll down */ - if (rep_cnt == 0) - rep_cnt = 1; - rep_cnt = MarkScrollDownDisplay(rep_cnt); - if (cy > D2W(fore->w_height-1)) - revto(cx, D2W(fore->w_height-1)); - else - LGotoPos(flayer, cx, W2D(cy)); - break; - case '@': + markdata->f_cmd.flag = 1; + markdata->f_cmd.direction = od; + debug("entering char search\n"); + continue; + case ';': + case ',': + if (!markdata->f_cmd.target) + break; + if (!rep_cnt) + rep_cnt = 1; + nextchar(&cx, + &cy, + od == ';' ? markdata->f_cmd.direction : (markdata->f_cmd.direction ^ 0x20), + markdata->f_cmd.target, + rep_cnt); + revto(cx, cy); + break; + case 'o': + case 'x': + if (!markdata->second) + break; + markdata->cx = markdata->x1; + markdata->cy = markdata->y1; + markdata->x1 = cx; + markdata->y1 = cy; + revto(markdata->cx, markdata->cy); + break; + case '\014': /* CTRL-L Redisplay */ + Redisplay(0); + LGotoPos(flayer, cx, W2D(cy)); + break; + case 0202: /* M-C-b */ + case '\010': /* CTRL-H Backspace */ + case 'h': + if (rep_cnt == 0) + rep_cnt = 1; + revto(cx - rep_cnt, cy); + break; + case 0216: /* M-C-p */ + case '\016': /* CTRL-N */ + case 'j': + if (rep_cnt == 0) + rep_cnt = 1; + revto(cx, cy + rep_cnt); + break; + case '+': + if (rep_cnt == 0) + rep_cnt = 1; + j = cy + rep_cnt; + if (j > fore->w_histheight + fore->w_height - 1) + j = fore->w_histheight + fore->w_height - 1; + revto(linestart(j), j); + break; + case '-': + if (rep_cnt == 0) + rep_cnt = 1; + cy -= rep_cnt; + if (cy < 0) + cy = 0; + revto(linestart(cy), cy); + break; + case '^': + revto(linestart(cy), cy); + break; + case '\n': + revto(markdata->left_mar, cy + 1); + break; + case 0220: /* M-C-p */ + case '\020': /* CTRL-P */ + case 'k': + if (rep_cnt == 0) + rep_cnt = 1; + revto(cx, cy - rep_cnt); + break; + case 0206: /* M-C-f */ + case 'l': + if (rep_cnt == 0) + rep_cnt = 1; + revto(cx + rep_cnt, cy); + break; + case '\001': /* CTRL-A from tcsh/emacs */ + case '0': + revto(markdata->left_mar, cy); + break; + case '\004': /* CTRL-D down half screen */ + if (rep_cnt == 0) + rep_cnt = (fore->w_height + 1) >> 1; + revto_line(cx, cy + rep_cnt, W2D(cy)); + break; + case '$': + revto(lineend(cy), cy); + break; + case '\022': /* CTRL-R emacs style backwards search */ + ISearch(-1); + in_mark = 0; + break; + case '\023': /* CTRL-S emacs style search */ + ISearch(1); + in_mark = 0; + break; + case '\025': /* CTRL-U up half screen */ + if (rep_cnt == 0) + rep_cnt = (fore->w_height + 1) >> 1; + revto_line(cx, cy - rep_cnt, W2D(cy)); + break; + case '\007': /* CTRL-G show cursorpos */ + if (markdata->left_mar == 0 && markdata->right_mar == fore->w_width - 1) + LMsg(0, "Column %d Line %d(+%d)", cx + 1, W2D(cy) + 1, markdata->hist_offset); + else + LMsg(0, "Column %d(%d..%d) Line %d(+%d)", + cx + 1, markdata->left_mar + 1, + markdata->right_mar + 1, W2D(cy) + 1, + markdata->hist_offset); + break; + case '\002': /* CTRL-B back one page */ + if (rep_cnt == 0) + rep_cnt = 1; + rep_cnt *= fore->w_height; + revto(cx, cy - rep_cnt); + break; + case '\006': /* CTRL-F forward one page */ + if (rep_cnt == 0) + rep_cnt = 1; + rep_cnt *= fore->w_height; + revto(cx, cy + rep_cnt); + break; + case '\005': /* CTRL-E scroll up */ + if (rep_cnt == 0) + rep_cnt = 1; + rep_cnt = MarkScrollUpDisplay(rep_cnt); + if (cy < D2W(0)) + revto(cx, D2W(0)); + else + LGotoPos(flayer, cx, W2D(cy)); + break; + case '\031': /* CTRL-Y scroll down */ + if (rep_cnt == 0) + rep_cnt = 1; + rep_cnt = MarkScrollDownDisplay(rep_cnt); + if (cy > D2W(fore->w_height - 1)) + revto(cx, D2W(fore->w_height - 1)); + else + LGotoPos(flayer, cx, W2D(cy)); + break; + case '@': /* it may be useful to have a key that does nothing */ - break; - case '%': + break; + case '%': /* rep_cnt is a percentage for the history buffer */ - if (rep_cnt < 0) - rep_cnt = 0; - if (rep_cnt > 100) - rep_cnt = 100; - revto_line(markdata->left_mar, - fore->w_histheight - fore->w_scrollback_height + - (int)(rep_cnt * (fore->w_scrollback_height + fore->w_height) / 100.0), - (fore->w_height - 1) / 2); - break; - case 0201: - case 'g': - rep_cnt = 1; + if (rep_cnt < 0) + rep_cnt = 0; + if (rep_cnt > 100) + rep_cnt = 100; + + revto_line(markdata->left_mar, + fore->w_histheight - fore->w_scrollback_height + + (int)(rep_cnt * (fore->w_scrollback_height + + fore->w_height) / 100.0), (fore->w_height - 1) / 2); + break; + case 0201: + case 'g': + rep_cnt = 1; /* FALLTHROUGH */ - case 0205: - case 'G': + case 0205: + case 'G': /* rep_cnt is here the WIN line number */ - if (rep_cnt == 0) - rep_cnt = fore->w_histheight + fore->w_height; - revto_line(markdata->left_mar, --rep_cnt, (fore->w_height - 1) / 2); - break; - case 'H': - revto(markdata->left_mar, D2W(0)); - break; - case 'M': - revto(markdata->left_mar, D2W((fore->w_height - 1) / 2)); - break; - case 'L': - revto(markdata->left_mar, D2W(fore->w_height - 1)); - break; - case '|': - revto(--rep_cnt, cy); - break; - case 'w': - if (rep_cnt == 0) - rep_cnt = 1; - nextword(&cx, &cy, NW_MUSTMOVE, rep_cnt); - revto(cx, cy); - break; - case 'e': - case 'E': - if (rep_cnt == 0) - rep_cnt = 1; - nextword(&cx, &cy, NW_ENDOFWORD|NW_MUSTMOVE | (od == 'E' ? NW_BIG : 0), rep_cnt); - revto(cx, cy); - break; - case 'b': - case 'B': - if (rep_cnt == 0) - rep_cnt = 1; - nextword(&cx, &cy, NW_BACK|NW_ENDOFWORD|NW_MUSTMOVE | (od == 'B' ? NW_BIG : 0), rep_cnt); - revto(cx, cy); - break; - case 'a': - markdata->append_mode = 1 - markdata->append_mode; - debug1("append mode %d--\n", markdata->append_mode); - LMsg(0, (markdata->append_mode) ? ":set append" : ":set noappend"); - break; - case 'v': - case 'V': + if (rep_cnt == 0) + rep_cnt = fore->w_histheight + fore->w_height; + revto_line(markdata->left_mar, --rep_cnt, (fore->w_height - 1) / 2); + break; + case 'H': + revto(markdata->left_mar, D2W(0)); + break; + case 'M': + revto(markdata->left_mar, D2W((fore->w_height - 1) / 2)); + break; + case 'L': + revto(markdata->left_mar, D2W(fore->w_height - 1)); + break; + case '|': + revto(--rep_cnt, cy); + break; + case 'w': + if (rep_cnt == 0) + rep_cnt = 1; + nextword(&cx, &cy, NW_MUSTMOVE, rep_cnt); + revto(cx, cy); + break; + case 'e': + case 'E': + if (rep_cnt == 0) + rep_cnt = 1; + nextword(&cx, &cy, NW_ENDOFWORD|NW_MUSTMOVE | (od == 'E' ? NW_BIG : 0), rep_cnt); + revto(cx, cy); + break; + case 'b': + case 'B': + if (rep_cnt == 0) + rep_cnt = 1; + nextword(&cx, &cy, NW_BACK|NW_ENDOFWORD|NW_MUSTMOVE | (od == 'B' ? NW_BIG : 0), rep_cnt); + revto(cx, cy); + break; + case 'a': + markdata->append_mode = 1 - markdata->append_mode; + debug1("append mode %d--\n", markdata->append_mode); + LMsg(0, (markdata->append_mode) ? ":set append" : ":set noappend"); + break; + case 'v': + case 'V': /* this sets start column to column 9 for VI :set nu users */ - if (markdata->left_mar == 8) - rep_cnt = 1; - else - rep_cnt = 9; + if (markdata->left_mar == 8) + rep_cnt = 1; + else + rep_cnt = 9; /* FALLTHROUGH */ - case 'c': - case 'C': + case 'c': + case 'C': /* set start column (c) and end column (C) */ - if (markdata->second) - { - rem(markdata->x1, markdata->y1, cx, cy, 1, (char *)0, fore->w_height-1); /* Hack */ - markdata->second = 1; /* rem turns off second */ - } - rep_cnt--; - if (rep_cnt < 0) - rep_cnt = cx; - if (od != 'C') - { - markdata->left_mar = rep_cnt; - if (markdata->left_mar > markdata->right_mar) - markdata->left_mar = markdata->right_mar; - } - else - { - markdata->right_mar = rep_cnt; - if (markdata->left_mar > markdata->right_mar) - markdata->right_mar = markdata->left_mar; - } - if (markdata->second) - { - markdata->cx = markdata->x1; markdata->cy = markdata->y1; - revto(cx, cy); - } - if (od == 'v' || od == 'V') - LMsg(0, (markdata->left_mar != 8) ? ":set nonu" : ":set nu"); - break; - case 'J': - /* how do you join lines in VI ? */ - markdata->nonl = (markdata->nonl + 1) % 4; - switch (markdata->nonl) - { - case 0: - if (join_with_cr) - LMsg(0, "Multiple lines (CR/LF)"); - else - LMsg(0, "Multiple lines (LF)"); - break; - case 1: - LMsg(0, "Lines joined"); - break; - case 2: - LMsg(0, "Lines joined with blanks"); - break; - case 3: - LMsg(0, "Lines joined with comma"); - break; - } - break; - case '/': - Search(1); - in_mark = 0; - break; - case '?': - Search(-1); - in_mark = 0; - break; - case 'n': - Search(0); - break; - case 'N': - markdata->isdir = -markdata->isdir; - Search(0); - markdata->isdir = -markdata->isdir; - break; - case 'y': - case 'Y': - if (markdata->second == 0) - { - revto(linestart(cy), cy); - markdata->second++; - cx = markdata->x1 = markdata->cx; - cy = markdata->y1 = markdata->cy; - } - if (--rep_cnt > 0) - revto(cx, cy + rep_cnt); - revto(lineend(markdata->cy), markdata->cy); - if (od == 'y') - break; + if (markdata->second) { + rem(markdata->x1, markdata->y1, cx, cy, 1, (char *)0, fore->w_height - 1); /* Hack */ + markdata->second = 1; /* rem turns off second */ + } + rep_cnt--; + if (rep_cnt < 0) + rep_cnt = cx; + if (od != 'C') { + markdata->left_mar = rep_cnt; + if (markdata->left_mar > markdata->right_mar) + markdata->left_mar = markdata->right_mar; + } else { + markdata->right_mar = rep_cnt; + if (markdata->left_mar > markdata->right_mar) + markdata->right_mar = markdata->left_mar; + } + if (markdata->second) { + markdata->cx = markdata->x1; + markdata->cy = markdata->y1; + revto(cx, cy); + } + if (od == 'v' || od == 'V') + LMsg(0, (markdata->left_mar != 8) ? ":set nonu" : ":set nu"); + break; + case 'J': + /* how do you join lines in VI ? */ + markdata->nonl = (markdata->nonl + 1) % 4; + switch (markdata->nonl) { + case 0: + if (join_with_cr) + LMsg(0, "Multiple lines (CR/LF)"); + else + LMsg(0, "Multiple lines (LF)"); + break; + case 1: + LMsg(0, "Lines joined"); + break; + case 2: + LMsg(0, "Lines joined with blanks"); + break; + case 3: + LMsg(0, "Lines joined with comma"); + break; + } + break; + case '/': + Search(1); + in_mark = 0; + break; + case '?': + Search(-1); + in_mark = 0; + break; + case 'n': + Search(0); + break; + case 'N': + markdata->isdir = -markdata->isdir; + Search(0); + markdata->isdir = -markdata->isdir; + break; + case 'y': + case 'Y': + if (markdata->second == 0) { + revto(linestart(cy), cy); + markdata->second++; + cx = markdata->x1 = markdata->cx; + cy = markdata->y1 = markdata->cy; + } + if (--rep_cnt > 0) + revto(cx, cy + rep_cnt); + revto(lineend(markdata->cy), markdata->cy); + if (od == 'y') + break; /* FALLTHROUGH */ - case 'W': - if (od == 'W') - { - if (rep_cnt == 0) - rep_cnt = 1; - if (!markdata->second) - { - nextword(&cx, &cy, NW_BACK|NW_ENDOFWORD, 1); - revto(cx, cy); - markdata->second++; - cx = markdata->x1 = markdata->cx; - cy = markdata->y1 = markdata->cy; - } - nextword(&cx, &cy, NW_ENDOFWORD, rep_cnt); - revto(cx, cy); - } - cx = markdata->cx; - cy = markdata->cy; + case 'W': + if (od == 'W') { + if (rep_cnt == 0) + rep_cnt = 1; + if (!markdata->second) { + nextword(&cx, &cy, NW_BACK|NW_ENDOFWORD, 1); + revto(cx, cy); + markdata->second++; + cx = markdata->x1 = markdata->cx; + cy = markdata->y1 = markdata->cy; + } + nextword(&cx, &cy, NW_ENDOFWORD, rep_cnt); + revto(cx, cy); + } + cx = markdata->cx; + cy = markdata->cy; /* FALLTHROUGH */ - case 'A': - if (od == 'A') - markdata->append_mode = 1; + case 'A': + if (od == 'A') + markdata->append_mode = 1; /* FALLTHROUGH */ - case '>': - if (od == '>') - markdata->write_buffer = 1; + case '>': + if (od == '>') + markdata->write_buffer = 1; /* FALLTHROUGH */ - case ' ': - case '\r': - if (!markdata->second) - { - markdata->second++; - markdata->x1 = cx; - markdata->y1 = cy; - revto(cx, cy); - LMsg(0, "First mark set - Column %d Line %d", cx+1, W2D(cy)+1); - break; - } - else - { - int append_mode = markdata->append_mode; - int write_buffer = markdata->write_buffer; - - x2 = cx; - y2 = cy; - newcopylen = rem(markdata->x1, markdata->y1, x2, y2, 2, (char *)0, 0); /* count */ - if (md_user->u_plop.buf && !append_mode) - UserFreeCopyBuffer(md_user); - yend = fore->w_height - 1; - if (fore->w_histheight - markdata->hist_offset < fore->w_height) - { - markdata->second = 0; - yend -= MarkScrollUpDisplay(fore->w_histheight - markdata->hist_offset); - } - if (newcopylen > 0) - { + case ' ': + case '\r': + if (!markdata->second) { + markdata->second++; + markdata->x1 = cx; + markdata->y1 = cy; + revto(cx, cy); + LMsg(0, "First mark set - Column %d Line %d", cx + 1, W2D(cy) + 1); + break; + } else { + int append_mode = markdata->append_mode; + int write_buffer = markdata->write_buffer; + + x2 = cx; + y2 = cy; + newcopylen = rem(markdata->x1, markdata->y1, x2, y2, 2, (char *)0, 0); /* count */ + if (md_user->u_plop.buf && !append_mode) + UserFreeCopyBuffer(md_user); + yend = fore->w_height - 1; + if (fore->w_histheight - markdata->hist_offset < fore->w_height) { + markdata->second = 0; + yend -= MarkScrollUpDisplay(fore->w_histheight - markdata->hist_offset); + } + if (newcopylen > 0) { /* the +3 below is for : cr + lf + \0 */ - if (md_user->u_plop.buf) - md_user->u_plop.buf = realloc(md_user->u_plop.buf, - (unsigned) (md_user->u_plop.len + newcopylen + 3)); - else - { - md_user->u_plop.len = 0; - md_user->u_plop.buf = malloc((unsigned) (newcopylen + 3)); - } - if (!md_user->u_plop.buf) - { - MarkAbort(); - in_mark = 0; - LMsg(0, "Not enough memory... Sorry."); - md_user->u_plop.len = 0; - md_user->u_plop.buf = 0; - break; - } - if (append_mode) - { - switch (markdata->nonl) - { + if (md_user->u_plop.buf) + md_user->u_plop.buf = realloc(md_user->u_plop.buf, (unsigned)(md_user->u_plop.len + newcopylen + 3)); + else { + md_user->u_plop.len = 0; + md_user->u_plop.buf = malloc((unsigned)(newcopylen + 3)); + } + if (!md_user->u_plop.buf) { + MarkAbort(); + in_mark = 0; + LMsg(0, "Not enough memory... Sorry."); + md_user->u_plop.len = 0; + md_user->u_plop.buf = 0; + break; + } + if (append_mode) { + switch (markdata->nonl) { /* * this code defines, what glues lines together */ - case 0: - if (join_with_cr) - { - md_user->u_plop.buf[md_user->u_plop.len] = '\r'; - md_user->u_plop.len++; - } - md_user->u_plop.buf[md_user->u_plop.len] = '\n'; - md_user->u_plop.len++; - break; - case 1: - break; - case 2: - md_user->u_plop.buf[md_user->u_plop.len] = ' '; - md_user->u_plop.len++; - break; - case 3: - md_user->u_plop.buf[md_user->u_plop.len] = ','; - md_user->u_plop.len++; - break; - } - } - md_user->u_plop.len += rem(markdata->x1, markdata->y1, x2, y2, - markdata->hist_offset == fore->w_histheight, - md_user->u_plop.buf + md_user->u_plop.len, yend); + case 0: + if (join_with_cr) { + md_user->u_plop.buf[md_user->u_plop.len] = '\r'; + md_user->u_plop.len++; + } + md_user->u_plop.buf[md_user->u_plop.len] = '\n'; + md_user->u_plop.len++; + break; + case 1: + break; + case 2: + md_user->u_plop.buf[md_user->u_plop.len] = ' '; + md_user->u_plop.len++; + break; + case 3: + md_user->u_plop.buf[md_user->u_plop.len] = ','; + md_user->u_plop.len++; + break; + } + } + md_user->u_plop.len += rem(markdata->x1, + markdata->y1, + x2, + y2, + markdata->hist_offset == fore->w_histheight, + md_user->u_plop.buf + md_user->u_plop.len, + yend); #ifdef ENCODINGS - md_user->u_plop.enc = fore->w_encoding; + md_user->u_plop.enc = fore->w_encoding; #endif - } - if (markdata->hist_offset != fore->w_histheight) - { - LAY_CALL_UP(LRefreshAll(flayer, 0)); - } - ExitOverlayPage(); - WindowChanged(fore, 'P'); - if (append_mode) - LMsg(0, "Appended %d characters to buffer", - newcopylen); - else - LMsg(0, "Copied %d characters into buffer", md_user->u_plop.len); - if (write_buffer) - WriteFile(md_user, (char *)0, DUMP_EXCHANGE); - in_mark = 0; - break; - } - - case 0222: - if (flayer->l_mouseevent.start) - { - int button = flayer->l_mouseevent.buffer[0]; - if (button == 'a') - { - /* Scroll down */ - od = 'j'; - } - else if (button == '`') - { - /* Scroll up */ - od = 'k'; - } - else if (button == ' ') - { - /* Left click */ - cx = flayer->l_mouseevent.buffer[1]; - cy = D2W(flayer->l_mouseevent.buffer[2]); - revto(cx, cy); - od = ' '; - } - else - od = 0; - LayProcessMouseSwitch(flayer, 0); - if (od) - goto processchar; - } - else - LayProcessMouseSwitch(flayer, 1); - break; + } + if (markdata->hist_offset != fore->w_histheight) { + LAY_CALL_UP(LRefreshAll(flayer, 0)); + } + ExitOverlayPage(); + WindowChanged(fore, 'P'); + + if (append_mode) + LMsg(0, "Appended %d characters to buffer", newcopylen); + else + LMsg(0, "Copied %d characters into buffer", md_user->u_plop.len); + + if (write_buffer) + WriteFile(md_user, (char *)0, DUMP_EXCHANGE); + in_mark = 0; + break; + } - default: - MarkAbort(); - LMsg(0, "Copy mode aborted"); - in_mark = 0; - break; - } - if (in_mark) /* markdata may be freed */ - markdata->rep_cnt = 0; - } - if (in_mark) - { - flayer->l_x = markdata->cx; - flayer->l_y = W2D(markdata->cy); - } - *inbufp = pt; - *inlenp = inlen; + case 0222: + if (flayer->l_mouseevent.start) { + int button = flayer->l_mouseevent.buffer[0]; + if (button == 'a') { + /* Scroll down */ + od = 'j'; + } else if (button == '`') { + /* Scroll up */ + od = 'k'; + } else if (button == ' ') { + /* Left click */ + cx = flayer->l_mouseevent.buffer[1]; + cy = D2W(flayer->l_mouseevent.buffer[2]); + revto(cx, cy); + od = ' '; + } else + od = 0; + LayProcessMouseSwitch(flayer, 0); + if (od) + goto processchar; + } else + LayProcessMouseSwitch(flayer, 1); + break; + + default: + MarkAbort(); + LMsg(0, "Copy mode aborted"); + in_mark = 0; + break; + } + if (in_mark) /* markdata may be freed */ + markdata->rep_cnt = 0; + } + if (in_mark) { + flayer->l_x = markdata->cx; + flayer->l_y = W2D(markdata->cy); + } + *inbufp = pt; + *inlenp = inlen; } -void revto(tx, ty) -int tx, ty; +void +revto(int tx, int ty) { - revto_line(tx, ty, -1); + revto_line(tx, ty, -1); } /* tx, ty: WINDOW, line: DISPLAY */ -void revto_line(tx, ty, line) -int tx, ty, line; +void +revto_line(int tx, int ty, int line) { - int fx, fy; - int x, y, t, revst, reven, qq, ff, tt, st, en, ce = 0; - int ystart = 0, yend = fore->w_height-1; - int i, ry; - unsigned char *wi; - struct mline *ml; - struct mchar mc; - - if (tx < 0) - tx = 0; - else if (tx > fore->w_width - 1) - tx = fore->w_width -1; - if (ty < fore->w_histheight - fore->w_scrollback_height) - ty = fore->w_histheight - fore->w_scrollback_height; - else if (ty > fore->w_histheight + fore->w_height - 1) - ty = fore->w_histheight + fore->w_height - 1; + int fx, fy; + int x, y, t, revst, reven, qq, ff, tt, st, en, ce = 0; + int ystart = 0, yend = fore->w_height - 1; + int i, ry; + unsigned char *wi; + struct mline *ml; + struct mchar mc; + + if (tx < 0) + tx = 0; + else if (tx > fore->w_width - 1) + tx = fore->w_width - 1; + if (ty < fore->w_histheight - fore->w_scrollback_height) + ty = fore->w_histheight - fore->w_scrollback_height; + else if (ty > fore->w_histheight + fore->w_height - 1) + ty = fore->w_histheight + fore->w_height - 1; - fx = markdata->cx; fy = markdata->cy; + fx = markdata->cx; + fy = markdata->cy; #ifdef DW_CHARS - /* don't just move inside of a kanji, the user wants to see something */ - ml = WIN(ty); - if (ty == fy && fx + 1 == tx && dw_right(ml, tx, fore->w_encoding) && tx < D_width - 1) - tx++; - if (ty == fy && fx - 1 == tx && dw_right(ml, fx, fore->w_encoding) && tx) - tx--; + /* don't just move inside of a kanji, the user wants to see something */ + ml = WIN(ty); + if (ty == fy && fx + 1 == tx && dw_right(ml, tx, fore->w_encoding) && tx < D_width - 1) + tx++; + if (ty == fy && fx - 1 == tx && dw_right(ml, fx, fore->w_encoding) && tx) + tx--; #endif - markdata->cx = tx; markdata->cy = ty; + markdata->cx = tx; + markdata->cy = ty; /* * if we go to a position that is currently offscreen * then scroll the screen */ - i = 0; - if (line >= 0 && line < fore->w_height) - i = W2D(ty) - line; - else if (ty < markdata->hist_offset) - i = ty - markdata->hist_offset; - else if (ty > markdata->hist_offset + (fore->w_height - 1)) - i = ty - markdata->hist_offset - (fore->w_height - 1); - if (i > 0) - yend -= MarkScrollUpDisplay(i); - else if (i < 0) - ystart += MarkScrollDownDisplay(-i); - - if (markdata->second == 0) - { - flayer->l_x = tx; - flayer->l_y = W2D(ty); - LGotoPos(flayer, tx, W2D(ty)); - return; - } - - qq = markdata->x1 + markdata->y1 * fore->w_width; - ff = fx + fy * fore->w_width; /* "from" offset in WIN coords */ - tt = tx + ty * fore->w_width; /* "to" offset in WIN coords*/ - - if (ff > tt) - { - st = tt; en = ff; - x = tx; y = ty; - } - else - { - st = ff; en = tt; - x = fx; y = fy; - } - if (st > qq) - { - st++; - x++; - } - if (en < qq) - en--; - if (tt > qq) - { - revst = qq; reven = tt; - } - else - { - revst = tt; reven = qq; - } - ry = y - markdata->hist_offset; - if (ry < ystart) - { - y += (ystart - ry); - x = 0; - st = y * fore->w_width; - ry = ystart; - } - ml = WIN(y); - for (t = st; t <= en; t++, x++) - { - if (x >= fore->w_width) - { - x = 0; - y++, ry++; - ml = WIN(y); - } - if (ry > yend) - break; - if (t == st || x == 0) - { - wi = ml->image + fore->w_width; - for (ce = fore->w_width; ce >= 0; ce--, wi--) - if (*wi != ' ') - break; + i = 0; + + if (line >= 0 && line < fore->w_height) + i = W2D(ty) - line; + else if (ty < markdata->hist_offset) + i = ty - markdata->hist_offset; + else if (ty > markdata->hist_offset + (fore->w_height - 1)) + i = ty - markdata->hist_offset - (fore->w_height - 1); + + if (i > 0) + yend -= MarkScrollUpDisplay(i); + else if (i < 0) + ystart += MarkScrollDownDisplay(-i); + + if (markdata->second == 0) { + flayer->l_x = tx; + flayer->l_y = W2D(ty); + LGotoPos(flayer, tx, W2D(ty)); + return; + } + + qq = markdata->x1 + markdata->y1 * fore->w_width; + ff = fx + fy * fore->w_width; /* "from" offset in WIN coords */ + tt = tx + ty * fore->w_width; /* "to" offset in WIN coords*/ + + if (ff > tt) { + st = tt; + en = ff; + x = tx; + y = ty; + } else { + st = ff; + en = tt; + x = fx; + y = fy; + } + + if (st > qq) { + st++; + x++; } - if (x <= ce && x >= markdata->left_mar && x <= markdata->right_mar) - { + + if (en < qq) + en--; + + if (tt > qq) { + revst = qq; + reven = tt; + } else { + revst = tt; + reven = qq; + } + ry = y - markdata->hist_offset; + + if (ry < ystart) { + y += (ystart - ry); + x = 0; + st = y * fore->w_width; + ry = ystart; + } + ml = WIN(y); + + for (t = st; t <= en; t++, x++) { + if (x >= fore->w_width) { + x = 0; + y++, ry++; + ml = WIN(y); + } + if (ry > yend) + break; + if (t == st || x == 0) { + wi = ml->image + fore->w_width; + for (ce = fore->w_width; ce >= 0; ce--, wi--) + if (*wi != ' ') + break; + } + + if (x <= ce && x >= markdata->left_mar && x <= markdata->right_mar) { #ifdef DW_CHARS - if (dw_right(ml, x, fore->w_encoding)) - { - if (t == revst) - revst--; - t--; - x--; - } + if (dw_right(ml, x, fore->w_encoding)) { + if (t == revst) + revst--; + t--; + x--; + } #endif - if (t >= revst && t <= reven) - { - mc = mchar_so; + if (t >= revst && t <= reven) { + mc = mchar_so; #ifdef FONT - if (pastefont) - { - mc.font = ml->font[x]; - mc.fontx = ml->fontx[x]; - } + if (pastefont) { + mc.font = ml->font[x]; + mc.fontx = ml->fontx[x]; + } #endif - mc.image = ml->image[x]; - } - else - copy_mline2mchar(&mc, ml, x); + mc.image = ml->image[x]; + } else + copy_mline2mchar(&mc, ml, x); #ifdef DW_CHARS - if (dw_left(ml, x, fore->w_encoding)) - { - mc.mbcs = ml->image[x + 1]; - LPutChar(flayer, &mc, x, W2D(y)); - t++; - } + if (dw_left(ml, x, fore->w_encoding)) { + mc.mbcs = ml->image[x + 1]; + LPutChar(flayer, &mc, x, W2D(y)); + t++; + } #endif - LPutChar(flayer, &mc, x, W2D(y)); + LPutChar(flayer, &mc, x, W2D(y)); #ifdef DW_CHARS - if (dw_left(ml, x, fore->w_encoding)) - x++; + if (dw_left(ml, x, fore->w_encoding)) + x++; #endif + } } - } - flayer->l_x = tx; - flayer->l_y = W2D(ty); - LGotoPos(flayer, tx, W2D(ty)); + flayer->l_x = tx; + flayer->l_y = W2D(ty); + LGotoPos(flayer, tx, W2D(ty)); } static void MarkAbort() { - int yend, redisp; + int yend, redisp; - debug("MarkAbort\n"); - markdata = (struct markdata *)flayer->l_data; - fore = markdata->md_window; - yend = fore->w_height - 1; - redisp = markdata->second; - if (fore->w_histheight - markdata->hist_offset < fore->w_height) - { - markdata->second = 0; - yend -= MarkScrollUpDisplay(fore->w_histheight - markdata->hist_offset); - } - if (markdata->hist_offset != fore->w_histheight) - { - LAY_CALL_UP(LRefreshAll(flayer, 0)); - } - else - { - rem(markdata->x1, markdata->y1, markdata->cx, markdata->cy, redisp, (char *)0, yend); - } - ExitOverlayPage(); - WindowChanged(fore, 'P'); + debug("MarkAbort\n"); + markdata = (struct markdata *)flayer->l_data; + fore = markdata->md_window; + yend = fore->w_height - 1; + redisp = markdata->second; + if (fore->w_histheight - markdata->hist_offset < fore->w_height) { + markdata->second = 0; + yend -= MarkScrollUpDisplay(fore->w_histheight - markdata->hist_offset); + } + if (markdata->hist_offset != fore->w_histheight) { + LAY_CALL_UP(LRefreshAll(flayer, 0)); + } else { + rem(markdata->x1, markdata->y1, markdata->cx, markdata->cy, redisp, (char *)0, yend); + } + ExitOverlayPage(); + WindowChanged(fore, 'P'); } - static void -MarkRedisplayLine(y, xs, xe, isblank) -int y; /* NOTE: y is in DISPLAY coords system! */ -int xs, xe; -int isblank; +MarkRedisplayLine(int y, int xs, int xe, int isblank) /* NOTE: y is in DISPLAY coords system! */ { - int wy, x, i, rm; - int sta, sto, cp; /* NOTE: these 3 are in WINDOW coords system */ - unsigned char *wi; - struct mline *ml; - struct mchar mchar_marked; - - if (y < 0) /* No special full page handling */ - return; - - markdata = (struct markdata *)flayer->l_data; - fore = markdata->md_window; - - mchar_marked = mchar_so; - - wy = D2W(y); - ml = WIN(wy); - - if (markdata->second == 0) - { - if (dw_right(ml, xs, fore->w_encoding) && xs > 0) - xs--; - if (dw_left(ml, xe, fore->w_encoding) && xe < fore->w_width - 1) - xe++; - if (xs == 0 && y > 0 && wy > 0 && WIN(wy - 1)->image[flayer->l_width] == 0) - LCDisplayLineWrap(flayer, ml, y, xs, xe, isblank); - else - LCDisplayLine(flayer, ml, y, xs, xe, isblank); - return; - } - - sta = markdata->y1 * fore->w_width + markdata->x1; - sto = markdata->cy * fore->w_width + markdata->cx; - if (sta > sto) - { - i=sta; sta=sto; sto=i; - } - cp = wy * fore->w_width + xs; - - rm = markdata->right_mar; - for (x = fore->w_width, wi = ml->image + fore->w_width; x >= 0; x--, wi--) - if (*wi != ' ') - break; - if (x < rm) - rm = x; - - for (x = xs; x <= xe; x++, cp++) - if (cp >= sta && x >= markdata->left_mar) - break; + int wy, x, i, rm; + int sta, sto, cp; /* NOTE: these 3 are in WINDOW coords system */ + unsigned char *wi; + struct mline *ml; + struct mchar mchar_marked; + + if (y < 0) /* No special full page handling */ + return; + + markdata = (struct markdata *)flayer->l_data; + fore = markdata->md_window; + + mchar_marked = mchar_so; + + wy = D2W(y); + ml = WIN(wy); + + if (markdata->second == 0) { + if (dw_right(ml, xs, fore->w_encoding) && xs > 0) + xs--; + if (dw_left(ml, xe, fore->w_encoding) && xe < fore->w_width - 1) + xe++; + if (xs == 0 && y > 0 && wy > 0 && WIN(wy - 1)->image[flayer->l_width] == 0) + LCDisplayLineWrap(flayer, ml, y, xs, xe, isblank); + else + LCDisplayLine(flayer, ml, y, xs, xe, isblank); + return; + } + + sta = markdata->y1 * fore->w_width + markdata->x1; + sto = markdata->cy * fore->w_width + markdata->cx; + if (sta > sto) { + i = sta; + sta = sto; + sto = i; + } + cp = wy * fore->w_width + xs; + + rm = markdata->right_mar; + for (x = fore->w_width, wi = ml->image + fore->w_width; x >= 0; x--, wi--) + if (*wi != ' ') + break; + if (x < rm) + rm = x; + + for (x = xs; x <= xe; x++, cp++) + if (cp >= sta && x >= markdata->left_mar) + break; #ifdef DW_CHARS - if (dw_right(ml, x, fore->w_encoding)) - x--; + if (dw_right(ml, x, fore->w_encoding)) + x--; #endif - if (x > xs) - LCDisplayLine(flayer, ml, y, xs, x - 1, isblank); - for (; x <= xe; x++, cp++) - { - if (cp > sto || x > rm) - break; + if (x > xs) + LCDisplayLine(flayer, ml, y, xs, x - 1, isblank); + for (; x <= xe; x++, cp++) { + if (cp > sto || x > rm) + break; #ifdef FONT - if (pastefont) - { - mchar_marked.font = ml->font[x]; - mchar_marked.fontx = ml->fontx[x]; - } + if (pastefont) { + mchar_marked.font = ml->font[x]; + mchar_marked.fontx = ml->fontx[x]; + } #endif - mchar_marked.image = ml->image[x]; + mchar_marked.image = ml->image[x]; #ifdef DW_CHARS - mchar_marked.mbcs = 0; - if (dw_left(ml, x, fore->w_encoding)) - { - mchar_marked.mbcs = ml->image[x + 1]; - cp++; - } + mchar_marked.mbcs = 0; + if (dw_left(ml, x, fore->w_encoding)) { + mchar_marked.mbcs = ml->image[x + 1]; + cp++; + } #endif - LPutChar(flayer, &mchar_marked, x, y); + LPutChar(flayer, &mchar_marked, x, y); #ifdef DW_CHARS - if (dw_left(ml, x, fore->w_encoding)) - x++; + if (dw_left(ml, x, fore->w_encoding)) + x++; #endif - } - if (x <= xe) - LCDisplayLine(flayer, ml, y, x, xe, isblank); + } + if (x <= xe) + LCDisplayLine(flayer, ml, y, x, xe, isblank); } - /* * This ugly routine is to speed up GotoPos() */ static int -MarkRewrite(ry, xs, xe, rend, doit) -int ry, xs, xe, doit; -struct mchar *rend; +MarkRewrite(int ry, int xs, int xe, struct mchar *rend, int doit) { - int dx, x, y, st, en, t, rm; - unsigned char *i; - struct mline *ml; - struct mchar mchar_marked; - - mchar_marked = mchar_so; - - debug3("MarkRewrite %d, %d-%d\n", ry, xs, xe); - markdata = (struct markdata *)flayer->l_data; - fore = markdata->md_window; - y = D2W(ry); - ml = WIN(y); + int dx, x, y, st, en, t, rm; + unsigned char *i; + struct mline *ml; + struct mchar mchar_marked; + + mchar_marked = mchar_so; + + debug3("MarkRewrite %d, %d-%d\n", ry, xs, xe); + markdata = (struct markdata *)flayer->l_data; + fore = markdata->md_window; + y = D2W(ry); + ml = WIN(y); #ifdef UTF8 - if (fore->w_encoding && fore->w_encoding != UTF8 && D_encoding == UTF8 && ContainsSpecialDeffont(ml, xs, xe, fore->w_encoding)) - return EXPENSIVE; + if (fore->w_encoding && fore->w_encoding != UTF8 && D_encoding == UTF8 && ContainsSpecialDeffont(ml, xs, xe, fore->w_encoding)) + return EXPENSIVE; #endif - dx = xe - xs + 1; - if (doit) - { - i = ml->image + xs; - while (dx--) - PUTCHAR(*i++); - return 0; - } - - if (markdata->second == 0) - st = en = -1; - else - { - st = markdata->y1 * fore->w_width + markdata->x1; - en = markdata->cy * fore->w_width + markdata->cx; - if (st > en) - { - t = st; st = en; en = t; - } - } - t = y * fore->w_width + xs; - for (rm = fore->w_width, i = ml->image + fore->w_width; rm >= 0; rm--) - if (*i-- != ' ') - break; - if (rm > markdata->right_mar) - rm = markdata->right_mar; - x = xs; - while (dx--) - { - if (t >= st && t <= en && x >= markdata->left_mar && x <= rm) - { + dx = xe - xs + 1; + if (doit) { + i = ml->image + xs; + while (dx--) + PUTCHAR(*i++); + return 0; + } + + if (markdata->second == 0) + st = en = -1; + else { + st = markdata->y1 * fore->w_width + markdata->x1; + en = markdata->cy * fore->w_width + markdata->cx; + if (st > en) { + t = st; + st = en; + en = t; + } + } + t = y * fore->w_width + xs; + for (rm = fore->w_width, i = ml->image + fore->w_width; rm >= 0; rm--) + if (*i-- != ' ') + break; + if (rm > markdata->right_mar) + rm = markdata->right_mar; + x = xs; + while (dx--) { + if (t >= st && t <= en && x >= markdata->left_mar && x <= rm) { #ifdef FONT - if (pastefont) - { - mchar_marked.font = ml->font[x]; - mchar_marked.fontx = ml->fontx[x]; - } + if (pastefont) { + mchar_marked.font = ml->font[x]; + mchar_marked.fontx = ml->fontx[x]; + } #endif - rend->image = mchar_marked.image; - if (!cmp_mchar(rend, &mchar_marked)) - return EXPENSIVE; - } - else - { - rend->image = ml->image[x]; - if (!cmp_mchar_mline(rend, ml, x)) - return EXPENSIVE; - } - x++; - } - return xe - xs + 1; + rend->image = mchar_marked.image; + if (!cmp_mchar(rend, &mchar_marked)) + return EXPENSIVE; + } else { + rend->image = ml->image[x]; + if (!cmp_mchar_mline(rend, ml, x)) + return EXPENSIVE; + } + x++; + } + return xe - xs + 1; } - /* * scroll the screen contents up/down. */ -static int MarkScrollUpDisplay(n) -int n; +static int +MarkScrollUpDisplay(int n) { - int i; + int i; - debug1("MarkScrollUpDisplay(%d)\n", n); - if (n <= 0) - return 0; - if (n > fore->w_histheight - markdata->hist_offset) - n = fore->w_histheight - markdata->hist_offset; - markdata->hist_offset += n; - i = (n < flayer->l_height) ? n : (flayer->l_height); - LScrollV(flayer, i, 0, flayer->l_height - 1, 0); - while (i-- > 0) - MarkRedisplayLine(flayer->l_height - i - 1, 0, flayer->l_width - 1, 1); - return n; + debug1("MarkScrollUpDisplay(%d)\n", n); + if (n <= 0) + return 0; + if (n > fore->w_histheight - markdata->hist_offset) + n = fore->w_histheight - markdata->hist_offset; + + markdata->hist_offset += n; + i = (n < flayer->l_height) ? n : (flayer->l_height); + LScrollV(flayer, i, 0, flayer->l_height - 1, 0); + while (i-- > 0) + MarkRedisplayLine(flayer->l_height - i - 1, 0, flayer->l_width - 1, 1); + return n; } static int -MarkScrollDownDisplay(n) -int n; +MarkScrollDownDisplay(int n) { - int i; + int i; - debug1("MarkScrollDownDisplay(%d)\n", n); - if (n <= 0) - return 0; - if (n > markdata->hist_offset) - n = markdata->hist_offset; - markdata->hist_offset -= n; - i = (n < flayer->l_height) ? n : (flayer->l_height); - LScrollV(flayer, -i, 0, fore->w_height - 1, 0); - while (i-- > 0) - MarkRedisplayLine(i, 0, flayer->l_width - 1, 1); - return n; + debug1("MarkScrollDownDisplay(%d)\n", n); + if (n <= 0) + return 0; + if (n > markdata->hist_offset) + n = markdata->hist_offset; + markdata->hist_offset -= n; + i = (n < flayer->l_height) ? n : (flayer->l_height); + LScrollV(flayer, -i, 0, fore->w_height - 1, 0); + while (i-- > 0) + MarkRedisplayLine(i, 0, flayer->l_width - 1, 1); + return n; } void -MakePaster(pa, buf, len, bufiscopy) -struct paster *pa; -char *buf; -int len; -int bufiscopy; +MakePaster(struct paster *pa, char *buf, int len, int bufiscopy) { - FreePaster(pa); - pa->pa_pasteptr = buf; - pa->pa_pastelen = len; - if (bufiscopy) - pa->pa_pastebuf = buf; - pa->pa_pastelayer = flayer; - DoProcess(Layer2Window(flayer), &pa->pa_pasteptr, &pa->pa_pastelen, pa); + FreePaster(pa); + pa->pa_pasteptr = buf; + pa->pa_pastelen = len; + if (bufiscopy) + pa->pa_pastebuf = buf; + pa->pa_pastelayer = flayer; + DoProcess(Layer2Window(flayer), &pa->pa_pasteptr, &pa->pa_pastelen, pa); } void -FreePaster(pa) -struct paster *pa; +FreePaster(struct paster *pa) { - if (pa->pa_pastebuf) - free(pa->pa_pastebuf); - pa->pa_pastebuf = 0; - pa->pa_pasteptr = 0; - pa->pa_pastelen = 0; - pa->pa_pastelayer = 0; - evdeq(&pa->pa_slowev); + if (pa->pa_pastebuf) + free(pa->pa_pastebuf); + pa->pa_pastebuf = 0; + pa->pa_pasteptr = 0; + pa->pa_pastelen = 0; + pa->pa_pastelayer = 0; + evdeq(&pa->pa_slowev); } #endif /* COPY_PASTE */ diff -ur screen.orig/misc.c screen/misc.c --- screen.orig/misc.c 2023-06-01 14:58:17.242665034 +0300 +++ screen/misc.c 2022-01-28 17:06:02.690612097 +0300 @@ -378,9 +378,7 @@ f = rl.rlim_max; else #endif /* SVR4 */ -#ifdef _SC_OPEN_MAX - f = sysconf(_SC_OPEN_MAX); -#elif defined(SYSV) && defined(NOFILE) && !defined(ISC) +#if defined(SYSV) && defined(NOFILE) && !defined(ISC) f = NOFILE; while (--f > 2) if (f != except) @@ -437,7 +435,6 @@ return 1; Usersigcld = signal(SIGCHLD, SIG_DFL); debug("UserContext: forking.\n"); - fflush(NULL); switch (UserPID = fork()) { case -1: diff -ur screen.orig/NEWS.3.5 screen/NEWS.3.5 --- screen.orig/NEWS.3.5 2023-06-01 14:58:17.229665004 +0300 +++ screen/NEWS.3.5 2022-01-28 17:06:02.662611403 +0300 @@ -27,7 +27,7 @@ Please run the 'newsyntax' script on your old screenrc files! * Emacs style isearch added to copy mode. Try ^A ESC ^R screen ^R ^R - to locate the last three occurences of the word 'screen' in the + to locate the last three occurrences of the word 'screen' in the history buffer. * New command 'silence'. Alarms the user whenever there was inactivity diff -ur screen.orig/osdef.h.in screen/osdef.h.in --- screen.orig/osdef.h.in 2023-06-01 14:58:17.243665036 +0300 +++ screen/osdef.h.in 2022-01-28 17:06:02.690612097 +0300 @@ -95,6 +95,9 @@ extern int setegid __P((int)); #endif +extern char *crypt __P((char *, char *)); +extern int putenv __P((char *)); + extern int tgetent __P((char *, char *)); extern char *tgetstr __P((char *, char **)); extern int tgetnum __P((char *)); @@ -108,7 +111,7 @@ extern int setpgid __P((int, int)); extern int tcsetpgrp __P((int, int)); #endif -extern int ioctl __P((int, int, char *)); +extern int ioctl __P((int, unsigned long, char *)); extern int kill __P((int, int)); diff -ur screen.orig/osdef.sh screen/osdef.sh --- screen.orig/osdef.sh 2023-06-01 14:58:17.243665036 +0300 +++ screen/osdef.sh 2022-01-28 17:06:02.690612097 +0300 @@ -27,7 +27,6 @@ #ifdef linux #include #include -#include #endif #include #ifndef NOSYSLOG diff -ur screen.orig/os.h screen/os.h --- screen.orig/os.h 2023-06-01 14:58:17.243665036 +0300 +++ screen/os.h 2022-01-28 17:06:02.690612097 +0300 @@ -281,7 +281,7 @@ # ifdef _PATH_UTMP # define UTMPFILE _PATH_UTMP # else -# define UTMPFILE "/var/run/utmp" +# define UTMPFILE "/etc/utmp" # endif /* _PATH_UTMP */ # endif # endif diff -ur screen.orig/patchlevel.h screen/patchlevel.h --- screen.orig/patchlevel.h 2023-06-01 14:58:17.243665036 +0300 +++ screen/patchlevel.h 2022-01-28 17:06:02.690612097 +0300 @@ -532,7 +532,7 @@ #define ORIGIN "GNU" #define REV 4 -#define VERS 8 +#define VERS 9 #define PATCHLEVEL 0 -#define DATE "05-Feb-20" +#define DATE "30-Jan-22" #define STATE "" diff -ur screen.orig/process.c screen/process.c --- screen.orig/process.c 2023-06-01 14:58:17.245665041 +0300 +++ screen/process.c 2022-01-28 17:06:02.694612196 +0300 @@ -2741,7 +2741,7 @@ #ifdef COPY_PASTE case RC_BUFFERFILE: if (*args == 0) - BufferFile = SaveStr(bufferfile); + BufferFile = SaveStr(DEFAULT_BUFFERFILE); else if (ParseSaveStr(act, &BufferFile)) break; if (msgok) @@ -5401,6 +5401,7 @@ static int MoreWindows() { + char *m = "No other window."; if (windows && (fore == 0 || windows->w_next)) return 1; if (fore == 0) @@ -5408,7 +5409,7 @@ Msg(0, "No window available"); return 0; } - Msg(0, "No other window%s.", fore->w_number > 1 ? "s" : ""); + Msg(0, m, fore->w_number); /* other arg for nethack */ return 0; } @@ -6273,8 +6274,7 @@ if (ktab[(int)(unsigned char)*buf].nr != RC_POW_DETACH) { if (display) - if (write(D_userfd, "\007", 1) < 1) - ; + write(D_userfd, "\007", 1); Msg(0, "Detach aborted."); } else diff -ur screen.orig/pty.c screen/pty.c --- screen.orig/pty.c 2023-06-01 14:58:17.245665041 +0300 +++ screen/pty.c 2022-01-28 17:06:02.694612196 +0300 @@ -31,6 +31,10 @@ #include #include +#if defined(__OpenBSD__) +#include /* for openpty() */ +#endif + #include "config.h" #include "screen.h" @@ -77,10 +81,7 @@ extern int eff_uid; /* used for opening a new pty-pair: */ -#ifndef HAVE_GETPT -static char PtyName[32]; -#endif -static char TtyName[32]; +static char PtyName[32], TtyName[32]; #if !(defined(sequent) || defined(_SEQUENT_) || defined(HAVE_SVR4_PTYS)) # ifdef hpux @@ -262,10 +263,10 @@ #endif sigret_t (*sigcld)__P(SIGPROTOARG); + strcpy(PtyName, "/dev/ptmx"); #if defined(HAVE_GETPT) && (defined(linux) || defined(__GLIBC__)) if ((f = getpt()) == -1) #else - strcpy(PtyName, "/dev/ptmx"); if ((f = open(PtyName, O_RDWR | O_NOCTTY)) == -1) #endif return -1; diff -ur screen.orig/resize.c screen/resize.c --- screen.orig/resize.c 2023-06-01 14:58:17.245665041 +0300 +++ screen/resize.c 2022-01-28 17:06:02.694612196 +0300 @@ -683,17 +683,6 @@ he = MAXWIDTH; } - if (wi > 1000) - { - Msg(0, "Window width too large, truncated"); - wi = 1000; - } - if (he > 1000) - { - Msg(0, "Window height too large, truncated"); - he = 1000; - } - if (p->w_width == wi && p->w_height == he && p->w_histheight == hi) { debug("ChangeWindowSize: No change.\n"); diff -ur screen.orig/sched.c screen/sched.c --- screen.orig/sched.c 2023-06-01 14:58:17.245665041 +0300 +++ screen/sched.c 2022-01-28 17:06:02.694612196 +0300 @@ -47,244 +47,226 @@ #endif void -evenq(ev) -struct event *ev; +evenq(struct event *ev) { - struct event *evp, **evpp; - debug3("New event fd %d type %d queued %d\n", ev->fd, ev->type, ev->queued); - if (ev->queued) - return; - evpp = &evs; - if (ev->type == EV_TIMEOUT) - { - calctimeout = 1; - evpp = &tevs; - } - for (; (evp = *evpp); evpp = &evp->next) - if (ev->pri > evp->pri) - break; - ev->next = evp; - *evpp = ev; - ev->queued = 1; + struct event *evp, **evpp; + debug3("New event fd %d type %d queued %d\n", ev -> fd, ev -> type, ev -> queued); + if (ev->queued) + return; + evpp = &evs; + if (ev->type == EV_TIMEOUT) { + calctimeout = 1; + evpp = &tevs; + } + for (; (evp = *evpp); evpp = &evp->next) + if (ev->pri > evp->pri) + break; + ev->next = evp; + *evpp = ev; + ev->queued = 1; } void -evdeq(ev) -struct event *ev; +evdeq(struct event *ev) { - struct event *evp, **evpp; - debug3("Deq event fd %d type %d queued %d\n", ev->fd, ev->type, ev->queued); - if (!ev->queued) - return; - evpp = &evs; - if (ev->type == EV_TIMEOUT) - { - calctimeout = 1; - evpp = &tevs; - } - for (; (evp = *evpp); evpp = &evp->next) - if (evp == ev) - break; - ASSERT(evp); - *evpp = ev->next; - ev->queued = 0; - if (ev == nextev) - nextev = nextev->next; + struct event *evp, **evpp; + debug3("Deq event fd %d type %d queued %d\n", ev -> fd, ev -> type, ev -> queued); + if (!ev->queued) + return; + evpp = &evs; + if (ev->type == EV_TIMEOUT) { + calctimeout = 1; + evpp = &tevs; + } + for (; (evp = *evpp); evpp = &evp->next) + if (evp == ev) + break; + ASSERT(evp); + *evpp = ev->next; + ev->queued = 0; + if (ev == nextev) + nextev = nextev->next; } static struct event * calctimo() { - struct event *ev, *min; - long mins; + struct event *ev, *min; + long mins; - if ((min = tevs) == 0) - return 0; - mins = min->timeout.tv_sec; - for (ev = tevs->next; ev; ev = ev->next) - { - ASSERT(ev->type == EV_TIMEOUT); - if (mins < ev->timeout.tv_sec) - continue; - if (mins > ev->timeout.tv_sec || min->timeout.tv_usec > ev->timeout.tv_usec) - { - min = ev; - mins = ev->timeout.tv_sec; + if ((min = tevs) == 0) + return 0; + mins = min->timeout.tv_sec; + for (ev = tevs->next; ev; ev = ev->next) { + ASSERT(ev->type == EV_TIMEOUT); + if (mins < ev->timeout.tv_sec) + continue; + if (mins > ev->timeout.tv_sec || min->timeout.tv_usec > ev->timeout.tv_usec) { + min = ev; + mins = ev->timeout.tv_sec; + } } - } - return min; + return min; } void sched() { - struct event *ev; - fd_set r, w, *set; - struct event *timeoutev = 0; - struct timeval timeout; - int nsel; - - for (;;) - { - if (calctimeout) - timeoutev = calctimo(); - if (timeoutev) - { - gettimeofday(&timeout, NULL); - /* tp - timeout */ - timeout.tv_sec = timeoutev->timeout.tv_sec - timeout.tv_sec; - timeout.tv_usec = timeoutev->timeout.tv_usec - timeout.tv_usec; - if (timeout.tv_usec < 0) - { - timeout.tv_usec += 1000000; - timeout.tv_sec--; - } - if (timeout.tv_sec < 0) - { - timeout.tv_usec = 0; - timeout.tv_sec = 0; - } - } + struct event *ev; + fd_set r, w, *set; + struct event *timeoutev = 0; + struct timeval timeout; + int nsel; + + for (;;) { + if (calctimeout) + timeoutev = calctimo(); + if (timeoutev) { + gettimeofday(&timeout, NULL); + /* tp - timeout */ + timeout.tv_sec = timeoutev->timeout.tv_sec - timeout.tv_sec; + timeout.tv_usec = timeoutev->timeout.tv_usec - timeout.tv_usec; + + if (timeout.tv_usec < 0) { + timeout.tv_usec += 1000000; + timeout.tv_sec--; + } + if (timeout.tv_sec < 0) { + timeout.tv_usec = 0; + timeout.tv_sec = 0; + } + } #ifdef DEBUG - debug("waiting for events"); - if (timeoutev) - debug2(" timeout %ld secs %ld usecs", timeout.tv_sec, timeout.tv_usec); - debug(":\n"); - for (ev = evs; ev; ev = ev->next) - debug3(" - fd %d type %d pri %d\n", ev->fd, ev->type, ev->pri); - if (tevs) - debug("timed events:\n"); - for (ev = tevs; ev; ev = ev->next) - debug3(" - pri %d sec %ld usec %ld\n", ev->pri, ev->timeout.tv_sec, ev->timeout.tv_usec); -#endif - - FD_ZERO(&r); - FD_ZERO(&w); - for (ev = evs; ev; ev = ev->next) - { - if (ev->condpos && *ev->condpos <= (ev->condneg ? *ev->condneg : 0)) - { - debug2(" - cond ev fd %d type %d failed\n", ev->fd, ev->type); - continue; - } - if (ev->type == EV_READ) - FD_SET(ev->fd, &r); - else if (ev->type == EV_WRITE) - FD_SET(ev->fd, &w); - } + debug("waiting for events"); + if (timeoutev) + debug2(" timeout %d secs %d usecs", timeout.tv_sec, timeout.tv_usec); + debug(":\n"); + for (ev = evs; ev; ev = ev->next) + debug3(" - fd %d type %d pri %d\n", ev->fd, ev->type, ev->pri); + if (tevs) + debug("timed events:\n"); + for (ev = tevs; ev; ev = ev->next) + debug3(" - pri %d sec %d usec %d\n", ev->pri, + ev->timeout.tv_sec, ev->timeout.tv_usec); +#endif + + FD_ZERO(&r); + FD_ZERO(&w); + for (ev = evs; ev; ev = ev->next) { + if (ev->condpos && *ev->condpos <= (ev->condneg ? *ev->condneg : 0)) { + debug2(" - cond ev fd %d type %d failed\n", ev->fd, ev->type); + continue; + } + if (ev->type == EV_READ) + FD_SET(ev->fd, &r); + else if (ev->type == EV_WRITE) + FD_SET(ev->fd, &w); + } #ifdef DEBUG - debug("readfds:"); - for (nsel = 0; nsel < FD_SETSIZE; nsel++) - if (FD_ISSET(nsel, &r)) - debug1(" %d", nsel); - debug("\n"); - debug("writefds:"); - for (nsel = 0; nsel < FD_SETSIZE; nsel++) - if (FD_ISSET(nsel, &w)) - debug1(" %d", nsel); - debug("\n"); -#endif - - nsel = select(FD_SETSIZE, &r, &w, (fd_set *)0, timeoutev ? &timeout : (struct timeval *) 0); - if (nsel < 0) - { - if (errno != EINTR) - { + debug("readfds:"); + for (nsel = 0; nsel < FD_SETSIZE; nsel++) + if (FD_ISSET(nsel, &r)) + debug1(" %d", nsel); + debug("\n"); + debug("writefds:"); + for (nsel = 0; nsel < FD_SETSIZE; nsel++) + if (FD_ISSET(nsel, &w)) + debug1(" %d", nsel); + debug("\n"); +#endif + + nsel = select(FD_SETSIZE, &r, &w, (fd_set *)0, timeoutev ? &timeout : (struct timeval *)0); + if (nsel < 0) { + if (errno != EINTR) { #if defined(sgi) && defined(SVR4) - if (errno == EIO && sgihack()) - continue; + if (errno == EIO && sgihack()) + continue; #endif #if defined(__osf__) || defined(M_UNIX) - /* OSF/1 3.x, SCO bug: EBADF */ - /* OSF/1 4.x bug: EIO */ - if ((errno == EIO || errno == EBADF) && sgihack()) - continue; -#endif - Panic(errno, "select"); - } - nsel = 0; - } - else if (nsel == 0) /* timeout */ - { - debug("TIMEOUT!\n"); - ASSERT(timeoutev); - evdeq(timeoutev); - timeoutev->handler(timeoutev, timeoutev->data); - } + /* OSF/1 3.x, SCO bug: EBADF */ + /* OSF/1 4.x bug: EIO */ + if ((errno == EIO || errno == EBADF) && sgihack()) + continue; +#endif + Panic(errno, "select"); + } + nsel = 0; + } else if (nsel == 0) { /* timeout */ + debug("TIMEOUT!\n"); + ASSERT(timeoutev); + evdeq(timeoutev); + timeoutev->handler(timeoutev, timeoutev->data); + } #ifdef SELECT_BROKEN /* * Sequents select emulation counts a descriptor which is * readable and writeable only as one hit. Waaaaa. */ - if (nsel) - nsel = 2 * FD_SETSIZE; + if (nsel) + nsel = 2 * FD_SETSIZE; #endif - for (ev = evs; ev; ev = nextev) - { - nextev = ev->next; - if (ev->type != EV_ALWAYS) - { - set = ev->type == EV_READ ? &r : &w; - if (nsel == 0 || !FD_ISSET(ev->fd, set)) - continue; - nsel--; - } - if (ev->condpos && *ev->condpos <= (ev->condneg ? *ev->condneg : 0)) - continue; - debug2(" + hit ev fd %d type %d!\n", ev->fd, ev->type); - ev->handler(ev, ev->data); - } - } + for (ev = evs; ev; ev = nextev) { + nextev = ev->next; + if (ev->type != EV_ALWAYS) { + set = ev->type == EV_READ ? &r : &w; + if (nsel == 0 || !FD_ISSET(ev->fd, set)) + continue; + nsel--; + } + if (ev->condpos && + *ev->condpos <= (ev->condneg ? *ev->condneg : 0)) + continue; + debug2(" + hit ev fd %d type %d!\n", ev->fd, ev->type); + ev->handler(ev, ev->data); + } + } } void -SetTimeout(ev, timo) -struct event *ev; -int timo; -{ - ASSERT(ev->type == EV_TIMEOUT); - debug2("event %p new timeout %d ms\n", ev, timo); - gettimeofday(&ev->timeout, NULL); - ev->timeout.tv_sec += timo / 1000; - ev->timeout.tv_usec += (timo % 1000) * 1000; - if (ev->timeout.tv_usec > 1000000) - { - ev->timeout.tv_usec -= 1000000; - ev->timeout.tv_sec++; - } - if (ev->queued) - calctimeout = 1; +SetTimeout(struct event *ev, int timo) +{ + ASSERT(ev->type == EV_TIMEOUT); + debug2("event %x new timeout %d ms\n", ev, timo); + gettimeofday(&ev->timeout, NULL); + ev->timeout.tv_sec += timo / 1000; + ev->timeout.tv_usec += (timo % 1000) * 1000; + + if (ev->timeout.tv_usec > 1000000) { + ev->timeout.tv_usec -= 1000000; + ev->timeout.tv_sec++; + } + if (ev->queued) + calctimeout = 1; } - #if (defined(sgi) && defined(SVR4)) || defined(__osf__) || defined(M_UNIX) - +/* do we still need it? + @anaumov */ extern struct display *display, *displays; -static int sgihack() +static int +sgihack() { - fd_set r, w; - struct timeval tv; + fd_set r, w; + struct timeval tv; - debug("IRIX5.2 workaround: searching for bad display\n"); - for (display = displays; display; ) - { - FD_ZERO(&r); - FD_ZERO(&w); - FD_SET(D_userfd, &r); - FD_SET(D_userfd, &w); - tv.tv_sec = tv.tv_usec = 0; - if (select(FD_SETSIZE, &r, &w, (fd_set *)0, &tv) == -1) - { - if (errno == EINTR) - continue; - Hangup(); /* goodbye display */ - return 1; - } - display = display->d_next; - } - return 0; + debug("IRIX5.2 workaround: searching for bad display\n"); + for (display = displays; display;) { + FD_ZERO(&r); + FD_ZERO(&w); + FD_SET(D_userfd, &r); + FD_SET(D_userfd, &w); + tv.tv_sec = tv.tv_usec = 0; + if (select(FD_SETSIZE, &r, &w, (fd_set *)0, &tv) == -1) { + if (errno == EINTR) + continue; + Hangup(); /* goodbye display */ + return 1; + } + display = display->d_next; + } + return 0; } #endif diff -ur screen.orig/screen.c screen/screen.c --- screen.orig/screen.c 2023-06-01 14:58:17.246665043 +0300 +++ screen/screen.c 2022-01-28 17:06:02.694612196 +0300 @@ -122,7 +122,6 @@ FILE *dfp; #endif -char bufferfile[MAXPATHLEN]; extern char Term[], screenterm[], **environ, Termcap[]; int force_vt = 1; @@ -154,9 +153,7 @@ static void SigChldHandler __P((void)); static sigret_t SigChld __P(SIGPROTOARG); static sigret_t SigInt __P(SIGPROTOARG); -#if 0 static sigret_t CoreDump __P(SIGPROTOARG); -#endif static sigret_t FinitHandler __P(SIGPROTOARG); static void DoWait __P((void)); static void serv_read_fn __P((struct event *, char *)); @@ -239,7 +236,7 @@ char HostName[MAXSTR]; int MasterPid, PanicPid; -int real_uid, real_gid, eff_uid, eff_gid, init_eff_gid; +int real_uid, real_gid, eff_uid, eff_gid; int default_startup; int ZombieKey_destroy, ZombieKey_resurrect, ZombieKey_onerror; char *preselect = NULL; /* only used in Attach() */ @@ -271,7 +268,7 @@ */ #include "extern.h" -const char strnomem[] = "Out of memory."; +char strnomem[] = "Out of memory."; static int InterruptPlease; static int GotSigChld; @@ -470,6 +467,9 @@ timestring = SaveStr("%c:%s %M %d %H%? %l%?"); wlisttit = SaveStr(" Num Name%=Flags"); wliststr = SaveStr("%4n %t%=%f"); +#ifdef COPY_PASTE + BufferFile = SaveStr(DEFAULT_BUFFERFILE); +#endif ShellProg = NULL; #ifdef POW_DETACH PowDetachString = 0; @@ -509,7 +509,7 @@ real_uid = getuid(); real_gid = getgid(); eff_uid = geteuid(); - init_eff_gid = eff_gid = getegid(); + eff_gid = getegid(); logreopen_register(lf_secreopen); @@ -778,6 +778,10 @@ if (--ac == 0) exit_with_usage(myname, "Specify session-name with -S", NULL); SockMatch = *++av; + debug1("SockMatch: '%s'\n", SockMatch); + debug1("SockMatch len: '%d'\n", (int)strlen(SockMatch)); + if (strlen(SockMatch) > 80) + exit_with_usage(myname, "Session-name is too long (max length is 80 symbols)", NULL); } if (!*SockMatch) exit_with_usage(myname, "Empty session-name?", NULL); @@ -806,19 +810,11 @@ break; } -#if 0 - if (eff_uid != real_uid) - { - /* if running with s-bit, we must install a special signal - * handler routine that resets the s-bit, so that we get a - * core file anyway. - */ #ifdef SIGBUS /* OOPS, linux has no bus errors! */ signal(SIGBUS, CoreDump); #endif /* SIGBUS */ signal(SIGSEGV, CoreDump); -#endif #ifdef USE_LOCALE setlocale(LC_ALL, ""); @@ -1042,11 +1038,6 @@ #endif /* DEBUG */ } -#ifdef COPY_PASTE - snprintf(bufferfile, sizeof(bufferfile), "%s/.screen-exchange", home); - BufferFile = SaveStr(bufferfile); -#endif - #ifdef _MODE_T oumask = umask(0); /* well, unsigned never fails? jw. */ #else @@ -1130,6 +1121,7 @@ if (access(SockPath, F_OK)) { if (mkdir(SockPath, 0700) == -1 && errno != EEXIST) Panic(errno, "Cannot make directory '%s'", SockPath); + (void) chown(SockPath, real_uid, real_gid); } } #endif @@ -1203,11 +1195,25 @@ eexit(0); } signal(SIG_BYE, AttacherFinit); /* prevent races */ + if (cmdflag) { + +#ifdef MULTIUSER + if (multi) + real_uid = multi_uid; +#endif + /* attach_tty is not mandatory */ SetTtyname(false, &st); if (!*av) Panic(0, "Please specify a command."); + if (!strncmp("sessionname", *av, 11)) { + if (!*++av) + Panic(0, "Please specify a parameter."); + if (strlen(*av) > 80) + Panic(0, "Parameter of command 'sessionname' is too long."); + *--av; + } SET_GUID(); SendCmdMessage(sty, SockMatch, av, queryflag >= 0); exit(0); @@ -1244,10 +1250,7 @@ nwin_compose(&nwin_default, &nwin_options, &nwin_default); if (!detached || dflag != 2) - { - fflush(NULL); - MasterPid = fork(); - } + MasterPid = fork(); else MasterPid = 0; @@ -1320,40 +1323,14 @@ } else n = -1; - - { - const char devnull[] = "/dev/null"; - int nullfdr, nullfdw; - - if (fflush(NULL)) - Panic(errno, "Cannot flush stdio streams"); - - nullfdr = open(devnull, O_RDONLY|O_NOCTTY|O_NOFOLLOW|O_NONBLOCK); - if (nullfdr < 0) - Panic(errno, "Cannot open '%s' for reading", devnull); - - nullfdw = open(devnull, O_WRONLY|O_NOCTTY|O_NOFOLLOW|O_NONBLOCK); - if (nullfdw < 0) - Panic(errno, "Cannot open '%s' for writing", devnull); - - if (dup2(nullfdr, fileno(stdin)) < 0) - Panic(errno, "Cannot reditect '%s' to '%s'", "stdin", devnull); - - close(nullfdr); - - if (dup2(nullfdw, fileno(stdout)) < 0) - Panic(errno, "Cannot reditect '%s' to '%s'", "stdout", devnull); + freopen("/dev/null", "r", stdin); + freopen("/dev/null", "w", stdout); #ifdef DEBUG if (dfp != stderr) #endif - if (dup2(nullfdw, fileno(stderr)) < 0) - Panic(errno, "Cannot reditect '%s' to '%s'", "stderr", devnull); - - close(nullfdw); - - debug("-- screen.back debug started\n"); - } + freopen("/dev/null", "w", stderr); + debug("-- screen.back debug started\n"); /* This guarantees that the session owner is listed, even when we * start detached. From now on we should not refer to 'LoginName' @@ -1672,7 +1649,6 @@ SIGRETURN; } -#if 0 static sigret_t CoreDump SIGDEFARG { /* if running with s-bit, we must reset the s-bit, so that we get a @@ -1723,7 +1699,6 @@ SIGRETURN; } -#endif static void DoWait() { @@ -1896,7 +1871,7 @@ { if (display == 0) return; - debug1("Hangup %p\n", display); + debug1("Hangup %x\n", display); if (D_userfd >= 0) { close(D_userfd); D_userfd = -1; @@ -2108,29 +2083,20 @@ #endif #define PROCESS_MESSAGE(B) do { \ + char *p = B; \ VA_LIST(ap) \ - ssize_t len; \ - const int errlen = err ? 100 : 0; \ VA_START(ap, fmt); \ fmt = DoNLS(fmt); \ - len = vsnprintf(B, sizeof(B) - errlen, fmt, VA_ARGS(ap)); \ + (void)vsnprintf(p, sizeof(B) - 100, fmt, VA_ARGS(ap)); \ VA_END(ap); \ - if (len < 0) \ - { \ - strncpy(B, fmt, sizeof(B) - errlen); \ - B[sizeof(B) - errlen - 1] = 0; \ - len = strlen(B); \ - } \ if (err) \ - { \ - const char *strerr = strerror(err); \ - if (strerr) \ - { \ - strncat(B, ": ", 2); \ - strncat(B, strerr, errlen - 3); \ - len = strlen(B); \ - } \ - } \ + { \ + p += strlen(p); \ + *p++ = ':'; \ + *p++ = ' '; \ + strncpy(p, strerror(err), B + sizeof(B) - p - 1); \ + B[sizeof(B) - 1] = 0; \ + } \ } while (0) DEFINE_VARARGS_FN(Msg) @@ -2157,12 +2123,7 @@ display = olddisplay; } else - { - ssize_t len = strlen(buf); - if (write(fileno(stderr), buf, len) > 0) - if (write(fileno(stderr), "\r\n", 2) > 0) - ; - } + printf("%s\r\n", buf); if (queryflag >= 0) write(queryflag, buf, strlen(buf)); @@ -2175,15 +2136,12 @@ { char buf[MAXPATHLEN*2]; PROCESS_MESSAGE(buf); - ssize_t len = strlen(buf); - debug3("Panic('%s'); display=%p displays=%p\n", buf, display, displays); + debug3("Panic('%s'); display=%x displays=%x\n", buf, display, displays); if (displays == 0 && display == 0) { - if (write(fileno(stderr), buf, len) > 0) - if (write(fileno(stderr), "\r\n", 2) > 0) - ; - if (PanicPid) - Kill(PanicPid, SIG_BYE); + printf("%s\r\n", buf); + if (PanicPid) + Kill(PanicPid, SIG_BYE); } else if (displays == 0) { /* no displays but a display - must have forked. @@ -2206,9 +2164,8 @@ #endif SetTTY(D_userfd, &D_OldMode); fcntl(D_userfd, F_SETFL, 0); - if (write(D_userfd, buf, len) > 0) - if (write(D_userfd, "\n", 1) > 0) - ; + write(D_userfd, buf, strlen(buf)); + write(D_userfd, "\n", 1); freetty(); if (D_userpid) Kill(D_userpid, SIG_BYE); @@ -2816,6 +2773,18 @@ p += strlen(p) - 1; break; +#ifdef ENCODINGS + case 'e': + *p = 0; + D_encoding = nwin_options.encoding > 0 ? nwin_options.encoding : 0; + if (win && win->w_encoding) { + *p++ = ' '; + strcpy(p, EncodingName(win->w_encoding)); + } + p += strlen(p) - 1; + break; +#endif + case '{': { char rbuf[128]; @@ -3065,7 +3034,7 @@ else now.tv_sec += tick - (now.tv_sec % tick); ev->timeout = now; - debug2("NEW timeout %ld %d\n", ev->timeout.tv_sec, tick); + debug2("NEW timeout %d %d\n", ev->timeout.tv_sec, tick); } return winmsg_buf; } @@ -3193,15 +3162,12 @@ #ifdef PSEUDOS - if (write(W_UWP(fore) ? fore->w_pwin->p_ptyfd : fore->w_ptyfd, &ibuf, 1) == 1) { - debug1("Backend wrote interrupt to %d", fore->w_number); - debug1("%s\n", W_UWP(fore) ? " (pseudowin)" : ""); - } + write(W_UWP(fore) ? fore->w_pwin->p_ptyfd : fore->w_ptyfd, &ibuf, 1); + debug1("Backend wrote interrupt to %d", fore->w_number); + debug1("%s\n", W_UWP(fore) ? " (pseudowin)" : ""); #else - if (write(fore->w_ptyfd, &ibuf, 1) == 1) - debug1("Backend wrote interrupt to %d\n", fore->w_number); - else - debug1("Backend FAILED to write interrupt to %d\n", fore->w_number); + write(fore->w_ptyfd, &ibuf, 1); + debug1("Backend wrote interrupt to %d\n", fore->w_number); #endif } InterruptPlease = 0; diff -ur screen.orig/screen.h screen/screen.h --- screen.orig/screen.h 2023-06-01 14:58:17.246665043 +0300 +++ screen/screen.h 2022-01-28 17:06:02.694612196 +0300 @@ -49,7 +49,6 @@ #include "layer.h" #include "term.h" -extern char bufferfile[MAXPATHLEN]; #ifdef DEBUG # define STATIC /* a function that the debugger should see */ @@ -104,6 +103,11 @@ */ #define MAXHISTHEIGHT 3000 #define DEFAULTHISTHEIGHT 100 +#if defined(NAME_MAX) && NAME_MAX < 16 +# define DEFAULT_BUFFERFILE "/tmp/screen-xchg" +#else +# define DEFAULT_BUFFERFILE "/tmp/screen-exchange" +#endif #if defined(hpux) && !(defined(VSUSP) && defined(VDSUSP) && defined(VWERASE) && defined(VLNEXT)) @@ -275,7 +279,7 @@ #define SILENCE_FOUND 2 /* Window is silent */ #define SILENCE_DONE 3 /* Window is silent and user is notified */ -extern const char strnomem[]; +extern char strnomem[]; /* * line modes used by Input() diff -ur screen.orig/search.c screen/search.c --- screen.orig/search.c 2023-06-01 14:58:17.246665043 +0300 +++ screen/search.c 2022-01-28 17:06:02.694612196 +0300 @@ -46,92 +46,80 @@ * VI style Search */ -static int matchword __P((char *, int, int, int)); -static void searchend __P((char *, int, char *)); -static void backsearchend __P((char *, int, char *)); +static int matchword __P((char*, int, int, int)); +static void searchend __P((char*, int, char *)); +static void backsearchend __P((char*, int, char *)); void -Search(dir) -int dir; +Search(int dir) { - struct markdata *markdata; - if (dir == 0) - { - markdata = (struct markdata *)flayer->l_data; - if (markdata->isdir > 0) - searchend(0, 0, NULL); - else if (markdata->isdir < 0) - backsearchend(0, 0, NULL); - else - LMsg(0, "No previous pattern"); - } - else - Input((dir > 0 ? "/" : "?"), sizeof(markdata->isstr)-1, INP_COOKED, - (dir > 0 ? searchend : backsearchend), NULL, 0); + struct markdata *markdata; + if (dir == 0) { + markdata = (struct markdata *)flayer->l_data; + if (markdata->isdir > 0) + searchend(0, 0, NULL); + else if (markdata->isdir < 0) + backsearchend(0, 0, NULL); + else + LMsg(0, "No previous pattern"); + } else + Input((dir > 0 ? "/" : "?"), sizeof(markdata->isstr) - 1, + INP_COOKED, (dir > 0 ? searchend : backsearchend), NULL, 0); } static void -searchend(buf, len, data) -char *buf; -int len; -char *data; /* dummy */ +searchend(char *buf, int len, char *data) { - int x = 0, sx, ex, y; - struct markdata *markdata; - struct win *p; - - markdata = (struct markdata *)flayer->l_data; - p = markdata->md_window; - markdata->isdir = 1; - if (len) - strcpy(markdata->isstr, buf); - sx = markdata->cx + 1; - ex = flayer->l_width - 1; - for (y = markdata->cy; y < p->w_histheight + flayer->l_height; y++, sx = 0) - { - if ((x = matchword(markdata->isstr, y, sx, ex)) >= 0) - break; - } - if (y >= p->w_histheight + flayer->l_height) - { - LGotoPos(flayer, markdata->cx, W2D(markdata->cy)); - LMsg(0, "Pattern not found"); - } - else - revto(x, y); + int x = 0, sx, ex, y; + struct markdata *markdata; + struct win *p; + + markdata = (struct markdata *)flayer->l_data; + p = markdata->md_window; + markdata->isdir = 1; + if (len) + strcpy(markdata->isstr, buf); + sx = markdata->cx + 1; + ex = flayer->l_width - 1; + for (y = markdata->cy; y < p->w_histheight + flayer->l_height; + y++, sx = 0) { + if ((x = matchword(markdata->isstr, y, sx, ex)) >= 0) + break; + } + if (y >= p->w_histheight + flayer->l_height) { + LGotoPos(flayer, markdata->cx, W2D(markdata->cy)); + LMsg(0, "Pattern not found"); + } else + revto(x, y); } static void -backsearchend(buf, len, data) -char *buf; -int len; -char *data; /* dummy */ +backsearchend(char *buf, int len, char *data) { - int sx, ex, x = -1, y; - struct markdata *markdata; + int sx, ex, x = -1, y; + struct markdata *markdata; - markdata = (struct markdata *)flayer->l_data; - markdata->isdir = -1; - if (len) - strcpy(markdata->isstr, buf); - ex = markdata->cx - 1; - for (y = markdata->cy; y >= 0; y--, ex = flayer->l_width - 1) - { - sx = 0; - while ((sx = matchword(markdata->isstr, y, sx, ex)) >= 0) - x = sx++; - if (x >= 0) - break; - } - if (y < 0) - { - LGotoPos(flayer, markdata->cx, W2D(markdata->cy)); - LMsg(0, "Pattern not found"); - } - else - revto(x, y); -} + markdata = (struct markdata *)flayer->l_data; + markdata->isdir = -1; + + if (len) + strcpy(markdata->isstr, buf); + ex = markdata->cx - 1; + + for (y = markdata->cy; y >= 0; y--, ex = flayer->l_width - 1) { + sx = 0; + while ((sx = matchword(markdata->isstr, y, sx, ex)) >= 0) + x = sx++; + if (x >= 0) + break; + } + if (y < 0) { + LGotoPos(flayer, markdata->cx, W2D(markdata->cy)); + LMsg(0, "Pattern not found"); + } else + revto(x, y); +} /* * Search for a string that matches pattern. The first character of the @@ -141,259 +129,255 @@ * or -1 if there's no match. */ static int -matchword(pattern, y, sx, ex) -char *pattern; -int y, sx, ex; +matchword(char *pattern, int y, int sx, int ex) { - unsigned char *ip, *cp, *pp, *cpe; - int cy; + unsigned char *cp, *pp, *cpe; + int cy; - fore = ((struct markdata *)flayer->l_data)->md_window; + fore = ((struct markdata *)flayer->l_data)->md_window; - for (;sx <= ex; sx++) - { - cy = y; - cp = WIN(cy)->image + sx; - cpe = WIN(cy)->image + flayer->l_width; - pp = (unsigned char *)pattern; - for (;;) - { - if (*cp != *pp) - if (!search_ic || ((*cp ^ *pp) & 0xdf) || (*cp | 0x20) < 'a' || (*cp | 0x20) > 'z') - break; - cp++; - pp++; - if (*pp == 0) - return sx; - if (cp == cpe) { + for (; sx <= ex; sx++) { + cy = y; + cp = WIN(cy)->image + sx; + cpe = WIN(cy)->image + flayer->l_width; + pp = (unsigned char *)pattern; + for (;;) { + if (*cp != *pp) + if (!search_ic || ((*cp ^ *pp) & 0xdf) || + (*cp | 0x20) < 'a' || (*cp | 0x20) > 'z') + break; + cp++; + pp++; + if (*pp == 0) + return sx; + if (cp == cpe) { /* * We have a partial match, but we've hit * the end of this line. Does it wrap onto * the following line? If not, we're done. */ - if (*cp == ' ' || cy >= fore->w_histheight + flayer->l_height - 1) - break; + if (*cp == ' ' || + cy >= + fore->w_histheight + flayer->l_height - 1) + break; /* * This line does wrap, so look on the next * line for the rest of our match. */ - cy++; - cp = WIN(cy)->image; - cpe = WIN(cy)->image + flayer->l_width; + cy++; + cp = WIN(cy)->image; + cpe = WIN(cy)->image + flayer->l_width; + } } } - } - return -1; + return -1; } - /******************************************************************** * Emacs style ISearch */ static char *isprompts[] = { - "I-search backward: ", "failing I-search backward: ", - "I-search: ", "failing I-search: " + "I-search backward: ", "failing I-search backward: ", + "I-search: ", "failing I-search: " }; - -static int is_redo __P((struct markdata *)); -static void is_process __P((char *, int, char *)); -static int is_bm __P((char *, int, int, int, int)); - +static int is_redo __P((struct markdata*)); +static void is_process __P((char*, int, char *)); +static int is_bm __P((char*, int, int, int, int)); static int -is_bm(str, l, p, end, dir) -char *str; -int l, p, end, dir; +is_bm(char *str, int l, int p, int end, int dir) { - int tab[256]; - int i, q; - unsigned char *s, c; - int w = flayer->l_width; + int tab[256]; + int i, q; + unsigned char *s, c; + int w = flayer->l_width; /* *sigh* to make WIN work */ - fore = ((struct markdata *)flayer->l_next->l_data)->md_window; - debug2("is_bm: searching for %s len %d\n", str, l); - debug3("start at %d end %d dir %d\n", p, end, dir); - if (p < 0 || p + l > end) - return -1; - if (l == 0) - return p; - if (dir < 0) - str += l - 1; - for (i = 0; i < 256; i++) - tab[i] = l * dir; - for (i = 0; i < l - 1; i++, str += dir) - { - q = *(unsigned char *)str; - tab[q] = (l - 1 - i) * dir; - if (search_ic && (q | 0x20) >= 'a' && ((q | 0x20) <= 'z')) - tab[q ^ 0x20] = (l - 1 - i) * dir; - } - if (dir > 0) - p += l - 1; - debug1("first char to match: %c\n", *str); - while (p >= 0 && p < end) - { - q = p; - s = (unsigned char *)str; - for (i = 0;;) - { - c = (WIN(q / w))->image[q % w]; - if (i == 0) - p += tab[(int)(unsigned char) c]; - if (c != *s) - if (!search_ic || ((c ^ *s) & 0xdf) || (c | 0x20) < 'a' || (c | 0x20) > 'z') - break; - q -= dir; - s -= dir; - if (++i == l) - return q + (dir > 0 ? 1 : -l); + fore = ((struct markdata *)flayer->l_next->l_data)->md_window; + debug2("is_bm: searching for %s len %d\n", str, l); + debug3("start at %d end %d dir %d\n", p, end, dir); + + if (p < 0 || p + l > end) + return -1; + if (l == 0) + return p; + if (dir < 0) + str += l - 1; + for (i = 0; i < 256; i++) + tab[i] = l * dir; + + for (i = 0; i < l - 1; i++, str += dir) { + q = *(unsigned char *)str; + tab[q] = (l - 1 - i) * dir; + if (search_ic && (q | 0x20) >= 'a' && ((q | 0x20) <= 'z')) + tab[q ^ 0x20] = (l - 1 - i) * dir; } - } - return -1; -} + if (dir > 0) + p += l - 1; + + debug1("first char to match: %c\n", *str); + + while (p >= 0 && p < end) { + q = p; + s = (unsigned char *)str; + for (i = 0;;) { + c = (WIN(q / w))->image[q % w]; + if (i == 0) + p += tab[(int)(unsigned char)c]; + if (c != *s) + if (!search_ic || ((c ^ *s) & 0xdf) || + (c | 0x20) < 'a' || (c | 0x20) > 'z') + break; + q -= dir; + s -= dir; + if (++i == l) + return q + (dir > 0 ? 1 : -l); + } + } + return -1; +} /*ARGSUSED*/ static void -is_process(p, n, data) /* i-search */ -char *p; -int n; -char *data; /* dummy */ +is_process(char *p, int n, char *data) /* i-search */ { - int pos, x, y, dir; - struct markdata *markdata; + int pos, x, y, dir; + struct markdata *markdata; - if (n == 0) - return; - ASSERT(p); - markdata = (struct markdata *)flayer->l_next->l_data; - - pos = markdata->cx + markdata->cy * flayer->l_width; - LGotoPos(flayer, markdata->cx, W2D(markdata->cy)); - - switch (*p) - { - case '\007': /* CTRL-G */ - pos = markdata->isstartpos; + if (n == 0) + return; + ASSERT(p); + markdata = (struct markdata *)flayer->l_next->l_data; + + pos = markdata->cx + markdata->cy * flayer->l_width; + LGotoPos(flayer, markdata->cx, W2D(markdata->cy)); + + switch (*p) { + case '\007': /* CTRL-G */ + pos = markdata->isstartpos; /*FALLTHROUGH*/ - case '\033': /* ESC */ - *p = 0; - break; - case '\013': /* CTRL-K */ - case '\027': /* CTRL-W */ - markdata->isistrl = 1; + case '\033': /* ESC */ + *p = 0; + break; + case '\013': /* CTRL-K */ + case '\027': /* CTRL-W */ + markdata->isistrl = 1; /*FALLTHROUGH*/ - case '\b': - case '\177': - if (markdata->isistrl == 0) - return; - markdata->isistrl--; - pos = is_redo(markdata); - *p = '\b'; - break; - case '\023': /* CTRL-S */ - case '\022': /* CTRL-R */ - if (markdata->isistrl >= (int)sizeof(markdata->isistr)) - return; - dir = (*p == '\023') ? 1 : -1; - pos += dir; - if (markdata->isdir == dir && markdata->isistrl == 0) - { - strcpy(markdata->isistr, markdata->isstr); - markdata->isistrl = markdata->isstrl = strlen(markdata->isstr); - break; + case '\b': + case '\177': + if (markdata->isistrl == 0) + return; + markdata->isistrl--; + pos = is_redo(markdata); + *p = '\b'; + break; + case '\023': /* CTRL-S */ + case '\022': /* CTRL-R */ + if (markdata->isistrl >= (int)sizeof(markdata->isistr)) + return; + dir = (*p == '\023') ? 1 : -1; + pos += dir; + if (markdata->isdir == dir && markdata->isistrl == 0) { + strcpy(markdata->isistr, markdata->isstr); + markdata->isistrl = markdata->isstrl = strlen(markdata->isstr); + break; + } + markdata->isdir = dir; + markdata->isistr[markdata->isistrl++] = *p; + break; + default: + if (*p < ' ' || + markdata->isistrl >= + (int)sizeof(markdata->isistr) || + markdata->isstrl >= (int)sizeof(markdata->isstr) - 1) + return; + markdata->isstr[markdata->isstrl++] = *p; + markdata->isistr[markdata->isistrl++] = *p; + markdata->isstr[markdata->isstrl] = 0; + debug2("New char: %c - left %d\n", *p, + (int)sizeof(markdata->isistr) - markdata->isistrl); } - markdata->isdir = dir; - markdata->isistr[markdata->isistrl++] = *p; - break; - default: - if (*p < ' ' || markdata->isistrl >= (int)sizeof(markdata->isistr) - || markdata->isstrl >= (int)sizeof(markdata->isstr) - 1) - return; - markdata->isstr[markdata->isstrl++] = *p; - markdata->isistr[markdata->isistrl++] = *p; - markdata->isstr[markdata->isstrl] = 0; - debug2("New char: %c - left %d\n", *p, (int)sizeof(markdata->isistr) - markdata->isistrl); - } - if (*p && *p != '\b') - pos = is_bm(markdata->isstr, markdata->isstrl, pos, flayer->l_width * (markdata->md_window->w_histheight + flayer->l_height), markdata->isdir); - if (pos >= 0) - { - x = pos % flayer->l_width; - y = pos / flayer->l_width; - LAY_CALL_UP - ( - LayRedisplayLine(INPUTLINE, 0, flayer->l_width - 1, 0); - revto(x, y); - if (W2D(markdata->cy) == INPUTLINE) - revto_line(markdata->cx, markdata->cy, INPUTLINE > 0 ? INPUTLINE - 1 : 1); - ); - } - if (*p) - inp_setprompt(isprompts[markdata->isdir + (pos < 0) + 1], markdata->isstrl ? markdata->isstr : ""); - flayer->l_x = markdata->cx; - flayer->l_y = W2D(markdata->cy); - LGotoPos(flayer, flayer->l_x, flayer->l_y); - if (!*p) - { + if (*p && *p != '\b') + pos = is_bm(markdata->isstr, markdata->isstrl, pos, + flayer->l_width * + (markdata->md_window->w_histheight + flayer->l_height), + markdata->isdir); + if (pos >= 0) { + x = pos % flayer->l_width; + y = pos / flayer->l_width; + LAY_CALL_UP(LayRedisplayLine(INPUTLINE, 0, flayer -> l_width - 1, + 0) ; revto(x, y) ; if(W2D(markdata -> cy) == INPUTLINE) revto_line(markdata + -> cx, markdata -> cy, INPUTLINE > 0 ? INPUTLINE - 1 : 1) ;); + } + if (*p) + inp_setprompt(isprompts[markdata->isdir + (pos < 0) + 1], + markdata->isstrl ? markdata->isstr : ""); + flayer->l_x = markdata->cx; + flayer->l_y = W2D(markdata->cy); + LGotoPos(flayer, flayer->l_x, flayer->l_y); + if (!*p) { /* we are about to finish, keep cursor position */ - flayer->l_next->l_x = markdata->cx; - flayer->l_next->l_y = W2D(markdata->cy); - } + flayer->l_next->l_x = markdata->cx; + flayer->l_next->l_y = W2D(markdata->cy); + } } static int -is_redo(markdata) -struct markdata *markdata; +is_redo(struct markdata *markdata) { - int i, pos, npos, dir; - char c; + int i, pos, npos, dir; + char c; - npos = pos = markdata->isstartpos; - dir = markdata->isstartdir; - markdata->isstrl = 0; - for (i = 0; i < markdata->isistrl; i++) - { - c = markdata->isistr[i]; - if (c == '\022') /* ^R */ - pos += (dir = -1); - else if (c == '\023') /* ^S */ - pos += (dir = 1); - else - markdata->isstr[markdata->isstrl++] = c; - if (pos >= 0) - { - npos = is_bm(markdata->isstr, markdata->isstrl, pos, flayer->l_width * (markdata->md_window->w_histheight + flayer->l_height), dir); - if (npos >= 0) - pos = npos; + npos = pos = markdata->isstartpos; + dir = markdata->isstartdir; + markdata->isstrl = 0; + + for (i = 0; i < markdata->isistrl; i++) { + c = markdata->isistr[i]; + if (c == '\022') /* ^R */ + pos += (dir = -1); + else if (c == '\023') /* ^S */ + pos += (dir = 1); + else + markdata->isstr[markdata->isstrl++] = c; + if (pos >= 0) { + npos = is_bm(markdata->isstr, markdata->isstrl, pos, + flayer->l_width * + (markdata->md_window->w_histheight + + flayer->l_height), dir); + if (npos >= 0) + pos = npos; + } } - } - markdata->isstr[markdata->isstrl] = 0; - markdata->isdir = dir; - return npos; + markdata->isstr[markdata->isstrl] = 0; + markdata->isdir = dir; + return npos; } void -ISearch(dir) -int dir; +ISearch(int dir) { - struct markdata *markdata; + struct markdata *markdata; - markdata = (struct markdata *)flayer->l_data; - markdata->isdir = markdata->isstartdir = dir; - markdata->isstartpos = markdata->cx + markdata->cy * flayer->l_width; - markdata->isistrl = markdata->isstrl = 0; - if (W2D(markdata->cy) == INPUTLINE) - revto_line(markdata->cx, markdata->cy, INPUTLINE > 0 ? INPUTLINE - 1 : 1); - Input(isprompts[dir + 1], sizeof(markdata->isstr) - 1, INP_RAW, - is_process, NULL, 0); - LGotoPos(flayer, markdata->cx, W2D(markdata->cy)); - flayer->l_x = markdata->cx; - flayer->l_y = W2D(markdata->cy); + markdata = (struct markdata *)flayer->l_data; + markdata->isdir = markdata->isstartdir = dir; + markdata->isstartpos = markdata->cx + markdata->cy * flayer->l_width; + markdata->isistrl = markdata->isstrl = 0; + + if (W2D(markdata->cy) == INPUTLINE) + revto_line(markdata->cx, markdata->cy, + INPUTLINE > 0 ? INPUTLINE - 1 : 1); + + Input(isprompts[dir + 1], sizeof(markdata->isstr) - 1, INP_RAW, + is_process, NULL, 0); + + LGotoPos(flayer, markdata->cx, W2D(markdata->cy)); + flayer->l_x = markdata->cx; + flayer->l_y = W2D(markdata->cy); } #endif /* COPY_PASTE */ diff -ur screen.orig/socket.c screen/socket.c --- screen.orig/socket.c 2023-06-01 14:58:17.247665046 +0300 +++ screen/socket.c 2022-01-28 17:06:02.698612295 +0300 @@ -393,10 +393,11 @@ } if (ndead && !quietflag) { + char *m = "Remove dead screens with 'screen -wipe'."; if (wipeflag) Msg(0, "%d socket%s wiped out.", nwipe, nwipe > 1 ? "s" : ""); else - Msg(0, "Remove dead screen%s with 'screen -wipe'.", ndead > 1 ? "s" : ""); + Msg(0, m, ndead > 1 ? "s" : "", ndead > 1 ? "" : "es"); /* other args for nethack */ } if (firsts != -1) { @@ -462,7 +463,7 @@ # ifdef USE_SETEUID (void) unlink(SockPath); if (mkfifo(SockPath, SOCKMODE) < 0) - Panic(errno, "mkfifo %s failed", SockPath); + Panic(0, "mkfifo %s failed", SockPath); # ifdef BROKEN_PIPE s = open(SockPath, O_RDWR | O_NONBLOCK, 0); # else @@ -753,11 +754,7 @@ m.m_tty[sizeof(m.m_tty) - 1] = 0; m.protocol_revision = MSG_REVISION; debug1("SendErrorMsg(): writing to '%s'\n", SockPath); - if (write(s, &m, sizeof(m)) < sizeof(m)) - { - close(s); - return -1; - } + (void) write(s, (char *) &m, sizeof m); close(s); return 0; } @@ -1879,7 +1876,7 @@ { char *oldrcname = rc_name; rc_name = "-X"; - debug3("Running command on display %p window %p (%d)\n", display, fore, fore ? fore->w_number : -1); + debug3("Running command on display %x window %x (%d)\n", display, fore, fore ? fore->w_number : -1); flayer = fore ? &fore->w_layer : 0; if (fore && fore->w_savelayer && (fore->w_blocked || fore->w_savelayer->l_cvlist == 0)) flayer = fore->w_savelayer; diff -ur screen.orig/teln.c screen/teln.c --- screen.orig/teln.c 2023-06-01 14:58:17.247665046 +0300 +++ screen/teln.c 2022-01-28 17:06:02.698612295 +0300 @@ -280,7 +280,7 @@ break; } if (l) - memmove(p + 1, p, l); + bcopy(p, p + 1, l); if (c == TC_IAC) *p++ = c; else if (c == '\r') @@ -369,7 +369,7 @@ if (free-- > 0) { if (len) - memmove(rp + 1, rp, len); + bcopy(rp, rp + 1, len); rp++; *wp++ = '\r'; } @@ -397,7 +397,7 @@ Msg(0, "Warning: telnet protocol overrun!"); return; } - memcpy(p->w_inbuf + p->w_inlen, str, len); + bcopy(str, p->w_inbuf + p->w_inlen, len); p->w_inlen += len; } diff -ur screen.orig/termcap.c screen/termcap.c --- screen.orig/termcap.c 2023-06-01 14:58:17.247665046 +0300 +++ screen/termcap.c 2022-01-28 17:06:02.698612295 +0300 @@ -1068,7 +1068,7 @@ { if (i >= T_KEYPAD) /* don't put keypad codes in TERMCAP */ continue; /* - makes it too big */ -#if (TERMCAP_BUF < 1024) +#if (TERMCAP_BUFSIZE < 1024) if (i >= T_FEXTRA && i < T_BACKTAB) /* also skip extra vt220 keys */ continue; if (i > T_BACKTAB && i < T_NAVIGATE) /* more vt220 keys */ Только в screen.orig/utf8encodings: a3 diff -ur screen.orig/utmp.c screen/utmp.c --- screen.orig/utmp.c 2023-06-01 14:58:17.252665057 +0300 +++ screen/utmp.c 2022-01-28 17:06:02.698612295 +0300 @@ -505,11 +505,7 @@ slot_t slot; slot = wi->w_slot; -#ifdef GETUTENT - debug1("RemoveUtmp slot=%p\n", slot); -#else debug1("RemoveUtmp slot=%#x\n", slot); -#endif if (!utmpok) return -1; if (slot == (slot_t)0 || slot == (slot_t)-1) @@ -581,11 +577,12 @@ #ifdef HAVE_UTEMPTER if (eff_uid && wi && wi->w_ptyfd != -1) { - utempter_set_helper ("/usr/lib/screen/utempter"); /* %_libexecdir */ + /* sigh, linux hackers made the helper functions void */ if (SLOT_USED(u)) - return utempter_add_record (wi->w_ptyfd, host); + addToUtmp(wi->w_tty, host, wi->w_ptyfd); else - return utempter_remove_record (wi->w_ptyfd); + removeLineFromUtmp(wi->w_tty, wi->w_ptyfd); + return 1; /* pray for success */ } #endif setutent(); diff -ur screen.orig/window.c screen/window.c --- screen.orig/window.c 2023-06-01 14:58:17.252665057 +0300 +++ screen/window.c 2022-01-28 17:06:02.698612295 +0300 @@ -979,10 +979,8 @@ if (wp->w_type == W_TYPE_PTY) { /* pty 4 SALE */ - if (fchown(wp->w_ptyfd, 0, 0) < 0) - ; - if (fchmod(wp->w_ptyfd, 0666) < 0) - ; + (void)chmod(wp->w_tty, 0666); + (void)chown(wp->w_tty, 0, 0); } close(wp->w_ptyfd); wp->w_ptyfd = -1; @@ -1247,7 +1245,8 @@ args = ShellArgs; proc = *args; } - fflush(NULL); + fflush(stdout); + fflush(stderr); switch (pid = fork()) { case -1: @@ -1294,16 +1293,11 @@ #endif if (slave != -1) { - /* preserver slave across closeallfiles(), along with w_ptyfd */ - if (dup2(slave, 0) < 0) - Panic(errno, "ForkWindow dup2"); - if (slave > 0) - close(slave); + close(0); + dup(slave); + close(slave); closeallfiles(win->w_ptyfd); - if (dup2(0, slave) < 0) - Panic(errno, "ForkWindow dup2"); - if (slave > 0) - close(0); + slave = dup(0); } else closeallfiles(win->w_ptyfd); @@ -1320,10 +1314,14 @@ } debug1("=== ForkWindow: pid %d\n", (int)getpid()); #endif + /* Close the three /dev/null descriptors */ + close(0); + close(1); + close(2); + newfd = -1; /* * distribute filedescriptors between the ttys */ - newfd = -1; #ifdef PSEUDOS pat = pwin ? pwin->p_fdpat : ((F_PFRONT<<(F_PSHIFT*2)) | (F_PFRONT<w_ptyfd, i) < 0) - Panic(errno, "Cannot duplicate %s", win->w_tty); + dup(win->w_ptyfd); wfdused = 1; } } @@ -1375,18 +1372,13 @@ # else newfd = open(ttyn, O_RDWR); # endif - if (newfd < 0) + if (newfd != 0) Panic(errno, "Cannot open %s", ttyn); - if (dup2(newfd, 0) < 0) - Panic(errno, "Cannot duplicate %s", ttyn); - if (dup2(newfd, 1) < 0) - Panic(errno, "Cannot duplicate %s", ttyn); - if (dup2(newfd, 2) < 0) - Panic(errno, "Cannot duplicate %s", ttyn); + dup(0); + dup(0); #endif /* PSEUDOS */ - if (win->w_ptyfd > 2) - close(win->w_ptyfd); - if (slave > 2) + close(win->w_ptyfd); + if (slave != -1) close(slave); if (newfd >= 0) { @@ -1432,8 +1424,6 @@ /* Always turn off nonblocking mode */ (void)fcntl(newfd, F_SETFL, 0); } - if (newfd > 2) - close(newfd); #ifndef TIOCSWINSZ sprintf(libuf, "LINES=%d", h); sprintf(cobuf, "COLUMNS=%d", w); @@ -1710,10 +1700,8 @@ } #endif /* should be able to use CloseDevice() here */ - if (fchown(pwin->p_ptyfd, 0, 0) < 0) - ; - if (fchmod(pwin->p_ptyfd, 0666) < 0) - ; + (void)chmod(pwin->p_tty, 0666); + (void)chown(pwin->p_tty, 0, 0); if (pwin->p_ptyfd >= 0) close(pwin->p_ptyfd); evdeq(&pwin->p_readev);