diff options
Diffstat (limited to 'src/libscream.c')
-rw-r--r-- | src/libscream.c | 473 |
1 files changed, 360 insertions, 113 deletions
diff --git a/src/libscream.c b/src/libscream.c index 82882a3..a46a3fc 100644 --- a/src/libscream.c +++ b/src/libscream.c @@ -12,6 +12,8 @@ * 2002/05/04 Azundris support for esoteric screens, thanks to Till * 2002/05/12 Azundris edit display names, send statement, tab completion * 2002/05/13 Azundris ssh tunnel through firewall + * 2002/05/17 Azundris supports systemwide screenrc (thanks mej) + * 2002/05/18 Azundris remote handling improved (thanks tillsan, tfing) ***************************************************************************/ @@ -42,6 +44,26 @@ +/* test if we have a valid callback for function-type "e". + !p a variable of the "_ns_efuns *" type. will contain a pointer to + an efun struct containing a function pointer to the requested function + if such a struct exists, or NULL, if it doesn't exist + s a variable of the "_ns_sess *" type, or NULL (see ns_get_efuns()) + d a variable of the "_nd_disp *" type, or NULL (see ns_get_efuns()) + e the name of an element of "_ns_efuns" + !<- conditional execution of next (compound-) statement (which would + normally be (p)->(e)(...), the call of the function e). + */ +#define NS_EFUN_EXISTS(p,s,d,e) (((p) = ns_get_efuns((s),(d))) && ((p)->e)) + + + +/***************************************************************************/ +/* module-global vars */ +/**********************/ + + + static long err_inhibit = 0; /* bits. avoid telling same error twice. */ static _ns_sess *sa = NULL; /* anchor for session list */ static _ns_hop *ha = NULL; /* anchor for hop list */ @@ -54,6 +76,20 @@ static _ns_hop *ha = NULL; /* anchor for hop list */ +/* ns_free + free a string (or whatever) */ + +void * +ns_free(char **x) +{ + if (!x || !*x) + return; + free(*x); + *x = NULL; +} + + + /* ns_new_hop. create and initialize a hop struct. lp local port. if 0: if otherwise matching hop exists, reuse that. otherwise, find the first free (as in, not used @@ -280,6 +316,7 @@ ns_new_sess(void) s->escape = NS_SCREEN_ESCAPE; /* default setup for the screen program */ s->literal = NS_SCREEN_LITERAL; s->dsbb = NS_SCREEN_DEFSBB; + s->delay = NS_INIT_DELAY; if (sa) { /* add to end of list */ _ns_sess *r = sa; while (r->next) @@ -341,28 +378,33 @@ ns_dst_sess(_ns_sess ** ss) int ns_screen_command(_ns_sess * sess, char *cmd) { + _ns_efuns *efuns; char *c; int ret = NS_SUCC; - if (!cmd || !*cmd) + if (!cmd || !*cmd) { return NS_FAIL; + } - if (sess->efuns->inp_text) { + if (NS_EFUN_EXISTS(efuns, sess, NULL, inp_text)) { if ((c = strdup(cmd))) { - { - char *p = c; /* replace default escape-char with that */ - while (*p) { /* actually used in this session */ - if (*p == NS_SCREEN_ESCAPE) - *p = sess->escape; - p++; + char *p; /* replace default escape-char with that */ + + for (p = c; *p; p++) { /* actually used in this session */ + if (*p == NS_SCREEN_ESCAPE) { + *p = sess->escape; } } - sess->efuns->inp_text(NULL, sess->fd, c); +#ifdef NS_DEBUG + ns_desc_string(c, "ns_screen_command: xlated string"); +#endif + efuns->inp_text(NULL, sess->fd, c); free(c); - } else + } else { + /* out of memory */ ret = NS_OOM; - } /* out of memory */ - else { + } + } else { ret = NS_EFUN_NOT_SET; fprintf(stderr, NS_PREFIX "ns_screen_command: sess->efuns->inp_text not set!\n"); } @@ -472,10 +514,12 @@ ns_upd_stat(_ns_sess * s) int ns_inp_dial(_ns_sess * s, char *prompt, int maxlen, char **retstr, int (*inp_tab) (void *, char *, size_t, size_t)) { + _ns_efuns *efuns; char *c; int ret = NS_SUCC; - if (s->efuns->inp_dial) { - (void) s->efuns->inp_dial((void *) s, prompt, maxlen, retstr, inp_tab); + + if (NS_EFUN_EXISTS(efuns, s, NULL, inp_dial)) { + (void) efuns->inp_dial((void *) s, prompt, maxlen, retstr, inp_tab); } else { ret = NS_EFUN_NOT_SET; fprintf(stderr, NS_PREFIX "ns_screen_command: sess->efuns->inp_dial not set!\n"); @@ -499,8 +543,10 @@ ns_inp_dial(_ns_sess * s, char *prompt, int maxlen, char **retstr, int (*inp_tab int ns_sess_init(_ns_sess * sess) { - if ((sess->backend == NS_MODE_NEGOTIATE) || (sess->backend == NS_MODE_SCREEN)) - return ns_parse_screenrc(sess); + if ((sess->backend == NS_MODE_NEGOTIATE) || (sess->backend == NS_MODE_SCREEN)) { + (void) ns_parse_screenrc(sess, sess->sysrc, NS_ESC_SYSSCREENRC); + return ns_parse_screenrc(sess, sess->home, NS_ESC_SCREENRC); + } return NS_SUCC; } @@ -579,11 +625,47 @@ ns_parse_hop(_ns_sess * s, char *h) +/* ns_desc_string + c the string + doc context-info + !stdout the string, in human-readable form */ + +void +ns_desc_string(char *c, char *doc) +{ + char *p = c; + + if (doc) + fprintf(stderr, NS_PREFIX "%s: ", doc); + + if (!c) { + fputs("NULL\n", stderr); + return; + } else if (!*c) { + fputs("empty\n", stderr); + return; + } + + while (*p) { + if (*p < ' ') + fprintf(stderr, "^%c", *p + 'A' - 1); + else + fputc(*p, stderr); + p++; + } + + fputs("\n", stderr); + + return; +} + + + /* ns_desc_hop print basic info about a hop (tunnel, firewall). mostly for debugging. hop: a hop struct as generated by (eg) ns_attach_by_URL() doc: info about the context - ! stdout: info about the hop */ + ! stderr: info about the hop */ void ns_desc_hop(_ns_hop * h, char *doc) @@ -607,13 +689,14 @@ ns_desc_hop(_ns_hop * h, char *doc) print basic info about a session. mostly for debugging. sess: a session struct as generated by (eg) ns_attach_by_URL() doc: info about the context - ! stdout: info about the session */ + ! stderr: info about the session */ void ns_desc_sess(_ns_sess * sess, char *doc) { if (!sess) { fprintf(stderr, NS_PREFIX "%s: ns_desc_sess called with broken pointer!\n", doc); + fflush(stderr); return; } if (sess->where == NS_LCL) @@ -627,8 +710,12 @@ ns_desc_sess(_ns_sess * sess, char *doc) fprintf(stderr, "%c%s\n", sess->where == NS_LCL ? ' ' : '/', sess->rsrc); if (sess->hop) ns_desc_hop(sess->hop, NULL); + if (sess->sysrc) + fprintf(stderr, NS_PREFIX "info: searching for sysrc in %s\n", sess->sysrc); if (sess->home) - fprintf(stderr, NS_PREFIX "info: searching for rc in %s\n", sess->home); + fprintf(stderr, NS_PREFIX "info: searching for usrrc in %s\n", sess->home); + fprintf(stderr, NS_PREFIX "info: escapes set to ^%c-%c\n", sess->escape + 'A' - 1, sess->literal); + fflush(stderr); } @@ -716,6 +803,64 @@ ns_run(_ns_efuns * efuns, char *cmd) +/* create a call line. used in ns_attach_ssh/lcl + tmpl the template. should contain one %s + dflt the default value + opt the user-supplied value (or NULL) + <- a new malloc'd string (or NULL) */ + +char * +ns_make_call_el(char *tmpl, char *dflt, char *opt) +{ + size_t l, r; + char *p; + + if (tmpl && dflt && *tmpl && strstr(tmpl, "%s")) { + l = strlen(tmpl) + (opt ? strlen(opt) : strlen(dflt)) - 1L; + if ((p = malloc(l))) { + r = snprintf(p, l, tmpl, opt ? opt : dflt); + if ((r >= 0) && (r < l)) { + return p; + } + free(p); + } + } + return NULL; +} + + + +char * +ns_make_call(_ns_sess * sess) +{ + char *call, *tmp = NULL, *screen = NULL, *scream = NULL, *screem = NULL; + + /* unless decidedly in other mode... */ + if (sess->backend != NS_MODE_SCREEN) + tmp = scream = ns_make_call_el(NS_SCREAM_CALL, NS_SCREAM_OPTS, sess->rsrc); + if (sess->backend != NS_MODE_SCREAM) + tmp = screen = ns_make_call_el(NS_SCREEN_CALL, NS_SCREEN_OPTS, sess->rsrc); + if (sess->backend == NS_MODE_NEGOTIATE) { + size_t r, l = strlen(NS_SCREEM_CALL) + strlen(scream) + strlen(screen) - 3; + if ((screem = malloc(l))) { + r = snprintf(screem, l, NS_SCREEM_CALL, scream, screen); +#ifdef NS_PARANOID + if ((r < 0) || (r > l)) { + ns_free(&screem); + } +#endif + } + tmp = screem; + } + call = ns_make_call_el(NS_WRAP_CALL, tmp, NULL); + ns_free(&screen); + ns_free(&scream); + ns_free(&screem); + return call; +} + + + /* attach a local session (using screen/scream) sp the session <- NS_FAIL, or the result of ns_run() */ @@ -724,28 +869,37 @@ int ns_attach_lcl(_ns_sess ** sp) { _ns_sess *sess; -#define MAXCMD 512 - char cmd[MAXCMD + 1]; - int ret; + char *call; + int ret = -1; if (!sp || !*sp) - return NS_FAIL; + return ret; + sess = *sp; - ret = snprintf(cmd, MAXCMD, "%s %s", NS_SCREEN_CALL, sess->rsrc ? sess->rsrc : NS_SCREEN_OPTS); - return (ret < 0 || ret > MAXCMD) ? NS_FAIL : ns_run(sess->efuns, cmd); + + if (call = ns_make_call(sess)) { + char *c2 = ns_make_call_el("/bin/sh -c \"%s\"", call, NULL); + ns_free(&call); + if (c2) { + ret = ns_run(sess->efuns, c2); + ns_free(&c2); + } + } + return ret; } /* attach a remote session (using screen/scream via ssh) sp the session - <- NS_FAIL, or the result of ns_run() */ + <- -1, or the result of ns_run() */ int ns_attach_ssh(_ns_sess ** sp) { _ns_sess *sess; - char cmd[MAXCMD + 1]; + char cmd[NS_MAXCMD + 1]; + char *call; int ret; if (!sp || !*sp) @@ -753,23 +907,31 @@ ns_attach_ssh(_ns_sess ** sp) sess = *sp; + call = ns_make_call(sess); + if (sess->hop) { if (sess->hop->established == NS_HOP_DOWN) { /* the nightmare foe */ - ret = snprintf(cmd, MAXCMD, "%s %s -p %d -L %d:%s:%d %s@%s", + ret = snprintf(cmd, NS_MAXCMD, "%s %s -p %d -L %d:%s:%d %s@%s", NS_SSH_CALL, NS_SSH_TUNNEL_OPTS, - sess->hop->fwport, sess->hop->localport, sess->host, sess->port, sess->user, sess->hop->fw, NS_SCREEM_CALL); - if (ret < 0 || ret > MAXCMD) + sess->hop->fwport, sess->hop->localport, sess->host, sess->port, sess->user, sess->hop->fw); + if (ret < 0 || ret > NS_MAXCMD) return NS_FAIL; ns_run(sess->efuns, cmd); sleep(sess->hop->delay); } - ret = snprintf(cmd, MAXCMD, "%s %s -p %d %s@localhost %s", - NS_SSH_CALL, NS_SSH_OPTS, sess->hop->localport, sess->user, NS_SCREEM_CALL); + ret = snprintf(cmd, NS_MAXCMD, "%s %s -p %d %s@localhost \"%s -e^%c%c\"", + NS_SSH_CALL, NS_SSH_OPTS, sess->hop->localport, sess->user, call, sess->escape + 'A' - 1, sess->literal); } else { - ret = snprintf(cmd, MAXCMD, "%s %s -p %d %s@%s %s", NS_SSH_CALL, NS_SSH_OPTS, sess->port, sess->user, sess->host, NS_SCREEM_CALL); + ret = + snprintf(cmd, NS_MAXCMD, "%s %s -p %d %s@%s \"%s -e^%c%c\"", NS_SSH_CALL, NS_SSH_OPTS, sess->port, sess->user, sess->host, call, + sess->escape + 'A' - 1, sess->literal); } - - return (ret < 0 || ret > MAXCMD) ? NS_FAIL : ns_run(sess->efuns, cmd); + ns_free(&call); +#ifdef NS_DEBUG + fprintf(stderr, "\n\n>>%s\n>>%s\n\n", call, cmd); + fflush(stderr); +#endif + return (ret < 0 || ret > NS_MAXCMD) ? NS_FAIL : ns_run(sess->efuns, cmd); } @@ -801,6 +963,8 @@ ns_attach_by_sess(_ns_sess ** sp, int *err) ns_desc_sess(sess, "ns_attach_by_sess()"); #endif + (void) ns_sess_init(sess); + switch (sess->where) { case NS_LCL: sess->fd = ns_attach_lcl(&sess); @@ -817,10 +981,9 @@ ns_attach_by_sess(_ns_sess ** sp, int *err) } #ifdef NS_DEBUG - fprintf(stderr, NS_PREFIX "ns_attach_by_sess: screen session-fd is %d\n", sess->fd); + fprintf(stderr, NS_PREFIX "ns_attach_by_sess: screen session-fd is %d, ^%c-%c\n", sess->fd, sess->escape + 'A' - 1, sess->literal); #endif - (void) ns_sess_init(sess); return sess; fail: @@ -929,6 +1092,7 @@ ns_attach_by_URL(char *url, char *hop, _ns_efuns ** ef, int *err, void *xd) if ((x = ns_parse_esc(&r)) && (y = ns_parse_esc(&r))) { sess->escape = x; sess->literal = y; + sess->escdef = NS_ESC_CMDLINE; } } else if (*r == 'c') { /* alt screenrc */ char *rc, *rx; @@ -991,20 +1155,37 @@ ns_attach_by_URL(char *url, char *hop, _ns_efuns ** ef, int *err, void *xd) goto fail; } else if (pwe && strcmp(pwe->pw_name, sess->user)) { /* user!=current_user */ sess->where = NS_SU; - if (!(pwe = getpwnam(sess->user))) { + if (!(pwe = getpwnam(sess->user)) && !sess->host && !sess->port) { *err = NS_UNKNOWN_USER; goto fail; } } - if (getenv("SCREENRC")) { + if (getenv("SYSSCREENRC")) { /* $SYSSCREENRC */ + if (!(sess->sysrc = strdup(getenv("SCREENRC")))) + goto fail; + } else { + char *loc[] = { "/usr/local/etc/screenrc", /* official */ + "/etc/screenrc", /* actual (on SuSE) */ + "/usr/etc/screenrc", + "/opt/etc/screenrc" + }; + int n, nloc = sizeof(loc) / sizeof(char *); + for (n = 0; n < nloc; n++) + if (!access(loc[n], R_OK)) { + if (!(sess->sysrc = strdup(loc[n]))) + goto fail; + n = nloc; + } + } + + if (getenv("SCREENRC")) { /* $SCREENRC */ sess->home = strdup(getenv("SCREENRC")); - } else if (pwe && !sess->home) { + } else if (pwe && !sess->home) { /* ~/.screenrc */ if ((sess->home = malloc(strlen(pwe->pw_dir) + strlen(NS_SCREEN_RC) + 2))) sprintf(sess->home, "%s/%s", pwe->pw_dir, NS_SCREEN_RC); - else - goto fail; - } + } else + goto fail; if (!sess->host) { /* no host */ if (!(sess->host = strdup("localhost"))) @@ -1020,7 +1201,7 @@ ns_attach_by_URL(char *url, char *hop, _ns_efuns ** ef, int *err, void *xd) sess->backend = NS_MODE_NEGOTIATE; if (!sess->proto) { - if (!(sess->proto = strdup("scream"))) + if (!(sess->proto = strdup("screXX"))) goto fail; } else if (!strcmp(sess->proto, "screen")) sess->backend = NS_MODE_SCREEN; @@ -1061,7 +1242,9 @@ ns_attach_by_URL(char *url, char *hop, _ns_efuns ** ef, int *err, void *xd) int ns_detach(_ns_sess ** sess) { +#ifdef NS_DEBUG ns_desc_sess(*sess, "ns_detach"); +#endif (void) ns_dst_sess(sess); return NS_SUCC; } @@ -1181,6 +1364,15 @@ ns_register_tab(_ns_efuns * efuns, int (*inp_tab) (void *, char *[], int, char * +/* function that will do whatever while waiting */ +void +ns_register_fun(_ns_efuns * efuns, int (*inp_fun) (void *, int)) +{ + efuns->waitstate = inp_fun; +} + + + /* get callbacks. at least one of session and display must be non-NULL. s session, or NULL. if NULL, will be initialized from d->sess d display, or NULL. if NULL, will be initialized from s->curr. @@ -1208,20 +1400,6 @@ ns_get_efuns(_ns_sess * s, _ns_disp * d) -/* test if we have a valid callback for function-type "e". - !p a variable of the "_ns_efuns *" type. will contain a pointer to - an efun struct containing a function pointer to the requested function - if such a struct exists, or NULL, if it doesn't exist - s a variable of the "_ns_sess *" type, or NULL (see ns_get_efuns()) - d a variable of the "_nd_disp *" type, or NULL (see ns_get_efuns()) - e the name of an element of "_ns_efuns" - !<- conditional execution of next (compound-) statement (which would - normally be (p)->(e)(...), the call of the function e). - */ -#define NS_IF_EFUN_EXISTS(p,s,d,e) if(((p)=ns_get_efuns((s),(d)))&&((p)->e)) - - - /***************************************************************************/ /* display-handling */ /********************/ @@ -1282,10 +1460,8 @@ disp_fetch_or_make(_ns_sess * s, int n) d->sess = s; /* note session on display */ -#if 1 if (!d->sess->curr) /* note as current on session if first display */ d->sess->curr = d; -#endif return d; } @@ -1407,11 +1583,13 @@ ns_inp_tab(void *xd, char *b, size_t l, size_t m) "writelock", "xoff", "xon", "zombie" }; + _ns_efuns *efuns; _ns_sess *s = (_ns_sess *) xd; int nsc = sizeof(sc) / sizeof(char *); - if (s->efuns->inp_tab) - return s->efuns->inp_tab((void *) s, sc, nsc, b, l, m) < 0 ? NS_FAIL : NS_SUCC; + if (NS_EFUN_EXISTS(efuns, s, NULL, inp_tab)) { + return efuns->inp_tab((void *) s, sc, nsc, b, l, m) < 0 ? NS_FAIL : NS_SUCC; + } fprintf(stderr, NS_PREFIX "ns_screen_command: sess->efuns->inp_tab not set!\n"); return NS_EFUN_NOT_SET; @@ -1470,12 +1648,13 @@ ns_parse_esc(char **x) /* ns_parse_screen_cmd parse a command the user intends to send to the screen program, either via .screenrc or using ^A: - s the affected (current) session. s->current should be set. - p the command + s the affected (current) session. s->current should be set. + p the command + whence which parsing stage (screenrc, interactive, ...) <- error code */ int -ns_parse_screen_cmd(_ns_sess * s, char *p) +ns_parse_screen_cmd(_ns_sess * s, char *p, int whence) { char *p2; long v1 = -1; @@ -1492,21 +1671,33 @@ ns_parse_screen_cmd(_ns_sess * s, char *p) v1 = -1; } #define IS_CMD(b) (strncasecmp(p,b,strlen(b))==0) - if (!p2) + if (!p2) { fprintf(stderr, NS_PREFIX "screenrc: ignoring \"%s\" without an argument...\n", p); - else if (IS_CMD("defescape")) + /* must return success so it's fowarded to screen in interactive mode. + that way, the user can read the original reply instead of a fake + one from us. */ + return NS_SUCC; + } else if (IS_CMD("defescape")) fprintf(stderr, NS_PREFIX "screenrc: ignoring \"defescape\", did you mean \"escape\"?\n"); - else if (IS_CMD("defhstatus") || IS_CMD("hardstatus") || IS_CMD("echo") || - IS_CMD("colon") || IS_CMD("nethack") || - IS_CMD("info") || IS_CMD("time") || IS_CMD("title") || IS_CMD("wall") || - IS_CMD("lastmsg") || IS_CMD("msgwait") || IS_CMD("msgminwait")) + else if (IS_CMD("defhstatus") || IS_CMD("hardstatus") || IS_CMD("echo") || IS_CMD("colon") || IS_CMD("wall") || +#ifdef NS_PARANOID + IS_CMD("nethack") || +#endif + IS_CMD("info") || IS_CMD("time") || IS_CMD("title") || IS_CMD("lastmsg") || IS_CMD("msgwait") || IS_CMD("msgminwait")) { fprintf(stderr, NS_PREFIX "screenrc: ignoring \"%s\", not applicable...\n", p); - else if (IS_CMD("escape")) { + return NS_NOT_ALLOWED; + } else if (IS_CMD("escape")) { char x = 0, y = 0; if ((x = ns_parse_esc(&p2)) && (y = ns_parse_esc(&p2))) { - s->escape = x; - s->literal = y; - return NS_SUCC; + if (s->escdef == NS_ESC_CMDLINE) { + fprintf(stderr, NS_PREFIX "screenrc: ignoring \"escape\"; overridden on command-line...\n", x, y); + return NS_NOT_ALLOWED; + } else { + s->escape = x; + s->literal = y; + s->escdef = whence; + return NS_SUCC; + } } else fprintf(stderr, NS_PREFIX "screenrc: ignoring \"escape\" because of invalid arguments %o %o...\n", x, y); } else if (IS_CMD("defscrollback")) { @@ -1570,8 +1761,11 @@ ns_parse_screen_key(_ns_sess * s, char c) case NS_SCREEN_CMD: /* send command (statement) to screen server */ (void) ns_inp_dial((void *) s, "Enter a command to send to the \"screen\" program", 64, &i, ns_inp_tab); if (i) { - ret = ns_screen_xcommand(s, c, i); - (void) ns_parse_screen_cmd(s, i); + if ((ret = ns_parse_screen_cmd(s, i, NS_ESC_INTERACTIVE)) == NS_SUCC) { + ret = ns_screen_xcommand(s, c, i); + } else if (ret == NS_NOT_ALLOWED) { + menu_dial(NULL, "Sorry, David, I cannot allow that.", 0, NULL, NULL); + } free(i); } break; @@ -1600,24 +1794,72 @@ ns_parse_screen_key(_ns_sess * s, char c) +/* ns_parse_screen_interactive + parse a whole string that may contain screen-escapes that should be + handled interactively (that should open dialog boxes etc.). + this will normally be called by menus, buttons etc. that want to send + input to the add without generating X events for the keystrokes (real + keystrokes do not come through here; the keyboard-handler should call + ns_parse_screen_key() directly when it sees the session's escape-char). + s the session in question + c the string to parse + <- error code */ + +int +ns_parse_screen_interactive(_ns_sess * sess, char *c) +{ + char *s, *p, *o; + + if (!c || !*c) + return NS_FAIL; +#ifdef NS_PARANOID + if (!(s = o = strdup(c))) + return NS_FAIL; +#else + s = c; +#endif + + p = s; + + while ((p = strchr(s, NS_SCREEN_ESCAPE))) { + *p = '\0'; + (void) ns_screen_command(sess, s); + *p = NS_SCREEN_ESCAPE; + if (*(++p)) + ns_parse_screen_key(sess, *(p++)); + s = p; + } + (void) ns_screen_command(sess, s); + +#ifdef NS_PARANOID + free(o); +#endif + + return NS_SUCC; +} + + + /* ns_parse_screenrc -- read the user's screenrc (if we can find it), parse it (we need to know if she changes the escapes etc.), and send it to the actually screen - s the session in question - <- error code */ + s the session + fn name of the file in question + whence which screenrc are we in? + <- error code */ int -ns_parse_screenrc(_ns_sess * s) +ns_parse_screenrc(_ns_sess * s, char *fn, int whence) { int fd = -1; char *rc = NULL; char _e = '\0', _l = '\0', *esc = NULL; - if (s->home) { + if (fn) { struct stat st; ssize_t rd = 0; - if ((fd = open(s->home, 0)) >= 0) { + if ((fd = open(fn, 0)) >= 0) { if (!fstat(fd, &st)) { if ((rc = malloc(st.st_size + 1))) { char *p; @@ -1655,7 +1897,7 @@ ns_parse_screenrc(_ns_sess * s) } if (strlen(p)) /* any commands in line? */ - ns_parse_screen_cmd(s, p); + ns_parse_screen_cmd(s, p, whence); p = n; /* done, next line */ } free(rc); @@ -1705,8 +1947,9 @@ ns_parse_screen_msg(_ns_sess * screen, char *p) type = (strlen(p) > 1) ? NS_SCREEN_STATUS : NS_SCREEN_ST_CLR; if (type == NS_SCREEN_ST_CLR) { - NS_IF_EFUN_EXISTS(efuns, screen, NULL, err_msg) + if (NS_EFUN_EXISTS(efuns, screen, NULL, err_msg)) { ret = efuns->err_msg(NULL, type, ""); + } } /* a screen display can disappear because the program in it dies, or because we explicitly ask screen to kill the display. in the latter @@ -1723,15 +1966,19 @@ ns_parse_screen_msg(_ns_sess * screen, char *p) p = NULL; } else if (!strcmp(p, "New screen...") || !strncmp(p, "msgwait", strlen("msgwait")) || !strncmp(p, "msgminwait", strlen("msgminwait"))) p = NULL; +#ifndef NS_PARANOID + /* FIXME. */ else if (sscanf(p, NS_SCREEN_VERSION, &p3, &ma, &mi, &mu, &p2, &d) == 6) { if (!strcmp("en", p3)) screen->backend = NS_MODE_SCREEN; else if (!strcmp("am", p3)) screen->backend = NS_MODE_SCREAM; -#ifdef NS_DEBUG +# ifdef NS_DEBUG fprintf(stderr, NS_PREFIX "ns_parse_screen_msg: scre%s %d.%2d.%2d %s a/o %s\n", p3, ma, mi, mu, p2, d); +# endif + } #endif - } else if (!strcmp(p, NS_SCREEN_NO_DEBUG)) + else if (!strcmp(p, NS_SCREEN_NO_DEBUG)) p = "debug info was not compiled into \"screen\"..."; else if (!strncmp(p, NS_SCREEN_DK_CMD, strlen(NS_SCREEN_DK_CMD))) { p[strlen(p) - 1] = '\0'; @@ -1739,8 +1986,9 @@ ns_parse_screen_msg(_ns_sess * screen, char *p) p = "unknown screen statement ignored"; } if (p) { /* status. send to status-line or dialog or whatever */ - NS_IF_EFUN_EXISTS(efuns, screen, NULL, err_msg) + if (NS_EFUN_EXISTS(efuns, screen, NULL, err_msg)) { ret = efuns->err_msg(NULL, type, p); + } } return ret; } @@ -1788,7 +2036,7 @@ ns_parse_screen(_ns_sess * screen, int force, int width, char *p) if (!screen || !p || !width) return NS_FAIL; - if (!force) + if (!force && screen->timestamp) return NS_SUCC; if (p = strdup(p)) { @@ -1803,17 +2051,26 @@ ns_parse_screen(_ns_sess * screen, int force, int width, char *p) fprintf(stderr, NS_PREFIX "parse_screen: screen sends ::%s::\n", p); #endif -#ifdef NS_PARANOID_ if (strlen(p) < 2) { /* special case: display 0 */ disp = screen->dsps; /* might not get a status-line in d0! */ if (disp && !(disp->flags & NS_SCREAM_CURR)) { /* flags need updating */ disp->flags |= NS_SCREAM_CURR; /* set flag to avoid calling inp_text */ ret = ns_upd_stat(screen); - } /* more than once */ + } /* more than once */ + else if (!screen->timestamp) { + screen->timestamp = time(NULL); + if (screen->delay > 0) { + if (NS_EFUN_EXISTS(efuns, screen, NULL, waitstate)) { + ret = efuns->waitstate(NULL, screen->delay * 1000); + } else { + sleep(screen->delay); + } + } + (void) ns_screen_command(screen, NS_SCREEN_INIT); + } free(p); return ret; } -#endif p3 = p; while (isspace(*p3)) /* skip left padding */ @@ -1876,8 +2133,9 @@ ns_parse_screen(_ns_sess * screen, int force, int width, char *p) fprintf(stderr, NS_PREFIX "parse_screen: out of memory in new_display(%d)\n", n); ret = NS_FAIL; } else { - NS_IF_EFUN_EXISTS(efuns, screen, NULL, ins_disp) + if (NS_EFUN_EXISTS(efuns, screen, NULL, ins_disp)) { ret = efuns->ins_disp(screen->userdef, pd[r].real - 1, disp->name); + } } } else if ((tmp = strcmp(disp->name, pd[r].name)) || /* upd display */ (disp->flags != pd[r].flags)) { @@ -1891,8 +2149,9 @@ ns_parse_screen(_ns_sess * screen, int force, int width, char *p) if (pd[r].flags & NS_SCREAM_CURR) disp->sess->curr = disp; disp->flags = pd[r].flags & NS_SCREAM_MASK; - NS_IF_EFUN_EXISTS(efuns, screen, NULL, upd_disp) + if (NS_EFUN_EXISTS(efuns, screen, NULL, upd_disp)) { ret = efuns->upd_disp(screen->userdef, r, disp->flags, disp->name); + } } /* remove any displays from list that have disappeared @@ -1904,8 +2163,9 @@ ns_parse_screen(_ns_sess * screen, int force, int width, char *p) fprintf(stderr, NS_PREFIX "parse_screen: remove expired middle %d \"%s\"...\n", d3->index, d3->name); #endif d4 = d3->prvs; - NS_IF_EFUN_EXISTS(efuns, screen, NULL, del_disp) + if (NS_EFUN_EXISTS(efuns, screen, NULL, del_disp)) { ret = efuns->del_disp(screen->userdef, disp_get_real_by_screen(screen, d3->index)); + } disp_kill(d3); d3 = d4; } @@ -1945,8 +2205,9 @@ ns_parse_screen(_ns_sess * screen, int force, int width, char *p) if (d2->sess->curr == d2) d2->sess->curr = d3; disp = disp->next; - NS_IF_EFUN_EXISTS(efuns, screen, NULL, del_disp) + if (NS_EFUN_EXISTS(efuns, screen, NULL, del_disp)) { ret = efuns->del_disp(screen->userdef, disp_get_real_by_screen(screen, d2->index)); + } disp_kill(d2); } d3->next = NULL; @@ -1963,26 +2224,12 @@ ns_parse_screen(_ns_sess * screen, int force, int width, char *p) we could send it before entering this function for the first time, but that would break if escapes or screenrc were set from the command-line. don't ask. */ -#ifdef NS_DEBUG - if (!screen) - fprintf(stderr, NS_PREFIX "parse_screen: session went away!?\n\n CONDITION RED!\n CONDITION RED!\n DANGER WILL ROBINSON!!!\n\n"); - else -#endif - { - if (!screen->timestamp) { - screen->timestamp = time(NULL); -#ifdef NS_DEBUG - fprintf(stderr, NS_PREFIX "parse_screen: sending NS_SCREEN_INIT with prefix %d...\n", screen->escape); -#endif - ret = ns_screen_command(screen, NS_SCREEN_INIT); - } #if (NS_SCREEN_UPD_FREQ>0) - else if ((t2 - screen->timestamp) > NS_SCREEN_UPD_FREQ) { - (void) ns_upd_stat(screen); - screen->timestamp = t2; - } -#endif + if ((t2 - screen->timestamp) > NS_SCREEN_UPD_FREQ) { + (void) ns_upd_stat(screen); + screen->timestamp = t2; } +#endif return ret; } |