diff --git a/elks/arch/i86/kernel/strace.h b/elks/arch/i86/kernel/strace.h index 81ffa91a1..4dca7fb1a 100644 --- a/elks/arch/i86/kernel/strace.h +++ b/elks/arch/i86/kernel/strace.h @@ -154,7 +154,7 @@ struct sc_info elks_table1[] = { ENTRY("sbrk", packinfo(1, P_SSHORT, P_NONE, P_NONE )), ENTRY("ustatfs", packinfo(3, P_USHORT, P_PDATA, P_SSHORT )), // 70 ENTRY("setitimer", packinfo(3, P_SSHORT, P_PDATA, P_PDATA )), - ENTRY(0, packinfo(0, P_NONE, P_NONE, P_NONE )), + ENTRY("sysctl", packinfo(3, P_SSHORT, P_STR, P_SSHORT )), ENTRY(0, packinfo(0, P_NONE, P_NONE, P_NONE )), ENTRY("uname", packinfo(1, P_PDATA, P_NONE, P_NONE )), // 74 }; diff --git a/elks/arch/i86/kernel/syscall.dat b/elks/arch/i86/kernel/syscall.dat index 015e4d271..fa0db4761 100644 --- a/elks/arch/i86/kernel/syscall.dat +++ b/elks/arch/i86/kernel/syscall.dat @@ -92,6 +92,7 @@ setsid +68 0 sbrk +69 2 * Legacy number from Linux ustatfs +70 3 setitimer +71 3 +sysctl +72 3 . ELKS uname +74 1 . was knlvsn # # From /usr/include/asm-generic/unistd.h diff --git a/elks/include/linuxmt/kernel.h b/elks/include/linuxmt/kernel.h index 4c40cc9e3..2cafe1e58 100644 --- a/elks/include/linuxmt/kernel.h +++ b/elks/include/linuxmt/kernel.h @@ -24,6 +24,7 @@ extern char running_qemu; extern dev_t dev_console; +extern int dprintk_on; extern void do_exit(int) noreturn; diff --git a/elks/include/linuxmt/sysctl.h b/elks/include/linuxmt/sysctl.h new file mode 100644 index 000000000..add019329 --- /dev/null +++ b/elks/include/linuxmt/sysctl.h @@ -0,0 +1,12 @@ +#ifndef __LINUXMT_SYSCTL_H +#define __LINUXMT_SYSCTL_H + +/* sysctl(2) parameters */ + +#define CTL_MAXNAMESZ 32 /* max size of option name */ + +#define CTL_LIST 0 /* get option list from index */ +#define CTL_GET (-1) /* get option value by name */ +#define CTL_SET (-2) /* set option value by name */ + +#endif diff --git a/elks/init/main.c b/elks/init/main.c index 4dfc2118c..3311a2387 100644 --- a/elks/init/main.c +++ b/elks/init/main.c @@ -73,7 +73,6 @@ static char *envp_init[MAX_INIT_ENVS+1]; static unsigned char options[OPTSEGSZ]; extern int boot_rootdev; -extern int dprintk_on; static char * INITPROC root_dev_name(int dev); static int INITPROC parse_options(void); static void INITPROC finalize_options(void); diff --git a/elks/kernel/Makefile b/elks/kernel/Makefile index 2a433950d..74a11fdfe 100644 --- a/elks/kernel/Makefile +++ b/elks/kernel/Makefile @@ -37,7 +37,7 @@ include $(BASEDIR)/Makefile-rules # unused: wait.o lock.o OBJS = sched.o printk.o sleepwake.o version.o sys.o sys2.o fork.o \ - exit.o time.o signal.o + exit.o time.o signal.o sysctl.o ######################################################################### # Commands: diff --git a/elks/kernel/sysctl.c b/elks/kernel/sysctl.c new file mode 100644 index 000000000..e4c1a26ff --- /dev/null +++ b/elks/kernel/sysctl.c @@ -0,0 +1,63 @@ +#include +#include +#include +#include + +#include +#include + +struct sysctl { + const char *name; + int *value; +}; + +static int malloc_debug; +static int net_debug; + +struct sysctl sysctl[] = { + { "kern.debug", &dprintk_on }, /* debug (^P) on/off */ + { "kern.strace", &tracing }, /* strace=1, kstack=2 */ + { "kern.console", (int *)&dev_console }, /* console */ + { "malloc.debug", &malloc_debug }, + { "net.debug", &net_debug }, +}; + +static char ctlname[CTL_MAXNAMESZ]; + +#define ARRAYLEN(a) (sizeof(a)/sizeof(a[0])) + +int sys_sysctl(int op, char *name, int *value) +{ + int error, n; + struct sysctl *sc; + + if (op >= CTL_LIST) { + if (!name) + return -EFAULT; + if (op >= ARRAYLEN(sysctl)) + return -ENOTDIR; + sc = &sysctl[op]; + return verified_memcpy_tofs(name, (void *)sc->name, strlen(sc->name)+1); + } + + n = strlen_fromfs(name, CTL_MAXNAMESZ) + 1; + if (n >= CTL_MAXNAMESZ) return -EFAULT; + error = verified_memcpy_fromfs(ctlname, name, n); + if (error) return error; + error = verfy_area(value, sizeof(int)); + if (error) return error; + + for (sc = sysctl;; sc++) { + if (sc >= &sysctl[ARRAYLEN(sysctl)]) return -ENOTDIR; + if (!strcmp(sc->name, ctlname)) + break; + } + + if (op == CTL_GET) + put_user(*sc->value, value); + else if (op == CTL_SET) + *sc->value = get_user(value); + else + return -EINVAL; + return 0; +} diff --git a/elkscmd/Applications b/elkscmd/Applications index a9f5af666..d67e85b84 100644 --- a/elkscmd/Applications +++ b/elkscmd/Applications @@ -100,6 +100,7 @@ sys_utils/console :sysutil :1200k sys_utils/unreal16 :sysutil :1440c sys_utils/beep :sysutil :1200k sys_utils/decomp :sysutil :360c :1440k +sys_utils/sysctl :sysutil :1200k screen/screen :screen :1200k cron/cron :cron :1200k cron/crontab :cron :1200k diff --git a/elkscmd/sys_utils/.gitignore b/elkscmd/sys_utils/.gitignore index 8c028e107..88ff861d9 100644 --- a/elkscmd/sys_utils/.gitignore +++ b/elkscmd/sys_utils/.gitignore @@ -22,6 +22,7 @@ ps reboot sercat shutdown +sysctl umount unreal16 who diff --git a/elkscmd/sys_utils/Makefile b/elkscmd/sys_utils/Makefile index d62fb17f8..6b09adb8b 100644 --- a/elkscmd/sys_utils/Makefile +++ b/elkscmd/sys_utils/Makefile @@ -40,6 +40,7 @@ PRGS = \ console \ makeboot \ decomp \ + sysctl \ # EOL HOSTPRGS = hostdecomp @@ -125,6 +126,9 @@ unreal.o: $(ELKS_LIB)/unreal.S beep: beep.o $(LD) $(LDFLAGS) -o beep beep.o $(LDLIBS) +sysctl: sysctl.o + $(LD) $(LDFLAGS) -o $@ $^ $(LDLIBS) + unreal16: unreal16.o unreal.o $(LD) -melks-libc -mcmodel=small -c unreal16.S -o unreal16.o $(LD) -melks-libc -mcmodel=small -nostdlib -o unreal16 unreal16.o unreal.o diff --git a/elkscmd/sys_utils/sysctl.c b/elkscmd/sys_utils/sysctl.c new file mode 100644 index 000000000..5bf03b333 --- /dev/null +++ b/elkscmd/sys_utils/sysctl.c @@ -0,0 +1,105 @@ +/* + * sysctl - system control utility for ELKS + * + * 8 May 2024 Greg Haerr + */ + +#include +#include +#include +#include +#include +#include + +#define errmsg(str) write(STDERR_FILENO, str, sizeof(str) - 1) + +static int digit(char c, int base) +{ + int d; + if (c <= '9') { + d = c - '0'; + } else if (c < 'A') { /* NEATLIBC bugfix */ + return -1; + } else if (c <= 'Z') { + d = 10 + c - 'A'; + } else { + d = 10 + c - 'a'; + } + return d < base ? d : -1; +} + +static int strtoi(const char *s) +{ + int num; + int dig; + int base; + int sgn = 1; + + if (*s == '-') + sgn = ',' - *s++; + if (*s == '0') { + if (s[1] == 'x' || s[1] == 'X') { + base = 16; + s += 2; + } else + base = 8; + } else { + base = 10; + } + for (num = 0; (dig = digit(*s, base)) >= 0; s++) + num = num*base + dig; + num *= sgn; + return num; +} + +static void msg(int fd, const char *s, ...) +{ + va_list va; + + va_start(va, s); + do { + write(fd, s, strlen(s)); + s = va_arg(va, const char *); + } while (s); + va_end(va); +} + +int main(int ac, char **av) +{ + int i, ret, val; + char name[CTL_MAXNAMESZ]; + + if (ac < 2) { + errmsg("usage: sysctl [-a] [name[=value]]\n"); + exit(-1); + } + + if (av[1][0] == '-' && av[1][1] == 'a') { + for (i = 0;; i++) { + ret = sysctl(CTL_LIST+i, name, 0); + if (ret) exit(0); + ret = sysctl(CTL_GET, name, &val); + msg(STDOUT_FILENO, name, "=", itoa(val), "\n", 0); + } + } + + for (i = 1; i < ac; i++) { + char *p = strchr(av[i], '='); + if (p) { + *p = '\0'; + val = strtoi(p+1); + ret = sysctl(CTL_SET, av[i], &val); + if (ret) { + msg(STDOUT_FILENO, "Unknown option: ", av[i], "\n", 0); + continue; + } + } + ret = sysctl(CTL_GET, av[i], &val); + if (ret) + msg(STDERR_FILENO, "Invalid option: ", av[i], "\n", 0); + else { + msg(STDOUT_FILENO, av[i], "=", itoa(val), "\n", 0); + } + } + return ret; +} diff --git a/libc/include/sys/sysctl.h b/libc/include/sys/sysctl.h new file mode 100644 index 000000000..377ef2415 --- /dev/null +++ b/libc/include/sys/sysctl.h @@ -0,0 +1,9 @@ +#ifndef __SYS_SYSCTL_H +#define __SYS_SYSCTL_H + +#include +#include __SYSINC__(sysctl.h) + +int sysctl(int op, char *name, int *value); + +#endif