Page MenuHomeFreeBSD

runat: A utility that executes a shell command on a named attribute
ClosedPublic

Authored by rmacklem on Apr 16 2025, 2:16 AM.
Tags
None
Referenced Files
Unknown Object (File)
Sun, May 25, 8:56 AM
Unknown Object (File)
Sun, May 25, 6:33 AM
Unknown Object (File)
Thu, May 22, 7:37 PM
Unknown Object (File)
Sun, May 18, 9:09 AM
Unknown Object (File)
Sat, May 17, 5:56 PM
Unknown Object (File)
Wed, May 14, 9:47 AM
Unknown Object (File)
Tue, May 13, 3:16 AM
Unknown Object (File)
Sun, May 11, 6:14 AM

Details

Summary

This simple utility (loosely modelled after the one on Solaris)
will open a named attribute directory for the "file" argument
and the fchdir() to it in a child process and execute a shell
command via system(3).

It allows named attributes to be manipulated via command
lines. It does not allow an interactive shell to be invoked.

In particular, this program needs to be reviewed to determine
if additional work related to signals is required, given that
it fork()s a child to perform the shell command.

Test Plan

It has seen a modicum of testing on a patched version
of FreeBSD that supports named attributes on both
ZFS and NFSv4.

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Skipped
Unit
Tests Skipped

Event Timeline

Update runat.c to use the up to date more Solaris-like
O_NAMEDATTR flag.

usr.bin/runat/runat.c
41

There seems to be no -nocreate parsing in main().

101

Why do you need this child? Could you fchdir() in the runat process directly, and then do system(), without forking?

112

This should be exit(WEXITSTATUS(sysret)); at least. Better, it can be

		if (WIFSIGNALED(sysret))
			raise(WTERMSIG(sysret));
		if (WIFEXITED(sysret))
			exit(WEXITSTATUS(sysret));
116

If you want to propagate the status of child to invoking shell, see above.

Updated runat.c to apply kib@'s suggestions.
For some reason (don't know where I got it) I
thought that fchdir() directory change would
affect more than the process, which was why I
did the fork(). (I think it came from ancient
recollections of how 6th Edition worked in the
1970s. I'm gettin old;-)

I see it does not, so I don't think the fork()
is needed and have taken it out.
(Thanks go to kib@ for recognizing my stupidity.)

usr.bin/runat/runat.c
101

In fact, why do you need system(3)? This kind of utilities, I believe, set up the exec(3) args vector by chomping consumed arguments, prepend "sh", "-c", and call exec(3) function. Then you do not need to try to perfectly pass the child exit status.

rmacklem marked 2 inline comments as done.

Oops, missed the last suggested change from kib@
the last time. It is here now.

I don't really understand it, but hopefully I got it
the way he suggested?

usr.bin/runat/runat.c
101

system(3) does a lot of signal blocking during
vfork(), etc. If you don't think that's necessary and
it's just exec(), then I an do that?

usr.bin/runat/runat.c
101

Yes, I suggest to use exec(). We have nothing to do after the child is spawn. Catching the child status and trying to propagate it causes the complications you already noted.

BTW, if you open file and directory with O_CLOEXEC, you do not even need to close them manually.

This version just does an execl() as suggested by kib@.

usr.bin/runat/runat.1
2

If you want you can use the SPDX short form. It's an iso standard and project's template in current style(9) or here: https://docs.freebsd.org/en/articles/license-guide/

41

I think function arguments aren't for utilities.

44

Since we have a manual for that it might be helpful to link it here. It will also be clickable in "modern" manual readers.

usr.bin/runat/runat.c
92

Since you are using exec now, it might be better to not concatenate all args into one string. Instead, allocate char *[] array and assign *argv[] elements to it.

The advantage is that the original quoting of the shell is preserved.

97

This open needs O_CLOEXEC too.

Updated the man page to reflect the use of /bin/sh.

Updated man page with changes suggested by ziaa@.

I also changed the copyright notices to the new short form.

rmacklem marked an inline comment as done.

Missed a couple of cases for .Ar file. Fixed now.

rmacklem added inline comments.
usr.bin/runat/runat.c
92

The "-c" argument for /bin/sh requires that the
entire command be in a single string argument.

Marked inline comments as done.

Note that O_CLOEXEC is set in "fmode" near the top of main()
for the second open.

This revision is now accepted and ready to land.Apr 22 2025, 2:19 PM
usr.bin/runat/runat.1
2

style(9) asks for a blank line before and after this, and sometimes this is controversial to clean up later. I also don't think that the copyright line has a period. Sorry to be pedantic, licenses are very specific and a bit scary.

41

Why not markup examples section?

usr.bin/runat/runat.c
2

The "-" was for a project Warner started, never went anywhere, and abandoned. It is still recommended in a style guide anywhere? We tried to clean them all up, but there's a lot of doc proliferation.

Updated the copyrights, as suggested by ziaa@.

This revision now requires review to proceed.Apr 23 2025, 12:26 AM

Marked inline comments as done.

usr.bin/runat/runat.1
41

Not sure what you mean here, but I made "file"
a .Ar.

rmacklem marked an inline comment as done.

Added chdir(2) to the SEE ALSO section of the runat.1.

Removed the "." after my name in the copyright.

This revision was not accepted when it landed; it landed in state Needs Review.Tue, May 6, 8:39 PM
This revision was automatically updated to reflect the committed changes.