/***********************************************************************
* *
* This software is part of the ast package *
* Copyright (c) 1990-2011 AT&T Intellectual Property *
* and is licensed under the *
* Eclipse Public License, Version 1.0 *
* by AT&T Intellectual Property *
* *
* A copy of the License is available at *
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
* *
* Information and Software Systems Research *
* AT&T Research *
* Florham Park NJ *
* *
* Glenn Fowler <gsf@research.att.com> *
* *
***********************************************************************/
#pragma prototyped
/*
* Glenn Fowler
* AT&T Bell Laboratories
*
* remote coshell server command interface support
*/
#include "service.h"
static struct
{
int* pass;
int fd;
} svc;
/*
* send command message to fd and read ack
* 0 returned after the last command
*/
static int
{
int i;
int m;
int x;
if (c == 'Q') return(0);
s = cmd;
{
else
{
n -= 4;
s += 4;
}
}
{
return(0);
}
{
n = 0;
i = n;
for (m = 0; m < n; m++)
{
{
}
}
{
{
else
{
}
}
else
{
}
}
while (--i > n)
}
return(1);
}
#ifdef SIGCONT
/*
* send a job control kill message to fd
*/
static void
{
int n;
}
/*
* pass job control signals to the server and self
*/
static void
{
}
#endif
/*
* command loop on server stream fd
* if ap!=0 then it is an argv of commands
* otherwise the commands are read from stdin
* exit code returned
*/
int
{
register char* s;
register int n;
int c;
int m;
int helped = 0;
int code = 0;
int prompt;
char* t;
char* arg;
char* att;
#ifdef SIGCONT
#ifdef SIGTSTP
#endif
#ifdef SIGTTIN
#endif
#ifdef SIGTTOU
#endif
#endif
{
}
for (;;)
{
if (!ap)
{
while (isspace(*s)) s++;
if (c = *s) s++;
}
else if (!(s = *ap++)) break;
else if (*s == '-' && s[1])
{
c = *++s;
s++;
}
if (c == 'q') break;
while (isspace(*s)) s++;
switch (c)
{
case 0:
case '#':
continue;
case 'a':
case 'c':
case 'l':
case 'o':
break;
case 'd':
case 'f':
case 'g':
case 'j':
case 'k':
case 's':
case 't':
case 'u':
case 'v':
case 'Q':
while (isspace(*s)) s++;
m = isalpha(*s) ? *s++ : '-';
while (isspace(*s)) s++;
if (isdigit(*s))
{
n = strtol(s, &t, 0);
s = t;
}
else n = *s ? *s : NOARG;
break;
case 'r':
case 'R':
m = 0;
att = s;
for (;;)
{
if (!(n = *s++))
{
s--;
break;
}
if (n == '\\')
{
if (*s) s++;
}
else if (!m)
{
if (n == '\'' || n == '"') m = n;
else if (isspace(*s))
{
*s++ = 0;
while (isspace(*s)) s++;
break;
}
}
else if (n == m) m = 0;
}
0,
1,
c == 'r' ? CO_SILENT : 0,
NiL,
NiL,
NiL);
if (ap)
{
while (s = *ap++)
ap--;
}
break;
default:
if (helped) continue;
/*FALLTHROUGH*/
case 'h':
case '?':
helped++;
error(0, "\
\n\
a host ... change host shell attributes\n\
c host ... close host shell\n\
d [level] set debug trace stderr [and level]\n\
f [fd] internal fd status [drop CON fd]\n\
g global state\n\
h help\n\
j job status\n\
k [ckst] job terminate [continue|kill|stop|term] job\n\
l host list matching host names\n\
o host ... open host shell\n\
q quit\n\
r host [cmd] run cmd [hostname] on host\n\
s [aelopst] shell status [attr|every|long|open|pid|sched|temp]\n\
t shell and user connection totals\n\
u user connection status\n\
v server version\n\
Q kill server and quit\n\
");
continue;
}
}
return(code);
}
/*
* return file mode given fd
* if must!=0 then 0 returned if fstat fails
*/
static char*
{
char* p;
#ifdef S_ISSOCK
*p = 's';
#else
*p = 'p';
#endif
return(p);
}
/*
* do CO_server op for user fd
*/
void
{
register char* s;
register int n;
int u;
int hdr;
char* t;
char* v;
hdr = 0;
switch (op)
{
case 0:
break;
case 'a':
if (dat)
{
while (s = tokread(t))
tokclose(t);
}
break;
case 'c':
if (dat)
{
while (s = tokread(t))
{
if (!(sp = search(GET, s, NiL, NiL))) error(ERROR_OUTPUT|2, con[fd].info.user.fds[2], "%s: not found", s);
}
tokclose(t);
}
break;
case 'd':
if (arg == 't')
{
break;
}
else if (arg == 'T')
{
break;
}
message((error_info.trace, "level=%d output=%s", -arg, dat ? dat : cspath(state.indirect.con ? 2 : con[fd].info.user.fds[2], 0)));
if (dat)
{
if ((n = open(dat, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) >= 0)
{
close(2);
dup(n);
close(n);
}
}
{
close(2);
}
break;
case 'f':
{
{
case ANON:
break;
case DEST:
break;
case IDENT:
break;
case MESG:
break;
case PASS:
if (jp = con[n].info.pass.job) sfprintf(state.string, "%3d pass %-3d %s %d%s\n", n, con[n].info.pass.fd, jp->shell->name, jp->pid, con[n].info.pass.serialize ? " serialize" : "");
break;
case POLL:
break;
case PUMP:
break;
case SHELL:
break;
case USER:
if (con[n].info.user.fds[0] == n) sfprintf(state.string, "%3d query %-3d %-3d %s\n", n, con[n].info.user.fds[1], con[n].info.user.fds[2], (sp = con[n].info.user.home) ? sp->name : "");
else sfprintf(state.string, "%3d user %-3d %-3d %-3d %s\n", n, con[n].info.user.fds[0], con[n].info.user.fds[1], con[n].info.user.fds[2], (sp = con[n].info.user.home) ? sp->name : "");
break;
case UCMD:
t = "ucmd";
goto path;
case UERR:
t = "uerr";
goto path;
case UOUT:
t = "uout";
goto path;
case 0:
t = "open";
path:
break;
}
}
else if (arg >= state.fdtotal || !con[arg].type) error(ERROR_OUTPUT|2, con[fd].info.user.fds[2], "cannot drop CON %d", arg);
break;
case 'g':
/*
* string values
*/
/*
* readonly values
*/
sfprintf(state.string, " access %-7s", state.access < cs.time ? "EXPIRED" : fmtelapsed(state.access - cs.time, 1));
/*
* global values
*/
/*
* done
*/
break;
case 'j':
{
{
case QUEUE:
t = "QUEUE";
break;
case START:
t = "START";
break;
case WARP:
t = "WARP";
break;
default:
break;
}
if (!hdr)
{
hdr = 1;
}
sfprintf(state.string, "%3d%4d%4d%6s%7s%c%-16s %s%s%s", jp - state.job, jp->fd, jp->rid, t, fmtelapsed(cs.time - jp->start, 1), jp->ref <= 0 ? '*' : jp->lost ? (jp->lost > cs.time ? '?' : '!') : ' ', jp->shell->name, v, *v ? " " : "", jp->label);
}
break;
case 'k':
else switch (sub)
{
#ifdef SIGCONT
case 'c':
break;
#endif
case 'k':
break;
#ifdef SIGSTOP
case 's':
break;
#endif
case 't':
case '-':
break;
default:
break;
}
break;
case 'l':
do
{
{
*sv = 0;
if (dat && (attr.global.set & SETPOOL) && attr.global.pool > 0 && attr.global.pool < n) sv[attr.global.pool] = 0;
}
break;
case 'o':
if (dat)
{
while (s = tokread(t))
{
if (!(sp = search(NEW, s, NiL, NiL))) error(ERROR_OUTPUT|2, con[fd].info.user.fds[2], "%s: invalid host name", s);
}
tokclose(t);
}
break;
case 's':
do
{
if (sub == 'a' || sub == 'e' || sp->fd || (sub == 'l' || sub == 's') && sp->temp && !(sp->flags & IGN)) *sv++ = sp;
{
*sv = 0;
strsort((char**)(sv = state.shellv), n, sub == 'a' || sub == 'e' || sub == 'p' ? byname : sub == 't' ? bytemp : byrank);
switch (sub)
{
case 'a':
sfprintf(state.string, "HOST CONF\n%-12.12s busy=%s grace=%s name=%s percpu=%d perserver=%d peruser=%d pool=%d\n", CS_HOST_LOCAL, fmtelapsed(state.busy, 1), fmtelapsed(state.grace, 1), state.shell->name, state.percpu, state.perserver, state.peruser, state.pool);
break;
case 'o':
case 's':
case 't':
break;
case 'p':
break;
default:
break;
}
{
switch (sub)
{
case 'a':
break;
case 'p':
break;
default:
if (sub == 'o' || sub == 's' || sub == 't') sfprintf(state.string, "%3s%c%4d%6d%7s%8s%7s%7s/%d%7s%7s%9s %s\n"
, t
);
, t
, sp->stat.up < 0 ? '-' : (sp->mode & SHELL_DISABLE) ? '$' : (sp->mode & SHELL_DENIED) ? '!' : sp->idle && sp->stat.idle < sp->idle ? (sp->home ? '~' : '*') : ' '
);
break;
}
}
}
break;
case 't':
do
{
{
}
{
}
{
}
sfprintf(state.string, "%6s%7s%8s%6d%7s%7s%7s%7s%8s%6s%7s\n", num[0], num[1], num[2], state.cmds, fmtelapsed(cs.time - state.start, 1), fmtelapsed(state.real, 1), fmtelapsed(state.user, CO_QUANT), fmtelapsed(state.sys, CO_QUANT), num[3], fmtfloat(tot.stat.load), fmtfloat(tot.rating));
break;
case 'u':
{
if (!hdr)
{
hdr = 1;
}
sfprintf(state.string, "%3d%6d%5d%6d %-28s %s\n", n, con[n].info.user.pid, con[n].info.user.running, con[n].info.user.total, cspath(con[n].info.user.fds[2], 0), con[n].info.user.attr.label);
}
break;
case 'v':
break;
case 'Q':
default:
break;
}
}