version 1.70, 2011/01/03 21:30:49 |
version 1.71, 2011/01/26 01:54:56 |
|
|
struct client *, time_t, int, struct grid_cell *, size_t *); |
struct client *, time_t, int, struct grid_cell *, size_t *); |
char *status_redraw_get_right( |
char *status_redraw_get_right( |
struct client *, time_t, int, struct grid_cell *, size_t *); |
struct client *, time_t, int, struct grid_cell *, size_t *); |
char *status_job(struct client *, char **); |
char *status_find_job(struct client *, char **); |
|
void status_job_free(void *); |
void status_job_callback(struct job *); |
void status_job_callback(struct job *); |
char *status_print( |
char *status_print( |
struct client *, struct winlink *, time_t, struct grid_cell *); |
struct client *, struct winlink *, time_t, struct grid_cell *); |
|
|
/* Status prompt history. */ |
/* Status prompt history. */ |
ARRAY_DECL(, char *) status_prompt_history = ARRAY_INITIALIZER; |
ARRAY_DECL(, char *) status_prompt_history = ARRAY_INITIALIZER; |
|
|
|
/* Status output tree. */ |
|
RB_GENERATE(status_out_tree, status_out, entry, status_out_cmp); |
|
|
|
/* Output tree comparison function. */ |
|
int |
|
status_out_cmp(struct status_out *so1, struct status_out *so2) |
|
{ |
|
return (strcmp(so1->cmd, so2->cmd)); |
|
} |
|
|
/* Retrieve options for left string. */ |
/* Retrieve options for left string. */ |
char * |
char * |
status_redraw_get_left(struct client *c, |
status_redraw_get_left(struct client *c, |
|
|
ch = ')'; |
ch = ')'; |
goto skip_to; |
goto skip_to; |
} |
} |
if ((ptr = status_job(c, iptr)) == NULL) |
if ((ptr = status_find_job(c, iptr)) == NULL) |
return; |
return; |
freeptr = ptr; |
|
goto do_replace; |
goto do_replace; |
case 'H': |
case 'H': |
if (gethostname(tmp, sizeof tmp) != 0) |
if (gethostname(tmp, sizeof tmp) != 0) |
|
|
|
|
/* Figure out job name and get its result, starting it off if necessary. */ |
/* Figure out job name and get its result, starting it off if necessary. */ |
char * |
char * |
status_job(struct client *c, char **iptr) |
status_find_job(struct client *c, char **iptr) |
{ |
{ |
struct job *job; |
struct status_out *so, so_find; |
char *cmd; |
char *cmd; |
int lastesc; |
int lastesc; |
size_t len; |
size_t len; |
|
|
if (**iptr == '\0') |
if (**iptr == '\0') |
return (NULL); |
return (NULL); |
|
|
(*iptr)++; /* skip final ) */ |
(*iptr)++; /* skip final ) */ |
cmd[len] = '\0'; |
cmd[len] = '\0'; |
|
|
job = job_get(&c->status_jobs, cmd); |
/* First try in the new tree. */ |
if (job == NULL) { |
so_find.cmd = cmd; |
job = job_add(&c->status_jobs, |
so = RB_FIND(status_out_tree, &c->status_new, &so_find); |
JOB_PERSIST, c, cmd, status_job_callback, xfree, NULL); |
if (so != NULL && so->out != NULL) |
job_run(job); |
return (so->out); |
|
|
|
/* If not found at all, start the job and add to the tree. */ |
|
if (so == NULL) { |
|
job_run(cmd, status_job_callback, status_job_free, c); |
|
c->references++; |
|
|
|
so = xmalloc(sizeof *so); |
|
so->cmd = xstrdup(cmd); |
|
so->out = NULL; |
|
RB_INSERT(status_out_tree, &c->status_new, so); |
} |
} |
|
|
|
/* Lookup in the old tree. */ |
|
so_find.cmd = cmd; |
|
so = RB_FIND(status_out_tree, &c->status_old, &so_find); |
xfree(cmd); |
xfree(cmd); |
if (job->data == NULL) |
if (so != NULL) |
return (xstrdup("")); |
return (so->out); |
return (xstrdup(job->data)); |
return (NULL); |
} |
} |
|
|
|
/* Free job tree. */ |
|
void |
|
status_free_jobs(struct status_out_tree *sotree) |
|
{ |
|
struct status_out *so, *so_next; |
|
|
|
so_next = RB_MIN(status_out_tree, sotree); |
|
while (so_next != NULL) { |
|
so = so_next; |
|
so_next = RB_NEXT(status_out_tree, sotree, so); |
|
|
|
RB_REMOVE(status_out_tree, sotree, so); |
|
if (so->out != NULL) |
|
xfree(so->out); |
|
xfree(so->cmd); |
|
xfree(so); |
|
} |
|
} |
|
|
|
/* Update jobs on status interval. */ |
|
void |
|
status_update_jobs(struct client *c) |
|
{ |
|
/* Free the old tree. */ |
|
status_free_jobs(&c->status_old); |
|
|
|
/* Move the new to old. */ |
|
memcpy(&c->status_old, &c->status_new, sizeof c->status_old); |
|
RB_INIT(&c->status_new); |
|
} |
|
|
|
/* Free status job. */ |
|
void |
|
status_job_free(void *data) |
|
{ |
|
struct client *c = data; |
|
|
|
c->references--; |
|
} |
|
|
/* Job has finished: save its result. */ |
/* Job has finished: save its result. */ |
void |
void |
status_job_callback(struct job *job) |
status_job_callback(struct job *job) |
{ |
{ |
char *line, *buf; |
struct client *c = job->data; |
size_t len; |
struct status_out *so, so_find; |
|
char *line, *buf; |
|
size_t len; |
|
|
|
if (c->flags & CLIENT_DEAD) |
|
return; |
|
|
|
so_find.cmd = job->cmd; |
|
so = RB_FIND(status_out_tree, &c->status_new, &so_find); |
|
if (so == NULL || so->out != NULL) |
|
return; |
|
|
buf = NULL; |
buf = NULL; |
if ((line = evbuffer_readline(job->event->input)) == NULL) { |
if ((line = evbuffer_readline(job->event->input)) == NULL) { |
len = EVBUFFER_LENGTH(job->event->input); |
len = EVBUFFER_LENGTH(job->event->input); |
|
|
if (len != 0) |
if (len != 0) |
memcpy(buf, EVBUFFER_DATA(job->event->input), len); |
memcpy(buf, EVBUFFER_DATA(job->event->input), len); |
buf[len] = '\0'; |
buf[len] = '\0'; |
} |
} else |
|
buf = xstrdup(line); |
|
|
if (job->data != NULL) |
so->out = buf; |
xfree(job->data); |
server_redraw_client(c); |
else |
|
server_redraw_client(job->client); |
|
|
|
if (line == NULL) |
|
job->data = buf; |
|
else |
|
job->data = xstrdup(line); |
|
} |
} |
|
|
/* Return winlink status line entry and adjust gc as necessary. */ |
/* Return winlink status line entry and adjust gc as necessary. */ |