diff options
author | Juan Cespedes <cespedes@debian.org> | 1998-02-22 11:16:46 +0100 |
---|---|---|
committer | Axel Beckert <abe@deuxchevaux.org> | 2011-09-03 14:05:22 +0200 |
commit | b84c852136060bca15274e7e8f66aa1e84a6c566 (patch) | |
tree | 85544acb697b5838f0343a9da973e178ba2f0c4c | |
parent | 46e81bca4286a25df6c3ec39234c7e2392af4ef0 (diff) | |
parent | 14a4b00c9ef680b78469333291270e4c276f100d (diff) | |
download | screen-b84c852136060bca15274e7e8f66aa1e84a6c566.tar.gz |
Imported Debian patch 3.7.4-6debian/3.7.4-6
-rw-r--r-- | acls.c | 610 | ||||
-rw-r--r-- | acls.h | 21 | ||||
-rw-r--r-- | ansi.c | 24 | ||||
-rw-r--r-- | attacher.c | 28 | ||||
-rw-r--r-- | attacher.c. | 820 | ||||
-rw-r--r-- | comm.c | 4 | ||||
-rw-r--r-- | config.h.in | 12 | ||||
-rwxr-xr-x | configure | 69 | ||||
-rw-r--r-- | configure.in | 6 | ||||
-rw-r--r-- | debian/README.terminfo | 5 | ||||
-rw-r--r-- | debian/changelog | 66 | ||||
-rw-r--r-- | debian/control | 6 | ||||
-rw-r--r-- | debian/copyright | 79 | ||||
-rw-r--r-- | debian/files | 1 | ||||
-rw-r--r-- | debian/postinst | 51 | ||||
-rw-r--r-- | debian/postrm | 9 | ||||
-rwxr-xr-x | debian/rules | 148 | ||||
-rw-r--r-- | debian/substvars | 1 | ||||
-rw-r--r-- | display.c | 16 | ||||
-rw-r--r-- | doc/Makefile.in | 2 | ||||
-rw-r--r-- | doc/screen.1 | 5 | ||||
-rw-r--r-- | doc/screen.info-4 | 9 | ||||
-rw-r--r-- | etc/etcscreenrc | 7 | ||||
-rw-r--r-- | etc/screenrc | 12 | ||||
-rw-r--r-- | extern.h | 26 | ||||
-rw-r--r-- | fileio.c | 160 | ||||
-rw-r--r-- | help.c | 22 | ||||
-rw-r--r-- | input.c | 155 | ||||
-rw-r--r-- | kmapdef.c.dist | 20 | ||||
-rw-r--r-- | mark.c | 12 | ||||
-rw-r--r-- | misc.c | 303 | ||||
-rw-r--r-- | os.h | 18 | ||||
-rw-r--r-- | osdef.h.in | 1 | ||||
-rw-r--r-- | patchlevel.h | 18 | ||||
-rw-r--r-- | process.c | 299 | ||||
-rw-r--r-- | screen.c | 111 | ||||
-rw-r--r-- | screen.h | 4 | ||||
-rw-r--r-- | search.c | 26 | ||||
-rw-r--r-- | socket.c | 147 | ||||
-rw-r--r-- | tek.patch | 27 | ||||
-rw-r--r-- | term.c | 22 | ||||
-rw-r--r-- | term.h.dist | 16 | ||||
-rw-r--r-- | termcap.c | 16 | ||||
-rw-r--r-- | terminfo/debian.README | 7 | ||||
-rw-r--r-- | terminfo/screencap | 2 | ||||
-rw-r--r-- | terminfo/screeninfo.src | 6 | ||||
-rw-r--r-- | tty.c.dist | 5 | ||||
-rw-r--r-- | tty.sh | 5 | ||||
-rw-r--r-- | utmp.c | 7 | ||||
-rw-r--r-- | window.c | 64 | ||||
-rw-r--r-- | window.h | 2 |
51 files changed, 2604 insertions, 908 deletions
@@ -36,34 +36,38 @@ RCS_ID("$Id: acls.c,v 1.12 1994/05/31 12:31:21 mlschroe Exp $ FAU") extern struct comm comms[]; extern struct win *windows, *wtab[]; +extern char NullStr[]; extern struct display *display, *displays; struct user *users; #ifdef MULTIUSER +int maxusercount = 0; /* used in process.c: RC_MONITOR, RC_SILENCE */ + /* record given user ids here */ static AclBits userbits; -/* rights a new unknown user will have on windows and cmds */ +/* + * rights a new unknown user will have on windows and cmds. + * These are changed by a "umask ?-..." command: + */ static char default_w_bit[ACL_BITS_PER_WIN] = { - 1, /* EXEC */ - 1, /* WRITE */ - 1 /* READ */ + 0, /* EXEC */ + 0, /* WRITE */ + 0 /* READ */ }; static char default_c_bit[ACL_BITS_PER_CMD] = { - 1 /* EXEC */ + 0 /* EXEC */ }; /* rights of all users per newly created window */ -static AclBits default_w_userbits[ACL_BITS_PER_WIN]; - /* -static AclBits default_c_userbits[ACL_BITS_PER_CMD]; -*/ - -static int maxusercount = 0; + * are now stored per user (umask) + * static AclBits default_w_userbits[ACL_BITS_PER_WIN]; + * static AclBits default_c_userbits[ACL_BITS_PER_CMD]; + */ static int GrowBitfield __P((AclBits *, int, int, int)); @@ -108,30 +112,40 @@ char *name; break; #ifdef MULTIUSER debug3("FindUserPtr %s %sfound, id %d\n", name, (*u)?"":"not ", - (*u)?(*u)->id:-1); -#else + (*u)?(*u)->u_id:-1); +#else /* MULTIUSER */ debug2("FindUserPtr %s %sfound\n", name, (*u)?"":"not "); -#endif +#endif /* MULTIUSER */ return u; } -int DefaultEsc = Ctrl('a'); -int DefaultMetaEsc = 'a'; +int DefaultEsc = -1; /* initialised by screen.c:main() */ +int DefaultMetaEsc = -1; /* - * Add a new user. His password may be NULL or "" if none. - * He has no rights. + * Add a new user. His password may be NULL or "" if none. His name must not + * be "none", as this represents the NULL-pointer when dealing with groups. + * He has default rights, determined by umask. */ int UserAdd(name, pass, up) char *name, *pass; struct user **up; { +#ifdef MULTIUSER + int j; +#endif + if (!up) up = FindUserPtr(name); if (*up) - return 1; /* he is already there */ - *up = (struct user *)calloc(1, sizeof(struct user)); + { + if (pass) + (*up)->u_password = SaveStr(pass); + return 1; /* he is already there */ + } + if (strcmp("none", name)) /* "none" is a reserved word */ + *up = (struct user *)calloc(1, sizeof(struct user)); if (!*up) return -1; /* he still does not exist */ #ifdef COPY_PASTE @@ -141,19 +155,24 @@ struct user **up; (*up)->u_Esc = DefaultEsc; (*up)->u_MetaEsc = DefaultMetaEsc; strncpy((*up)->u_name, name, 20); + (*up)->u_password = NULL; if (pass) - strncpy((*up)->u_password, pass, 20); + (*up)->u_password = SaveStr(pass); + if (!(*up)->u_password) + (*up)->u_password = NullStr; #ifdef MULTIUSER + (*up)->u_group = NULL; /* now find an unused index */ - for ((*up)->id = 0; (*up)->id < maxusercount; (*up)->id++) - if (!(ACLBIT((*up)->id) & ACLBYTE(userbits, (*up)->id))) + for ((*up)->u_id = 0; (*up)->u_id < maxusercount; (*up)->u_id++) + if (!(ACLBIT((*up)->u_id) & ACLBYTE(userbits, (*up)->u_id))) break; - debug2("UserAdd %s id %d\n", name, (*up)->id); - if ((*up)->id == maxusercount) + debug2("UserAdd %s id %d\n", name, (*up)->u_id); + if ((*up)->u_id == maxusercount) { - int i, j; + int j; struct win *w; + struct user *u; debug2("growing all bitfields %d += %d\n", maxusercount, USER_CHUNK); /* the bitfields are full, grow a chunk */ @@ -173,55 +192,89 @@ struct user **up; } */ /* third, the bits for each commands */ - for (i = 0; i <= RC_LAST; i++) - for (j = 0; j < ACL_BITS_PER_CMD; j++) - if (GrowBitfield(&comms[i].userbits[j], maxusercount, USER_CHUNK, - default_c_bit[j])) + for (j = 0; j <= RC_LAST; j++) + { + int i; + + for (i = 0; i < ACL_BITS_PER_CMD; i++) + if (GrowBitfield(&comms[j].userbits[i], maxusercount, USER_CHUNK, + default_c_bit[i])) + { + free((char *)*up); *up = NULL; return -1; + } + } + /* fourth, default window creation bits per user */ + for (u = users; u != *up; u = u->u_next) + { + for (j = 0; j < ACL_BITS_PER_WIN; j++) { - free((char *)*up); *up = NULL; return -1; + if (GrowBitfield(&u->u_umask_w_bits[j], maxusercount, USER_CHUNK, + default_w_bit[j])) + { + free((char *)*up); *up = NULL; return -1; + } } - /* fourth, default window and bits */ - for (j = 0; j < ACL_BITS_PER_WIN; j++) - if (GrowBitfield(&default_w_userbits[j], maxusercount, USER_CHUNK, - default_w_bit[j])) - { - free((char *)*up); *up = NULL; return -1; - } + } + /* fifth, the bits for each window */ + /* keep these in sync with NewWindowAcl() */ for (w = windows; w; w = w->w_next) - for (j = 0; j < ACL_BITS_PER_WIN; j++) - if (GrowBitfield(&w->w_userbits[j], maxusercount, USER_CHUNK, - default_w_bit[j])) - { - free((char *)*up); *up = NULL; return -1; + { + /* five a: the access control list */ + for (j = 0; j < ACL_BITS_PER_WIN; j++) + if (GrowBitfield(&w->w_userbits[j], maxusercount, USER_CHUNK, + default_w_bit[j])) + { + free((char *)*up); *up = NULL; return -1; + } + /* five b: the activity notify list */ + /* five c: the silence notify list */ + if (GrowBitfield(&w->w_mon_notify, maxusercount, USER_CHUNK, 0) || + GrowBitfield(&w->w_lio_notify, maxusercount, USER_CHUNK, 0)) + { + free((char *)*up); *up = NULL; return -1; } + } maxusercount += USER_CHUNK; } - ACLBYTE(userbits, (*up)->id) |= ACLBIT((*up)->id); + + /* mark the user-entry as "in-use" */ + ACLBYTE(userbits, (*up)->u_id) |= ACLBIT((*up)->u_id); + /* user id 0 is the session creator, he has all rights */ - if ((*up)->id == 0) - AclSetPerm(*up, "+rwx", "#?"); + if ((*up)->u_id == 0) + AclSetPerm(NULL, *up, "+a", "#?"); + + /* user nobody has a fixed set of rights: */ + if (!strcmp((*up)->u_name, "nobody")) + { + AclSetPerm(NULL, *up, "-rwx", "#?"); + AclSetPerm(NULL, *up, "+x", "su"); + AclSetPerm(NULL, *up, "+x", "detach"); + AclSetPerm(NULL, *up, "+x", "displays"); + AclSetPerm(NULL, *up, "+x", "version"); + } + + /* + * Create his umask: + * Give default_w_bit's for all users, + * but allow himself everything on "his" windows. + */ + for (j = 0; j < ACL_BITS_PER_WIN; j++) + { + if (GrowBitfield(&(*up)->u_umask_w_bits[j], 0, maxusercount, + default_w_bit[j])) + { + free((char *)*up); *up = NULL; return -1; + } + ACLBYTE((*up)->u_umask_w_bits[j], (*up)->u_id) |= ACLBIT((*up)->u_id); + } #else /* MULTIUSER */ debug1("UserAdd %s\n", name); #endif /* MULTIUSER */ return 0; } -/* change user's password */ -int -UserSetPass(name, pass, up) -char *name, *pass; -struct user **up; -{ - if (!up) - up = FindUserPtr(name); - if (!*up) - return UserAdd(name, pass, up); - strncpy((*up)->u_password, pass ? pass : "", 20); - (*up)->u_password[20] = '\0'; - return 0; -} - /* * Remove a user from the list. * Destroy all his permissions and completely detach him from the session. @@ -232,37 +285,66 @@ char *name; struct user **up; { struct user *u; +#ifdef MULTIUSER + int i; +#endif struct display *old, *next; if (!up) up = FindUserPtr(name); - if ((u = *up) == 0) + if (!(u = *up)) return -1; /* he who does not exist cannot be removed */ old = display; for (display = displays; display; display = next) { - next = display->d_next; + next = display->d_next; /* read the next ptr now, Detach may zap it. */ if (D_user != u) continue; if (display == old) - old = 0; + old = NULL; Detach(D_REMOTE); } display = old; *up = u->u_next; + #ifdef MULTIUSER - ACLBYTE(userbits, u->id) &= ~ACLBIT(u->id); + for (up = &users; *up; up = &(*up)->u_next) + { + /* unlink all group references to this user */ + struct usergroup **g = &(*up)->u_group; + + while (*g) + { + if ((*g)->u == u) + { + struct usergroup *next = (*g)->next; + + free((char *)(*g)); + *g = next; + } + else + g = &(*g)->next; + } + } + ACLBYTE(userbits, u->u_id) &= ~ACLBIT(u->u_id); /* restore the bits in his slot to default: */ - AclSetPerm(u, default_w_bit[ACL_READ] ? "+r" : "-r", "#"); - AclSetPerm(u, default_w_bit[ACL_WRITE]? "+w" : "-w", "#"); - AclSetPerm(u, default_w_bit[ACL_EXEC] ? "+x" : "-x", "#"); - AclSetPerm(u, default_c_bit[ACL_EXEC] ? "+x" : "-x", "?"); -#endif + AclSetPerm(NULL, u, default_w_bit[ACL_READ] ? "+r" : "-r", "#"); + AclSetPerm(NULL, u, default_w_bit[ACL_WRITE]? "+w" : "-w", "#"); + AclSetPerm(NULL, u, default_w_bit[ACL_EXEC] ? "+x" : "-x", "#"); + AclSetPerm(NULL, u, default_c_bit[ACL_EXEC] ? "+x" : "-x", "?"); + for (i = 0; i < ACL_BITS_PER_WIN; i++) + free((char *)u->u_umask_w_bits[i]); +#endif /* MULTIUSER */ debug1("FREEING user structure for %s\n", u->u_name); #ifdef COPY_PASTE UserFreeCopyBuffer(u); #endif free((char *)u); + if (!users) + { + debug("Last user deleted. Feierabend.\n"); + Finit(0); /* Destroying whole session. Noone could ever attach again. */ + } return 0; } @@ -287,18 +369,17 @@ struct user *u; w->w_pasteptr - u->u_copybuffer < u->u_copylen) { if (w->w_pastebuf) - free(w->w_pastebuf); + free((char *)w->w_pastebuf); w->w_pastebuf = 0; w->w_pasteptr = 0; w->w_pastelen = 0; } } - free(u->u_copybuffer); - D_user->u_copylen = 0; + free((char *)u->u_copybuffer); + u->u_copylen = 0; u->u_copybuffer = NULL; return 0; } - #endif /* COPY_PASTE */ /************************************************************************ @@ -308,16 +389,21 @@ struct user *u; #ifdef MULTIUSER -extern char *multi; /* username */ - -/* This gives the users default rights to the new window */ +/* This gives the users default rights to the new window w created by u */ int -NewWindowAcl(w) +NewWindowAcl(w, u) struct win *w; +struct user *u; { int i, j; - debug1("NewWindowAcl default_w_userbits for window %d\n", w->w_number); + debug2("NewWindowAcl %s's umask_w_bits for window %d\n", + u ? u->u_name : "everybody", w->w_number); + + /* keep these in sync with UserAdd part five. */ + if (GrowBitfield(&w->w_mon_notify, 0, maxusercount, 0) || + GrowBitfield(&w->w_lio_notify, 0, maxusercount, 0)) + return -1; for (j = 0; j < ACL_BITS_PER_WIN; j++) { /* we start with len 0 for the new bitfield size and add maxusercount */ @@ -328,27 +414,30 @@ struct win *w; return -1; } for (i = 0; i < maxusercount; i++) - if (ACLBIT(i) & ACLBYTE(default_w_userbits[j], i)) + if (u ? (ACLBIT(i) & ACLBYTE(u->u_umask_w_bits[j], i)) : + default_w_bit[j]) ACLBYTE(w->w_userbits[j], i) |= ACLBIT(i); } return 0; } /* if mode starts with '-' we remove the users exec bit for cmd */ -int +/* + * NOTE: before you make this function look the same as + * AclSetPermWin, try to merge both functions. + */ +static int AclSetPermCmd(u, mode, cmd) struct user *u; char *mode; struct comm *cmd; { int neg = 0; + char *m = mode; - if (!multi) - return 0; - debug3("AclSetPermCmd %s %s %s\n", u->u_name, mode, cmd->name); - while (*mode) + while (*m) { - switch (*mode++) + switch (*m++) { case '-': neg = 1; @@ -356,12 +445,14 @@ struct comm *cmd; case '+': neg = 0; continue; + case 'a': case 'e': case 'x': +/* debug3("AclSetPermCmd %s %s %s\n", u->u_name, mode, cmd->name); */ if (neg) - ACLBYTE(cmd->userbits[ACL_EXEC], u->id) &= ~ACLBIT(u->id); + ACLBYTE(cmd->userbits[ACL_EXEC], u->u_id) &= ~ACLBIT(u->u_id); else - ACLBYTE(cmd->userbits[ACL_EXEC], u->id) |= ACLBIT(u->id); + ACLBYTE(cmd->userbits[ACL_EXEC], u->u_id) |= ACLBIT(u->u_id); break; case 'r': case 'w': @@ -377,22 +468,35 @@ struct comm *cmd; /* * aclchg nerd -w+w 2 * releases a writelock on window 2 held by user nerd. + * Letter n allows network access on a window. + * uu should be NULL, except if you want to change his umask. */ -int -AclSetPermWin(u, mode, win) -struct user *u; +static int +AclSetPermWin(uu, u, mode, win) +struct user *u, *uu; char *mode; struct win *win; { int neg = 0; - int bit; + int bit, bits; + AclBits *bitarray; + char *m = mode; + + if (uu) + { + debug3("AclSetPermWin %s UMASK %s %s\n", uu->u_name, u->u_name, mode); + bitarray = uu->u_umask_w_bits; + } + else + { + ASSERT(win); + bitarray = win->w_userbits; + debug3("AclSetPermWin %s %s %d\n", u->u_name, mode, win->w_number); + } - if (!multi) - return 0; - debug3("AclSetPermWin %s %s %d\n", u->u_name, mode, win->w_number); - while (*mode) + while (*m) { - switch (*mode++) + switch (*m++) { case '-': neg = 1; @@ -401,67 +505,114 @@ struct win *win; neg = 0; continue; case 'r': - bit = ACL_READ; + bits = (1 << ACL_READ); break; case 'w': - bit = ACL_WRITE; + bits = (1 << ACL_WRITE); break; case 'x': - bit = ACL_EXEC; + bits = (1 << ACL_EXEC); + break; + case 'a': + bits = (1 << ACL_BITS_PER_WIN) - 1; break; default: return -1; } - if (neg) - ACLBYTE(win->w_userbits[bit], u->id) &= ~ACLBIT(u->id); - else - ACLBYTE(win->w_userbits[bit], u->id) |= ACLBIT(u->id); - if ((win->w_wlockuser == u) && neg && (bit == ACL_WRITE)) + for (bit = 0; bit < ACL_BITS_PER_WIN; bit++) + { + if (!(bits & (1 << bit))) + continue; + if (neg) + ACLBYTE(bitarray[bit], u->u_id) &= ~ACLBIT(u->u_id); + else + ACLBYTE(bitarray[bit], u->u_id) |= ACLBIT(u->u_id); + if (!uu && (win->w_wlockuser == u) && neg && (bit == ACL_WRITE)) + { + debug2("%s lost writelock on win %d\n", u->u_name, win->w_number); + win->w_wlockuser = NULL; + if (win->w_wlock == WLOCK_ON) + win->w_wlock = WLOCK_AUTO; + } + } + } + if (uu && u->u_name[0] == '?' && u->u_name[1] == '\0') + { + /* + * It is Mr. '?', the unknown user. He deserves special treatment as + * he defines the defaults. Sorry, this is global, not per user. + */ + if (win) { - debug2("%s lost writelock on win %d\n", u->u_name, win->w_number); - win->w_wlockuser = NULL; - if (win->w_wlock == WLOCK_ON) - win->w_wlock = WLOCK_AUTO; - } + debug1("AclSetPermWin: default_w_bits '%s'.\n", mode); + for (bit = 0; bit < ACL_BITS_PER_WIN; bit++) + default_w_bit[bit] = + (ACLBYTE(bitarray[bit], u->u_id) & ACLBIT(u->u_id)) ? 1 : 0; + } + else + { + /* + * Hack. I do not want to duplicate all the above code for + * AclSetPermCmd. This asumes that there are not more bits + * per cmd than per win. + */ + debug1("AclSetPermWin: default_c_bits '%s'.\n", mode); + for (bit = 0; bit < ACL_BITS_PER_CMD; bit++) + default_c_bit[bit] = + (ACLBYTE(bitarray[bit], u->u_id) & ACLBIT(u->u_id)) ? 1 : 0; + } + UserDel(u->u_name, NULL); } return 0; } -/* string is broken down into comand and window names, mode applies */ +/* + * String is broken down into comand and window names, mode applies + * A command name matches first, so do not use these as window names. + * uu should be NULL, except if you want to change his umask. + */ int -AclSetPerm(u, mode, s) -struct user *u; +AclSetPerm(uu, u, mode, s) +struct user *uu, *u; char *mode, *s; { struct win *w; int i; char *p, ch; + debug3("AclSetPerm(uu, user '%s', mode '%s', object '%s')\n", + u->u_name, mode, s); while (*s) { switch (*s) { - case '*': /* all windows and all commands */ - return AclSetPerm(u, mode, "#?"); - case '#': /* all windows */ - for (w = windows; w; w = w->w_next) - AclSetPermWin(u, mode, w); + case '*': /* all windows and all commands */ + return AclSetPerm(uu, u, mode, "#?"); + case '#': + if (uu) /* window umask or .. */ + AclSetPermWin(uu, u, mode, (struct win *)1); + else /* .. or all windows */ + for (w = windows; w; w = w->w_next) + AclSetPermWin(NULL, u, mode, w); s++; break; - case '?': /* all commands */ - for (i = 0; i <= RC_LAST; i++) - AclSetPermCmd(u, mode, &comms[i]); + case '?': + if (uu) /* command umask or .. */ + AclSetPermWin(uu, u, mode, (struct win *)0); + else /* .. or all commands */ + for (i = 0; i <= RC_LAST; i++) + AclSetPermCmd(u, mode, &comms[i]); s++; break; default: for (p = s; *p && *p != ' ' && *p != '\t' && *p != ','; p++) ; - if ((ch = *p) != 0) + if ((ch = *p)) *p++ = '\0'; if ((i = FindCommnr(s)) != RC_ILLEGAL) AclSetPermCmd(u, mode, &comms[i]); else if (((i = WindowByNoN(s)) >= 0) && wtab[i]) - AclSetPermWin(u, mode, wtab[i]); + AclSetPermWin(NULL, u, mode, wtab[i]); else /* checking group name */ return -1; @@ -473,6 +624,156 @@ char *mode, *s; return 0; } +/* + * Generic ACL Manager: + * + * This handles acladd and aclchg identical. + * With 2 or 4 parameters, the second parameter is a password. + * With 3 or 4 parameters the last two parameters specify the permissions + * else user is added with full permissions. + * With 1 parameter the users permissions are copied from user *argv. + * Unlike the other cases, u->u_name should not match *argv here. + * uu should be NULL, except if you want to change his umask. + */ +static int +UserAcl(uu, u, argc, argv) +struct user *uu, **u; +int argc; +char **argv; +{ + if ((*u && !strcmp((*u)->u_name, "nobody")) || + (argc > 1 && !strcmp(argv[0], "nobody"))) + return -1; /* do not change nobody! */ + + switch (argc) + { + case 1+1+2: + debug2("UserAcl: user '%s', password '%s':", argv[0], argv[1]); + return (UserAdd(argv[0], argv[1], u) < 0) || + AclSetPerm(uu, *u, argv[2], argv[3]); + case 1+2: + debug1("UserAcl: user '%s', no password:", argv[0]); + return (UserAdd(argv[0], NULL, u) < 0) || + AclSetPerm(uu, *u, argv[1], argv[2]); + case 1+1: + debug2("UserAcl: user '%s', password '%s'\n", argv[0], argv[1]); + return UserAdd(argv[0], argv[1], u) < 0; + case 1: + debug1("UserAcl: user '%s', no password:", argv[0]); + return (UserAdd(argv[0], NULL, u) < 0) || + AclSetPerm(uu, *u, "+a", "#?"); + default: + return -1; + } +} + +static int +UserAclCopy(to_up, from_up) +struct user **to_up, **from_up; +{ + struct win *w; + int i, j, to_id, from_id; + + if (!*to_up || !*from_up) + return -1; + debug2("UserAclCopy: from user '%s' to user '%s'\n", + (*from_up)->u_name, (*to_up)->u_name); + if ((to_id = (*to_up)->u_id) == (from_id = (*from_up)->u_id)) + return -1; + for (w = windows; w; w = w->w_next) + { + for (i = 0; i < ACL_BITS_PER_WIN; i++) + { + if (ACLBYTE(w->w_userbits[i], from_id) & ACLBIT(from_id)) + ACLBYTE(w->w_userbits[i], to_id) |= ACLBIT(to_id); + else + { + ACLBYTE(w->w_userbits[i], to_id) &= ~ACLBIT(to_id); + if ((w->w_wlockuser == *to_up) && (i == ACL_WRITE)) + { + debug2("%s lost wlock on win %d\n", + (*to_up)->u_name, w->w_number); + w->w_wlockuser = NULL; + if (w->w_wlock == WLOCK_ON) + w->w_wlock = WLOCK_AUTO; + } + } + } + } + for (j = 0; j <= RC_LAST; j++) + { + for (i = 0; i < ACL_BITS_PER_CMD; i++) + { + if (ACLBYTE(comms[j].userbits[i], from_id) & ACLBIT(from_id)) + ACLBYTE(comms[j].userbits[i], to_id) |= ACLBIT(to_id); + else + ACLBYTE(comms[j].userbits[i], to_id) &= ~ACLBIT(to_id); + } + } + + return 0; +} + +/* + * Syntax: + * user [password] [+rwx #?] + * * [password] [+rwx #?] + * user1,user2,user3 [password] [+rwx #?] + * user1,user2,user3=user + * uu should be NULL, except if you want to change his umask. + */ +int +UsersAcl(uu, argc, argv) +struct user *uu; +int argc; +char **argv; +{ + char *s; + int r; + struct user **cf_u = NULL; + + if (argc == 1) + { + char *p = NULL; + + s = argv[0]; + while (*s) + if (*s++ == '=') p = s; + if (p) + { + p[-1] = '\0'; + cf_u = FindUserPtr(p); + } + } + + if (argv[0][0] == '*' && argv[0][1] == '\0') + { + struct user **u; + + debug("all users acls.\n"); + for (u = &users; *u; u = &(*u)->u_next) + if (strcmp("nobody", (*u)->u_name) && + ((cf_u) ? + ((r = UserAclCopy(u, cf_u)) < 0) : + ((r = UserAcl(uu, u, argc, argv)) < 0))) + return -1; + return 0; + } + + do + { + for (s = argv[0]; *s && *s!=' ' && *s!='\t' && *s!=',' && *s!='='; s++) + ; + *s ? (*s++ = '\0') : (*s = '\0'); + debug2("UsersAcl(uu, \"%s\", argc=%d)\n", argv[0], argc); + if ((cf_u) ? + ((r = UserAclCopy(FindUserPtr(argv[0]), cf_u)) < 0) : + ((r = UserAcl(uu, FindUserPtr(argv[0]), argc, argv)) < 0)) + return -1; + } while (*(argv[0] = s)); + return 0; +} + #if 0 void AclWinSwap(a, b) @@ -512,19 +813,44 @@ int a, b; } #endif +struct user *EffectiveAclUser = NULL; /* hook for AT command permission */ + int AclCheckPermWin(u, mode, w) struct user *u; int mode; struct win *w; { - if (!multi) - return 0; + int ok; + if (mode < 0 || mode >= ACL_BITS_PER_WIN) return -1; + if (EffectiveAclUser) + { + debug1("AclCheckPermWin: WARNING user %s overridden!\n", u->u_name); + u = EffectiveAclUser; + } + ok = ACLBYTE(w->w_userbits[mode], u->u_id) & ACLBIT(u->u_id); debug3("AclCheckPermWin(%s, %d, %d) = ", u->u_name, mode, w->w_number); - debug1("%d\n", !(ACLBYTE(w->w_userbits[mode], u->id) & ACLBIT(u->id))); - return !(ACLBYTE(w->w_userbits[mode], u->id) & ACLBIT(u->id)); + + if (!ok) + { + struct usergroup **g = &u->u_group; + struct user *saved_eff = EffectiveAclUser; + + EffectiveAclUser = NULL; + while (*g) + { + if (!AclCheckPermWin((*g)->u, mode, w)) + break; + g = &(*g)->next; + } + EffectiveAclUser = saved_eff; + if (*g) + ok = 1; + } + debug1("%d\n", !ok); + return !ok; } int @@ -533,13 +859,35 @@ struct user *u; int mode; struct comm *c; { - if (!multi) - return 0; + int ok; + if (mode < 0 || mode >= ACL_BITS_PER_CMD) return -1; + if (EffectiveAclUser) + { + debug1("AclCheckPermCmd: WARNING user %s overridden!\n", u->u_name); + u = EffectiveAclUser; + } + ok = ACLBYTE(c->userbits[mode], u->u_id) & ACLBIT(u->u_id); debug3("AclCheckPermCmd(%s %d %s) = ", u->u_name, mode, c->name); - debug1("%d\n", !(ACLBYTE(c->userbits[mode], u->id) & ACLBIT(u->id))); - return !(ACLBYTE(c->userbits[mode], u->id) & ACLBIT(u->id)); + if (!ok) + { + struct usergroup **g = &u->u_group; + struct user *saved_eff = EffectiveAclUser; + + EffectiveAclUser = NULL; + while (*g) + { + if (!AclCheckPermCmd((*g)->u, mode, c)) + break; + g = &(*g)->next; + } + EffectiveAclUser = saved_eff; + if (*g) + ok = 1; + } + debug1("%d\n", !ok); + return !ok; } #endif /* MULTIUSER */ @@ -58,7 +58,16 @@ typedef struct grouplist struct grouplist *next; } AclGroupList; -#endif +/* + * How a user joins a group. + * Here is the node to construct one list per user. + */ +struct usergroup +{ + struct user *u; /* the user who borrows us his rights */ + struct usergroup *next; +}; +#endif /* MULTIUSER */ /*************** * ==> user.h @@ -71,17 +80,21 @@ typedef struct grouplist */ typedef struct user { - struct user *u_next; + struct user *u_next; /* continue the main user list */ char u_name[20+1]; /* login name how he showed up */ - char u_password[20+1]; /* his password (may be zero length). */ + char *u_password; /* his password (may be NullStr). */ + int u_checkpassword; /* nonzero if this u_password is valid */ int u_detachwin; /* the window where he last detached */ + int u_detachotherwin; /* window that was "other" when he detached */ int u_Esc, u_MetaEsc; /* the users screen escape character */ #ifdef COPY_PASTE char *u_copybuffer; int u_copylen; #endif #ifdef MULTIUSER - int id; /* a uniq index in the bitfields. */ + int u_id; /* a uniq index in the bitfields. */ + AclBits u_umask_w_bits[ACL_BITS_PER_WIN]; /* his window create umask */ + struct usergroup *u_group; /* linked list of pointers to other users */ #endif } User; @@ -415,7 +415,7 @@ register struct win *p; #ifdef KANJI static char *kanjicharsets[3] = { "BBBB02", /* jis */ - "\002IBB01", /* euc */ + "B\002IB01", /* euc */ "BIBB01" /* sjis */ }; #endif @@ -955,6 +955,16 @@ skip: if (--len == 0) if (font != KANJI) { debug2("SJIS !! %x %x\n", c, t); + /* + * SJIS -> EUC mapping: + * First byte: + * 81,82...9f -> 21,23...5d + * e0,e1...ef -> 5f,61...7d + * Second byte: + * 40-7e -> 21-5f + * 80-9e -> 60-7e + * 9f-fc -> 21-7e (increment first byte!) + */ if (0x40 <= t && t <= 0xfc && t != 0x7f) { if (c <= 0x9f) c = (c - 0x81) * 2 + 0x21; @@ -1424,8 +1434,14 @@ int c, intermediate; ASetMode(0); break; case 'i': - if (display && a1 == 5) - PrintStart(); + { + struct display *odisplay = display; + if (display == 0 && displays && displays->d_next == 0) + display = displays; + if (display && a1 == 5) + PrintStart(); + display = odisplay; + } break; case 'n': if (a1 == 5) /* Report terminal status */ @@ -2464,7 +2480,7 @@ char *fmt; int n1, n2; { register int len; - char rbuf[40]; + char rbuf[40]; /* enough room for all replys */ sprintf(rbuf, fmt, n1, n2); len = strlen(rbuf); @@ -31,6 +31,9 @@ RCS_ID("$Id: attacher.c,v 1.8 1994/05/31 12:31:32 mlschroe Exp $ FAU") #include "config.h" #include "screen.h" #include "extern.h" +#ifndef sun +#include <sys/ioctl.h> +#endif #include <pwd.h> @@ -164,7 +167,8 @@ int how; bzero((char *) &m, sizeof(m)); m.type = how; - strcpy(m.m_tty, attach_tty); + strncpy(m.m_tty, attach_tty, sizeof(m.m_tty) - 1); + m.m_tty[sizeof(m.m_tty) - 1] = 0; if (how == MSG_WINCH) { @@ -186,7 +190,7 @@ int how; } else { - n = FindSocket(&lasts, (int *)0, SockMatch); + n = FindSocket(&lasts, (int *)0, (int *)0, SockMatch); switch (n) { case 0: @@ -225,7 +229,7 @@ int how; eff_uid = real_uid; eff_gid = real_gid; - debug2("Attach: uid %d euid %d\n", getuid(), geteuid()); + debug2("Attach: uid %d euid %d\n", (int)getuid(), (int)geteuid()); MasterPid = 0; for (s = SockName; *s; s++) { @@ -238,7 +242,7 @@ int how; if (stat(SockPath, &st) == -1) Panic(errno, "stat %s", SockPath); if ((st.st_mode & 0600) != 0600) - Panic(0, "Socket is in wrong mode (%03o)", st.st_mode); + Panic(0, "Socket is in wrong mode (%03o)", (int)st.st_mode); if ((dflag || !xflag) && (st.st_mode & 0700) != (dflag ? 0700 : 0600)) Panic(0, "That screen is %sdetached.", dflag ? "already " : "not "); #ifdef REMOTE_DETACH @@ -266,7 +270,8 @@ int how; } #endif ASSERT(how == MSG_ATTACH || how == MSG_CONT); - strcpy(m.m.attach.envterm, attach_term); + strncpy(m.m.attach.envterm, attach_term, sizeof(m.m.attach.envterm) - 1); + m.m.attach.envterm[sizeof(m.m.attach.envterm) - 1] = 0; debug1("attach: sending %d bytes... ", (int)sizeof(m)); strncpy(m.m.attach.auser, LoginName, sizeof(m.m.attach.auser) - 1); @@ -349,7 +354,7 @@ char *pwto; sighup = signal(SIG_PW_FAIL, trysendfail); for (tries = 0; ; ) { - strcpy(pwto, screenpw); + strncpy(pwto, screenpw, 9); trysendstatok = trysendstatfail = 0; if (write(fd, (char *) m, sizeof(*m)) != sizeof(*m)) Panic(errno, "write"); @@ -423,7 +428,8 @@ AttacherFinit SIGDEFARG { debug("Detaching backend!\n"); bzero((char *) &m, sizeof(m)); - strcpy(m.m_tty, attach_tty); + strncpy(m.m_tty, attach_tty, sizeof(m.m_tty) - 1); + m.m_tty[sizeof(m.m_tty) - 1] = 0; debug1("attach_tty is %s\n", attach_tty); m.m.detach.dpid = getpid(); m.type = MSG_HANGUP; @@ -726,7 +732,7 @@ LockTerminal() static void screen_builtin_lck() { - char fullname[100], *cp1, message[BUFSIZ]; + char fullname[100], *cp1, message[100 + 100]; char *pass, mypass[9]; #ifdef undef @@ -773,12 +779,14 @@ screen_builtin_lck() } debug("screen_builtin_lck looking in gcos field\n"); - strcpy(fullname, ppp->pw_gecos); + strncpy(fullname, ppp->pw_gecos, sizeof(fullname) - 9); + fullname[sizeof(fullname) - 9] = 0; if ((cp1 = index(fullname, ',')) != NULL) *cp1 = '\0'; if ((cp1 = index(fullname, '&')) != NULL) { - sprintf(cp1, "%s", ppp->pw_name); + strncpy(cp1, ppp->pw_name, 8); + cp1[8] = 0; if (*cp1 >= 'a' && *cp1 <= 'z') *cp1 -= 'a' - 'A'; } diff --git a/attacher.c. b/attacher.c. new file mode 100644 index 0000000..447994f --- /dev/null +++ b/attacher.c. @@ -0,0 +1,820 @@ +/* Copyright (c) 1993 + * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de) + * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de) + * Copyright (c) 1987 Oliver Laumann + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program (see the file COPYING); if not, write to the + * Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + **************************************************************** + */ + +#include "rcs.h" +RCS_ID("$Id: attacher.c,v 1.8 1994/05/31 12:31:32 mlschroe Exp $ FAU") + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <signal.h> +#include "config.h" +#include "screen.h" +#include "extern.h" + +#include <pwd.h> + +static sigret_t AttacherSigInt __P(SIGPROTOARG); +#ifdef PASSWORD +static void trysend __P((int, struct msg *, char *)); +#endif +#if defined(SIGWINCH) && defined(TIOCGWINSZ) +static sigret_t AttacherWinch __P(SIGPROTOARG); +#endif +#ifdef LOCK +static sigret_t DoLock __P(SIGPROTOARG); +static void LockTerminal __P((void)); +static sigret_t LockHup __P(SIGPROTOARG); +static void screen_builtin_lck __P((void)); +#endif +#ifdef DEBUG +static sigret_t AttacherChld __P(SIGPROTOARG); +#endif + +extern int real_uid, real_gid, eff_uid, eff_gid; +extern char *SockName, *SockMatch, SockPath[]; +extern struct passwd *ppp; +extern char *attach_tty, *attach_term, *LoginName; +extern int xflag, dflag, rflag, quietflag, adaptflag; +extern struct mode attach_Mode; +extern int MasterPid; +extern int nethackflag; + +#ifdef MULTIUSER +extern char *multi; +extern int multiattach, multi_uid, own_uid; +extern int tty_mode, tty_oldmode; +# ifndef USE_SETEUID +static int multipipe[2]; +# endif +#endif + + + +/* + * Send message to a screen backend. + * returns 1 if we could attach one, or 0 if none. + * Understands MSG_ATTACH, MSG_DETACH, MSG_POW_DETACH + * MSG_CONT, MSG_WINCH and nothing else! + */ + +int +Attach(how) +int how; +{ + int n, lasts; + struct msg m; + struct stat st; + char *s; + + debug2("Attach: how=%d, tty=%s\n", how, attach_tty); +#ifdef MULTIUSER +# ifndef USE_SETEUID + while ((how == MSG_ATTACH || how == MSG_CONT) && multiattach) + { + int ret; + + if (pipe(multipipe)) + Panic(errno, "pipe"); + if (chmod(attach_tty, 0666)) + Panic(errno, "chmod %s", attach_tty); + tty_oldmode = tty_mode; + eff_uid = -1; /* make UserContext fork */ + real_uid = multi_uid; + if ((ret = UserContext()) <= 0) + { + char dummy; + eff_uid = 0; + real_uid = own_uid; + if (ret < 0) + Panic(errno, "UserContext"); + close(multipipe[1]); + read(multipipe[0], &dummy, 1); + if (tty_oldmode >= 0) + { + chmod(attach_tty, tty_oldmode); + tty_oldmode = -1; + } + ret = UserStatus(); +#ifdef LOCK + if (ret == SIG_LOCK) + LockTerminal(); + else +#endif +#ifdef SIGTSTP + if (ret == SIG_STOP) + kill(getpid(), SIGTSTP); + else +#endif + if (ret == SIG_POWER_BYE) + { + int ppid; + setuid(real_uid); + setgid(real_gid); + if ((ppid = getppid()) > 1) + Kill(ppid, SIGHUP); + exit(0); + } + else + exit(ret); + dflag = 0; +#ifdef MULTI + xflag = 1; +#endif + how = MSG_ATTACH; + continue; + } + close(multipipe[0]); + eff_uid = real_uid; + break; + } +# else /* USE_SETEUID */ + if ((how == MSG_ATTACH || how == MSG_CONT) && multiattach) + { + real_uid = multi_uid; + eff_uid = own_uid; + xseteuid(multi_uid); + xseteuid(own_uid); + if (chmod(attach_tty, 0666)) + Panic(errno, "chmod %s", attach_tty); + tty_oldmode = tty_mode; + } +# endif /* USE_SETEUID */ +#endif /* MULTIUSER */ + + bzero((char *) &m, sizeof(m)); + m.type = how; + strncpy(m.m_tty, attach_tty, sizeof(m.m_tty) - 1); + m.m_tty[sizeof(m.m_tty) - 1] = 0; + + if (how == MSG_WINCH) + { + if ((lasts = MakeClientSocket(0)) >= 0) + { + write(lasts, (char *)&m, sizeof(m)); + close(lasts); + } + return 0; + } + + if (how == MSG_CONT) + { + if ((lasts = MakeClientSocket(0)) < 0) + { + Panic(0, "Sorry, cannot contact session \"%s\" again.\r\n", + SockName); + } + } + else + { + n = FindSocket(&lasts, (int *)0, (int *)0, SockMatch); + switch (n) + { + case 0: + if (rflag == 2) + return 0; + if (quietflag) + eexit(10); + Panic(0, SockMatch && *SockMatch ? "There is no screen to be %sed matching %s." : "There is no screen to be %sed.", + xflag ? "attach" : + dflag ? "detach" : + "resum", SockMatch); + /* NOTREACHED */ + case 1: + break; + default: + if (quietflag) + eexit(10 + n); + Panic(0, "Type \"screen [-d] -r [pid.]tty.host\" to resume one of them."); + /* NOTREACHED */ + } + } + /* + * Go in UserContext. Advantage is, you can kill your attacher + * when things go wrong. Any disadvantages? jw. + * Do this before the attach to prevent races! + */ +#ifdef MULTIUSER + if (!multiattach) +#endif + setuid(real_uid); +#if defined(MULTIUSER) && defined(USE_SETEUID) + else + xseteuid(real_uid); /* multi_uid, allow backend to send signals */ +#endif + setgid(real_gid); + eff_uid = real_uid; + eff_gid = real_gid; + + debug2("Attach: uid %d euid %d\n", (int)getuid(), (int)geteuid()); + MasterPid = 0; + for (s = SockName; *s; s++) + { + if (*s > '9' || *s < '0') + break; + MasterPid = 10 * MasterPid + (*s - '0'); + } + debug1("Attach decided, it is '%s'\n", SockPath); + debug1("Attach found MasterPid == %d\n", MasterPid); + if (stat(SockPath, &st) == -1) + Panic(errno, "stat %s", SockPath); + if ((st.st_mode & 0600) != 0600) + Panic(0, "Socket is in wrong mode (%03o)", (int)st.st_mode); + if ((dflag || !xflag) && (st.st_mode & 0700) != (dflag ? 0700 : 0600)) + Panic(0, "That screen is %sdetached.", dflag ? "already " : "not "); +#ifdef REMOTE_DETACH + if (dflag && + (how == MSG_ATTACH || how == MSG_DETACH || how == MSG_POW_DETACH)) + { + m.m.detach.dpid = getpid(); + strncpy(m.m.detach.duser, LoginName, sizeof(m.m.detach.duser) - 1); + m.m.detach.duser[sizeof(m.m.detach.duser) - 1] = 0; +# ifdef POW_DETACH + if (dflag == 2) + m.type = MSG_POW_DETACH; + else +# endif + m.type = MSG_DETACH; + if (write(lasts, (char *) &m, sizeof(m)) != sizeof(m)) + Panic(errno, "write"); + close(lasts); + if (how != MSG_ATTACH) + return 0; /* we detached it. jw. */ + sleep(1); /* we dont want to overrun our poor backend. jw. */ + if ((lasts = MakeClientSocket(0)) == -1) + Panic(0, "Cannot contact screen again. Sigh."); + m.type = how; + } +#endif + ASSERT(how == MSG_ATTACH || how == MSG_CONT); + strncpy(m.m.attach.envterm, attach_term, sizeof(m.m.attach.envterm) - 1); + m.m.attach.envterm[sizeof(m.m.attach.envterm) - 1] = 0; + debug1("attach: sending %d bytes... ", (int)sizeof(m)); + + strncpy(m.m.attach.auser, LoginName, sizeof(m.m.attach.auser) - 1); + m.m.attach.auser[sizeof(m.m.attach.auser) - 1] = 0; + m.m.attach.apid = getpid(); + m.m.attach.adaptflag = adaptflag; + m.m.attach.lines = m.m.attach.columns = 0; + if ((s = getenv("LINES"))) + m.m.attach.lines = atoi(s); + if ((s = getenv("COLUMNS"))) + m.m.attach.columns = atoi(s); + +#ifdef PASSWORD + if (how == MSG_ATTACH || how == MSG_CONT) + trysend(lasts, &m, m.m.attach.password); + else +#endif + { + if (write(lasts, (char *) &m, sizeof(m)) != sizeof(m)) + Panic(errno, "write"); + close(lasts); + } + debug1("Attach(%d): sent\n", m.type); +#ifdef MULTIUSER + if (multi && (how == MSG_ATTACH || how == MSG_CONT)) + { +# ifndef PASSWORD + pause(); +# endif +# ifndef USE_SETEUID + close(multipipe[1]); +# else + xseteuid(own_uid); + if (tty_oldmode >= 0) + if (chmod(attach_tty, tty_oldmode)) + Panic(errno, "chmod %s", attach_tty); + tty_oldmode = -1; + xseteuid(real_uid); +# endif + } +#endif + rflag = 0; + return 1; +} + + +#ifdef PASSWORD + +static trysendstatok, trysendstatfail; + +static sigret_t +trysendok SIGDEFARG +{ + trysendstatok = 1; +} + +static sigret_t +trysendfail SIGDEFARG +{ +# ifdef SYSVSIGS + signal(SIG_PW_FAIL, trysendfail); +# endif /* SYSVSIGS */ + trysendstatfail = 1; +} + +static char screenpw[9]; + +static void +trysend(fd, m, pwto) +int fd; +struct msg *m; +char *pwto; +{ + char *npw = NULL; + sigret_t (*sighup)__P(SIGPROTOARG); + sigret_t (*sigusr1)__P(SIGPROTOARG); + int tries; + + sigusr1 = signal(SIG_PW_OK, trysendok); + sighup = signal(SIG_PW_FAIL, trysendfail); + for (tries = 0; ; ) + { + strncpy(pwto, screenpw, 9); + trysendstatok = trysendstatfail = 0; + if (write(fd, (char *) m, sizeof(*m)) != sizeof(*m)) + Panic(errno, "write"); + close(fd); + while (trysendstatok == 0 && trysendstatfail == 0) + pause(); + if (trysendstatok) + { + signal(SIG_PW_OK, sigusr1); + signal(SIG_PW_FAIL, sighup); + if (trysendstatfail) + kill(getpid(), SIG_PW_FAIL); + return; + } + if (++tries > 1 || (npw = getpass("Screen Password:")) == 0 || *npw == 0) + { +#ifdef NETHACK + if (nethackflag) + Panic(0, "The guard slams the door in your face."); + else +#endif + Panic(0, "Password incorrect."); + } + strncpy(screenpw, npw, 8); + if ((fd = MakeClientSocket(0)) == -1) + Panic(0, "Cannot contact screen again. Sigh."); + } +} +#endif /* PASSWORD */ + + +#ifdef DEBUG +static int AttacherPanic; + +static sigret_t +AttacherChld SIGDEFARG +{ + AttacherPanic=1; + SIGRETURN; +} +#endif + +/* + * the frontend's Interrupt handler + * we forward SIGINT to the poor backend + */ +static sigret_t +AttacherSigInt SIGDEFARG +{ + signal(SIGINT, AttacherSigInt); + Kill(MasterPid, SIGINT); + SIGRETURN; +} + +/* + * Unfortunatelly this is also the SIGHUP handler, so we have to + * check, if the backend is already detached. + */ + +sigret_t +AttacherFinit SIGDEFARG +{ + struct stat statb; + struct msg m; + int s; + + debug("AttacherFinit();\n"); + signal(SIGHUP, SIG_IGN); + /* Check if signal comes from backend */ + if (stat(SockPath, &statb) == 0 && (statb.st_mode & 0777) != 0600) + { + debug("Detaching backend!\n"); + bzero((char *) &m, sizeof(m)); + strncpy(m.m_tty, attach_tty, sizeof(m.m_tty) - 1); + m.m_tty[sizeof(m.m_tty) - 1] = 0; + debug1("attach_tty is %s\n", attach_tty); + m.m.detach.dpid = getpid(); + m.type = MSG_HANGUP; + if ((s = MakeClientSocket(0)) >= 0) + { + write(s, (char *)&m, sizeof(m)); + close(s); + } + } +#ifdef MULTIUSER + if (tty_oldmode >= 0) + { + setuid(own_uid); + chmod(attach_tty, tty_oldmode); + } +#endif + exit(0); + SIGRETURN; +} + +#ifdef POW_DETACH +static sigret_t +AttacherFinitBye SIGDEFARG +{ + int ppid; + debug("AttacherFintBye()\n"); +#if defined(MULTIUSER) && !defined(USE_SETEUID) + if (multiattach) + exit(SIG_POWER_BYE); +#endif +#ifdef MULTIUSER + setuid(own_uid); +#else + setuid(real_uid); +#endif + setgid(real_gid); + /* we don't want to disturb init (even if we were root), eh? jw */ + if ((ppid = getppid()) > 1) + Kill(ppid, SIGHUP); /* carefully say good bye. jw. */ + exit(0); + SIGRETURN; +} +#endif + +static int SuspendPlease; + +static sigret_t +SigStop SIGDEFARG +{ + debug("SigStop()\n"); + SuspendPlease = 1; + SIGRETURN; +} + +#ifdef LOCK +static int LockPlease; + +static sigret_t +DoLock SIGDEFARG +{ +# ifdef SYSVSIGS + signal(SIG_LOCK, DoLock); +# endif + debug("DoLock()\n"); + LockPlease = 1; + SIGRETURN; +} +#endif + +#if defined(SIGWINCH) && defined(TIOCGWINSZ) +static int SigWinchPlease; + +static sigret_t +AttacherWinch SIGDEFARG +{ + debug("AttacherWinch()\n"); + SigWinchPlease = 1; + SIGRETURN; +} +#endif + + +/* + * Attacher loop - no return + */ + +void +Attacher() +{ + signal(SIGHUP, AttacherFinit); + signal(SIG_BYE, AttacherFinit); +#ifdef POW_DETACH + signal(SIG_POWER_BYE, AttacherFinitBye); +#endif +#ifdef LOCK + signal(SIG_LOCK, DoLock); +#endif + signal(SIGINT, AttacherSigInt); +#ifdef BSDJOBS + signal(SIG_STOP, SigStop); +#endif +#if defined(SIGWINCH) && defined(TIOCGWINSZ) + signal(SIGWINCH, AttacherWinch); +#endif +#ifdef DEBUG + signal(SIGCHLD, AttacherChld); +#endif + debug("attacher: going for a nap.\n"); + dflag = 0; +#ifdef MULTI + xflag = 1; +#endif + for (;;) + { +#ifdef DEBUG + sleep(1); + if (kill(MasterPid, 0) < 0 && errno != EPERM) + { + debug1("attacher: Panic! MasterPid %d does not exist.\n", MasterPid); + AttacherPanic++; + } +#else + pause(); +#endif +/* + debug("attacher: ding!\n"); +*/ +#ifdef DEBUG + if (AttacherPanic) + { + fcntl(0, F_SETFL, 0); + SetTTY(0, &attach_Mode); + printf("\nSuddenly the Dungeon collapses!! - You die...\n"); + eexit(1); + } +#endif +#ifdef BSDJOBS + if (SuspendPlease) + { + SuspendPlease = 0; +#if defined(MULTIUSER) && !defined(USE_SETEUID) + if (multiattach) + exit(SIG_STOP); +#endif + signal(SIGTSTP, SIG_DFL); + debug("attacher: killing myself SIGTSTP\n"); + kill(getpid(), SIGTSTP); + debug("attacher: continuing from stop\n"); + signal(SIG_STOP, SigStop); + (void) Attach(MSG_CONT); + } +#endif +#ifdef LOCK + if (LockPlease) + { + LockPlease = 0; +#if defined(MULTIUSER) && !defined(USE_SETEUID) + if (multiattach) + exit(SIG_LOCK); +#endif + LockTerminal(); +# ifdef SYSVSIGS + signal(SIG_LOCK, DoLock); +# endif + (void) Attach(MSG_CONT); + } +#endif /* LOCK */ +#if defined(SIGWINCH) && defined(TIOCGWINSZ) + if (SigWinchPlease) + { + SigWinchPlease = 0; +# ifdef SYSVSIGS + signal(SIGWINCH, AttacherWinch); +# endif + (void) Attach(MSG_WINCH); + } +#endif /* SIGWINCH */ + } +} + +#ifdef LOCK + +/* ADDED by Rainer Pruy 10/15/87 */ +/* POLISHED by mls. 03/10/91 */ + +static char LockEnd[] = "Welcome back to screen !!\n"; + +static sigret_t +LockHup SIGDEFARG +{ + int ppid = getppid(); +#ifdef MULTIUSER + setuid(own_uid); +#else + setuid(real_uid); +#endif + setgid(real_gid); + if (ppid > 1) + Kill(ppid, SIGHUP); + exit(0); +} + +static void +LockTerminal() +{ + char *prg; + int sig, pid; + sigret_t (*sigs[NSIG])__P(SIGPROTOARG); + + for (sig = 1; sig < NSIG; sig++) + sigs[sig] = signal(sig, SIG_IGN); + signal(SIGHUP, LockHup); + printf("\n"); + + prg = getenv("LOCKPRG"); + if (prg && strcmp(prg, "builtin") && !access(prg, X_OK)) + { + signal(SIGCHLD, SIG_DFL); + debug1("lockterminal: '%s' seems executable, execl it!\n", prg); + if ((pid = fork()) == 0) + { + /* Child */ +#ifdef MULTIUSER + setuid(own_uid); +#else + setuid(real_uid); /* this should be done already */ +#endif + setgid(real_gid); + closeallfiles(0); /* important: /etc/shadow may be open */ + execl(prg, "SCREEN-LOCK", NULL); + exit(errno); + } + if (pid == -1) + { +#ifdef NETHACK + if (nethackflag) + Msg(errno, "Cannot fork terminal - lock failed"); + else +#endif + Msg(errno, "Cannot lock terminal - fork failed"); + } + else + { +#ifdef BSDWAIT + union wait wstat; +#else + int wstat; +#endif + int wret; + +#ifdef hpux + signal(SIGCHLD, SIG_DFL); +#endif + errno = 0; + while (((wret = wait(&wstat)) != pid) || + ((wret == -1) && (errno == EINTR)) + ) + errno = 0; + + if (errno) + { + Msg(errno, "Lock"); + sleep(2); + } + else if (WTERMSIG(wstat) != 0) + { + fprintf(stderr, "Lock: %s: Killed by signal: %d%s\n", prg, + WTERMSIG(wstat), WIFCORESIG(wstat) ? " (Core dumped)" : ""); + sleep(2); + } + else if (WEXITSTATUS(wstat)) + { + debug2("Lock: %s: return code %d\n", prg, WEXITSTATUS(wstat)); + } + else + printf(LockEnd); + } + } + else + { + if (prg) + { + debug1("lockterminal: '%s' seems NOT executable, we use our builtin\n", prg); + } + else + { + debug("lockterminal: using buitin.\n"); + } + screen_builtin_lck(); + } + /* reset signals */ + for (sig = 1; sig < NSIG; sig++) + { + if (sigs[sig] != (sigret_t(*)__P(SIGPROTOARG)) -1) + signal(sig, sigs[sig]); + } +} /* LockTerminal */ + +/* -- original copyright by Luigi Cannelloni 1985 (luigi@faui70.UUCP) -- */ +static void +screen_builtin_lck() +{ + char fullname[100], *cp1, message[100 + 100]; + char *pass, mypass[9]; + +#ifdef undef + /* get password entry */ + if ((ppp = getpwuid(real_uid)) == NULL) + { + fprintf(stderr, "screen_builtin_lck: No passwd entry.\007\n"); + sleep(2); + return; + } + if (!isatty(0)) + { + fprintf(stderr, "screen_builtin_lck: Not a tty.\007\n"); + sleep(2); + return; + } +#endif + pass = ppp->pw_passwd; + if (pass == 0 || *pass == 0) + { + if ((pass = getpass("Key: "))) + { + strncpy(mypass, pass, 8); + mypass[8] = 0; + if (*mypass == 0) + return; + if ((pass = getpass("Again: "))) + { + if (strcmp(mypass, pass)) + { + fprintf(stderr, "Passwords don't match.\007\n"); + sleep(2); + return; + } + } + } + if (pass == 0) + { + fprintf(stderr, "Getpass error.\007\n"); + sleep(2); + return; + } + pass = 0; + } + + debug("screen_builtin_lck looking in gcos field\n"); + strncpy(fullname, ppp->pw_gecos, sizeof(fullname) - 9); + fullname[sizeof(fullname) - 9] = 0; + if ((cp1 = index(fullname, ',')) != NULL) + *cp1 = '\0'; + if ((cp1 = index(fullname, '&')) != NULL) + { + strncpy(cp1, ppp->pw_name, 8); + cp1[8] = 0; + if (*cp1 >= 'a' && *cp1 <= 'z') + *cp1 -= 'a' - 'A'; + } + + sprintf(message, "Screen used by %s <%s>.\nPassword:\007", + fullname, ppp->pw_name); + + /* loop here to wait for correct password */ + for (;;) + { + debug("screen_builtin_lck awaiting password\n"); + errno = 0; + if ((cp1 = getpass(message)) == NULL) + { + AttacherFinit(SIGARG); + /* NOTREACHED */ + } + debug3("getpass(%d): %x == %s\n", errno, (unsigned int)cp1, cp1); + if (pass) + { + if (!strncmp(crypt(cp1, pass), pass, strlen(pass))) + break; + } + else + { + if (!strcmp(cp1, mypass)) + break; + } + debug("screen_builtin_lck: NO!!!!!\n"); + } + debug("password ok.\n"); +} + +#endif /* LOCK */ @@ -63,12 +63,12 @@ struct comm comms[RC_LAST + 1] = #ifdef MULTI { "clone", NEED_DISPLAY|ARGS_ONE|ARGS_ORMORE }, #endif - { "colon", NEED_DISPLAY|ARGS_ZERO }, + { "colon", NEED_DISPLAY|ARGS_ZEROONE }, { "command", NEED_DISPLAY|ARGS_ZERO }, { "console", NEED_FORE|ARGS_ZEROONE }, #ifdef COPY_PASTE { "copy", NEED_FORE|ARGS_ZERO }, - { "crlf", ARGS_ONE }, + { "crlf", ARGS_ZEROONE }, #endif { "debug", ARGS_ZEROONE }, #ifdef AUTO_NUKE diff --git a/config.h.in b/config.h.in index a1102e6..5c65ecb 100644 --- a/config.h.in +++ b/config.h.in @@ -47,7 +47,7 @@ */ #ifndef TMPTEST -# define SOCKDIR "/tmp/screens" +# define SOCKDIR "/var/run/screens" #else # define SOCKDIR "/tmp/testscreens" #endif @@ -449,6 +449,16 @@ #undef HAVE_LSTAT /* + * define HAVE_UTIMES if your system has the utimes() call. + */ +#undef HAVE_UTIMES + +/* + * define HAVE_VSNPRINTF if your system has vsnprintf() (GNU lib). + */ +#undef HAVE_VSNPRINTF + +/* * define HAVE_DEV_PTC if you have a /dev/ptc character special * device. */ @@ -1619,6 +1619,9 @@ if test "$ptys" != "$pdir/pty??" ; then p0=`echo $ptys | tr ' ' '\012' | sed -e 's/^.*\(.\).$/\1/g' | sort -u | tr -d '\012'` p1=`echo $ptys | tr ' ' '\012' | sed -e 's/^.*\(.\)$/\1/g' | sort -u | tr -d '\012'` +#hack for 256 pty's: +p0=abcdepqrstuvwxyz + { test -n "$verbose" && \ echo " defining" PTYRANGE0 to be "\"$p0\"" @@ -2622,10 +2625,10 @@ rm -f /tmp/conftest* test -n "$silent" || echo "checking for vsprintf" cat > conftest.${ac_ext} <<EOF #include "confdefs.h" -#include <varargs.h> + #include <stdio.h> int main() { return 0; } -int t() { vsprintf();; return 0; } +int t() { vsprintf(0,0,0);; return 0; } EOF if eval $ac_compile; then rm -rf conftest* @@ -2964,6 +2967,56 @@ ac_sed_defs="${ac_sed_defs}\${ac_dA}HAVE_STRERROR\${ac_dB}HAVE_STRERROR\${ac_dC} fi rm -f conftest* +test -n "$silent" || echo "checking for utimes" +cat > conftest.${ac_ext} <<EOF +#include "confdefs.h" + +int main() { return 0; } +int t() { utimes(0,0);; return 0; } +EOF +if eval $ac_compile; then + rm -rf conftest* + +{ +test -n "$verbose" && \ +echo " defining HAVE_UTIMES" +echo "#define" HAVE_UTIMES "1" >> confdefs.h +DEFS="$DEFS -DHAVE_UTIMES=1" +ac_sed_defs="${ac_sed_defs}\${ac_dA}HAVE_UTIMES\${ac_dB}HAVE_UTIMES\${ac_dC}1\${ac_dD} +\${ac_uA}HAVE_UTIMES\${ac_uB}HAVE_UTIMES\${ac_uC}1\${ac_uD} +\${ac_eA}HAVE_UTIMES\${ac_eB}HAVE_UTIMES\${ac_eC}1\${ac_eD} +" +} + + +fi +rm -f conftest* + +test -n "$silent" || echo "checking for vsnprintf" +cat > conftest.${ac_ext} <<EOF +#include "confdefs.h" + +int main() { return 0; } +int t() { vsnprintf(0,0,0);; return 0; } +EOF +if eval $ac_compile; then + rm -rf conftest* + +{ +test -n "$verbose" && \ +echo " defining HAVE_VSNPRINTF" +echo "#define" HAVE_VSNPRINTF "1" >> confdefs.h +DEFS="$DEFS -DHAVE_VSNPRINTF=1" +ac_sed_defs="${ac_sed_defs}\${ac_dA}HAVE_VSNPRINTF\${ac_dB}HAVE_VSNPRINTF\${ac_dC}1\${ac_dD} +\${ac_uA}HAVE_VSNPRINTF\${ac_uB}HAVE_VSNPRINTF\${ac_uC}1\${ac_uD} +\${ac_eA}HAVE_VSNPRINTF\${ac_eB}HAVE_VSNPRINTF\${ac_eC}1\${ac_eD} +" +} + + +fi +rm -f conftest* + test -n "$seqptx" && LIBS="-ltermcap -lc -lsocket -linet -lsec -lseq" @@ -2982,12 +3035,12 @@ if test -n "$prefix"; then { test -n "$verbose" && \ -echo " defining" ETCSCREENRC to be "\"$prefix/etc/screenrc\"" -echo "#define" ETCSCREENRC "\"$prefix/etc/screenrc\"" >> confdefs.h -DEFS="$DEFS -DETCSCREENRC=\"$prefix/etc/screenrc\"" -ac_sed_defs="${ac_sed_defs}\${ac_dA}ETCSCREENRC\${ac_dB}ETCSCREENRC\${ac_dC}\"$prefix/etc/screenrc\"\${ac_dD} -\${ac_uA}ETCSCREENRC\${ac_uB}ETCSCREENRC\${ac_uC}\"$prefix/etc/screenrc\"\${ac_uD} -\${ac_eA}ETCSCREENRC\${ac_eB}ETCSCREENRC\${ac_eC}\"$prefix/etc/screenrc\"\${ac_eD} +echo " defining" ETCSCREENRC to be "\"/etc/screenrc\"" +echo "#define" ETCSCREENRC "\"/etc/screenrc\"" >> confdefs.h +DEFS="$DEFS -DETCSCREENRC=\"/etc/screenrc\"" +ac_sed_defs="${ac_sed_defs}\${ac_dA}ETCSCREENRC\${ac_dB}ETCSCREENRC\${ac_dC}\"/etc/screenrc\"\${ac_dD} +\${ac_uA}ETCSCREENRC\${ac_uB}ETCSCREENRC\${ac_uC}\"/etc/screenrc\"\${ac_uD} +\${ac_eA}ETCSCREENRC\${ac_eB}ETCSCREENRC\${ac_eC}\"/etc/screenrc\"\${ac_eD} " } diff --git a/configure.in b/configure.in index a655f0a..92c4c58 100644 --- a/configure.in +++ b/configure.in @@ -978,8 +978,8 @@ else AC_DEFINE(NAME_MAX, 14) fi rm -f /tmp/conftest* -AC_COMPILE_CHECK(vsprintf, [#include <varargs.h> -#include <stdio.h>], [vsprintf();], AC_DEFINE(USEVARARGS)) +AC_COMPILE_CHECK(vsprintf, [ +#include <stdio.h>], [vsprintf(0,0,0);], AC_DEFINE(USEVARARGS)) AC_DIR_HEADER AC_XENIX_DIR @@ -993,6 +993,8 @@ AC_COMPILE_CHECK(rename, , [rename(0,0);], , AC_DEFINE(NEED_RENAME)) AC_COMPILE_CHECK(_exit, , [_exit(0);], AC_DEFINE(HAVE__EXIT)) AC_COMPILE_CHECK(lstat, , [lstat(0,0);], AC_DEFINE(HAVE_LSTAT)) AC_COMPILE_CHECK(strerror, ,[strerror(0);], AC_DEFINE(HAVE_STRERROR)) +AC_COMPILE_CHECK(utimes, ,[utimes(0,0);], AC_DEFINE(HAVE_UTIMES)) +AC_COMPILE_CHECK(vsnprintf, ,[vsnprintf(0,0,0);], AC_DEFINE(HAVE_VSNPRINTF)) dnl dnl **** the end **** diff --git a/debian/README.terminfo b/debian/README.terminfo new file mode 100644 index 0000000..78afbf5 --- /dev/null +++ b/debian/README.terminfo @@ -0,0 +1,5 @@ +Debian 1.3 uses ncurses/terminfo, not curses/termcap, so you really +shouldn't need the screencap file in this directory. + +The screeninfo.src file is installed by the `ncurses-term' package +-- it's here for reference, and to recover from stupid errors (like?). diff --git a/debian/changelog b/debian/changelog index 3fb8c6b..3de3ff4 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,69 @@ +screen (3.7.4-6) unstable; urgency=low + + * Pass SIGWINCH to applications when size changes (fixes:Bug#18471) + + -- Juan Cespedes <cespedes@debian.org> Sun, 22 Feb 1998 11:16:46 +0100 + +screen (3.7.4-5) unstable; urgency=low + + * Fixed minor bug in debian/rules clean + * `screen' now depends on `ncurses-term', so it doesn't install its + own terminfo entry + * New Standards-Version: 2.4.0.0 + + -- Juan Cespedes <cespedes@debian.org> Thu, 12 Feb 1998 16:10:22 +0100 + +screen (3.7.4-4) unstable; urgency=low + + * Changed upstream changelog name (ChangeLog.gz -> changelog.gz) + * Changed sockets from /tmp to /var/run (closes:Bug#6487) + * New Standards-Version: 2.3.0.1 + * Changed behaviour of backspace key (now sends `DEL' == 0177) + + -- Juan Cespedes <cespedes@debian.org> Sun, 4 Jan 1998 21:13:51 +0100 + +screen (3.7.4-3) unstable; urgency=low + + * New maintainer + * New Standards-Version: 2.3.0.0 + * Minor fixes in /usr/doc/screen + * Pristine Source + * Fixed Bug#12626 + + -- Juan Cespedes <cespedes@debian.org> Sat, 11 Oct 1997 02:14:43 +0200 + +screen (3.7.4-2) unstable; urgency=low + + * Added definition of kend to screeninfo.src. + * Recompiled for libc6. + + -- joost witteveen <joost@rulcmc.leidenuniv.nl> Fri, 3 Oct 1997 22:18:45 +0200 + +screen (3.7.4-1) unstable; urgency=low + + * Upgraded to upstream version. + * fixed /etc/screenrc problem (used to read: /usr/etc/screenrc). + + -- joost witteveen <joost@rulcmc.leidenuniv.nl> Sat, 2 Aug 1997 22:26:08 +0200 + +screen (3.7.2-5) unstable; urgency=low + + * Recompiled for libc6 (now should be using libc functions for utmp access) + + -- joost witteveen <joost@rulcmc.leidenuniv.nl> Thu, 19 Jun 1997 17:48:26 +0200 + +screen (3.7.2-4) unstable; urgency=low + + * After suggestions from David Luyer, increase the number of tty's to 256. + + -- joost witteveen <joost@rulcmc.leidenuniv.nl> Sun, 4 May 1997 17:25:00 +0200 + +screen (3.7.2-3) stable unstable; urgency=high + + * Security fix for buffer-overrun posted to bugtraq. + + -- joost witteveen <joost@rulcmc.leidenuniv.nl> Fri, 21 Feb 1997 17:02:30 +0100 + screen (3.7.2-2) unstable; urgency=low * This package contained a /usr/doc/screen/screeninfo.src.gz (compressed) diff --git a/debian/control b/debian/control index 751cb2b..da02af4 100644 --- a/debian/control +++ b/debian/control @@ -1,12 +1,12 @@ Source: screen Section: misc Priority: optional -Maintainer: joost witteveen <joostje@debian.org> -Standards-Version: 2.1.1.0 +Maintainer: Juan Cespedes <cespedes@debian.org> +Standards-Version: 2.4.0.0 Package: screen Architecture: any -Depends: ${shlibs:Depends} +Depends: ${shlibs:Depends}, ncurses-term (>= 1.9.9g-8) Description: A screen manager with VT100/ANSI terminal emulation. screen is a terminal multiplexor that runs several separate "screens" on a single physical character-based terminal. Each virtual terminal diff --git a/debian/copyright b/debian/copyright index a6606c9..c41135a 100644 --- a/debian/copyright +++ b/debian/copyright @@ -1,44 +1,47 @@ This is the Debian GNU/Linux prepackaged version of screen, a screen -manager with VT100/ANSI terminal emulation. screen was originally -written by Oliver Laumann; the most recent version was produced by -Wayne Davison, Juergen Weigert and Michael Schroeder. - -This package was put together by Ian Murdock <imurdock@debian.org>, -from sources obtained from: - prep.ai.mit.edu:/pub/gnu/screen-3.6.2.tar.gz - -Later taken over by joost witteveen <joostje@master.debian.org>, -who only added minor changes. - -Changes: - * added Debian GNU/Linux package maintenance system files - * ETCSCREENRC definition changed to "/etc/screenrc" in config.h.in - * remove /tmp/screens after installation and removal, as this prevents - permission conflicts between different screen versions. - * 3.7.1-5--3.7.1-7 had "Depends: login (>=1.0-5) | shadow-login" - because of a bug in the utmp handling in screen. This bug - has been fixed by the upstream maintainer, and it should now - not anymore need login-1.0-5 (or higer). +manager with VT100/ANSI terminal emulation. + +This package was put together from sources obtained from: + ftp://ftp.gnu.ai.mit.edu/pub/gnu/screen-3.7.4.tar.gz + +Changes for Debian: + * added Debian GNU/Linux package maintenance system files + * ETCSCREENRC definition changed to "/etc/screenrc" in config.h.in + * 3.7.1-5--3.7.1-7 had "Depends: login (>=1.0-5) | shadow-login" + because of a bug in the utmp handling in screen. This bug + has been fixed by the upstream maintainer, and it should now + not anymore need login-1.0-5 (or higer). + * Used /var/run/screens instead of /tmp/screens + + +Copyrights +---------- +Copyright (C) 1987 Oliver Laumann +Copyright (C) 1991 Wayne Davidson +Copyright (C) 1993 Juergen Weigert <jnweiger@immd4.informatik.uni-erlangen.de> +Copyright (C) 1993 Michael Schroeder <mlschroe@immd4.informatik.uni-erlangen.de> + +Modifications for Debian: + Copyright (C) Ian Murdock <imurdock@debian.org> + Copyright (C) 1997 joost witteveen <joost@rulcmc.leidenuniv.nl> + Copyright (C) 1997 Juan Cespedes <cespedes@debian.org> -screen is Copyright (C) 1993 - Juergen Weigert <jnweiger@immd4.informatik.uni-erlangen.de> - Michael Schroeder <mlschroe@immd4.informatik.uni-erlangen.de> +License +------- +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. - Copyright (C) 1987 Oliver Laumann +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 dated June, 1991. +A copy of the GNU General Public License is available as +`/usr/doc/copyright/GPL' in the Debian GNU/Linux distribution or on +the World Wide Web at `http://www.gnu.org/copyleft/gpl.html'. You can +also obtain it by writing to the Free Software Foundation, Inc., 59 +Temple Place - Suite 330, Boston, MA 02111-1307, USA - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave., Cambridge, MA 02139, USA. - -On Debian GNU/Linux systems, the complete text of the GNU General -Public License can be found in `/usr/doc/copyright/GPL'. diff --git a/debian/files b/debian/files deleted file mode 100644 index da591f2..0000000 --- a/debian/files +++ /dev/null @@ -1 +0,0 @@ -screen_3.7.2-2_i386.deb misc optional diff --git a/debian/postinst b/debian/postinst index 803ca7f..9c8d27f 100644 --- a/debian/postinst +++ b/debian/postinst @@ -2,52 +2,9 @@ install-info --quiet --section "General Commands" "General Commands" \ /usr/info/screen.info.gz -# after a suggestion from Guy Maor, I removed the stuff here -# that installs a screen entry in /etc/termcap -- this is the -# job of the termcap compatibility package. +# the terminfo/termcap entries don't get installed now; it's done by +# the `termcap-compat' and the `ncurses-term' packages -# Anyway, see /usr/doc/screen/README. - -#install the terminfo stuff: -tic /usr/doc/screen/screeninfo.src - -#this is to remove the "/tmp/screens has incorrect permissions" -#error message from screen 3.7.1 after upgrading to this (3.7.1) -#version of screen from 3.6 or earlier. - -if test -d /tmp/screens; then - if test "`ls -ald /tmp/screens|cut -d" " -f 1`" = "drwxr-xr-x"; then - echo you seem to be upgrading from a post 3.6 version of screen. - echo "If I'm wrong, plase type \"rm -rf /tmp/screens\" right after" - echo installation, to avoid problems with permissions later. - else - if killall -0 screen; then - echo you seem to be upgrading from a pre-3.7 version of screen, - echo but you still have screen-sessions running. - echo This will cause problems with permissions of /tmp/screens, - echo unless I remove this directory now. - echo Unfortunately, if I remove /tmp/screens now, the running - echo screen sessions will lose the ability to reattach. - echo - echo Do you want me to remove /tmp/screens anyway "(advised)", - echo thereby crippling the current screen sessions, or shall I - echo leave screen unconfigured so that you can rerun the installtion - echo later, when the screen sessions have ended? - echo type - echo " 1 to rm -rf /tmp/screens now" - echo " 2 to leave screen unconfigured" - read ans - if test "$ans" = "1"; then - rm -rf /tmp/screens - else - exit 1 - fi - else - echo you seem to be upgrading from a pre-3.7 version of screen. - echo "to avoid problems with permissions later, I'm now removing" - echo '/tmp/screens (you should not notice this)' - rm -rf /tmp/screens - fi - fi -fi +# No need to remove /tmp/screens from older versions; +# the directory used now for sockets is /var/run/screens diff --git a/debian/postrm b/debian/postrm index e44f1aa..6bc8db3 100644 --- a/debian/postrm +++ b/debian/postrm @@ -1,10 +1,7 @@ #! /bin/sh install-info --quiet --remove screen -#if a user later wants to install an old version of screen -#(like 3.6.2), that version will expect /tmp/screens to have different -#permissions than it has now, so we remove it now: - -if test "$1" = "remove"; then - rm -rf /tmp/screens +if test "$1" = "purge" ; then + rm -rf /var/run/screens fi + diff --git a/debian/rules b/debian/rules index 7453449..32235dd 100755 --- a/debian/rules +++ b/debian/rules @@ -1,115 +1,51 @@ #!/usr/bin/make -f -# -*- mode: makefile; -*- # -# Last updated: Sat Dec 17 10:52:20 EST 1994 by imurdock. -# -# To make the binary distribution package, the ``Debianized'' source package -# and the context diff to the original package, type `./debian.rules dist'. -# Make sure that `debian.rules' is executable before the final distribution -# is made. -# -# Invoke each target with `./debian.rules <target>'. All targets should be -# invoked with the package root as the current directory. -# -# The `binary' target must be run as root, as it needs to install files with -# specific ownerships. The `diff' target assumes that you have the original -# source package available, unpacked, in ../$(p)-$(v).orig, or that you have -# the previous revision of the ``Debianized'' source package and context diff -# in the parent directory. - -CC = gcc -CFLAGS = -O2 -LDFLAGS = -s - -# The name of the package (for example, `emacs'). -p = screen -# # The version of the package (for example, `19.28'). -v = 3.7.2 -# # The Debian revision of the package (for example, `2'). -# d = 8 -# # The target architecture. -# a = $(shell dpkg --print-architecture) -# package=$(p) -# version=$(v) -# debian=$(d) -# arch=$(a) +# Copyright (C) 1997 joost witteveen <joost@rulcmc.leidenuniv.nl> +# Copyright (C) 1997 Juan Cespedes <cespedes@debian.org> build: -# Builds the binary package. - ./configure --prefix=/usr - make CC="$(CC)" CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" - touch build - -clean: -# Undoes the effect of `debian/rules build'. - -$(MAKE) distclean - rm -f comm.h config.h kmapdef.c term.h tty.c - rm -f build - rm -rf debian/tmp - rm -f Makefile.rej* - -binary-indep: checkroot build - $(checkdir) -# There are no architecture-independent files to be uploaded -# generated by this package. If there were any they would be -# made here. - -binary-arch: checkroot build -# Makes a binary package. - rm -rf debian/tmp - install -d -g root -m 755 -o root debian/tmp - chmod g-s debian/tmp - install -d -g root -m 755 -o root debian/tmp/DEBIAN - install -d -g root -m 755 -o root debian/tmp/etc - install -d -g root -m 755 -o root debian/tmp/usr/bin - install -d -g root -m 755 -o root debian/tmp/usr/info - install -d -g root -m 755 -o root debian/tmp/usr/man/man1 - install -d -g root -m 755 -o root debian/tmp/usr/doc/$(p) - install -g root -m 644 -o root etc/etcscreenrc \ - debian/tmp/etc/screenrc - install -g root -m 4755 -o root screen \ - debian/tmp/usr/bin/screen-$(v) - ( cd debian/tmp/usr/bin ; ln -fs screen-$(v) screen ) - install -g root -m 644 -o root doc/screen.info* \ - debian/tmp/usr/info - install -g root -m 644 -o root doc/screen.1 \ - debian/tmp/usr/man/man1/screen.1 - install -g root -m 644 -o root terminfo/* \ - debian/tmp/usr/doc/screen - install -g root -m 644 -o root debian/copyright \ - debian/tmp/usr/doc/$(p)/copyright - install -g root -m 644 -o root debian/changelog \ - debian/tmp/usr/doc/$(p)/changelog.Debian - rm -f debian/tmp/usr/info/$(p).info*.gz - gzip -9f debian/tmp/usr/info/$(p).info* \ - debian/tmp/usr/doc/$(p)/* - gunzip debian/tmp/usr/doc/$(p)//screeninfo.src - install -g root -m 755 -o root debian/conffiles \ - debian/tmp/DEBIAN/conffiles - install -g root -m 755 -o root debian/postinst \ - debian/tmp/DEBIAN/postinst - install -g root -m 755 -o root debian/postrm \ - debian/tmp/DEBIAN/postrm - dpkg-shlibdeps screen - dpkg-gencontrol - chown -R root.root debian/tmp - chmod -R g-ws debian/tmp - dpkg --build debian/tmp .. - - -define checkdir - test -f $(p).c -a -f debian/rules -endef - -# Below here is fairly generic really + ./configure --prefix=/usr + $(MAKE) CFLAGS='-O2 -g -Wall' + touch build binary: binary-indep binary-arch -source diff: - @echo >&2 'source and diff are obsolete - use dpkg-source -b'; false +binary-indep: + +binary-arch: build + @test 0 = `id -u` || { echo "Error: not super-user"; exit 1; } + rm -rf debian/tmp + install -d -m 755 debian/tmp/{DEBIAN,etc,usr/{bin,info,man/man1,doc/screen}} + cp -a etc/etcscreenrc debian/tmp/etc/screenrc + install -s -m 4755 screen debian/tmp/usr/bin/screen + cp -a doc/screen.info* debian/tmp/usr/info + cp -a doc/screen.1 debian/tmp/usr/man/man1/screen.1 + cp -a debian/changelog debian/tmp/usr/doc/screen/changelog.Debian + cp -a ChangeLog debian/tmp/usr/doc/screen/changelog + cp -a README NEWS FAQ debian/tmp/usr/doc/screen + rm -f debian/tmp/usr/info/screen.info*.gz + gzip -9f debian/tmp/usr/info/screen.info* debian/tmp/usr/doc/screen/* + gzip -9f debian/tmp/usr/man/man1/* + install -d debian/tmp/usr/doc/screen/terminfo + cp -a terminfo/* debian/tmp/usr/doc/screen/terminfo + cp -a debian/README.terminfo debian/tmp/usr/doc/screen/terminfo/README.Debian + gzip -9f debian/tmp/usr/doc/screen/terminfo/* + cp -a debian/copyright debian/tmp/usr/doc/screen/copyright + cp -a debian/conffiles debian/tmp/DEBIAN/conffiles + install -m 755 debian/postinst debian/tmp/DEBIAN/postinst + install -m 755 debian/postrm debian/tmp/DEBIAN/postrm + + dpkg-shlibdeps screen + dpkg-gencontrol + chown -R root.root debian/tmp + chmod -R go=rX debian/tmp + dpkg --build debian/tmp .. -checkroot: - $(checkdir) - test root = "`whoami`" +clean: + rm -f build debian/files debian/substvars + -$(MAKE) realclean + rm -f kmapdef.c + rm -f osdef[012]* + rm -rf debian/tmp -.PHONY: binary binary-arch binary-indep clean checkroot +.PHONY: binary binary-arch binary-indep clean diff --git a/debian/substvars b/debian/substvars deleted file mode 100644 index c06ea2e..0000000 --- a/debian/substvars +++ /dev/null @@ -1 +0,0 @@ -shlibs:Depends=libc5 (>= 5.4.17-1), ncurses3.0 @@ -269,9 +269,10 @@ struct mode *Mode; D_dospeed = (short) D_OldMode.m_ttyb.sg_ospeed; #endif /* POSIX || TERMIO */ debug1("New displays ospeed = %d\n", D_dospeed); - strcpy(D_usertty, utty); - strcpy(D_termname, term); - + strncpy(D_usertty, utty, sizeof(D_usertty) - 1); + D_usertty[sizeof(D_usertty) - 1] = 0; + strncpy(D_termname, term, sizeof(D_termname) - 1); + D_termname[sizeof(D_termname) - 1] = 0; D_user = *u; D_lay = &BlankLayer; D_layfn = BlankLayer.l_layfn; @@ -477,7 +478,7 @@ int c; else if (D_kanji == SJIS) { t += (c & 1) ? ((t <= 0x5f) ? 0x1f : 0x20) : 0x7e; - c = (c - 0x21) / 2 + ((c < 0x5e) ? 0x81 : 0xc1); + c = (c - 0x21) / 2 + ((c < 0x5f) ? 0x81 : 0xc1); } D_mbcs = t; } @@ -1887,7 +1888,12 @@ NukePending() PutStr(D_EI); D_insert = 0; /* Check for toggle */ -#ifndef MAPKEYS +#ifdef MAPKEYS + if (D_KS && strcmp(D_KS, D_KE)) + PutStr(D_KS); + if (D_CCS && strcmp(D_CCS, D_CCE)) + PutStr(D_CCS); +#else if (D_KS && strcmp(D_KS, D_KE)) PutStr(D_KE); D_keypad = 0; diff --git a/doc/Makefile.in b/doc/Makefile.in index ce1930b..74dcc37 100644 --- a/doc/Makefile.in +++ b/doc/Makefile.in @@ -29,7 +29,7 @@ install: installdirs if test -f $$d/screen.info; then \ for f in $$d/screen.info*; do $(INSTALL_DATA) $$f $(infodir);done; \ if $(SHELL) -c 'install-info --version' >/dev/null 2>&1; then \ - install-info --infodir=$(infodir) $$d/screen.info; \ + install-info --info-dir=$(infodir) $$d/screen.info; \ else true; fi; \ fi diff --git a/doc/screen.1 b/doc/screen.1 index f006f20..e31a7d6 100644 --- a/doc/screen.1 +++ b/doc/screen.1 @@ -481,7 +481,7 @@ Start/stop monitoring the current window for inactivity. .SH CUSTOMIZATION The \*Qsocket directory\*U defaults either to $HOME/.screen or simply to /tmp/screens or preferably to /usr/local/screens chosen at -compile-time. (/tmp/screens for debian) +compile-time. (/var/run/screens for Debian GNU/Linux) If .I screen is installed setuid-root, then the administrator @@ -861,6 +861,7 @@ Clears the current window and saves its image to the scrollback buffer. .sp .ne 3 .B colon +.RI [ prefix ] .PP Allows you to enter \*Q.screenrc\*U command lines. Useful for on-the-fly modification of key bindings, @@ -3209,7 +3210,7 @@ Read in after /etc/screenrc .IP $ISCREENDIR/S-<login> .IP $SCREENDIR/S-<login> .IP /tmp/screens/S-<login> -Socket directories (default) +Socket directories (default for Debian GNU/Linux) .IP /usr/tmp/screens/S-<login> Alternate socket directories. .IP "<socket directory>/.termcap" diff --git a/doc/screen.info-4 b/doc/screen.info-4 index f466b1a..4ab0067 100644 --- a/doc/screen.info-4 +++ b/doc/screen.info-4 @@ -73,10 +73,11 @@ Socket Directory The socket directory defaults either to `$HOME/.screen' or simply to `/tmp/screens' or preferably to `/usr/local/screens' chosen at -compile-time. If `screen' is installed setuid root, then the -administrator should compile screen with an adequate (not NFS mounted) -`SOCKDIR'. If `screen' is not running setuid-root, the user can specify -any mode 777 directory in the environment variable `$SCREENDIR'. +compile-time (`/var/run/screens' for Debian GNU/Linux). If `screen' is +installed setuid root, then the administrator should compile screen +with an adequate (not NFS mounted) `SOCKDIR'. If `screen' is not +running setuid-root, the user can specify any mode 777 directory in the +environment variable `$SCREENDIR'. File: screen.info, Node: Compiling Screen, Prev: Socket Directory, Up: Installation diff --git a/etc/etcscreenrc b/etc/etcscreenrc index fe98163..6021d5f 100644 --- a/etc/etcscreenrc +++ b/etc/etcscreenrc @@ -93,3 +93,10 @@ bind 'K' kill bind 'I' login on bind 'O' login off bind '}' history + +# colon takes a parameter since screen-3.8.6 +bind 'R' colon "screen -ln rlogin faui -8^b^b^b" +bind 'P' colon "^p" + +# On Debian GNU/Linux, `<--' (Backspace key) should send char `\177': +bindkey -k kb stuff "\177" diff --git a/etc/screenrc b/etc/screenrc index 839ad8c..76fc888 100644 --- a/etc/screenrc +++ b/etc/screenrc @@ -32,6 +32,8 @@ pow_detach_msg "Screen session of \$LOGNAME \$:cr:\$:nl:ended." defscrollback 1000 +# don't kill window after the process died +# zombie "^[" ################ # @@ -55,7 +57,7 @@ termcapinfo xterm* OL=10000 # keys. termcapinfo xterm 'VR=\E[?5h:VN=\E[?5l' termcapinfo xterm 'k1=\E[11~:k2=\E[12~:k3=\E[13~:k4=\E[14~' -termcapinfo xterm 'kh=\E[1~:kI=\E[2~:kD=\E[3~:kH=\E[4~:kP=\E[5~:kN=\E[6~' +termcapinfo xterm 'kh=\E[1~:kI=\E[2~:kD=\E[3~:kH=\E[4~:kP=\E[H:kN=\E[6~' # special xterm hardstatus: use the window title. termcapinfo xterm 'hs:ts=\E]2;:fs=\007:ds=\E]0;screen\007' @@ -122,3 +124,11 @@ register [ "\033:se noai\015a" register ] "\033:se ai\015a" bind ^] paste [.] +################ +# +# default windows +# + +# screen -t local 0 +# screen -t mail 1 elm +# screen -t 40 2 rlogin faui40 @@ -24,7 +24,7 @@ /* screen.c */ -extern void main __P((int, char **)); +extern int main __P((int, char **)); extern sigret_t SigHup __P(SIGPROTOARG); extern void eexit __P((int)); extern void Detach __P((int)); @@ -69,7 +69,7 @@ extern int secopen __P((char *, int, int)); extern void WriteFile __P((int)); extern char *ReadFile __P((char *, int *)); extern void KillBuffers __P((void)); -extern char *expand_vars __P((char *)); +extern char *expand_vars __P((char *, struct display *)); /* tty.c */ extern int OpenTTY __P((char *)); @@ -99,10 +99,11 @@ extern void ISearch __P((int)); /* input.c */ extern void inp_setprompt __P((char *, char *)); -extern void Input __P((char *, int, void (*)(), int)); +extern void Input __P((char *, int, int, void (*)(), char *)); +extern int InInput __P((void)); /* help.c */ -extern void exit_with_usage __P((char *)); +extern void exit_with_usage __P((char *, char *, char *)); extern void display_help __P((void)); extern void display_copyright __P((void)); extern void display_displays __P((void)); @@ -161,7 +162,7 @@ extern int IsNumColon __P((char *, int, char *, int)); extern void ShowWindows __P((void)); extern int WindowByNoN __P((char *)); #ifdef COPY_PASTE -extern int CompileKeys __P((char *, char *)); +extern int CompileKeys __P((char *, unsigned char *)); #endif /* termcap.c */ @@ -247,7 +248,7 @@ extern void DoResize __P((int, int)); extern char *xrealloc __P((char *, int)); /* socket.c */ -extern int FindSocket __P((int *, int *, char *)); +extern int FindSocket __P((int *, int *, int *, char *)); extern int MakeClientSocket __P((int)); extern int MakeServerSocket __P((void)); extern int RecoverSocket __P((void)); @@ -292,6 +293,14 @@ extern void xsetegid __P((int)); #endif extern int AddXChar __P((char *, int)); extern int AddXChars __P((char *, int, char *)); +extern void opendebug __P((int, int)); +#ifdef USEVARARGS +# ifndef HAVE_VSNPRINTF +extern int xvsnprintf __P((char *, int, char *, va_list)); +# endif +#else +extern int xsnprintf __P(()); +#endif /* acl.c */ #ifdef MULTIUSER @@ -306,9 +315,10 @@ extern int AclUserAddGroup __P((char *, char *)); extern int AclUserDelGroup __P((char *, char *)); extern int AclCheckPermWin __P((struct user *, int, struct win *)); extern int AclCheckPermCmd __P((struct user *, int, struct comm *)); -extern int AclSetPerm __P((struct user *, char *, char *)); +extern int AclSetPerm __P((struct user *, struct user *, char *, char *)); +extern int UsersAcl __P((struct user *, int, char **)); extern void AclWinSwap __P((int, int)); -extern int NewWindowAcl __P((struct win *)); +extern int NewWindowAcl __P((struct win *, struct user *)); #endif /* MULTIUSER */ extern struct user **FindUserPtr __P((char *)); extern int UserAdd __P((char *, char *, struct user **)); @@ -121,7 +121,7 @@ char *rcfile; else { debug(" ...nothing in $SCREENRC, defaulting $HOME/.screenrc\n"); - if (strlen(home) > 244) + if (strlen(home) > sizeof(buf) - 12) Panic(0, "Rc: home too large"); sprintf(buf, "%s/.iscreenrc", home); if (access(buf, R_OK)) @@ -176,7 +176,7 @@ char *rcfilename; { if ((p = rindex(buf, '\n')) != NULL) *p = '\0'; - if ((argc = Parse(expand_vars(buf), args)) == 0) + if ((argc = Parse(expand_vars(buf, display), args)) == 0) continue; if (strcmp(args[0], "echo") == 0) { @@ -279,160 +279,13 @@ char *rcfilename; rc_name = ""; } -/* - * "$HOST blafoo" -> "localhost blafoo" - * "${HOST}blafoo" -> "localhostblafoo" - * "\$HOST blafoo" -> "$HOST blafoo" - * "\\$HOST blafoo" -> "\localhost blafoo" - * "'$HOST ${HOST}'" -> "'$HOST ${HOST}'" - * "'\$HOST'" -> "'\$HOST'" - * "\'$HOST' $HOST" -> "'localhost' $HOST" - * - * "$:termcapname:" -> "termcapvalue" - * "$:terminfoname:" -> "termcapvalue" - * - * "\101" -> "A" - * "^a" -> "\001" - */ -char * -expand_vars(ss) -char *ss; -{ - static char ebuf[2048]; - register int esize = 2047, vtype, quofl = 0; - register char *e = ebuf; - register char *s = ss; - register char *v; - char xbuf[11]; - int i; - - while (*s && *s != '\0' && *s != '\n' && esize > 0) - { - if (*s == '\'') - quofl ^= 1; - if (*s == '$' && !quofl) - { - char *p, c; - - p = ++s; - switch (*s) - { - case '{': - p = ++s; - while (*p != '}') - if (*p++ == '\0') - return ss; - vtype = 0; /* env var */ - break; - case ':': - p = ++s; - while (*p != ':') - if (*p++ == '\0') - return ss; - vtype = 1; /* termcap string */ - break; - default: - while (*p != ' ' && *p != '\0' && *p != '\n') - p++; - vtype = 0; /* env var */ - } - c = *p; - debug1("exp: c='%c'\n", c); - *p = '\0'; - if (vtype == 0) - { - v = xbuf; - if (strcmp(s, "TERM") == 0) - v = display ? D_termname : "unknown"; - else if (strcmp(s, "COLUMNS") == 0) - sprintf(xbuf, "%d", display ? D_width : -1); - else if (strcmp(s, "LINES") == 0) - sprintf(xbuf, "%d", display ? D_height : -1); - else - v = getenv(s); - } - else - v = gettermcapstring(s); - if (v) - { - debug2("exp: $'%s'='%s'\n", s, v); - while (*v && esize-- > 0) - *e++ = *v++; - } - else - debug1("exp: '%s' not env\n", s); /* '{'-: */ - if ((*p = c) == '}' || c == ':') - p++; - s = p; - } - else if (*s == '^' && !quofl) - { - s++; - i = *s++; - if (i == '?') - i = '\177'; - else - i &= 0x1f; - *e++ = i; - esize--; - } - else - { - /* - * \$, \\$, \\, \\\, \012 are reduced here, - * other sequences starting whith \ are passed through. - */ - if (s[0] == '\\' && !quofl) - { - if (s[1] >= '0' && s[1] <= '7') - { - s++; - i = *s - '0'; - s++; - if (*s >= '0' && *s <= '7') - { - i = i * 8 + *s - '0'; - s++; - if (*s >= '0' && *s <= '7') - { - i = i * 8 + *s - '0'; - s++; - } - } - debug2("expandvars: octal coded character %o (%d)\n", i, i); - *e++ = i; - esize--; - continue; - } - else - { - if (s[1] == '$' || - (s[1] == '\\' && s[2] == '$') || - s[1] == '\'' || - (s[1] == '\\' && s[2] == '\'') || - s[1] == '^' || - (s[1] == '\\' && s[2] == '^')) - s++; - } - } - *e++ = *s++; - esize--; - } - } - if (esize <= 0) - Msg(0, "expand_vars: buffer overflow\n"); - *e = '\0'; - debug1("expand_var returns '%s'\n", ebuf); - return ebuf; -} - void RcLine(ubuf) char *ubuf; { char *args[MAXARGS], *buf; - buf = expand_vars(ubuf); + buf = expand_vars(ubuf, display); if (Parse(buf, args) <= 0) return; DoCommand(args); @@ -458,11 +311,13 @@ int dump; { case DUMP_TERMCAP: i = SockName - SockPath; + if (i > sizeof(fn) - 9) + i = 0; strncpy(fn, SockPath, i); strcpy(fn + i, ".termcap"); break; case DUMP_HARDCOPY: - if (hardcopydir) + if (hardcopydir && strlen(hardcopydir) < sizeof(fn) - 21) sprintf(fn, "%s/hardcopy.%d", hardcopydir, fore->w_number); else sprintf(fn, "hardcopy.%d", fore->w_number); @@ -471,7 +326,8 @@ int dump; break; #ifdef COPY_PASTE case DUMP_EXCHANGE: - sprintf(fn, "%s", BufferFile); + strncpy(fn, BufferFile, sizeof(fn) - 1); + fn[sizeof(fn) - 1] = 0; umask(0); break; #endif @@ -39,8 +39,8 @@ extern struct mchar mchar_null; void -exit_with_usage(myname) -char *myname; +exit_with_usage(myname, message, arg) +char *myname, *message, *arg; { printf("Use: %s [-opts] [cmd [args]]\n", myname); printf(" or: %s -r [host.tty]\n\nOptions:\n", myname); @@ -74,6 +74,12 @@ char *myname; #ifdef MULTI printf("-x Attach to a not detached screen. (Multi display mode).\n"); #endif /* MULTI */ + if (message && *message) + { + printf("\nError: "); + printf(message, arg); + printf("\n"); + } exit(1); } @@ -287,7 +293,8 @@ helppage() debug1("help: searching key %d\n", n); buf[0] = '\0'; for (key = 0; key < 256; key++) - if (ktab[key].nr == n && ktab[key].args == noargs) + if (ktab[key].nr == n && ktab[key].args == noargs && strlen(buf) < sizeof(buf) - 7) + { strcat(buf, " "); add_key_to_buf(buf, key); @@ -360,7 +367,7 @@ int fr; *bp++ = del = '\''; } while (*cp && bp < buf + 250) - bp += AddXChar(bp, *cp++); + bp += AddXChar(bp, *(unsigned char *)cp++); if (del) *bp++ = del; *bp = 0; @@ -389,10 +396,11 @@ int key; debug1("help: key found: %c\n", key); buf += strlen(buf); if (key < 0) - sprintf(buf, "unset"); + strcpy(buf, "unset"); else if (key == ' ') - sprintf(buf, "sp"); - else buf[AddXChar(buf, key)] = 0; + strcpy(buf, "sp"); + else + buf[AddXChar(buf, key)] = 0; } @@ -37,15 +37,25 @@ static void InpSetCursor __P((void)); extern struct display *display; extern struct mchar mchar_blank, mchar_so; +struct inpline +{ + char buf[101]; /* text buffer */ + int len; /* length of the editible string */ + int pos; /* cursor position in editable string */ +}; + +static struct inpline inphist; /* XXX: should be a dynamic list */ + + struct inpdata { - char inpbuf[101]; - int inplen; - int inpmaxlen; - char *inpstring; - int inpstringlen; - int inpmode; - void (*inpfinfunc)(); + struct inpline inp; + int inpmaxlen; /* 100, or less, if caller has shorter buffer */ + char *inpstring; /* the prompt */ + int inpstringlen; /* length of the prompt */ + int inpmode; /* INP_NOECHO, INP_RAW, INP_EVERY */ + void (*inpfinfunc) __P((char *buf, int len, char *priv)); + char *priv; }; static struct LayFuncs InpLf = @@ -78,9 +88,10 @@ char *p, *s; } if (s) { - strncpy(inpdata->inpbuf, s, sizeof(inpdata->inpbuf) - 1); - inpdata->inpbuf[sizeof(inpdata->inpbuf) - 1] = 0; - inpdata->inplen = strlen(inpdata->inpbuf); + if (s != inpdata->inp.buf) + strncpy(inpdata->inp.buf, s, sizeof(inpdata->inp.buf) - 1); + inpdata->inp.buf[sizeof(inpdata->inp.buf) - 1] = 0; + inpdata->inp.pos = inpdata->inp.len = strlen(inpdata->inp.buf); } RefreshLine(STATLINE, 0, D_width - 1, 0); } @@ -93,13 +104,15 @@ char *p, *s; * mode is an OR of * INP_NOECHO == suppress echoing of characters. * INP_RAW == raw mode. call finfunc after each character typed. + * INP_EVERY == digraph mode. */ void -Input(istr, len, finfunc, mode) +Input(istr, len, mode, finfunc, data) char *istr; int len; -void (*finfunc)(); int mode; +void (*finfunc) __P((char *buf, int len, char *data)); +char *data; { int maxlen; struct inpdata *inpdata; @@ -129,8 +142,9 @@ int mode; inpdata = (struct inpdata *)D_lay->l_data; inpdata->inpmaxlen = len; inpdata->inpfinfunc = finfunc; - inpdata->inplen = 0; + inpdata->inp.pos = inpdata->inp.len = 0; inpdata->inpmode = mode; + inpdata->priv = data; inp_setprompt(istr, (char *)NULL); } @@ -140,7 +154,7 @@ InpSetCursor() struct inpdata *inpdata; inpdata = (struct inpdata *)D_lay->l_data; - GotoPos(inpdata->inpstringlen + (inpdata->inpmode & INP_NOECHO ? 0 : inpdata->inplen), STATLINE); + GotoPos(inpdata->inpstringlen + (inpdata->inpmode & INP_NOECHO ? 0 : inpdata->inp.pos), STATLINE); } static void @@ -155,70 +169,134 @@ int *plen; inpdata = (struct inpdata *)D_lay->l_data; - GotoPos(inpdata->inpstringlen + (inpdata->inpmode & INP_NOECHO ? 0 : inpdata->inplen), STATLINE); + GotoPos(inpdata->inpstringlen + (inpdata->inpmode & INP_NOECHO ? 0 : inpdata->inp.pos), STATLINE); if (ppbuf == 0) { InpAbort(); return; } - x = inpdata->inpstringlen + inpdata->inplen; + x = inpdata->inpstringlen + inpdata->inp.pos; len = *plen; pbuf = *ppbuf; while (len) { + char *p = inpdata->inp.buf + inpdata->inp.pos; + ch = *pbuf++; len--; if (inpdata->inpmode & INP_EVERY) { - inpdata->inpbuf[inpdata->inplen] = ch; - inpdata->inpbuf[inpdata->inplen + 1] = ch; /* gross */ - (*inpdata->inpfinfunc)(inpdata->inpbuf, inpdata->inplen); - ch = inpdata->inpbuf[inpdata->inplen]; + inpdata->inp.buf[inpdata->inp.len] = ch; + inpdata->inp.buf[inpdata->inp.len + 1] = ch; /* gross */ + (*inpdata->inpfinfunc)(inpdata->inp.buf, inpdata->inp.len, inpdata->priv); + ch = inpdata->inp.buf[inpdata->inp.len]; } else if (inpdata->inpmode & INP_RAW) { - (*inpdata->inpfinfunc)(&ch, 1); /* raw */ + (*inpdata->inpfinfunc)(&ch, 1, inpdata->priv); /* raw */ if (ch) continue; } - if ((unsigned char)ch >= ' ' && ch != 0177 && inpdata->inplen < inpdata->inpmaxlen) + if (((unsigned char)ch & 0177) >= ' ' && ch != 0177 && inpdata->inp.len < inpdata->inpmaxlen) { - inpdata->inpbuf[inpdata->inplen++] = ch; + if (inpdata->inp.len > inpdata->inp.pos) + bcopy(p, p+1, inpdata->inp.len - inpdata->inp.pos); + inpdata->inp.len++; + inpdata->inp.buf[inpdata->inp.pos++] = ch; + if (!(inpdata->inpmode & INP_NOECHO)) { GotoPos(x, STATLINE); SetRendition(&mchar_so); - PUTCHAR(ch); + PUTCHAR(*p++); x++; + if (p < inpdata->inp.buf+inpdata->inp.len) + { + while (p < inpdata->inp.buf+inpdata->inp.len) + PUTCHAR(*p++); + GotoPos(x, STATLINE); + } } } - else if ((ch == '\b' || ch == 0177) && inpdata->inplen > 0) + else if ((ch == '\b' || ch == 0177) && inpdata->inp.pos > 0) { - inpdata->inplen--; + if (inpdata->inp.len > inpdata->inp.pos) + bcopy(p, p-1, inpdata->inp.len - inpdata->inp.pos); + inpdata->inp.len--; + inpdata->inp.pos--; + p--; if (!(inpdata->inpmode & 1)) { x--; GotoPos(x, STATLINE); + SetRendition(&mchar_so); + while (p < inpdata->inp.buf+inpdata->inp.len) + PUTCHAR(*p++); SetRendition(&mchar_blank); PUTCHAR(' '); GotoPos(x, STATLINE); } } + else if (ch == '\001' || (unsigned char)ch == 0201) /* CTRL-A */ + { + GotoPos(x -= inpdata->inp.pos, STATLINE); + inpdata->inp.pos = 0; + } + else if ((ch == '\002' || (unsigned char)ch == 0202) && inpdata->inp.pos > 0) /* CTRL-B */ + { + GotoPos(--x, STATLINE); + inpdata->inp.pos--; + } + else if (ch == '\005' || (unsigned char)ch == 0205) /* CTRL-E */ + { + GotoPos(x += inpdata->inp.len - inpdata->inp.pos, STATLINE); + inpdata->inp.pos = inpdata->inp.len; + } + else if ((ch == '\006' || (unsigned char)ch == 0206) && inpdata->inp.pos < inpdata->inp.len) /* CTRL-F */ + { + GotoPos(++x, STATLINE); + inpdata->inp.pos++; + } + else if (ch == '\020' || (unsigned char)ch == 0220) /* CTRL-P */ + { + p = inpdata->inp.buf; + GotoPos(inpdata->inpstringlen, STATLINE); + SetRendition(&mchar_blank); + while (p++ < inpdata->inp.buf+inpdata->inp.len) + PUTCHAR(' '); + + inpdata->inp = inphist; /* structure copy */ + if (inpdata->inp.len > inpdata->inpmaxlen) + inpdata->inp.len = inpdata->inpmaxlen; + if (inpdata->inp.pos > inpdata->inp.len) + inpdata->inp.pos = inpdata->inp.len; + x = inpdata->inpstringlen + inpdata->inp.pos; + + p = inpdata->inp.buf; + GotoPos(inpdata->inpstringlen, STATLINE); + SetRendition(&mchar_so); + while (p < inpdata->inp.buf+inpdata->inp.len) + PUTCHAR(*p++); + GotoPos(x, STATLINE); + } else if (ch == '\004' || ch == '\003' || ch == '\007' || ch == '\033' || ch == '\000' || ch == '\n' || ch == '\r') { - if (ch != '\033' && ch != '\n' && ch != '\r') - inpdata->inplen = 0; - inpdata->inpbuf[inpdata->inplen] = 0; + if (ch != '\004' && ch != '\n' && ch != '\r') + inpdata->inp.len = 0; + inpdata->inp.buf[inpdata->inp.len] = 0; + + if (inpdata->inp.len) + inphist = inpdata->inp; /* structure copy */ D_lay->l_data = 0; InpAbort(); /* redisplays... */ *ppbuf = pbuf; *plen = len; if ((inpdata->inpmode & INP_RAW) == 0) - (*inpdata->inpfinfunc)(inpdata->inpbuf, inpdata->inplen); + (*inpdata->inpfinfunc)(inpdata->inp.buf, inpdata->inp.len, inpdata->priv); else - (*inpdata->inpfinfunc)(pbuf - 1, 0); + (*inpdata->inpfinfunc)(pbuf - 1, 0, inpdata->priv); free((char *)inpdata); return; } @@ -248,7 +326,7 @@ int y, xs, xe, isblank; LAY_CALL_UP(RefreshLine(y, xs, xe, isblank)); return; } - inpdata->inpbuf[inpdata->inplen] = 0; + inpdata->inp.buf[inpdata->inp.len] = 0; GotoPos(xs, y); q = xs; v = xe - xs + 1; @@ -265,14 +343,14 @@ int y, xs, xe, isblank; v -= l; } s = r; - r += inpdata->inplen; + r += inpdata->inp.len; if (!(inpdata->inpmode & INP_NOECHO) && v > 0 && q < r) { SetRendition(&mchar_so); l = v; if (l > r-q) l = r-q; - AddStrn(inpdata->inpbuf + q - s, l); + AddStrn(inpdata->inp.buf + q - s, l); q += l; v -= l; } @@ -289,3 +367,12 @@ int y, xs, xe, isblank; } SetLastPos(q, y); } + +int +InInput() +{ + if (display && D_layfn->LayProcess == InpProcess) + return 1; + return 0; +} + diff --git a/kmapdef.c.dist b/kmapdef.c.dist index 943c600..fef98ed 100644 --- a/kmapdef.c.dist +++ b/kmapdef.c.dist @@ -20,6 +20,14 @@ char *kmapdef[] = { "\033[21~", "\033[23~", "\033[24~", +0, +0, +0, +0, +0, +0, +0, +0, "\010", "\033[1~", 0, @@ -96,7 +104,7 @@ char *kmapadef[] = { }; char *kmapmdef[] = { -"g", +"\201", 0, 0, 0, @@ -109,7 +117,7 @@ char *kmapmdef[] = { 0, 0, "\004", -"G", +"\205", 0, 0, 0, @@ -121,10 +129,10 @@ char *kmapmdef[] = { 0, 0, 0, -"k", -"j", -"l", -"h" +"\220", +"\216", +"\206", +"\202" }; #endif @@ -73,7 +73,7 @@ static struct LayFuncs MarkLf = }; int join_with_cr = 0; -char mark_key_tab[256]; /* this array must be initialised first! */ +unsigned char mark_key_tab[256]; /* this array must be initialised first! */ static struct markdata *markdata; @@ -528,7 +528,7 @@ int *inlenp; else */ { - od = mark_key_tab[(unsigned int)*pt++]; + od = mark_key_tab[(int)(unsigned char)*pt++]; inlen--; } rep_cnt = markdata->rep_cnt; @@ -567,12 +567,14 @@ int *inlenp; Redisplay(0); GotoPos(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) @@ -601,12 +603,14 @@ int *inlenp; case '\n': revto(markdata->left_mar, cy + 1); break; - case 'k': + 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; @@ -687,9 +691,11 @@ int *inlenp; rep_cnt = 100; revto_line(markdata->left_mar, (rep_cnt * (fore->w_histheight + D_height)) / 100, (D_height - 1) / 2); break; + case 0201: case 'g': rep_cnt = 1; /* FALLTHROUGH */ + case 0205: case 'G': /* rep_cnt is here the WIN line number */ if (rep_cnt == 0) @@ -25,6 +25,7 @@ RCS_ID("$Id: misc.c,v 1.5 1994/05/31 12:32:19 mlschroe Exp $ FAU") #include <sys/types.h> +#include <sys/stat.h> /* mkdir() declaration */ #include <signal.h> #include "config.h" @@ -196,7 +197,7 @@ int egid; Panic(errno, "setegid"); } -#else +#else /* HAVE_SETEUID */ # ifdef HAVE_SETREUID void @@ -229,8 +230,8 @@ int egid; Panic(errno, "setregid"); } -# endif -#endif +# endif /* HAVE_SETREUID */ +#endif /* HAVE_SETEUID */ @@ -293,8 +294,6 @@ int except; close(f); } - - /* * Security - switch to real uid */ @@ -427,6 +426,11 @@ int len; { char *p; + if (str == 0) + { + *buf = 0; + return 0; + } len -= 4; /* longest sequence produced by AddXChar() */ for (p = buf; p < buf + len && *str; str++) { @@ -439,6 +443,181 @@ int len; return p - buf; } +#ifdef DEBUG +void +opendebug(new, shout) +int new, shout; +{ + char buf[256]; + +#ifdef _MODE_T + mode_t oumask = umask(0); +#else + int oumask = umask(0); +#endif + + ASSERT(!dfp); + + (void) mkdir(DEBUGDIR, 0777); + sprintf(buf, shout ? "%s/SCREEN.%d" : "%s/screen.%d", DEBUGDIR, getpid()); + if (!(dfp = fopen(buf, new ? "w" : "a"))) + dfp = stderr; + else + (void)chmod(buf, 0666); + + (void)umask(oumask); + debug("opendebug: done.\n"); +} +#endif /* DEBUG */ + +/* + * "$HOST blafoo" -> "localhost blafoo" + * "${HOST}blafoo" -> "localhostblafoo" + * "\$HOST blafoo" -> "$HOST blafoo" + * "\\$HOST blafoo" -> "\localhost blafoo" + * "'$HOST ${HOST}'" -> "'$HOST ${HOST}'" + * "'\$HOST'" -> "'\$HOST'" + * "\'$HOST' $HOST" -> "'localhost' $HOST" + * + * "$:termcapname:" -> "termcapvalue" + * "$:terminfoname:" -> "termcapvalue" + * + * "\101" -> "A" + * "^a" -> "\001" + * + * display == NULL is valid here! + */ +char * +expand_vars(ss, d) +char *ss; +struct display *d; +{ + static char ebuf[2048]; + register int esize = 2047, vtype, quofl = 0; + register char *e = ebuf; + register char *s = ss; + register char *v; + char xbuf[11]; + int i; + + while (s && *s != '\0' && *s != '\n' && esize > 0) + { + if (*s == '\'') + quofl ^= 1; + if (*s == '$' && !quofl) + { + char *p, c; + + p = ++s; + switch (*s) + { + case '{': + p = ++s; + while (*p != '}') + if (*p++ == '\0') + return ss; + vtype = 0; /* env var */ + break; + case ':': + p = ++s; + while (*p != ':') + if (*p++ == '\0') + return ss; + vtype = 1; /* termcap string */ + break; + default: + while (*p != ' ' && *p != '\0' && *p != '\n') + p++; + vtype = 0; /* env var */ + } + c = *p; + debug1("exp: c='%c'\n", c); + *p = '\0'; + if (vtype == 0) + { + v = xbuf; + if (strcmp(s, "TERM") == 0) + v = d ? d->d_termname : "unknown"; + else if (strcmp(s, "COLUMNS") == 0) + sprintf(xbuf, "%d", d ? d->d_width : -1); + else if (strcmp(s, "LINES") == 0) + sprintf(xbuf, "%d", d ? d->d_height : -1); + else + v = getenv(s); + } + else + v = gettermcapstring(s); + if (v) + { + debug2("exp: $'%s'='%s'\n", s, v); + while (*v && esize-- > 0) + *e++ = *v++; + } + else + debug1("exp: '%s' not env\n", s); /* '{'-: */ + if ((*p = c) == '}' || c == ':') + p++; + s = p; + } + else if (*s == '^' && !quofl) + { + s++; + i = *s++; + if (i == '?') + i = '\177'; + else + i &= 0x1f; + *e++ = i; + esize--; + } + else + { + /* + * \$, \\$, \\, \\\, \012 are reduced here, + * other sequences starting whith \ are passed through. + */ + if (s[0] == '\\' && !quofl) + { + if (s[1] >= '0' && s[1] <= '7') + { + s++; + i = *s - '0'; + s++; + if (*s >= '0' && *s <= '7') + { + i = i * 8 + *s - '0'; + s++; + if (*s >= '0' && *s <= '7') + { + i = i * 8 + *s - '0'; + s++; + } + } + debug2("expandvars: octal coded character %o (%d)\n", i, i); + *e++ = i; + esize--; + continue; + } + else + { + if (s[1] == '$' || + (s[1] == '\\' && s[2] == '$') || + s[1] == '\'' || + (s[1] == '\\' && s[2] == '\'') || + s[1] == '^' || + (s[1] == '\\' && s[2] == '^')) + s++; + } + } + *e++ = *s++; + esize--; + } + } + if (esize <= 0) + Msg(0, "expand_vars: buffer overflow\n"); + *e = '\0'; + return ebuf; +} #ifdef TERMINFO /* @@ -466,3 +645,117 @@ int (*outc)(); } #endif + +#ifndef USEVARARGS + +# define xva_arg(s, t, tn) (*(t *)(s += xsnoff(tn, 0, 0), s - xsnoff(tn, 0, 0))) +# define xva_list char * + +static int +xsnoff(a, b, c) +int a; +char *b; +int c; +{ + return a ? (char *)&c - (char *)&b : (char *)&b - (char *)&a; +} + +int +xsnprintf(s, n, fmt, p1, p2, p3, p4, p5, p6) +char *s; +int n; +char *fmt; +unsigned long p1, p2, p3, p4, p5, p6; +{ + int xvsnprintf __P((char *, int, char *, xva_list)); + return xvsnprintf(s, n, fmt, (char *)&fmt + xsnoff(1, 0, 0)); +} + +#else + +# define xva_arg(s, t, tn) va_arg(s, t) +# define xva_list va_list + +#endif + + +#if !defined(USEVARARGS) || !defined(HAVE_VSNPRINTF) + +int +xvsnprintf(s, n, fmt, stack) +char *s; +int n; +char *fmt; +xva_list stack; +{ + char *f, *sf = 0; + int i, on, argl = 0; + char myf[10], buf[20]; + char *arg, *myfp; + + on = n; + f = fmt; + arg = 0; + while(arg || (sf = index(f, '%')) || (sf = f + strlen(f))) + { + if (arg == 0) + { + arg = f; + argl = sf - f; + } + if (argl) + { + i = argl > n - 1 ? n - 1 : argl; + strncpy(s, arg, i); + s += i; + n -= i; + if (i < argl) + { + *s = 0; + return on; + } + } + arg = 0; + if (sf == 0) + continue; + f = sf; + sf = 0; + if (!*f) + break; + myfp = myf; + *myfp++ = *f++; + while (((*f >= '0' && *f <='9') || *f == '#') && myfp - myf < 8) + *myfp++ = *f++; + *myfp++ = *f; + *myfp = 0; + if (!*f++) + break; + switch(f[-1]) + { + case '%': + arg = "%"; + break; + case 'c': + case 'o': + case 'd': + case 'x': + i = xva_arg(stack, int, 0); + sprintf(buf, myf, i); + arg = buf; + break; + case 's': + arg = xva_arg(stack, char *, 1); + if (arg == 0) + arg = "NULL"; + break; + default: + arg = ""; + break; + } + argl = strlen(arg); + } + *s = 0; + return on - n; +} + +#endif @@ -27,6 +27,11 @@ #include <sys/param.h> +/* In strict ANSI mode, HP-UX machines define __hpux but not hpux */ +#if defined(__hpux) && !defined(hpux) +# define hpux +#endif + #if defined(BSDI) || defined(__386BSD__) || defined(_CX_UX) || defined(hpux) # include <signal.h> #endif /* BSDI || __386BSD__ || _CX_UX */ @@ -111,7 +116,9 @@ extern int errno; # define bcmp memcmp # define killpg(pgrp,sig) kill( -(pgrp), sig) #else -# define getcwd(b,l) getwd(b) +# ifndef linux +# define getcwd(b,l) getwd(b) +# endif #endif #ifndef USEBCOPY @@ -137,7 +144,14 @@ extern int errno; #endif #if !defined(HAVE__EXIT) && !defined(_exit) -#define _exit(x) exit(x) +# define _exit(x) exit(x) +#endif + +#ifndef HAVE_UTIMES +# define utimes utime +#endif +#ifndef HAVE_VSNPRINTF +# define vsnprintf xvsnprintf #endif /***************************************************************** @@ -161,6 +161,7 @@ extern int vsprintf __P((char *, char *, va_list)); #endif struct timeval; /* for select __P */ extern int select __P((int, fd_set *, fd_set *, fd_set *, struct timeval *)); +extern int utimes __P((char *, struct timeval *)); extern void unsetenv __P((char *)); diff --git a/patchlevel.h b/patchlevel.h index e7bd579..f25e500 100644 --- a/patchlevel.h +++ b/patchlevel.h @@ -227,11 +227,25 @@ * linux: elf, but no SVR4, check for utmpx. * hpux10.10 libcurses breaks select()! * -- DISTRIBUTED + * 27.09.96 -- 3.07.03 ncurses tgetflag returns -1 if cap not valid. + * autonuke fix: reset application mode. An init + * string may have cleared it. + * Small UTMPOK patch from Douglas B. Jones. + * 23.06.97 -- 3.07.04 Some bugfixes. Kanji fixed. + * Code update from 3.8.6: Colon line editing added. + * Digraph made line-editing resistant. + * DEC ALPHA ut_user[0] = 0; + * Added error messages to exit_with_usage. + * FindSocket code improved (the MULTIUSER part). + * Use utimes() if available. Power-detached start. + * vsnprintf() support. exit -> _exit in window.c. + * AddXChars now tolerates NULL string. + * -- DISTRIBUTED */ #define ORIGIN "FAU" #define REV 3 #define VERS 7 -#define PATCHLEVEL 2 -#define DATE "1-Sep-96" +#define PATCHLEVEL 4 +#define DATE "23-Jun-97" #define STATE "" @@ -69,7 +69,7 @@ extern int intrc, origintrc; /* display? */ extern struct NewWindow nwin_default, nwin_undef; #ifdef COPY_PASTE extern int join_with_cr, pastefont; -extern char mark_key_tab[]; +extern unsigned char mark_key_tab[]; extern char *BufferFile; #endif #ifdef POW_DETACH @@ -107,25 +107,27 @@ static int ParseWinNum __P((struct action *act, int *)); static int ParseBase __P((struct action *act, char *, int *, int, char *)); static char *ParseChar __P((char *, char *)); static int IsNum __P((char *, int)); -static void InputColon __P((void)); -static void Colonfin __P((char *, int)); +static void Colonfin __P((char *, int, char *)); static void InputSelect __P((void)); static void InputSetenv __P((char *)); static void InputAKA __P((void)); -static void AKAfin __P((char *, int)); +static void AKAfin __P((char *, int, char *)); #ifdef COPY_PASTE -static void copy_reg_fn __P((char *, int)); -static void ins_reg_fn __P((char *, int)); +static void copy_reg_fn __P((char *, int, char *)); +static void ins_reg_fn __P((char *, int, char *)); #endif -static void process_fn __P((char *, int)); +static void process_fn __P((char *, int, char *)); #ifdef PASSWORD -static void pass1 __P((char *, int)); -static void pass2 __P((char *, int)); +static void pass1 __P((char *, int, char *)); +static void pass2 __P((char *, int, char *)); #endif #ifdef POW_DETACH -static void pow_detach_fn __P((char *, int)); +static void pow_detach_fn __P((char *, int, char *)); +#endif +static void digraph_fn __P((char *, int, char *)); +#ifdef MAPKEYS +static int StuffKey __P((int)); #endif -static void digraph_fn __P((char *, int)); @@ -150,7 +152,9 @@ struct win *wtab[MAXWIN]; /* window table, should be dynamic */ #ifdef MULTIUSER extern char *multi; +extern int maxusercount; #endif +char NullStr[] = ""; /* not really used */ #ifdef PASSWORD int CheckPassword; char Password[30]; @@ -462,17 +466,16 @@ char *ibuf; int ilen; { int ch, slen; - char *s; - struct action *act; + unsigned char *s; int i, l; if (display == 0 || ilen == 0) return; slen = ilen; - s = ibuf; + s = (unsigned char *)ibuf; while(ilen-- > 0) { - ch = *(unsigned char *)s++; + ch = *s++; if (D_dontmap) D_dontmap = 0; else if (D_nseqs) @@ -503,7 +506,7 @@ int ilen; ProcessInput2(ibuf, slen); D_seqruns = 0; } - ibuf = s; + ibuf = (char *)s; slen = ilen; ch = -1; if (*++D_seqp == 0) @@ -511,29 +514,7 @@ int ilen; i = (struct kmap *)(D_seqp - D_seql - KMAP_SEQ) - D_kmaps; debug1("Mapping #%d", i); i = D_kmaps[i].nr & ~KMAP_NOTIMEOUT; -#ifdef DEBUG - if (i < KMAP_KEYS) - debug1(" - %s", term[i + T_CAPS].tcname); -#endif - if (i >= T_CURSOR - T_CAPS && i < T_KEYPAD - T_CAPS && D_cursorkeys) - i += T_OCAPS - T_CURSOR; - else if (i >= T_KEYPAD - T_CAPS && i < T_OCAPS - T_CAPS && D_keypad) - i += T_OCAPS - T_CURSOR; - debug1(" - action %d\n", i); - fore = D_fore; - act = 0; -#ifdef COPY_PASTE - if (InMark()) - act = &mmtab[i]; -#endif - if ((!act || act->nr == RC_ILLEGAL) && !D_mapdefault) - act = &umtab[i]; - D_mapdefault = 0; - if (!act || act->nr == RC_ILLEGAL) - act = &dmtab[i]; - if (act && act->nr != RC_ILLEGAL) - DoAction(act, 0); - else + if (StuffKey(i)) { D_seqp -= D_seql; ProcessInput2(D_seqp, D_seql); @@ -604,7 +585,7 @@ int ilen; if (ch >= 0) DoAction(&ktab[ch], ch); - ibuf = s + 1; + ibuf = (char *)(s + 1); ilen--; } } @@ -821,7 +802,7 @@ int key; static char buf[2]; buf[0] = key; - Input(buf, 1, pow_detach_fn, INP_RAW); + Input(buf, 1, INP_RAW, pow_detach_fn, NULL); } else Detach(D_POWER); /* detach and kill Attacher's parent */ @@ -845,14 +826,7 @@ int key; dfp = NULL; } if (strcmp("off", *args)) - { - char buf[255]; - - sprintf(buf, "%s/SCREEN.%d", DEBUGDIR, getpid()); - if ((dfp = fopen(buf, "a")) == NULL) - dfp = stderr; - debug("debug: opening debug file.\n"); - } + opendebug(0, 1); #else Msg(0, "Sorry, screen was compiled without -DDEBUG option."); #endif @@ -1045,7 +1019,7 @@ int key; */ if ((s = *args) == NULL) { - Input("Copy to register:", 1, copy_reg_fn, INP_RAW); + Input("Copy to register:", 1, INP_RAW, copy_reg_fn, NULL); break; } if (((s = ParseChar(s, &ch)) == NULL) || *s) @@ -1075,7 +1049,7 @@ int key; * This could be done with RC_PASTE too, but is here to be consistent * with the zero argument call. */ - copy_reg_fn(&ch, 0); + copy_reg_fn(&ch, 0, NULL); break; #endif case RC_REGISTER: @@ -1095,7 +1069,7 @@ int key; case RC_PROCESS: if ((s = *args) == NULL) { - Input("Process register:", 1, process_fn, INP_RAW); + Input("Process register:", 1, INP_RAW, process_fn, NULL); break; } if ((s = ParseChar(s, &ch)) == NULL || *s) @@ -1104,7 +1078,7 @@ int key; rc_name); break; } - process_fn(&ch, 0); + process_fn(&ch, 0, NULL); break; case RC_STUFF: s = *args; @@ -1245,7 +1219,13 @@ int key; ChangeAKA(fore, *args, 20); break; case RC_COLON: - InputColon(); + Input(":", 100, INP_COOKED, Colonfin, NULL); + if (*args && **args) + { + s = *args; + n = strlen(s); + Process(&s, &n); + } break; case RC_LASTMSG: if (D_status_lastmsg) @@ -1399,7 +1379,7 @@ int key; */ if ((s = *args) == NULL) { - Input("Paste from register:", 1, ins_reg_fn, INP_RAW); + Input("Paste from register:", 1, INP_RAW, ins_reg_fn, NULL); break; } /* @@ -1833,6 +1813,14 @@ int key; break; if (n) { +#ifdef MULTIUSER + if (display) /* we tell only this user */ + ACLBYTE(fore->w_lio_notify, D_user->u_id) |= ACLBIT(D_user->u_id); + else + for (i = 0; i < maxusercount; i++) + ACLBYTE(fore->w_mon_notify, i) |= ACLBIT(i); + if (!fore->w_tstamp.seconds) +#endif fore->w_tstamp.lastio = time(0); fore->w_tstamp.seconds = i; if (!msgok) @@ -1848,8 +1836,22 @@ int key; } else { - fore->w_tstamp.lastio = (time_t)0; - fore->w_tstamp.seconds = 0; +#ifdef MULTIUSER + if (display) /* we remove only this user */ + ACLBYTE(fore->w_lio_notify, D_user->u_id) + &= ~ACLBIT(D_user->u_id); + else + for (i = 0; i < maxusercount; i++) + ACLBYTE(fore->w_lio_notify, i) &= ~ACLBIT(i); + for (i = maxusercount - 1; i >= 0; i--) + if (ACLBYTE(fore->w_lio_notify, i)) + break; + if (i < 0) +#endif + { + fore->w_tstamp.lastio = (time_t)0; + fore->w_tstamp.seconds = 0; + } if (!msgok) break; #ifdef NETHACK @@ -1882,13 +1884,13 @@ int key; s = NULL; if (ParseSaveStr(act, &s)) break; - if (!*s || strlen(s) > MAXPATHLEN - 13) + if (!*s || strlen(s) + (SockName - SockPath) > MAXPATHLEN - 13) { Msg(0, "%s: bad session name '%s'\n", rc_name, s); free(s); break; } - sprintf(buf, "%s", SockPath); + strncpy(buf, SockPath, SockName - SockPath); sprintf(buf + (SockName - SockPath), "%d.%s", (int)getpid(), s); free(s); if ((access(buf, F_OK) == 0) || (errno != ENOENT)) @@ -1902,7 +1904,7 @@ int key; break; } debug2("rename(%s, %s) done\n", SockPath, buf); - sprintf(SockPath, "%s", buf); + strcpy(SockPath, buf); MakeNewEnv(); } break; @@ -1980,7 +1982,7 @@ int key; Msg(0, "Will %spaste font settings", pastefont ? "" : "not "); break; case RC_CRLF: - (void)ParseOnOff(act, &join_with_cr); + (void)ParseSwitch(act, &join_with_cr); break; #endif #ifdef NETHACK @@ -2036,8 +2038,8 @@ int key; debug("prompting for password on no display???\n"); break; } - Input("New screen password:", sizeof(Password) - 1, pass1, - INP_NOECHO); + Input("New screen password:", sizeof(Password) - 1, INP_NOECHO, + pass1, NULL); } break; #endif /* PASSWORD */ @@ -2103,7 +2105,7 @@ int key; if (*args == 0) { if (mf) - display_bindkey("Copy mode", mmtab); + display_bindkey("Edit mode", mmtab); else if (df) display_bindkey("Default", dmtab); else @@ -2216,39 +2218,18 @@ int key; #ifdef MULTIUSER case RC_ACLCHG: case RC_ACLADD: - { - struct user **u; - - if (args[0][0] == '*' && args[0][1] == '\0' && args[1] && args[2]) - { - for (u = &users; *u; u = &(*u)->u_next) - AclSetPerm(*u, args[1], args[2]); - break; - } - do - { - for (s = args[0]; *s && *s != ' ' && *s != '\t' && *s != ','; s++) - ; - *s ? (*s++ = '\0') : (*s = '\0'); - u = FindUserPtr(args[0]); - UserAdd(args[0], (char *)0, u); - if (args[1] && args[2]) - AclSetPerm(*u, args[1], args[2]); - else - AclSetPerm(*u, "+rwx", "#?"); - } while (*(args[0] = s)); - break; - } + for (n = 0; args[n]; n++) + ; + UsersAcl(NULL, n, args); + break; case RC_ACLDEL: - { - if (UserDel(args[0], (struct user **)0)) - break; - if (msgok) - Msg(0, "%s removed from acl database", args[0]); - break; - } + if (UserDel(args[0], NULL)) + break; + if (msgok) + Msg(0, "%s removed from acl database", args[0]); + break; case RC_ACLGRP: - { + { break; } case RC_MULTIUSER: @@ -2334,7 +2315,7 @@ int key; Msg(0, "using termcap entries for printing"); break; case RC_DIGRAPH: - Input("Enter digraph: ", 10, digraph_fn, INP_EVERY); + Input("Enter digraph: ", 10, INP_EVERY, digraph_fn, NULL); if (*args && **args) { s = *args; @@ -2462,6 +2443,15 @@ char **args; return ap; } +/* + * buf is split into argument vector args. + * leading whitespace is removed. + * @!| abbreviations are expanded. + * the end of buffer is recognized by '\0' or an un-escaped '#'. + * " and ' are interpreted. + * + * argc is returned. + */ int Parse(buf, args) char *buf, **args; @@ -2797,6 +2787,13 @@ char *bname; return 0; } +/* + * Interprets ^?, ^@ and other ^-control-char notation. + * Interprets \ddd octal notation + * + * The result is placed in *cp, p is advanced behind the parsed expression and + * returned. + */ static char * ParseChar(p, cp) char *p, *cp; @@ -3132,7 +3129,7 @@ ShowWindows() continue; cmd = p->w_title; - if (s - buf + strlen(cmd) > sizeof(buf) - 6) + if (s - buf + strlen(cmd) > sizeof(buf) - 24) break; if (s > buf) { @@ -3276,9 +3273,10 @@ ShowInfo() static void -AKAfin(buf, len) +AKAfin(buf, len, data) char *buf; int len; +char *data; /* dummy */ { ASSERT(display); if (len && fore) @@ -3288,28 +3286,24 @@ int len; static void InputAKA() { - Input("Set window's title to: ", 20, AKAfin, INP_COOKED); + Input("Set window's title to: ", 20, INP_COOKED, AKAfin, NULL); } static void -Colonfin(buf, len) +Colonfin(buf, len, data) char *buf; int len; +char *data; /* dummy */ { if (len) RcLine(buf); } static void -InputColon() -{ - Input(":", 100, Colonfin, INP_COOKED); -} - -static void -SelectFin(buf, len) +SelectFin(buf, len, data) char *buf; int len; +char *data; /* dummy */ { int n; @@ -3323,16 +3317,17 @@ int len; static void InputSelect() { - Input("Switch to window: ", 20, SelectFin, INP_COOKED); + Input("Switch to window: ", 20, INP_COOKED, SelectFin, NULL); } static char setenv_var[31]; static void -SetenvFin1(buf, len) +SetenvFin1(buf, len, data) char *buf; int len; +char *data; /* dummy */ { if (!len || !display) return; @@ -3340,9 +3335,10 @@ int len; } static void -SetenvFin2(buf, len) +SetenvFin2(buf, len, data) char *buf; int len; +char *data; /* dummy */ { struct action act; char *args[3]; @@ -3362,18 +3358,25 @@ static void InputSetenv(arg) char *arg; { - static char setenv_buf[80]; /* need to be static here, cannot be freed */ + static char setenv_buf[50 + sizeof(setenv_var)]; /* need to be static here, cannot be freed */ if (arg) { - strncpy(setenv_var, arg, 30); - sprintf(setenv_buf, "Enter value for %s: ", arg); - Input(setenv_buf, 30, SetenvFin2, INP_COOKED); + strncpy(setenv_var, arg, sizeof(setenv_var) - 1); + sprintf(setenv_buf, "Enter value for %s: ", setenv_var); + Input(setenv_buf, 30, INP_COOKED, SetenvFin2, NULL); } else - Input("Setenv: Enter variable name: ", 30, SetenvFin1, INP_COOKED); + Input("Setenv: Enter variable name: ", 30, INP_COOKED, SetenvFin1, NULL); } +/* + * the following options are understood by this parser: + * -f, -f0, -f1, -fy, -fa + * -t title, -T terminal-type, -h height-of-scrollback, + * -ln, -l0, -ly, -l1, -l + * -a, -M, -L + */ void DoScreen(fn, av) char *fn, **av; @@ -3503,7 +3506,8 @@ char *fn, **av; */ int CompileKeys(s, array) -char *s, *array; +char *s; +unsigned char *array; { int i; unsigned char key, value; @@ -3541,11 +3545,12 @@ char *s, *array; * Asynchronous input functions */ -#ifdef POW_DETACH +#if defined(POW_DETACH) static void -pow_detach_fn(buf, len) +pow_detach_fn(buf, len, data) char *buf; int len; +char *data; /* dummy */ { if (len) { @@ -3568,9 +3573,10 @@ int len; #ifdef COPY_PASTE static void -copy_reg_fn(buf, len) +copy_reg_fn(buf, len, data) char *buf; int len; +char *data; /* dummy */ { struct plop *pp = plop_tab + (int)(unsigned char)*buf; @@ -3592,9 +3598,10 @@ int len; } static void -ins_reg_fn(buf, len) +ins_reg_fn(buf, len, data) char *buf; int len; +char *data; /* dummy */ { struct plop *pp = plop_tab + (int)(unsigned char)*buf; @@ -3627,9 +3634,10 @@ int len; #endif /* COPY_PASTE */ static void -process_fn(buf, len) +process_fn(buf, len, data) char *buf; int len; +char *data; /* dummy */ { struct plop *pp = plop_tab + (int)(unsigned char)*buf; @@ -3656,19 +3664,21 @@ int len; /* ARGSUSED */ static void -pass1(buf, len) +pass1(buf, len, data) char *buf; int len; +char *data; { strncpy(Password, buf, sizeof(Password) - 1); - Input("Retype new password:", sizeof(Password) - 1, pass2, 1); + Input("Retype new password:", sizeof(Password) - 1, INP_NOECHO, pass2, NULL); } /* ARGSUSED */ static void -pass2(buf, len) +pass2(buf, len, data) char *buf; int len; +char *data; { int st; char salt[2]; @@ -3717,9 +3727,10 @@ int len; #endif /* PASSWORD */ static void -digraph_fn(buf, len) +digraph_fn(buf, len, data) char *buf; int len; +char *data; /* dummy */ { int ch, i, x; @@ -3732,7 +3743,7 @@ int len; { if (ch < '0' || ch > '7') { - buf[len] = '\001'; /* ignore */ + buf[len] = '\034'; /* ^] is ignored by Input() */ return; } if (len == 3) @@ -3775,3 +3786,39 @@ int len; while(i) Process(&buf, &i); } + +#ifdef MAPKEYS +static int +StuffKey(i) +int i; +{ + struct action *act; + + debug1("StuffKey #%d", i); +#ifdef DEBUG + if (i < KMAP_KEYS) + debug1(" - %s", term[i + T_CAPS].tcname); +#endif + if (i >= T_CURSOR - T_CAPS && i < T_KEYPAD - T_CAPS && D_cursorkeys) + i += T_OCAPS - T_CURSOR; + else if (i >= T_KEYPAD - T_CAPS && i < T_OCAPS - T_CAPS && D_keypad) + i += T_OCAPS - T_CURSOR; + debug1(" - action %d\n", i); + fore = D_fore; + act = 0; +#ifdef COPY_PASTE + if (InMark() || InInput()) + act = &mmtab[i]; +#endif + if ((!act || act->nr == RC_ILLEGAL) && !D_mapdefault) + act = &umtab[i]; + D_mapdefault = 0; + if (!act || act->nr == RC_ILLEGAL) + act = &dmtab[i]; + if (act == 0 || act->nr == RC_ILLEGAL) + return -1; + DoAction(act, 0); + return 0; +} +#endif + @@ -106,7 +106,7 @@ extern int intrc; extern int use_hardstatus; #ifdef COPY_PASTE -extern char mark_key_tab[]; +extern unsigned char mark_key_tab[]; #endif extern char version[]; extern char DefaultShell[]; @@ -135,7 +135,7 @@ char *attach_term; char *LoginName; struct mode attach_Mode; -char SockPath[MAXPATHLEN]; +char SockPath[MAXPATHLEN + 2 * MAXSTR]; char *SockName, *SockMatch; /* SockName is pointer in SockPath */ int ServerSocket = -1; @@ -313,7 +313,7 @@ fd_set *rp, *wp; FD_SET(ServerSocket, rp); } -void +int main(ac, av) int ac; char **av; @@ -367,16 +367,7 @@ char **av; */ closeallfiles(0); #ifdef DEBUG - { - char buf[255]; - - sprintf(buf, "%s/screen.%d", DEBUGDIR, getpid()); - (void) mkdir(DEBUGDIR, 0777); - if ((dfp = fopen(buf, "w")) == NULL) - dfp = stderr; - else - (void) chmod(buf, 0666); - } + opendebug(1, 0); #endif sprintf(version, "%d.%.2d.%.2d%s (%s) %s", REV, VERS, PATCHLEVEL, STATE, ORIGIN, DATE); @@ -490,7 +481,7 @@ char **av; else { if (--ac == 0) - exit_with_usage(myname); + exit_with_usage(myname, "Specify an alternate rc-filename with -c", NULL); RcFileName = *++av; } break; @@ -500,11 +491,12 @@ char **av; else { if (--ac == 0) - exit_with_usage(myname); + exit_with_usage(myname, "Specify command escape characters with -e", NULL); ap = *++av; } if (ParseEscape((struct user *)0, ap)) - Panic(0, "Two characters are required with -e option."); + Panic(0, "Two characters are required with -e option, not '%s'", ap); + ap = NULL; break; case 'f': switch (ap[2]) @@ -522,7 +514,7 @@ char **av; nwin_options.flowflag = FLOW_AUTOFLAG; break; default: - exit_with_usage(myname); + exit_with_usage(myname, "Unknown flow option -%s", --ap); } break; case 'h': @@ -531,23 +523,23 @@ char **av; else { if (--ac == 0) - exit_with_usage(myname); + exit_with_usage(myname, NULL, NULL); nwin_options.histheight = atoi(*++av); } if (nwin_options.histheight < 0) - exit_with_usage(myname); + exit_with_usage(myname, "-h %s: negative scrollback size?",*av); break; case 'i': iflag = 1; break; - case 't': /* title is a synonym for AkA */ - case 'k': + case 't': + case 'k': /* obsolete */ if (ap[2]) nwin_options.aka = ap + 2; else { if (--ac == 0) - exit_with_usage(myname); + exit_with_usage(myname, "Specify a new window-name with -t", NULL); nwin_options.aka = *++av; } break; @@ -573,7 +565,7 @@ char **av; } break; default: - exit_with_usage(myname); + exit_with_usage(myname, "%s: Unknown suboption to -l", ap); } break; case 'w': @@ -598,7 +590,7 @@ char **av; else { if (--ac == 0) - exit_with_usage(myname); + exit_with_usage(myname, "Specify terminal-type with -T", NULL); if (strlen(*++av) < 20) strcpy(screenterm, *av); } @@ -616,7 +608,7 @@ char **av; { SockMatch = ap + 2; if (ac != 1) - exit_with_usage(myname); + exit_with_usage(myname, "must have exact one parameter after %s", ap); } else if (ac > 1 && *av[1] != '-') { @@ -659,7 +651,7 @@ char **av; else { if (--ac == 0) - exit_with_usage(myname); + exit_with_usage(myname, "Specify shell with -s", NULL); if (ShellProg) free(ShellProg); ShellProg = SaveStr(*++av); @@ -672,22 +664,24 @@ char **av; else { if (--ac == 0) - exit_with_usage(myname); + exit_with_usage(myname, "Specify session-name with -S", NULL); SockMatch = *++av; if (!*SockMatch) - exit_with_usage(myname); + exit_with_usage(myname, "-S: Empty session-name?", NULL); } break; case 'v': Panic(0, "Screen version %s", version); /* NOTREACHED */ default: - exit_with_usage(myname); + exit_with_usage(myname, "Unknown option %s", ap); } } else break; } + if (SockMatch && strlen(SockMatch) >= MAXSTR) + Panic(0, "Ridiculously long socketname - try again."); if (dflag && mflag && SockMatch && !(rflag || xflag)) detached = 1; nwin = nwin_options; @@ -754,6 +748,8 @@ char **av; Panic(0, "Cannot identify account '%s'.", multi); multi_uid = mppp->pw_uid; multi_home = SaveStr(mppp->pw_dir); + if (strlen(multi_home) > MAXPATHLEN - 10) + Panic(0, "home directory path too long"); # ifdef MULTI if (rflag || lsflag) { @@ -842,6 +838,10 @@ pw_try_again: home = ppp->pw_dir; if (strlen(LoginName) > 20) Panic(0, "LoginName too long - sorry."); +#ifdef MULTIUSER + if (multi && strlen(multi) > 20) + Panic(0, "Screen owner name too long - sorry."); +#endif if (strlen(home) > MAXPATHLEN - 25) Panic(0, "$HOME too long - sorry."); @@ -866,7 +866,7 @@ pw_try_again: tty_mode = st.st_mode & 0777; #endif if ((n = secopen(attach_tty, O_RDWR, 0)) < 0) - Panic(0, "Cannot open '%s' - please check.", attach_tty); + Panic(0, "Cannot open your terminal '%s' - please check.", attach_tty); close(n); debug1("attach_tty is %s\n", attach_tty); if ((attach_term = getenv("TERM")) == 0 || *attach_term == 0) @@ -942,6 +942,7 @@ pw_try_again: { if (mkdir(SockDir, eff_uid ? 0777 : 0755) == -1) Panic(errno, "Cannot make directory '%s'", SockDir); + chown(SockDir, 0, 0); /* no matter if this fails */ } else { @@ -1001,7 +1002,7 @@ pw_try_again: if (lsflag) { - int i, fo; + int i, fo, oth; #ifdef MULTIUSER if (multi) @@ -1011,9 +1012,9 @@ pw_try_again: setgid(real_gid); eff_uid = real_uid; eff_gid = real_gid; - i = FindSocket((int *)NULL, &fo, SockMatch); + i = FindSocket((int *)NULL, &fo, &oth, SockMatch); if (quietflag) - exit(10 + i); + exit(8 + (fo ? ((oth || i) ? 2 : 1) : 0) + i); if (fo == 0) { #ifdef NETHACK @@ -1061,7 +1062,18 @@ pw_try_again: } } nwin_compose(&nwin_default, &nwin_options, &nwin_default); - switch (MasterPid = fork()) + + if (DefaultEsc == -1) + DefaultEsc = Ctrl('a'); + if (DefaultMetaEsc == -1) + DefaultMetaEsc = 'a'; + + if (!detached || dflag != 2) + MasterPid = fork(); + else + MasterPid = 0; + + switch (MasterPid) { case -1: Panic(errno, "fork"); @@ -1117,7 +1129,7 @@ pw_try_again: if (dfp && dfp != stderr) fclose(dfp); - sprintf(buf, "%s/SCREEN.%d", DEBUGDIR, getpid()); + sprintf(buf, "%s/SCREEN.%d", DEBUGDIR, (int)getpid()); if ((dfp = fopen(buf, "w")) == NULL) dfp = stderr; else @@ -1247,7 +1259,7 @@ pw_try_again: #endif FinishRc(RcFileName); - debug2("UID %d EUID %d\n", getuid(), geteuid()); + debug2("UID %d EUID %d\n", (int)getuid(), (int)geteuid()); if (windows == NULL) { debug("We open one default window, as screenrc did not specify one.\n"); @@ -1633,6 +1645,11 @@ pw_try_again: { if (errno == EINTR) continue; +#ifdef EAGAIN + /* IBM's select() doesn't always tell the truth */ + if (errno == EAGAIN) + continue; +#endif debug1("Read error: %d - SigHup()ing!\n", errno); SigHup(SIGARG); sleep(1); @@ -1829,14 +1846,20 @@ struct win *p; debug3("window %d (%s) going into zombie state fd %d", p->w_number, p->w_title, p->w_ptyfd); #ifdef UTMPOK - RemoveUtmp(p); + if (p->w_slot != (slot_t)0 && p->w_slot != (slot_t)-1) + { + RemoveUtmp(p); + p->w_slot = 0; /* "detached" */ + } #endif (void) chmod(p->w_tty, 0666); (void) chown(p->w_tty, 0, 0); close(p->w_ptyfd); p->w_ptyfd = -1; +#ifdef UTMPOK /* zap saved utmp as the slot may change */ bzero((char *)&p->w_savut, sizeof(p->w_savut)); +#endif p->w_pid = 0; ResetWindow(p); p->w_y = p->w_bot; @@ -1871,7 +1894,7 @@ SigChldHandler() debug1("'%s' reconstructed\n", SockPath); } else - debug2("SigChldHandler: stat '%s' o.k. (%03o)\n", SockPath, st.st_mode); + debug2("SigChldHandler: stat '%s' o.k. (%03o)\n", SockPath, (int)st.st_mode); } static sigret_t @@ -2180,7 +2203,7 @@ int mode; AddStr("[power detached]\r\n"); if (PowDetachString) { - AddStr(expand_vars(PowDetachString)); + AddStr(expand_vars(PowDetachString, display)); AddStr("\r\n"); } sign = SIG_POWER_BYE; @@ -2190,7 +2213,7 @@ int mode; AddStr("[remote power detached]\r\n"); if (PowDetachString) { - AddStr(expand_vars(PowDetachString)); + AddStr(expand_vars(PowDetachString, display)); AddStr("\r\n"); } sign = SIG_POWER_BYE; @@ -2340,10 +2363,10 @@ unsigned long p1, p2, p3, p4, p5, p6; # else /* __STDC__ */ va_start(ap); # endif /* __STDC__ */ - (void) vsprintf(p, fmt, ap); + (void) vsnprintf(p, sizeof(buf) - 100, fmt, ap); va_end(ap); #else /* USEVARARRGS */ - sprintf(p, fmt, p1, p2, p3, p4, p5, p6); + xsnprintf(p, sizeof(buf) - 100, fmt, p1, p2, p3, p4, p5, p6); #endif /* USEVARARRGS */ if (err) { @@ -2392,10 +2415,10 @@ unsigned long p1, p2, p3, p4, p5, p6; # else /* __STDC__ */ va_start(ap); # endif /* __STDC__ */ - (void) vsprintf(p, fmt, ap); + (void) vsnprintf(p, sizeof(buf) - 100, fmt, ap); va_end(ap); #else /* USEVARARRGS */ - sprintf(p, fmt, p1, p2, p3, p4, p5, p6); + xsnprintf(p, sizeof(buf) - 100, fmt, p1, p2, p3, p4, p5, p6); #endif /* USEVARARRGS */ if (err) { @@ -64,9 +64,9 @@ #ifndef NOASSERT # if defined(__STDC__) -# define ASSERT(lousy_cpp) {if (!(lousy_cpp)) {debug2("ASSERT("#lousy_cpp")ion failed file %s line %d\n", __FILE__, __LINE__);abort();}} +# define ASSERT(lousy_cpp) do {if (!(lousy_cpp)) {if (!dfp) opendebug(0, 1);debug2("ASSERT("#lousy_cpp") failed file %s line %d\n", __FILE__, __LINE__);abort();}} while (0) # else -# define ASSERT(lousy_cpp) {if (!(lousy_cpp)) {debug2("ASSERT(lousy_cpp)ion failed file %s line %d\n", __FILE__, __LINE__);abort();}} +# define ASSERT(lousy_cpp) do {if (!(lousy_cpp)) {if (!dfp) opendebug(0, 1);debug2("ASSERT(lousy_cpp) failed file %s line %d\n", __FILE__, __LINE__);abort();}} while (0) # endif #else # define ASSERT(lousy_cpp) {;} @@ -41,8 +41,8 @@ extern struct display *display; */ static int matchword __P((char *, int, int, int)); -static void searchend __P((char *, int)); -static void backsearchend __P((char *, int)); +static void searchend __P((char *, int, char *)); +static void backsearchend __P((char *, int, char *)); void Search(dir) @@ -53,20 +53,22 @@ int dir; { markdata = (struct markdata *)D_lay->l_data; if (markdata->isdir > 0) - searchend((char *)0, 0); + searchend(0, 0, NULL); else if (markdata->isdir < 0) - backsearchend((char *)0, 0); + backsearchend(0, 0, NULL); else Msg(0, "No previous pattern"); } else - Input((dir > 0 ? "/" : "?"), sizeof(markdata->isstr)-1, (dir > 0 ? searchend : backsearchend), INP_COOKED); + Input((dir > 0 ? "/" : "?"), sizeof(markdata->isstr)-1, INP_COOKED, + (dir > 0 ? searchend : backsearchend), NULL); } static void -searchend(buf, len) +searchend(buf, len, data) char *buf; int len; +char *data; /* dummy */ { int x = 0, sx, ex, y; struct markdata *markdata; @@ -92,9 +94,10 @@ int len; } static void -backsearchend(buf, len) +backsearchend(buf, len, data) char *buf; int len; +char *data; /* dummy */ { int sx, ex, x = -1, y; struct markdata *markdata; @@ -157,7 +160,7 @@ static char *isprompts[] = { static int is_redo __P((struct markdata *)); -static void is_process __P((char *, int)); +static void is_process __P((char *, int, char *)); static int is_bm __P((char *, int, int, int, int)); @@ -209,9 +212,10 @@ int l, p, end, dir; /*ARGSUSED*/ static void -is_process(p, n) +is_process(p, n, data) /* i-search */ char *p; int n; +char *data; /* dummy */ { int pos, x, y, dir; struct markdata *markdata; @@ -323,13 +327,15 @@ ISearch(dir) int dir; { struct markdata *markdata; + markdata = (struct markdata *)D_lay->l_data; markdata->isdir = markdata->isstartdir = dir; markdata->isstartpos = markdata->cx + markdata->cy * D_width; markdata->isistrl = markdata->isstrl = 0; if (W2D(markdata->cy) == STATLINE) revto_line(markdata->cx, markdata->cy, STATLINE > 0 ? STATLINE - 1 : 1); - Input(isprompts[dir + 1], sizeof(markdata->isstr) - 1, is_process, INP_RAW); + Input(isprompts[dir + 1], sizeof(markdata->isstr) - 1, INP_RAW, + is_process, NULL); GotoPos(markdata->cx, W2D(markdata->cy)); } @@ -93,19 +93,20 @@ extern char SockPath[]; * match: string to match socket name. * * The socket directory must be in SockPath! - * - * Returns: number of good sockets. + * The global variables LoginName, multi, rflag, xflag, dflag, quietflag, + * nethackflag, SockPath are used. * * The first good socket is stored in fdp and its name is * appended to SockPath. * If none exists or fdp is NULL SockPath is not changed. * + * Returns: number of good sockets. */ int -FindSocket(fdp, nfoundp, match) +FindSocket(fdp, nfoundp, notherp, match) int *fdp; -int *nfoundp; +int *nfoundp, *notherp; char *match; { DIR *dirp; @@ -115,9 +116,9 @@ char *match; int sdirlen; int matchlen = 0; char *name, *n; - int firsts = -1, s; + int firsts = -1, sockfd; char *firstn = 0; - int nfound = 0, ngood = 0, ndead = 0, nwipe = 0; + int nfound = 0, ngood = 0, ndead = 0, nwipe = 0, npriv = 0; struct sent { struct sent *next; @@ -155,7 +156,7 @@ char *match; { name = dp->d_name; debug1("- %s\n", name); - if (*name == 0 || *name == '.') + if (*name == 0 || *name == '.' || strlen(name) > 2*MAXSTR) continue; if (matchlen) { @@ -177,8 +178,15 @@ char *match; } sprintf(SockPath + sdirlen, "/%s", name); + debug1("stat %s\n", SockPath); + errno = 0; + debug2("uid = %d, gid = %d\n", (int)getuid(), (int)getgid()); + debug2("euid = %d, egid = %d\n", (int)geteuid(), (int)getegid()); if (stat(SockPath, &st)) - continue; + { + debug1("errno = %d\n", errno); + continue; + } #ifndef SOCK_NOT_IN_FS # ifdef NAMEDPIPE @@ -194,13 +202,25 @@ char *match; # endif #endif + debug2("st.st_uid = %d, real_uid = %d\n", (int)st.st_uid, real_uid); if (st.st_uid != real_uid) continue; mode = st.st_mode & 0777; debug1(" has mode 0%03o\n", mode); #ifdef MULTIUSER if (multi && ((mode & 0677) != 0601)) - continue; + { + debug(" is not a MULTI-USER session"); + if (strcmp(multi, LoginName)) + { + debug(" and we are in a foreign directory.\n"); + mode = -4; + } + else + { + debug(", but it is our own session.\n"); + } + } #endif debug(" store it.\n"); if ((sent = (struct sent *)malloc(sizeof(struct sent))) == 0) @@ -211,14 +231,16 @@ char *match; *slisttail = sent; slisttail = &sent->next; nfound++; - s = MakeClientSocket(0); + sockfd = MakeClientSocket(0); #ifdef USE_SETEUID /* MakeClientSocket sets ids back to eff */ xseteuid(real_uid); xsetegid(real_gid); #endif - if (s == -1) + if (sockfd == -1) { + debug2(" MakeClientSocket failed, unreachable? %d %d\n", + matchlen, wipeflag); sent->mode = -3; /* Unreachable - it is dead if we detect that it's local * or we specified a match @@ -239,37 +261,47 @@ char *match; } } } + npriv++; continue; } - /* Shall we connect ? */ + mode &= 0776; + /* Shall we connect ? */ + debug2(" connecting: mode=%03o, rflag=%d, ", mode, rflag); + debug2("xflag=%d, dflag=%d ?\n", xflag, dflag); - /* - * mode 600: socket is detached. - * mode 700: socket is attached. - * xflag implies rflag here. - * - * fail, when socket mode mode is not 600 or 700 - * fail, when we want to detach, but it already is. - * fail, when we only want to attach, but mode 700 and not xflag. - * fail, if none of dflag, rflag, xflag is set. - */ - if ((mode != 0700 && mode != 0600) || - (dflag && mode == 0600) || - (!dflag && rflag && mode == 0700 && !xflag) || - (!dflag && !rflag && !xflag)) + /* + * mode 600: socket is detached. + * mode 700: socket is attached. + * xflag implies rflag here. + * + * fail, when socket mode is not 600 or 700 + * fail, when we want to detach w/o reattach, but it already is detached. + * fail, when we only want to attach, but mode 700 and not xflag. + * fail, if none of dflag, rflag, xflag is set. + */ + if ((mode != 0700 && mode != 0600) || + (dflag && !rflag && mode == 0600) || + (!dflag && rflag && mode == 0700 && !xflag) || + (!dflag && !rflag && !xflag)) { - close(s); + close(sockfd); + debug(" no!\n"); + npriv++; /* a good socket that was not for us */ continue; } ngood++; if (fdp && firsts == -1) { - firsts = s; + firsts = sockfd; firstn = sent->name; + debug(" taken\n"); } else - close(s); + { + debug(" discarded.\n"); + close(sockfd); + } } (void)closedir(dirp); if (nfound && (lsflag || ngood != 1) && !quietflag) @@ -319,14 +351,16 @@ char *match; break; #endif case -1: - /* No trigraphs, please */ + /* No trigraphs here! */ printf("\t%s\t(Dead ?%c?)\n", sent->name, '?'); break; case -2: printf("\t%s\t(Removed)\n", sent->name); break; case -3: - printf("\t%s\t(Unreachable)\n", sent->name); + printf("\t%s\t(Remote or dead)\n", sent->name); + case -4: + printf("\t%s\t(Private)\n", sent->name); break; } } @@ -371,6 +405,8 @@ char *match; xseteuid(eff_uid); xsetegid(eff_gid); #endif + if (notherp) + *notherp = npriv; if (nfoundp) *nfoundp = nfound - nwipe; return ngood; @@ -477,7 +513,8 @@ MakeServerSocket() if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) Panic(errno, "socket"); a.sun_family = AF_UNIX; - strcpy(a.sun_path, SockPath); + strncpy(a.sun_path, SockPath, sizeof(a.sun_path)); + a.sun_path[sizeof(a.sun_path) - 1] = 0; # ifdef USE_SETEUID xseteuid(real_uid); xsetegid(real_gid); @@ -549,7 +586,8 @@ int err; if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) Panic(errno, "socket"); a.sun_family = AF_UNIX; - strcpy(a.sun_path, SockPath); + strncpy(a.sun_path, SockPath, sizeof(a.sun_path)); + a.sun_path[sizeof(a.sun_path) - 1] = 0; # ifdef USE_SETEUID xseteuid(real_uid); xsetegid(real_gid); @@ -601,25 +639,28 @@ struct NewWindow *nwin; if (strlen(sty) > NAME_MAX) sty[NAME_MAX] = 0; #endif + if (strlen(sty) > 2 * MAXSTR - 1) + sty[2 * MAXSTR - 1] = 0; sprintf(SockPath + strlen(SockPath), "/%s", sty); if ((s = MakeClientSocket(1)) == -1) exit(1); debug1("SendCreateMsg() to '%s'\n", SockPath); bzero((char *)&m, sizeof(m)); m.type = MSG_CREATE; - strcpy(m.m_tty, attach_tty); + strncpy(m.m_tty, attach_tty, sizeof(m.m_tty) - 1); + m.m_tty[sizeof(m.m_tty) - 1] = 0; p = m.m.create.line; n = 0; if (nwin->args != nwin_undef.args) for (av = nwin->args; *av && n < MAXARGS - 1; ++av, ++n) { len = strlen(*av) + 1; - if (p + len >= m.m.create.line + MAXPATHLEN - 1) + if (p + len >= m.m.create.line + sizeof(m.m.create.line) - 1) break; strcpy(p, *av); p += len; } - if (nwin->aka != nwin_undef.aka && p + strlen(nwin->aka) + 1 < m.m.create.line + MAXPATHLEN) + if (nwin->aka != nwin_undef.aka && p + strlen(nwin->aka) + 1 < m.m.create.line + sizeof(m.m.create.line)) strcpy(p, nwin->aka); else *p = '\0'; @@ -670,17 +711,18 @@ unsigned long p1, p2, p3, p4, p5, p6; # else /* __STDC__ */ va_start(ap); # endif /* __STDC__ */ - (void) vsprintf(m.m.message, fmt, ap); + (void) vsnprintf(m.m.message, sizeof(m.m.message), fmt, ap); va_end(ap); #else /* USEVARARGS */ - sprintf(m.m.message, fmt, p1, p2, p3, p4, p5, p6); + xsnprintf(m.m.message, sizeof(m.m.message), fmt, p1, p2, p3, p4, p5, p6); #endif /* USEVARARGS */ debug1("SendErrorMsg: '%s'\n", m.m.message); if (display == 0) return; s = MakeClientSocket(0); m.type = MSG_ERROR; - strcpy(m.m_tty, D_usertty); + strncpy(m.m_tty, D_usertty, sizeof(m.m_tty) - 1); + m.m_tty[sizeof(m.m_tty) - 1] = 0; debug1("SendErrorMsg(): writing to '%s'\n", SockPath); (void) write(s, (char *) &m, sizeof m); close(s); @@ -701,10 +743,10 @@ char *pwd, *utty; { # ifdef NETHACK if (nethackflag) - Msg(0, "'%s' tries to explode in the sky, but fails. (%s)", utty, pwd); + Msg(0, "'%s' tries to explode in the sky, but fails.", utty); else # endif /* NETHACK */ - Msg(0, "Illegal reattach attempt from terminal %s, \"%s\"", utty, pwd); + Msg(0, "Illegal reattach attempt from terminal %s.", utty); } debug1("CheckPass() wrong password kill(%d, SIG_PW_FAIL)\n", pid); Kill(pid, SIG_PW_FAIL); @@ -882,6 +924,7 @@ ReceiveMsg() if (TTYCMP(D_usertty, m.m_tty) == 0) break; debug2("display: %s display %sfound\n", m.m_tty, display ? "" : "not "); + wi = 0; if (!display) { for (wi = windows; wi; wi = wi->w_next) @@ -946,12 +989,12 @@ ReceiveMsg() Kill(m.m.attach.apid, SIGCONT); # endif #endif /* PASSWORD */ - if (display) + if (display || wi) { - write(i, "Attaching to a not detached screen?\n", 36); + write(i, "Attaching from inside of screen?\n", 33); close(i); Kill(m.m.attach.apid, SIG_BYE); - Msg(0, "Attach msg ignored: We are not detached."); + Msg(0, "Attach msg ignored: coming from inside."); break; } @@ -1045,15 +1088,24 @@ ReceiveMsg() RemoveLoginSlot(); if (displays->d_next == 0) for (wi = windows; wi; wi = wi->w_next) - if (wi->w_slot != (slot_t) -1) + if (wi->w_ptyfd >= 0 && wi->w_slot != (slot_t) -1) SetUtmp(wi); #endif SetMode(&D_OldMode, &D_NewMode); SetTTY(D_userfd, &D_NewMode); D_fore = NULL; + /* there may be a window that we remember from last detach: */ if (D_user->u_detachwin >= 0) fore = wtab[D_user->u_detachwin]; + /* Wayne wants us to restore the other window too. */ + if (D_user->u_detachotherwin >= 0) + D_other = wtab[D_user->u_detachotherwin]; + /* + * We want a window to start with. + * It is the window we left from, which is not occupied and + * grants us full read/write permissions. + */ #ifdef MULTIUSER if (!fore || fore->w_display || AclCheckPermWin(D_user, ACL_WRITE, fore)) #else @@ -1092,7 +1144,8 @@ ReceiveMsg() Msg(0, "%s", m.m.message); break; case MSG_HANGUP: - SigHup(SIGARG); + if (!wi) /* ignore hangups from inside */ + SigHup(SIGARG); break; #ifdef REMOTE_DETACH case MSG_DETACH: @@ -1160,7 +1213,7 @@ chsock() * may be happy to remove old files. We manually prevent the socket * from becoming old. (chmod does not touch mtime). */ - (void)utime(SockPath, NULL); + (void)utimes(SockPath, NULL); if (euid != real_uid) UserReturn(r); @@ -1,14 +1,5 @@ -Zhang has developed a patch to the "screen" VT100 terminal emulation program -that allows one to perform tektronics "tek40xx" style graphics in a -screen window. I've tested it with gnuplot and it works quite well. - -Send flames or technical inquries to the patch author Xiaoguang -Zhang (zhang@gmsds.ms.ornl.gov) and to screen@uni-erlangen.de - -===================================================================== - -*** ./ansi.h.orig Fri Jan 2 19:12:05 1970 ---- ./ansi.h Wed Nov 15 19:25:11 1995 +*** ./ansi.h.orig Tue Jan 9 19:16:35 1996 +--- ./ansi.h Sat Jun 14 22:38:37 1997 *************** *** 56,62 **** PRIN, /* Printer mode */ @@ -29,11 +20,11 @@ Zhang (zhang@gmsds.ms.ornl.gov) and to screen@uni-erlangen.de }; enum string_t -*** ./ansi.c.orig Sun Oct 29 16:01:26 1995 ---- ./ansi.c Wed Nov 15 19:25:11 1995 +*** ./ansi.c.orig Thu May 1 17:33:31 1997 +--- ./ansi.c Sat Jun 14 22:38:37 1997 *************** -*** 805,810 **** ---- 805,815 ---- +*** 813,818 **** +--- 813,823 ---- case 'k': StartString(AKA); break; @@ -46,8 +37,8 @@ Zhang (zhang@gmsds.ms.ornl.gov) and to screen@uni-erlangen.de if (Special(c)) { *************** -*** 868,873 **** ---- 873,899 ---- +*** 876,881 **** +--- 881,907 ---- goto tryagain; } } @@ -75,5 +66,3 @@ Zhang (zhang@gmsds.ms.ornl.gov) and to screen@uni-erlangen.de break; case LIT: default: - -===================================================================== @@ -184,8 +184,18 @@ struct term term[T_N] = { "k;", T_STR }, KMAPDEF("\033[21~") { "F1", T_STR }, KMAPDEF("\033[23~") { "F2", T_STR }, KMAPDEF("\033[24~") + /* extra keys for vt220 (David.Leonard@it.uq.edu.au) */ + { "F3", T_STR }, + { "F4", T_STR }, + { "F5", T_STR }, + { "F6", T_STR }, + { "F7", T_STR }, + { "F8", T_STR }, + { "F9", T_STR }, + { "FA", T_STR }, + { "kb", T_STR }, KMAPDEF("\010") - { "kh", T_STR }, KMAPDEF("\033[1~") KMAPMDEF("g") + { "kh", T_STR }, KMAPDEF("\033[1~") KMAPMDEF("\201") { "K1", T_STR }, { "K2", T_STR }, { "K3", T_STR }, @@ -199,7 +209,7 @@ struct term term[T_N] = { "kD", T_STR }, KMAPDEF("\033[3~") { "kE", T_STR }, { "kF", T_STR }, KMAPMDEF("\004") - { "kH", T_STR }, KMAPDEF("\033[4~") KMAPMDEF("G") + { "kH", T_STR }, KMAPDEF("\033[4~") KMAPMDEF("\205") { "kI", T_STR }, KMAPDEF("\033[2~") { "kL", T_STR }, { "kM", T_STR }, @@ -213,10 +223,10 @@ struct term term[T_N] = { "@7", T_STR }, /* keys that can have two bindings */ /* define T_CURSOR */ - { "ku", T_STR }, KMAPDEF("\033[A") KMAPADEF("\033OA") KMAPMDEF("k") - { "kd", T_STR }, KMAPDEF("\033[B") KMAPADEF("\033OB") KMAPMDEF("j") - { "kr", T_STR }, KMAPDEF("\033[C") KMAPADEF("\033OC") KMAPMDEF("l") - { "kl", T_STR }, KMAPDEF("\033[D") KMAPADEF("\033OD") KMAPMDEF("h") + { "ku", T_STR }, KMAPDEF("\033[A") KMAPADEF("\033OA") KMAPMDEF("\220") + { "kd", T_STR }, KMAPDEF("\033[B") KMAPADEF("\033OB") KMAPMDEF("\216") + { "kr", T_STR }, KMAPDEF("\033[C") KMAPADEF("\033OC") KMAPMDEF("\206") + { "kl", T_STR }, KMAPDEF("\033[D") KMAPADEF("\033OD") KMAPMDEF("\202") /* define T_KEYPAD */ { "f0", T_STR }, KMAPDEF("0") KMAPADEF("\033Op") { "f1", T_STR }, KMAPDEF("1") KMAPADEF("\033Oq") diff --git a/term.h.dist b/term.h.dist index 73f021d..7dd41b8 100644 --- a/term.h.dist +++ b/term.h.dist @@ -221,17 +221,17 @@ union tcu #define d_CXC d_tcs[99].str #define D_CXC (D_tcs[99].str) #define T_CAPS 100 -#define T_CURSOR 139 -#define T_KEYPAD 143 -#define T_OCAPS 161 -#define T_ECAPS 174 -#define T_N 174 +#define T_CURSOR 147 +#define T_KEYPAD 151 +#define T_OCAPS 169 +#define T_ECAPS 182 +#define T_N 182 #ifdef MAPKEYS # define KMAPDEFSTART 100 -# define NKMAPDEF 61 -# define KMAPADEFSTART 139 +# define NKMAPDEF 69 +# define KMAPADEFSTART 147 # define NKMAPADEF 22 -# define KMAPMDEFSTART 114 +# define KMAPMDEFSTART 122 # define NKMAPMDEF 29 #endif @@ -677,21 +677,21 @@ int aflag; if ((s = getenv("SCREENCAP")) && strlen(s) < TERMCAP_BUFSIZE) { sprintf(Termcap, "TERMCAP=%s", s); - sprintf(Term, "TERM=screen"); + strcpy(Term, "TERM=screen"); debug("getenvSCREENCAP o.k.\n"); return Termcap; } Termcaplen = 0; debug1("MakeTermcap screenterm='%s'\n", screenterm); debug1("MakeTermcap termname='%s'\n", tname); - if (*screenterm == '\0') + if (*screenterm == '\0' || strlen(screenterm) > MAXSTR - 3) { debug("MakeTermcap sets screenterm=screen\n"); strcpy(screenterm, "screen"); } do { - sprintf(Term, "TERM="); + strcpy(Term, "TERM="); p = Term + 5; if (!aflag && strlen(screenterm) + strlen(tname) < MAXSTR-1) { @@ -705,10 +705,10 @@ int aflag; if (tgetent(buf, p) == 1) break; } - sprintf(p, "%s", screenterm); + strcpy(p, screenterm); if (tgetent(buf, p) == 1) break; - sprintf(p, "vt100"); + strcpy(p, "vt100"); } while (0); /* Goto free programming... */ @@ -726,6 +726,8 @@ int aflag; } tcLineLen = 100; /* Force NL */ + if (strlen(Term) > TERMCAP_BUFSIZE - 40) + strcpy(Term, "too_long"); sprintf(Termcap, "TERMCAP=SC|%s|VT 100/ANSI X3.64 virtual terminal", Term + 5); Termcaplen = strlen(Termcap); @@ -928,7 +930,7 @@ char *s; *p++ = 'E'; break; case ':': - sprintf(p, "\\072"); + strcpy(p, "\\072"); p += 4; break; case '^': @@ -1243,7 +1245,7 @@ char *cap; bufp = buf; if ((tep = findcap(cap, &bufp, 2))) return (*tep == '@') ? 0 : 1; - return tgetflag(cap); + return tgetflag(cap) > 0; } static int diff --git a/terminfo/debian.README b/terminfo/debian.README deleted file mode 100644 index 5866482..0000000 --- a/terminfo/debian.README +++ /dev/null @@ -1,7 +0,0 @@ -Debian 1.1 uses ncurses/terminfo, not curses/termcap, so you really -shouldn't need the screencap file in this directory, nor a /etc/termcap -file. - -The screeninfo.src file has been installed with the postinst of -screen, so you don't need to do it manually -- it's here for -reference, and to recover from stupid errors (like?). diff --git a/terminfo/screencap b/terminfo/screencap index 5738532..582863c 100644 --- a/terminfo/screencap +++ b/terminfo/screencap @@ -9,7 +9,7 @@ SC|screen|VT 100/ANSI X3.64 virtual terminal:\ :AL=\E[%dL:dl=\E[M:DL=\E[%dM:cs=\E[%i%d;%dr:dc=\E[P:\ :DC=\E[%dP:im=\E[4h:ei=\E[4l:IC=\E[%d@:\ :ks=\E[?1h\E=:ke=\E[?1l\E>:vb=\Eg:\ - :ku=\EOA:kd=\EOB:kr=\EOC:kl=\EOD:kb=^H:\ + :ku=\EOA:kd=\EOB:kr=\EOC:kl=\EOD:kb=\177:\ :k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:k5=\E[15~:k6=\E[17~:\ :k7=\E[18~:k8=\E[19~:k9=\E[20~:k;=\E[21~:F1=\E[23~:F2=\E[24~:\ :kh=\E[1~:kI=\E[2~:kD=\E[3~:kH=\E[4~:kP=\E[5~:kN=\E[6~:\ diff --git a/terminfo/screeninfo.src b/terminfo/screeninfo.src index ab17d2d..1046562 100644 --- a/terminfo/screeninfo.src +++ b/terminfo/screeninfo.src @@ -9,11 +9,12 @@ screen|VT 100/ANSI X3.64 virtual terminal, dl=\E[%p1%dM, dl1=\E[M, ed=\E[J, el=\E[K, el1=\E[1K, enacs=\E(B\E)0, home=\E[H, ht=\t, hts=\EH, ich=\E[%p1%d@, il=\E[%p1%dL, il1=\E[L, - ind=\n, is2=\E)0, kbs=\b, kcub1=\EOD, kcud1=\EOB, + ind=\n, is2=\E)0, kbs=\177, kcub1=\EOD, kcud1=\EOB, kcuf1=\EOC, kcuu1=\EOA, kdch1=\E[3~, kf1=\EOP, kf10=\E[21~, kf11=\E[23~, kf12=\E[24~, kf2=\EOQ, kf3=\EOR, kf4=\EOS, kf5=\E[15~, kf6=\E[17~, kf7=\E[18~, kf8=\E[19~, kf9=\E[20~, khome=\E[1~, + kend=\E[4~, kich1=\E[2~, kll=\E[4~, knp=\E[6~, kpp=\E[5~, nel=\EE, rc=\E8, rev=\E[7m, ri=\EM, rmir=\E[4l, rmkx=\E[?1l\E>, rmso=\E[23m, rmul=\E[24m, rs2=\Ec, sc=\E7, sgr0=\E[m, @@ -33,11 +34,12 @@ screen-w|VT 100/ANSI X3.64 virtual terminal with 132 cols, dl=\E[%p1%dM, dl1=\E[M, ed=\E[J, el=\E[K, el1=\E[1K, enacs=\E(B\E)0, home=\E[H, ht=\t, hts=\EH, ich=\E[%p1%d@, il=\E[%p1%dL, il1=\E[L, - ind=\n, is2=\E)0, kbs=\b, kcub1=\EOD, kcud1=\EOB, + ind=\n, is2=\E)0, kbs=\177, kcub1=\EOD, kcud1=\EOB, kcuf1=\EOC, kcuu1=\EOA, kdch1=\E[3~, kf1=\EOP, kf10=\E[21~, kf11=\E[23~, kf12=\E[24~, kf2=\EOQ, kf3=\EOR, kf4=\EOS, kf5=\E[15~, kf6=\E[17~, kf7=\E[18~, kf8=\E[19~, kf9=\E[20~, khome=\E[1~, + kend=\E[4~, kich1=\E[2~, kll=\E[4~, knp=\E[6~, kpp=\E[5~, nel=\EE, rc=\E8, rev=\E[7m, ri=\EM, rmir=\E[4l, rmkx=\E[?1l\E>, rmso=\E[23m, rmul=\E[24m, rs2=\Ec, sc=\E7, sgr0=\E[m, @@ -107,8 +107,9 @@ char *line; */ #ifdef TIOCEXCL errno = 0; - ioctl(f, TIOCEXCL, (char *) 0); - debug3("%d %d %d\n", getuid(), geteuid(), getpid()); + if (ioctl(f, TIOCEXCL, (char *) 0) < 0) + Msg(errno, "%s: ioctl TIOCEXCL failed", line); + debug3("%d %d %d\n", (int)getuid(), (int)geteuid(), (int)getpid()); debug2("%s TIOCEXCL errno %d\n", line, errno); #endif /* TIOCEXCL */ /* @@ -124,8 +124,9 @@ char *line; */ #ifdef TIOCEXCL errno = 0; - ioctl(f, TIOCEXCL, (char *) 0); - debug3("%d %d %d\n", getuid(), geteuid(), getpid()); + if (ioctl(f, TIOCEXCL, (char *) 0) < 0) + Msg(errno, "%s: ioctl TIOCEXCL failed", line); + debug3("%d %d %d\n", (int)getuid(), (int)geteuid(), (int)getpid()); debug2("%s TIOCEXCL errno %d\n", line, errno); #endif /* TIOCEXCL */ /* @@ -279,7 +279,14 @@ RemoveLoginSlot() if (ut_delete_user(D_loginslot, uu->ut_pid, 0, 0) == 0) # else /* _SEQUENT_ */ u = *uu; + /* + * Ed Hill (ed-hill@uiowa.edu) screen-3.5.2 under AIX 3.2.5 + * when you are down to a single screen, and you log out of it (thus exiting + * screen), it leaves a stray entry in the utmp file. Seems better: + * u.ut_type = EMPTY; + */ u.ut_type = DEAD_PROCESS; + u.ut_user[0] = '\0'; /* for Digital UNIX 3.2C, kilbi@rad.rwth-aachen.de */ u.ut_exit.e_termination = 0; u.ut_exit.e_exit= 0; if (pututline(&u) == 0) @@ -121,6 +121,9 @@ struct NewWindow *newwin; struct NewWindow nwin; int ttyflag; char *TtyName; +#ifdef MULTIUSER + extern struct user *users; +#endif debug1("NewWindow: StartAt %d\n", newwin->StartAt); debug1("NewWindow: aka %s\n", newwin->aka?newwin->aka:"NULL"); @@ -175,7 +178,12 @@ struct NewWindow *newwin; p->w_cmdargs[i] = 0; #ifdef MULTIUSER - if (NewWindowAcl(p)) + /* + * This is dangerous: without a display we use creators umask + * This is intended to be usefull for detached startup. + * But is still better than default bits with a NULL user. + */ + if (NewWindowAcl(p, display ? D_user : users)) { free((char *)p); close(f); @@ -324,16 +332,8 @@ struct win *p; } #ifdef UTMPOK - p->w_slot = (slot_t) -1; - debug1("RemakeWindow will %slog in.\n", lflag ? "" : "not "); -# ifdef LOGOUTOK - if (lflag) -# endif - { - p->w_slot = (slot_t) 0; - if (display) - SetUtmp(p); - } + if (display && p->w_slot == (slot_t)0) + SetUtmp(p); #endif return p->w_number; } @@ -488,6 +488,8 @@ struct win *win; args = ShellArgs; proc = *args; } + fflush(stdout); + fflush(stderr); switch (pid = fork()) { case -1: @@ -513,14 +515,14 @@ struct win *win; if (setuid(real_uid) || setgid(real_gid)) { SendErrorMsg("Setuid/gid: %s", strerror(errno)); - exit(1); + _exit(1); } eff_uid = real_uid; eff_gid = real_gid; if (dir && *dir && chdir(dir) == -1) { SendErrorMsg("Cannot chdir to %s: %s", dir, strerror(errno)); - exit(1); + _exit(1); } if (display) @@ -553,7 +555,7 @@ struct win *win; else (void) chmod(buf, 0666); } - debug1("=== ForkWindow: pid %d\n", getpid()); + debug1("=== ForkWindow: pid %d\n", (int)getpid()); #endif /* Close the three /dev/null descriptors */ close(0); @@ -576,7 +578,7 @@ struct win *win; if ((newfd = open(ttyn, O_RDWR)) < 0) { SendErrorMsg("Cannot open %s: %s", ttyn, strerror(errno)); - exit(1); + _exit(1); } } else @@ -602,7 +604,7 @@ struct win *win; if ((newfd = open(ttyn, O_RDWR)) != 0) { SendErrorMsg("Cannot open %s: %s", ttyn, strerror(errno)); - exit(1); + _exit(1); } dup(0); dup(0); @@ -619,17 +621,17 @@ struct win *win; if (ioctl(newfd, I_PUSH, "ptem")) { SendErrorMsg("Cannot I_PUSH ptem %s %s", ttyn, strerror(errno)); - exit(1); + _exit(1); } if (ioctl(newfd, I_PUSH, "ldterm")) { SendErrorMsg("Cannot I_PUSH ldterm %s %s", ttyn, strerror(errno)); - exit(1); + _exit(1); } if (ioctl(newfd, I_PUSH, "ttcompat")) { SendErrorMsg("Cannot I_PUSH ttcompat %s %s", ttyn, strerror(errno)); - exit(1); + _exit(1); } #endif if (fgtty(newfd)) @@ -687,8 +689,8 @@ struct win *win; NewEnv[2] = Termcap; #endif strcpy(shellbuf, "SHELL="); - strncpy(shellbuf + 6, ShellProg, MAXPATHLEN); - shellbuf[MAXPATHLEN + 6] = 0; + strncpy(shellbuf + 6, ShellProg + (*ShellProg == '-'), sizeof(shellbuf) - 7); + shellbuf[sizeof(shellbuf) - 1] = 0; NewEnv[4] = shellbuf; debug1("ForkWindow: NewEnv[4] = '%s'\n", shellbuf); if (term && *term && strcmp(screenterm, term) && @@ -723,7 +725,7 @@ struct win *win; execvpe(proc, args, NewEnv); debug1("exec error: %d\n", errno); SendErrorMsg("Cannot exec '%s': %s", proc, strerror(errno)); - exit(1); + _exit(1); default: break; } @@ -749,11 +751,13 @@ char *prog, **args, **env; path = DefaultPath; do { - p = buf; - while (*path && *path != ':') - *p++ = *path++; + for (p = buf; *path && *path != ':'; path++) + if (p - buf < sizeof(buf) - 2) + *p++ = *path; if (p > buf) *p++ = '/'; + if (p - buf + strlen(prog) >= sizeof(buf) - 1) + continue; strcpy(p, prog); execve(buf, args, env); switch (errno) @@ -998,6 +1002,8 @@ char **av; SetMode(&D_OldMode, &D_NewMode); SetTTY(f, &D_NewMode); + fflush(stdout); + fflush(stderr); switch (fork()) { case -1: @@ -1012,7 +1018,7 @@ char **av; if (setuid(real_uid) || setgid(real_gid)) { SendErrorMsg("Setuid/gid: %s", strerror(errno)); - exit(1); + _exit(1); } eff_uid = real_uid; eff_gid = real_gid; @@ -1030,7 +1036,7 @@ char **av; else (void) chmod(buf, 0666); } - debug1("=== Clone: pid %d\n", getpid()); + debug1("=== Clone: pid %d\n", (int)getpid()); #endif for (avp = av; *avp; avp++) { @@ -1039,7 +1045,7 @@ char **av; if (strcmp(*avp, "%X") == 0) *avp = specialbuf; } - sprintf(specialbuf, "-SXX1"); + strcpy(specialbuf, "-SXX1"); namep += strlen(namep); specialbuf[3] = *--namep; specialbuf[2] = *--namep; @@ -1051,7 +1057,7 @@ char **av; #endif execvpe(*av, av, environ); SendErrorMsg("Cannot exec '%s': %s", *av, strerror(errno)); - exit(1); + _exit(1); default: break; } @@ -200,6 +200,8 @@ struct win struct user *w_wlockuser; /* NULL when unlocked or user who writes */ #ifdef MULTIUSER AclBits w_userbits[ACL_BITS_PER_WIN]; + AclBits w_lio_notify; /* whom to tell when lastio+seconds < time() */ + AclBits w_mon_notify; /* whom to tell monitor statis */ #endif }; |