Add a simple utility to send control messages

The svrctl utility allows you to send control messages to VFS or PM.
This way you can retrieve runtime information or alter behavior.
This commit is contained in:
Thomas Veerman 2012-04-13 12:58:41 +00:00
parent 0d63d9e125
commit 8dd0880985
5 changed files with 190 additions and 2 deletions

View file

@ -26,7 +26,7 @@ SUBDIR= add_route arp ash at awk \
reboot remsync rev rget rlogin \ reboot remsync rev rget rlogin \
rotate rsh rshd sed service setup shar acksize \ rotate rsh rshd sed service setup shar acksize \
sleep slip sort spell split srccrc \ sleep slip sort spell split srccrc \
stty sum svclog swifi sync synctree sysenv \ stty sum svclog svrctl swifi sync synctree sysenv \
syslogd tail tar tcpd tcpdp tcpstat tee telnet \ syslogd tail tar tcpd tcpdp tcpstat tee telnet \
telnetd term termcap tget time touch tr \ telnetd term termcap tget time touch tr \
truncate tsort tty udpstat umount uname unexpand \ truncate tsort tty udpstat umount uname unexpand \

5
commands/svrctl/Makefile Normal file
View file

@ -0,0 +1,5 @@
PROG= svrctl
BINDIR= /usr/bin
MAN=
.include <bsd.prog.mk>

118
commands/svrctl/svrctl.c Normal file
View file

@ -0,0 +1,118 @@
#include <sys/svrctl.h>
#include <sys/types.h>
#include <ctype.h>
#include <lib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
static void usage(void);
#define VFS "vfs"
#define PM "pm"
#define SET "set"
#define GET "get"
static char *bin_name;
int main (int argc, char *argv[])
{
int r, param;
endpoint_t proc_e = NONE;
struct sysgetenv sysgetenv;
message m;
char *to_whom, *operation, *what, *value;
unsigned i;
bin_name = argv[0];
if (argc < 4 || argc > 5) usage();
if (geteuid() != 0) {
fprintf(stderr, "You have to be root to run this utility\n");
exit(EXIT_FAILURE);
}
/* Make some parameters lower case to ease comparing */
to_whom = argv[1];
operation = argv[2];
what = argv[3];
for (i = 0; i < strlen(to_whom); ++i) to_whom[i] = tolower(to_whom[i]);
for (i = 0; i < strlen(operation); ++i) operation[i] = tolower(operation[i]);
for (i = 0; i < strlen(what); ++i) what[i] = tolower(what[i]);
if (!strncmp(to_whom, VFS, strlen(VFS)+1)) proc_e = VFS_PROC_NR;
else if (!strncmp(to_whom, PM, strlen(PM)+1)) proc_e = PM_PROC_NR;
else usage();
sysgetenv.key = what;
sysgetenv.keylen = strlen(what) + 1;
if (!strncmp(operation, SET, strlen(SET)+1)) {
if (argc != 5) usage();
value = argv[4];
sysgetenv.val = value;
sysgetenv.vallen = strlen(value) + 1;
if (proc_e == VFS_PROC_NR)
param = VFSSETPARAM;
else if (proc_e == PM_PROC_NR)
param = PMSETPARAM;
else
usage();
m.m2_i1 = param;
m.m2_p1 = (char *) &sysgetenv;
r = _syscall(proc_e, SVRCTL, &m);
if (r != 0) {
if (errno == ESRCH)
fprintf(stderr, "invalid parameter: %s\n", what);
else if (errno == EINVAL)
fprintf(stderr, "invalid value: %s\n", value);
else
perror("");
exit(EXIT_FAILURE);
}
return(EXIT_SUCCESS);
} else if (!strncmp(operation, GET, strlen(GET)+1)) {
char get_param_buffer[4096];
memset(get_param_buffer, '\0', sizeof(get_param_buffer));
sysgetenv.val = get_param_buffer;
sysgetenv.vallen = sizeof(get_param_buffer) - 1;
if (proc_e == VFS_PROC_NR)
param = VFSGETPARAM;
else if (proc_e == PM_PROC_NR)
param = PMGETPARAM;
else
usage();
m.m2_i1 = param;
m.m2_p1 = (char *) &sysgetenv;
r = _syscall(proc_e, SVRCTL, &m);
if (r != 0) {
if (errno == ESRCH)
fprintf(stderr, "invalid parameter: %s\n", what);
else
perror("");
return(EXIT_FAILURE);
} else {
if (sysgetenv.vallen > 0) {
get_param_buffer[sysgetenv.vallen] = '\0';
printf("%s\n", get_param_buffer);
}
}
return(EXIT_SUCCESS);
} else
usage();
return(EXIT_FAILURE);
}
static void usage()
{
fprintf(stderr, "Usage:\n");
fprintf(stderr, " %s <vfs|pm> set <request> <value>\n", bin_name);
fprintf(stderr, " %s <vfs|pm> get <request>\n", bin_name);
exit(EXIT_FAILURE);
}

