On Sat, Jul 29, 2017 at 02:19:50PM +0200, Martin Natano wrote:
> On Sat, Jul 29, 2017 at 02:03:22PM +0200, Mark Kettenis wrote:
> >
> > I don't think we want to add string parsing like this in the kernel.
> > Maybe the sysctl(8) frontend should do the mapping from strings to
> > numbers?
>
> Ok, I'll try to come up with an alternative diff that does the parsing
> in sysctl(8). Let me fetch my rubber gloves...
Here's the alternative diff. Ok?
Index: etc/etc.amd64/sysctl.conf
===================================================================
RCS file: /cvs/src/etc/etc.amd64/sysctl.conf,v
retrieving revision 1.7
diff -u -p -r1.7 sysctl.conf
--- etc/etc.amd64/sysctl.conf 2 Mar 2017 10:38:09 -0000 1.7
+++ etc/etc.amd64/sysctl.conf 25 Jul 2017 18:40:31 -0000
@@ -1,3 +1,3 @@
#machdep.allowaperture=2 # See xf86(4)
#machdep.kbdreset=1 # permit console CTRL-ALT-DEL to do a nice halt
-#machdep.lidaction=0 # 1=suspend, 2=hibernate laptop upon lid closing
+#machdep.lidaction=none # action upon lid closing: none,
suspend or hibernate
Index: etc/etc.i386/sysctl.conf
===================================================================
RCS file: /cvs/src/etc/etc.i386/sysctl.conf,v
retrieving revision 1.21
diff -u -p -r1.21 sysctl.conf
--- etc/etc.i386/sysctl.conf 2 Mar 2017 10:38:09 -0000 1.21
+++ etc/etc.i386/sysctl.conf 25 Jul 2017 18:40:35 -0000
@@ -1,4 +1,4 @@
#machdep.allowaperture=2 # See xf86(4)
#machdep.apmhalt=1 # 1=powerdown hack, try if halt -p doesn't work
#machdep.kbdreset=1 # permit console CTRL-ALT-DEL to do a nice halt
-#machdep.lidaction=0 # 1=suspend, 2=hibernate laptop upon lid closing
+#machdep.lidaction=none # action upon lid closing: none,
suspend or hibernate
Index: etc/etc.loongson/sysctl.conf
===================================================================
RCS file: /cvs/src/etc/etc.loongson/sysctl.conf,v
retrieving revision 1.4
diff -u -p -r1.4 sysctl.conf
--- etc/etc.loongson/sysctl.conf 2 Mar 2017 10:38:09 -0000 1.4
+++ etc/etc.loongson/sysctl.conf 25 Jul 2017 18:40:40 -0000
@@ -1 +1 @@
-#machdep.lidaction=0 # 1=suspend, 2=hibernate laptop upon lid closing
+#machdep.lidaction=none # action upon lid closing: none,
suspend or hibernate
Index: sbin/sysctl/sysctl.c
===================================================================
RCS file: /cvs/src/sbin/sysctl/sysctl.c,v
retrieving revision 1.228
diff -u -p -r1.228 sysctl.c
--- sbin/sysctl/sysctl.c 19 Jul 2017 06:30:54 -0000 1.228
+++ sbin/sysctl/sysctl.c 29 Jul 2017 16:57:13 -0000
@@ -158,6 +158,15 @@ struct list secondlevel[] = {
{ 0, 0 }, /* CTL_VFS */
};
+struct enum_vals {
+ int size;
+ const char **names;
+};
+#ifdef CPU_LIDACTION
+const char *cpu_lidaction_names[] = { "none", "suspend", "hibernate" };
+struct enum_vals cpu_lidaction_enum = { 3, cpu_lidaction_names };
+#endif
+
int Aflag, aflag, nflag, qflag;
/*
@@ -167,10 +176,10 @@ int Aflag, aflag, nflag, qflag;
#define BOOTTIME 0x00000002
#define CHRDEV 0x00000004
#define BLKDEV 0x00000008
+#define ENUM 0x00000010
#define BADDYNAMIC 0x00000020
#define BIOSGEO 0x00000040
#define BIOSDEV 0x00000080
-#define MAJ2DEV 0x00000100
#define UNSIGNED 0x00000200
#define KMEMBUCKETS 0x00000400
#define LONGARRAY 0x00000800
@@ -211,6 +220,8 @@ void print_sensor(struct sensor *);
int sysctl_chipset(char *, char **, int *, int, int *);
#endif
void vfsinit(void);
+int strtoenum(const char *, struct enum_vals *, const char **);
+const char *enumtostr(int, struct enum_vals *);
char *equ = "=";
@@ -297,6 +308,7 @@ parse(char *string, int flags)
int indx, type, state, intval, len;
size_t size, newsize = 0;
int lal = 0, special = 0;
+ struct enum_vals *enump;
void *newval = NULL;
int64_t quadval;
struct list *lp;
@@ -615,6 +627,12 @@ parse(char *string, int flags)
if (mib[1] == CPU_CPUFEATURE)
special |= HEX;
#endif
+#ifdef CPU_LIDACTION
+ if (mib[1] == CPU_LIDACTION) {
+ special |= ENUM;
+ enump = &cpu_lidaction_enum;
+ }
+#endif
#ifdef CPU_BLK2CHR
if (mib[1] == CPU_BLK2CHR) {
if (bufp == NULL)
@@ -700,6 +718,8 @@ parse(char *string, int flags)
case CTLTYPE_INT:
if (special & UNSIGNED)
intval = strtonum(newval, 0, UINT_MAX, &errstr);
+ else if (special & ENUM)
+ intval = strtoenum(newval, enump, &errstr);
else
intval = strtonum(newval, INT_MIN, INT_MAX,
&errstr);
@@ -917,17 +937,31 @@ parse(char *string, int flags)
(void)printf("%s%s", string, equ);
if (special & HEX)
(void)printf("0x%x\n", *(int *)buf);
+ else if (special & ENUM)
+ (void)printf("%s\n",
+ enumtostr(*(int *)buf, enump));
else
(void)printf("%d\n", *(int *)buf);
} else {
if (!qflag) {
- if (!nflag)
- (void)printf("%s: %d -> ", string,
- *(int *)buf);
- if (special & HEX)
+ if (special & HEX) {
+ if (!nflag)
+ (void)printf("%s: 0x%x -> ",
+ string, *(int *)buf);
(void)printf("0x%x\n", *(int *)newval);
- else
+ } else if (special & ENUM) {
+ if (!nflag)
+ (void)printf("%s: %s -> ",
+ string,
+ enumtostr(*(int *)buf,
enump));
+ (void)printf("%s\n",
+ enumtostr(*(int *)newval, enump));
+ } else {
+ if (!nflag)
+ (void)printf("%s: %d -> ",
+ string, *(int *)buf);
(void)printf("%d\n", *(int *)newval);
+ }
}
}
return;
@@ -2635,4 +2669,28 @@ usage(void)
" sysctl [-n] name ...\n"
" sysctl [-nq] name=value ...\n");
exit(1);
+}
+
+int
+strtoenum(const char *str, struct enum_vals *enump, const char **errstr)
+{
+ int i;
+
+ for (i = 0; i < enump->size; i++) {
+ if (strcmp(enump->names[i], str) == 0) {
+ *errstr = NULL;
+ return i;
+ }
+ }
+
+ *errstr = "invalid";
+ return -1;
+}
+
+const char *
+enumtostr(int val, struct enum_vals *enump)
+{
+ if (val < 0 || val >= enump->size)
+ return "unknown";
+ return enump->names[val];
}