summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--acls.c610
-rw-r--r--acls.h21
-rw-r--r--ansi.c24
-rw-r--r--attacher.c25
-rw-r--r--comm.c4
-rw-r--r--config.h.in10
-rwxr-xr-xconfigure54
-rw-r--r--configure.in6
-rw-r--r--display.c16
-rw-r--r--doc/Makefile.in2
-rw-r--r--doc/screen.11
-rw-r--r--etc/etcscreenrc4
-rw-r--r--etc/screenrc12
-rw-r--r--extern.h26
-rw-r--r--fileio.c160
-rw-r--r--help.c22
-rw-r--r--input.c155
-rw-r--r--kmapdef.c.dist20
-rw-r--r--mark.c12
-rw-r--r--misc.c303
-rw-r--r--os.h14
-rw-r--r--osdef.h.in1
-rw-r--r--patchlevel.h18
-rw-r--r--process.c299
-rw-r--r--screen.c110
-rw-r--r--screen.h4
-rw-r--r--search.c26
-rw-r--r--socket.c147
-rw-r--r--tek.patch27
-rw-r--r--term.c22
-rw-r--r--term.h.dist16
-rw-r--r--termcap.c16
-rw-r--r--tty.c.dist5
-rw-r--r--tty.sh5
-rw-r--r--utmp.c7
-rw-r--r--window.c64
-rw-r--r--window.h2
37 files changed, 1588 insertions, 682 deletions
diff --git a/acls.c b/acls.c
index f13e13c..1157af5 100644
--- a/acls.c
+++ b/acls.c
@@ -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 */
diff --git a/acls.h b/acls.h
index 3cbd583..b30f714 100644
--- a/acls.h
+++ b/acls.h
@@ -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;
diff --git a/ansi.c b/ansi.c
index 3edbc81..1bb02c2 100644
--- a/ansi.c
+++ b/ansi.c
@@ -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);
diff --git a/attacher.c b/attacher.c
index d0b330d..447994f 100644
--- a/attacher.c
+++ b/attacher.c
@@ -164,7 +164,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 +187,7 @@ int how;
}
else
{
- n = FindSocket(&lasts, (int *)0, SockMatch);
+ n = FindSocket(&lasts, (int *)0, (int *)0, SockMatch);
switch (n)
{
case 0:
@@ -225,7 +226,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 +239,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 +267,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 +351,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 +425,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 +729,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 +776,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/comm.c b/comm.c
index a676cb6..1679929 100644
--- a/comm.c
+++ b/comm.c
@@ -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 2d79d57..4ed1791 100644
--- a/config.h.in
+++ b/config.h.in
@@ -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.
*/
diff --git a/configure b/configure
index 4ab7d58..8a04ae8 100755
--- a/configure
+++ b/configure
@@ -2622,10 +2622,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 +2964,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"
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/display.c b/display.c
index e4cdb1c..3a47928 100644
--- a/display.c
+++ b/display.c
@@ -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 558e314..d30e94e 100644
--- a/doc/screen.1
+++ b/doc/screen.1
@@ -859,6 +859,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,
diff --git a/etc/etcscreenrc b/etc/etcscreenrc
index 301d6b9..7c6aa42 100644
--- a/etc/etcscreenrc
+++ b/etc/etcscreenrc
@@ -93,3 +93,7 @@ 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"
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
diff --git a/extern.h b/extern.h
index f218c8a..61b39a1 100644
--- a/extern.h
+++ b/extern.h
@@ -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 **));
diff --git a/fileio.c b/fileio.c
index 81d2e81..32c73c5 100644
--- a/fileio.c
+++ b/fileio.c
@@ -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
diff --git a/help.c b/help.c
index 5fa31a3..88745fc 100644
--- a/help.c
+++ b/help.c
@@ -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;
}
diff --git a/input.c b/input.c
index 79208e7..6edff14 100644
--- a/input.c
+++ b/input.c
@@ -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
diff --git a/mark.c b/mark.c
index 2e84f27..e85d29a 100644
--- a/mark.c
+++ b/mark.c
@@ -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)
diff --git a/misc.c b/misc.c
index 0adfe19..0a73e22 100644
--- a/misc.c
+++ b/misc.c
@@ -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
diff --git a/os.h b/os.h
index b77df51..bdba088 100644
--- a/os.h
+++ b/os.h
@@ -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 */
@@ -137,7 +142,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
/*****************************************************************
diff --git a/osdef.h.in b/osdef.h.in
index d28a401..419434e 100644
--- a/osdef.h.in
+++ b/osdef.h.in
@@ -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 ""
diff --git a/process.c b/process.c
index 92b9f9e..737a348 100644
--- a/process.c
+++ b/process.c
@@ -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
+
diff --git a/screen.c b/screen.c
index fcb11e4..dea1311 100644
--- a/screen.c
+++ b/screen.c
@@ -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)
@@ -1001,7 +1001,7 @@ pw_try_again:
if (lsflag)
{
- int i, fo;
+ int i, fo, oth;
#ifdef MULTIUSER
if (multi)
@@ -1011,9 +1011,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 +1061,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 +1128,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 +1258,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 +1644,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 +1845,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 +1893,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 +2202,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 +2212,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 +2362,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 +2414,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)
{
diff --git a/screen.h b/screen.h
index ba9040b..72b6697 100644
--- a/screen.h
+++ b/screen.h
@@ -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) {;}
diff --git a/search.c b/search.c
index fa87ffe..513dc32 100644
--- a/search.c
+++ b/search.c
@@ -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));
}
diff --git a/socket.c b/socket.c
index ca8f327..0b93cb1 100644
--- a/socket.c
+++ b/socket.c
@@ -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);
diff --git a/tek.patch b/tek.patch
index 10e0868..b057347 100644
--- a/tek.patch
+++ b/tek.patch
@@ -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:
-
-=====================================================================
diff --git a/term.c b/term.c
index 18cc080..23e10a3 100644
--- a/term.c
+++ b/term.c
@@ -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
diff --git a/termcap.c b/termcap.c
index d4f748f..bb2a854 100644
--- a/termcap.c
+++ b/termcap.c
@@ -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/tty.c.dist b/tty.c.dist
index d9eba86..572a3ff 100644
--- a/tty.c.dist
+++ b/tty.c.dist
@@ -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 */
/*
diff --git a/tty.sh b/tty.sh
index 134f838..6733136 100644
--- a/tty.sh
+++ b/tty.sh
@@ -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 */
/*
diff --git a/utmp.c b/utmp.c
index 66f83f1..befe6cb 100644
--- a/utmp.c
+++ b/utmp.c
@@ -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)
diff --git a/window.c b/window.c
index 021c9a0..fc2e62d 100644
--- a/window.c
+++ b/window.c
@@ -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)
@@ -984,6 +988,8 @@ char **av;
SetMode(&D_OldMode, &D_NewMode);
SetTTY(f, &D_NewMode);
+ fflush(stdout);
+ fflush(stderr);
switch (fork())
{
case -1:
@@ -998,7 +1004,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;
@@ -1016,7 +1022,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++)
{
@@ -1025,7 +1031,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;
@@ -1037,7 +1043,7 @@ char **av;
#endif
execvpe(*av, av, environ);
SendErrorMsg("Cannot exec '%s': %s", *av, strerror(errno));
- exit(1);
+ _exit(1);
default:
break;
}
diff --git a/window.h b/window.h
index 51a1797..4a14eeb 100644
--- a/window.h
+++ b/window.h
@@ -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
};