From nobody Sun Dec 25 06:59:21 2022 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4NfsGd3x5Tz20b7b; Sun, 25 Dec 2022 06:59:21 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4NfsGd3TNtz4MtV; Sun, 25 Dec 2022 06:59:21 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1671951561; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=NlT0kOGN/JA8T3uvWqLyt/GQY1ZwH9IKfix013RY9JI=; b=wb8Y7cdCCXx3nax+kPE9g1otxt6l+vLfh0x4bBZPd4Z64PJJhPas9r+6Mqxxhc6uEwOd5S 6dAuxxjOqyWQT7MTfLGUlpnueFQl9BmyJYCYRYTXRq3xdxWnmcPI/s4yIPmIzy6daxCFmP JMTgUm34BR+NfGP+jwZcpQR9OOldl/5DrOgKKD2+Orcz+vqX3k67g30rJz2pPzcGp9bbXe GLmYIj8Do0pe6mUee2pZAh22nuD3N2iBXXQma1YARY5b3vRK8mZ2UIaCFz9/i3lxC7aJb6 sshkY5/Ts+8MV0+OmuhCLKd2xZDqsfRj3VfS3XNpxctYesC9Hll2XlLTj0AzlA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1671951561; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=NlT0kOGN/JA8T3uvWqLyt/GQY1ZwH9IKfix013RY9JI=; b=Rn7S29FokE0KXl+fakFdMu6AtliOQ5rUQnDrpbNlq6YpgSZXxK5ZbERu6eU7Sj46iXNAks 7cGctoo+hYqYl+IjjWKfXL3wtOhCElhTwfg1XC4fJCefdyg0swsHTSwsfvi+GANLIIygTp DTnzLKlsZm3BBJi1Bw5KjAQ6L6/kiC9yeAI55ml8jI1wmpndMhMebIx/w7W1tQWfCDRZ6x mBxgSMvDQ/3eoJz2R2Cr5EOxZbK0gJt6hJW+t7iUq8VaBZODLiPoChOBpmHyk/U4ZBPU4T ssRNd1KC6p3aECKbyjiY+s8I81y1JQLhPV2CLKAgd9AVdDUM88ok/VTwdNT6SA== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1671951561; a=rsa-sha256; cv=none; b=Kn8i89xl30RRm4q9dmsvmWumfwHoHSQwNBq5vXYAETRd06XlTGrv3x9MU2R/Q76LPvO5IA /by4BIroEgBDo4ApW0IqdiyS9AmHynNCdspFg2g0DpMycrhNTpNsGXfrCZZ8y3n+WpMFs1 p2PR8Cn3NMOCJcjvEQn2/CPA9HOxe+dY3NIygv9kqtXeHmmSlTDkApAvHznwc3xAkmMtPB Halw3lduEJ5qDv4cG8t3a4eF3JbgQyY9YtRMVe1ie4EXbT3wPUI0/0V5CqPR/6/s43vIRz UAQ4eeI80QCUYyPuMMxPmvnRA+BwWJDB/J5laSRR9zUAv//PQNL64/bhciBGcw== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4NfsGd2J4Dzjkm; Sun, 25 Dec 2022 06:59:21 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 2BP6xLBe000651; Sun, 25 Dec 2022 06:59:21 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 2BP6xLmd000650; Sun, 25 Dec 2022 06:59:21 GMT (envelope-from git) Date: Sun, 25 Dec 2022 06:59:21 GMT Message-Id: <202212250659.2BP6xLmd000650@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Kirk McKusick Subject: git: f126d349810f - main - Add -F option to sysctl(8) to display sysctl format. List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-main@freebsd.org X-BeenThere: dev-commits-src-main@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: mckusick X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: f126d349810fdb512c0b01e101342d430b947488 Auto-Submitted: auto-generated X-ThisMailContainsUnwantedMimeParts: N The branch main has been updated by mckusick: URL: https://cgit.FreeBSD.org/src/commit/?id=f126d349810fdb512c0b01e101342d430b947488 commit f126d349810fdb512c0b01e101342d430b947488 Author: Kirk McKusick AuthorDate: 2022-12-25 06:57:13 +0000 Commit: Kirk McKusick CommitDate: 2022-12-25 06:59:00 +0000 Add -F option to sysctl(8) to display sysctl format. Also add a test to ensure that it is working correctly. Submitted by: ota_j.email.ne.jp Reviewed by: mckusick Differential Revision: https://reviews.freebsd.org/D34012 --- sbin/sysctl/sysctl.8 | 15 ++++- sbin/sysctl/sysctl.c | 101 ++++++++++++++++++++++++--------- sbin/sysctl/tests/Makefile | 5 ++ sbin/sysctl/tests/Makefile.depend | 11 ++++ sbin/sysctl/tests/sysctl_test.sh | 116 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 218 insertions(+), 30 deletions(-) diff --git a/sbin/sysctl/sysctl.8 b/sbin/sysctl/sysctl.8 index 17c9b8c28346..c4c2e68edfca 100644 --- a/sbin/sysctl/sysctl.8 +++ b/sbin/sysctl/sysctl.8 @@ -28,7 +28,7 @@ .\" From: @(#)sysctl.8 8.1 (Berkeley) 6/6/93 .\" $FreeBSD$ .\" -.Dd June 30, 2022 +.Dd December 24, 2022 .Dt SYSCTL 8 .Os .Sh NAME @@ -36,13 +36,13 @@ .Nd get or set kernel state .Sh SYNOPSIS .Nm -.Op Fl bdehiNnoTtqWx +.Op Fl bdeFhilNnoTtqWx .Op Fl B Ar bufsize .Op Fl f Ar filename .Ar name Ns Op = Ns Ar value Ns Op , Ns Ar value .Ar ... .Nm -.Op Fl bdehNnoTtqWx +.Op Fl bdeFhlNnoTtqWx .Op Fl B Ar bufsize .Fl a .Sh DESCRIPTION @@ -100,6 +100,10 @@ Specify a file which contains a pair of name and value in each line. .Nm reads and processes the specified file first and then processes the name and value pairs in the command line argument. +.It Fl F +Print the format of the variable. +This is additional information to describe the type of the variable and +most useful with struct types such as clockinfo, timeval, and loadavg. .It Fl h Format output for human, rather than machine, readability. .It Fl i @@ -108,6 +112,11 @@ The purpose is to make use of .Nm for collecting data from a variety of machines (not all of which are necessarily running exactly the same software) easier. +.It Fl l +Show the length of variables along with their values. +This option cannot be combined with the +.Fl N +option. .It Fl N Show only variable names, not their values. This is particularly useful with shells that offer programmable diff --git a/sbin/sysctl/sysctl.c b/sbin/sysctl/sysctl.c index 5a090ca20fc4..9a1f8c5431a9 100644 --- a/sbin/sysctl/sysctl.c +++ b/sbin/sysctl/sysctl.c @@ -66,6 +66,7 @@ static const char *conffile; static int aflag, bflag, Bflag, dflag, eflag, hflag, iflag; static int Nflag, nflag, oflag, qflag, tflag, Tflag, Wflag, xflag; +static bool Fflag, lflag; static int oidfmt(int *, int, char *, u_int *); static int parsefile(const char *); @@ -123,8 +124,8 @@ usage(void) { (void)fprintf(stderr, "%s\n%s\n", - "usage: sysctl [-bdehiNnoqTtWx] [ -B ] [-f filename] name[=value] ...", - " sysctl [-bdehNnoqTtWx] [ -B ] -a"); + "usage: sysctl [-bdeFhilNnoqTtWx] [ -B ] [-f filename] name[=value] ...", + " sysctl [-bdeFhlNnoqTtWx] [ -B ] -a"); exit(1); } @@ -138,7 +139,7 @@ main(int argc, char **argv) setbuf(stdout,0); setbuf(stderr,0); - while ((ch = getopt(argc, argv, "AabB:def:hiNnoqtTwWxX")) != -1) { + while ((ch = getopt(argc, argv, "AabB:def:FhilNnoqtTwWxX")) != -1) { switch (ch) { case 'A': /* compatibility */ @@ -162,12 +163,18 @@ main(int argc, char **argv) case 'f': conffile = optarg; break; + case 'F': + Fflag = true; + break; case 'h': hflag = 1; break; case 'i': iflag = 1; break; + case 'l': + lflag = true; + break; case 'N': Nflag = 1; break; @@ -207,14 +214,15 @@ main(int argc, char **argv) argc -= optind; argv += optind; - if (Nflag && nflag) + /* Nflag is name only and doesn't make sense to combind with these */ + /* TODO: few other combinations do not make sense but come back later */ + if (Nflag && (lflag || nflag)) usage(); if (aflag && argc == 0) exit(sysctl_all(NULL, 0)); if (argc == 0 && conffile == NULL) usage(); - warncount = 0; if (conffile != NULL) warncount += parsefile(conffile); @@ -949,6 +957,55 @@ oidfmt(int *oid, int len, char *fmt, u_int *kind) return (0); } +/* + * This displays a combination of name, type, format, and/or description. + * + * Returns zero if anything was actually output. + * Returns one if there is an error. + */ +static int +show_info(char *name, const char *sep, int ctltype, char *fmt, int *qoid, int nlen) +{ + u_char buf[BUFSIZ]; + const char *prntype; + int error = 0, i; + size_t j; + + if (!nflag) + printf("%s%s", name, sep); + if (tflag) { + if (ctl_typename[ctltype] != NULL) + prntype = ctl_typename[ctltype]; + else { + prntype = "unknown"; + error++; + } + if (Fflag || dflag) + printf("%s%s", prntype, sep); + else + fputs(prntype, stdout); + } + if (Fflag) { + if (!isprint(fmt[0])) /* Few codes doesn't have formats */ + fmt = ""; + if (dflag) + printf("%s%s", fmt, sep); + else + fputs(fmt, stdout); + } + if (!dflag) + return (error); + + qoid[1] = CTL_SYSCTL_OIDDESCR; + bzero(buf, BUFSIZ); + j = sizeof(buf); + i = sysctl(qoid, nlen + 2, buf, &j, 0, 0); + if (i < 0) + return (1); + fputs(buf, stdout); + return (error); +} + /* * This formats and outputs the value of one variable * @@ -960,9 +1017,9 @@ static int show_var(int *oid, int nlen, bool honor_skip) { static int skip_len = 0, skip_oid[CTL_MAXNAME]; - u_char buf[BUFSIZ], *val, *oval, *p; + u_char *val, *oval, *p; char name[BUFSIZ], fmt[BUFSIZ]; - const char *sep, *sep1, *prntype; + const char *sep, *sep1; int qoid[CTL_MAXNAME+2]; uintmax_t umv; intmax_t mv; @@ -977,7 +1034,6 @@ show_var(int *oid, int nlen, bool honor_skip) /* Silence GCC. */ umv = mv = intlen = 0; - bzero(buf, BUFSIZ); bzero(fmt, BUFSIZ); bzero(name, BUFSIZ); qoid[0] = CTL_SYSCTL; @@ -1008,25 +1064,8 @@ show_var(int *oid, int nlen, bool honor_skip) sep = ": "; ctltype = (kind & CTLTYPE); - if (tflag || dflag) { - if (!nflag) - printf("%s%s", name, sep); - if (ctl_typename[ctltype] != NULL) - prntype = ctl_typename[ctltype]; - else - prntype = "unknown"; - if (tflag && dflag) - printf("%s%s", prntype, sep); - else if (tflag) { - printf("%s", prntype); - return (0); - } - qoid[1] = CTL_SYSCTL_OIDDESCR; - j = sizeof(buf); - i = sysctl(qoid, nlen + 2, buf, &j, 0, 0); - printf("%s", buf); - return (0); - } + if (tflag || Fflag || dflag) + return show_info(name, sep, ctltype, fmt, qoid, nlen); /* keep track of encountered skip nodes, ignoring descendants */ if ((skip_len == 0 || skip_len >= nlen * (int)sizeof(int)) && @@ -1109,6 +1148,8 @@ show_var(int *oid, int nlen, bool honor_skip) case CTLTYPE_STRING: if (!nflag) printf("%s%s", name, sep); + if (lflag) + printf("%zd%s", len, sep); printf("%.*s", (int)len, p); free(oval); return (0); @@ -1127,6 +1168,8 @@ show_var(int *oid, int nlen, bool honor_skip) case CTLTYPE_U64: if (!nflag) printf("%s%s", name, sep); + if (lflag) + printf("%zd%s", len, sep); hexlen = 2 + (intlen * CHAR_BIT + 3) / 4; sep1 = ""; while (len >= intlen) { @@ -1197,6 +1240,8 @@ show_var(int *oid, int nlen, bool honor_skip) if (func) { if (!nflag) printf("%s%s", name, sep); + if (lflag) + printf("%zd%s", len, sep); i = (*func)(len, p); free(oval); return (i); @@ -1209,6 +1254,8 @@ show_var(int *oid, int nlen, bool honor_skip) } if (!nflag) printf("%s%s", name, sep); + if (lflag) + printf("%zd%s", len, sep); printf("Format:%s Length:%zu Dump:0x", fmt, len); while (len-- && (xflag || p < val + 16)) printf("%02x", *p++); diff --git a/sbin/sysctl/tests/Makefile b/sbin/sysctl/tests/Makefile new file mode 100644 index 000000000000..4a8dd4af6d72 --- /dev/null +++ b/sbin/sysctl/tests/Makefile @@ -0,0 +1,5 @@ +# $FreeBSD$ + +ATF_TESTS_SH= sysctl_test + +.include diff --git a/sbin/sysctl/tests/Makefile.depend b/sbin/sysctl/tests/Makefile.depend new file mode 100644 index 000000000000..f80275d86ab1 --- /dev/null +++ b/sbin/sysctl/tests/Makefile.depend @@ -0,0 +1,11 @@ +# $FreeBSD$ +# Autogenerated - do NOT edit! + +DIRDEPS = \ + + +.include + +.if ${DEP_RELDIR} == ${_DEP_RELDIR} +# local dependencies - needed for -jN in clean tree +.endif diff --git a/sbin/sysctl/tests/sysctl_test.sh b/sbin/sysctl/tests/sysctl_test.sh new file mode 100644 index 000000000000..a26c2c77b998 --- /dev/null +++ b/sbin/sysctl/tests/sysctl_test.sh @@ -0,0 +1,116 @@ +# Copyright (c) 2022 Yoshihiro Ota +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. + +sysctl_name="kern.ostype" +sysctl_value="FreeBSD" +sysctl_type="string" +sysctl_description="Operating system type" + +atf_test_case sysctl_by_name +sysctl_by_name_head() +{ + atf_set "descr" "Verify name without any arguments" +} +sysctl_by_name_body() +{ + atf_check -o "inline:${sysctl_name}: ${sysctl_value}\n" sysctl ${sysctl_name} +} + + +atf_test_case sysctl_nflag +sysctl_nflag() +{ + atf_set "descr" "Verify -n argument" +} +sysctl_nflag_body() +{ + atf_check -o "inline:${sysctl_value}\n" sysctl -n ${sysctl_name} +} + + +atf_test_case sysctl_eflag +sysctl_eflag() +{ + atf_set "descr" "Verify -e argument" +} +sysctl_eflag_body() +{ + atf_check -o "inline:${sysctl_name}=${sysctl_value}\n" sysctl -e ${sysctl_name} +} + + +atf_test_case sysctl_tflag +sysctl_tflag() +{ + atf_set "descr" "Verify -t argument" +} +sysctl_tflag_body() +{ + atf_check -o "inline:${sysctl_name}: ${sysctl_type}\n" sysctl -t ${sysctl_name} +} + + +atf_test_case sysctl_dflag +sysctl_dflag() +{ + atf_set "descr" "Verify -d argument" +} +sysctl_dflag_body() +{ + atf_check -o "inline:${sysctl_name}: ${sysctl_description}\n" sysctl -d ${sysctl_name} +} + + +atf_test_case sysctl_tflag_dflag +sysctl_tflag_dflag() +{ + atf_set "descr" "Verify -t -d arguments" +} +sysctl_tflag_dflag_body() +{ + atf_check -o "inline:${sysctl_name}: ${sysctl_type}: ${sysctl_description}\n" sysctl -t -d ${sysctl_name} + atf_check -o "inline:${sysctl_name}: ${sysctl_type}: ${sysctl_description}\n" sysctl -d -t ${sysctl_name} +} + + +atf_test_case sysctl_nflag_tflag_dflag +sysctl_nflag_tflag_dflag() +{ + atf_set "descr" "Verify -n -t -d arguments" +} +sysctl_nflag_tflag_dflag_body() +{ + atf_check -o "inline:${sysctl_type}: ${sysctl_description}\n" sysctl -n -t -d ${sysctl_name} +} + + +atf_init_test_cases() +{ + atf_add_test_case sysctl_by_name + atf_add_test_case sysctl_nflag + atf_add_test_case sysctl_eflag + atf_add_test_case sysctl_tflag + atf_add_test_case sysctl_dflag + atf_add_test_case sysctl_tflag_dflag + atf_add_test_case sysctl_nflag_tflag_dflag +}