From nobody Tue May 6 20:38:46 2025 X-Original-To: dev-commits-src-all@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 4ZsVbp5ZrTz5vQ3x; Tue, 06 May 2025 20:38:46 +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 "R11" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4ZsVbp4PNKz3T1M; Tue, 06 May 2025 20:38:46 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1746563926; 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=EFc9+ABgSBED42DNBhBFgFAKXZCmoNgARxOW9LrDZ7A=; b=Ngwgw+/6xPTz94o4g0162bkOv+uMfEwm35oc/XkRaH+6QYHFOD1XagdgQJ72wVtoeGcKOu 0DIwrhCNIkLv+XxLtEqpN2p/M67n7R1+bUFlvy5EabK8z1Ra7aTLKpro81GzQNkUnFyFMy iMRQFOf0eXYfunPC5Dwk4BkuRK5rsc+F/84WBZ4gjSxCmEMhcPsLTd7bLB9J+Orz2W+TtN DcMuRuJ2Pijyj65bjZPqSqRrFO2W6E4CVe8xSBWB1QUW8etclHXJvHwmb+/RAl9+Q5rMqj JbL3b3bj/wK7HMR/LSF+4kTZhQltbs8UxLc9j7TbbDdA1MaEFp1ipCn55WgavA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1746563926; 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=EFc9+ABgSBED42DNBhBFgFAKXZCmoNgARxOW9LrDZ7A=; b=NlQqfstIw3wr07ZT5vfOUihrXAIOo0JsGl0ha6O1l96itdTznaEQpl4u6L40VPQ+JPZAVT +B8s4oMmBAdKeNg/3epJGzGC+CkWiY5pJwJ/1jyRbkYzsOG5EA/WgU9XszkpUuerxFNdiJ /ua2eqQe6E7IlIqIUlWh70UaeTSvuOtfITFx3j+dqfcjP88cSRDEi38fNFkL7/A4kWpvFb LDU4CPbC0yhOK/+MA957Qn68ov64kIkPSq1hnzj0f+McUKmpqn8TOigp5Biyho8A4P3cnT 0kAcGhwVNKr9KSe/qloz8OHMWogUAejfR/MxL7DdklEWx+wOIbE/SsMo+JBRMg== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1746563926; a=rsa-sha256; cv=none; b=VhEtosIkp9ROqfB0Xr1ZpauyKY/+cdbhAkclSzIC6tZnL+rYFmnybpsrxhJOpA91mfYZQM 0GmCYARbQZS38YepahY6N5xs0n3PiT4JyDCD+7pr5G4v8bVhKxsA3l803+9pXJuYlXnpTJ +IDuSpcEuglETFXPJu+G/QpHM9kpoItDk+vm0TsD3WqlUGv9JCIrHJcuvWD3Vm9Ohbjj1Z SSiEMvmgVSxXwkdOlz+aIaHO/BB13NZNNwCCMV0QPnZgvEdUVU8G4f4iy0/K5jCIXz+c4c SxYLhUU28P/eWZTmXTKvSSM7w1TqiICv34vVSg0GYGrq5+LMqHuWXW70loaCfA== ARC-Authentication-Results: i=1; mx1.freebsd.org; none 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 4ZsVbp3mFVz1DbB; Tue, 06 May 2025 20:38:46 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.18.1/8.18.1) with ESMTP id 546KckNO072762; Tue, 6 May 2025 20:38:46 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 546KckHj072759; Tue, 6 May 2025 20:38:46 GMT (envelope-from git) Date: Tue, 6 May 2025 20:38:46 GMT Message-Id: <202505062038.546KckHj072759@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Rick Macklem Subject: git: 0660de8172cd - main - runat: Add a runat(1) utility similar to the Solaris one List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: rmacklem X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 0660de8172cd5a03affb9e87a1007cac5ba30425 Auto-Submitted: auto-generated The branch main has been updated by rmacklem: URL: https://cgit.FreeBSD.org/src/commit/?id=0660de8172cd5a03affb9e87a1007cac5ba30425 commit 0660de8172cd5a03affb9e87a1007cac5ba30425 Author: Rick Macklem AuthorDate: 2025-05-06 20:36:06 +0000 Commit: Rick Macklem CommitDate: 2025-05-06 20:36:06 +0000 runat: Add a runat(1) utility similar to the Solaris one Solaris has a utility called runat(1) that runs a shell command on a named attribute directory. This utility is modelled after that one. Reviewed by: kib (earlier version) Differential Revision: https://reviews.freebsd.org/D49850 --- usr.bin/Makefile | 1 + usr.bin/runat/Makefile | 3 ++ usr.bin/runat/runat.1 | 63 +++++++++++++++++++++++++++++++++++++++++ usr.bin/runat/runat.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 143 insertions(+) diff --git a/usr.bin/Makefile b/usr.bin/Makefile index 7f35a87b0d93..e99670ec2d3e 100644 --- a/usr.bin/Makefile +++ b/usr.bin/Makefile @@ -123,6 +123,7 @@ SUBDIR= alias \ revoke \ rpcinfo \ rs \ + runat \ rup \ ruptime \ rusers \ diff --git a/usr.bin/runat/Makefile b/usr.bin/runat/Makefile new file mode 100644 index 000000000000..6be86ce4a60b --- /dev/null +++ b/usr.bin/runat/Makefile @@ -0,0 +1,3 @@ +PROG= runat + +.include diff --git a/usr.bin/runat/runat.1 b/usr.bin/runat/runat.1 new file mode 100644 index 000000000000..ceaf70ed1dba --- /dev/null +++ b/usr.bin/runat/runat.1 @@ -0,0 +1,63 @@ +.\" +.\" Copyright (c) 2025 Rick Macklem +.\" +.\" SPDX-License-Identifier: BSD-2-Clause +.\" +.Dd April 15, 2025 +.Dt RUNAT 1 +.Os +.Sh NAME +.Nm runat +.Nd run a shell command on a named attribute directory +.Sh SYNOPSIS +.Nm +.Op Ar file +.Op Ar shell command +.Sh DESCRIPTION +The +.Nm +utility runs the shell command on the named attribute directory for the +.Ar file +argument. +It does a +.Xr fchdir 2 +system call to change the current working directory into the +named attribute directory for the +.Ar file +argument and then performs the shell command via +.Xr sh 1 . +.Pp +If a named attribute directory does not exist for +.Ar file , +an empty one will be created. +If an application needs to determine if a named attribute +exists for the +.Ar file , +.Xr pathconf 2 +with the name +.Fa _PC_HAS_NAMEDATTR +may be used. +This will not create an empty named attribute directory +if one does not exist for +.Ar file . +.Sh EXAMPLES +For a +.Ar file +called +.Dq myfile : +.Bd -literal +$ runat myfile ls -l # lists the attributes for myfile +$ runat myfile cp /etc/hosts attrhosts # creates attrhosts +$ runat myfile cat attrhosts # displays contents of attrhosts +.Ed +.Sh SEE ALSO +.Xr sh 1 , +.Xr fchdir 2 , +.Xr pathconf 2 , +.Xr open 2 , +.Xr named_attribute 7 +.Sh HISTORY +The +.Nm +utility first appeared in +.Fx 15.0 . diff --git a/usr.bin/runat/runat.c b/usr.bin/runat/runat.c new file mode 100644 index 000000000000..66f4ebadd180 --- /dev/null +++ b/usr.bin/runat/runat.c @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2025 Rick Macklem + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void +usage(void) +{ + (void)fprintf(stderr, "usage: runat " + "\n"); + exit(1); +} + +int +main(int argc, char *argv[]) +{ + int i, file_fd, nameddir_fd, outsiz; + char *buf; + long named_enabled; + size_t pos, siz; + + if (argc <= 2) + usage(); + argv++; + argc--; + if (argc < 2) + usage(); + + named_enabled = pathconf(argv[0], _PC_NAMEDATTR_ENABLED); + if (named_enabled <= 0) + errx(1, "Named attributes not enabled for %s", argv[0]); + + /* Generate the command string for "sh". */ + siz = 0; + for (i = 1; i < argc; i++) + siz += strlen(argv[i]) + 1; + buf = malloc(siz); + if (buf == NULL) + errx(1, "Cannot malloc"); + pos = 0; + for (i = 1; i < argc; i++) { + outsiz = snprintf(&buf[pos], siz, "%s ", argv[i]); + if ((size_t)outsiz > siz) + errx(1, "Arguments too large"); + pos += outsiz; + siz -= outsiz; + } + buf[pos - 1] = '\0'; + + file_fd = open(argv[0], O_RDONLY | O_CLOEXEC, 0); + if (file_fd < 0) + err(1, "Cannot open %s", argv[0]); + nameddir_fd = openat(file_fd, ".", O_RDONLY | O_CLOEXEC | O_NAMEDATTR, + 0); + if (nameddir_fd < 0) + err(1, "Cannot open named attribute directory " + "for %s", argv[0]); + + if (fchdir(nameddir_fd) < 0) + err(1, "Cannot fchdir to named attribute dir"); + + execl(_PATH_BSHELL, "sh", "-c", buf, NULL); + err(1, "Could not exec %s", _PATH_BSHELL); +}