View file

@ -16,7 +16,7 @@ MAN= ash.1 at.1 banner.1 basename.1 \
profile.1 ps.1 pwd.1 rcp.1 readall.1 recwave.1 \ profile.1 ps.1 pwd.1 rcp.1 readall.1 recwave.1 \
ref.1 remsync.1 rget.1 rlogin.1 rsh.1 rz.1 \ ref.1 remsync.1 rget.1 rlogin.1 rsh.1 rz.1 \
shar.1 acksize.1 sleep.1 sort.1 spell.1 \ shar.1 acksize.1 sleep.1 sort.1 spell.1 \
split.1 stty.1 sum.1 svc.1 \ split.1 stty.1 sum.1 svc.1 svrctl.1 \
synctree.1 sysenv.1 sz.1 tail.1 tee.1 telnet.1 template.1 \ synctree.1 sysenv.1 sz.1 tail.1 tee.1 telnet.1 template.1 \
term.1 termcap.1 tget.1 time.1 tr.1 true.1 \ term.1 termcap.1 tget.1 time.1 tr.1 true.1 \
truncate.1 tsort.1 tty.1 umount.1 uname.1 unexpand.1 \ truncate.1 tsort.1 tty.1 umount.1 uname.1 unexpand.1 \

65
man/man1/svrctl.1 Normal file
View file

@ -0,0 +1,65 @@
.Dd $April 5, 2012$
.Dt SVRCTL 1
.Os
.Sh NAME
.Nm svrctl
.Nd send servers control messages
.Sh SYNOPSIS
.Nm
.Ar <vfs|pm> Ar get Ar <request>
.Nm
.Ar <vfs|pm> Ar set Ar <request> Ar <value>
.Sh DESCRIPTION
The
.Nm
utility allows to override the values of variables inside VFS or PM or to
retrieve the values of variables. The variables that are allowed to be
overridden are hard coded in the servers.
.Sh EXAMPLES
To retrieve how many threads are currently actively carrying out work in VFS:
.Bd -literal -offset indent
svrctl vfs get active_threads
.Ed
.Pp
To generate a stack trace of all threads in VFS:
.Bd -literal -offset indent
svrctl vfs get print_traces
.Ed
.Pp
To set verbosity level of VFS (allowed values range from 0 to 4)
.Bd -literal -offset indent
svrctl vfs set verbose 1
.Ed
.Pp
To retrieve boot monitor parameters (note that these are also available through
.Xr sysenv 1
) such as
.Va rootdevname
,
.Va memory
,
.Va hz
, and if set,
.Va bootopts
,
.Va cttyline
,
.Va cttybaud
:
.Bd -literal -offset indent
svrctl pm get rootdevname
svrctl pm get memory
svrctl pm get hz
svrctl pm get bootopts
svrctl pm get cttyline
svrctl pm get cttybaud
.Ed
.Sh EXIT STATUS
In case
.Nm
is not properly invoked or the provided
.Va request
is not valid 1 is returned, otherwise 0.
.Sh AUTHORS
.An Thomas Veerman
.Aq thomas@minix3.org