]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
Optionally execute a program after group change
authorGábor Németh <homar@riseup.net>
Thu, 29 Aug 2024 06:59:23 +0000 (08:59 +0200)
committerGábor Németh <homar@riseup.net>
Thu, 29 Aug 2024 08:13:48 +0000 (10:13 +0200)
We accept a `-c` command option or possible second argument which is then
invoked through the user's shell after the group change, as by the `sg`
utility. The default is still running the shell itself.

bash-completion/newgrp
login-utils/newgrp.1.adoc
login-utils/newgrp.c

index 1e39c0f42ef4472a3e8cce80f5639b8dfca316ca..c6d678b934cc8890be62542234c491b775e600c2 100644 (file)
@@ -8,15 +8,23 @@ _newgrp_module()
                '-h'|'--help'|'-V'|'--version')
                        return 0
                        ;;
+               '-c'|'--command')
+                       COMPREPLY=( $(compgen -c -- $cur) )
+                       return 0
+                       ;;
        esac
        case $cur in
                -*)
-                       OPTS="--version --help"
+                       OPTS="--version --help --command"
                        COMPREPLY=( $(compgen -W "${OPTS[*]}" -- $cur) )
                        return 0
                        ;;
        esac
-       COMPREPLY=( $(compgen -g -- $cur) )
+       if (( COMP_CWORD == 1 )) || [[ " ${COMP_WORDS[@]}" =~ " "-?-c ]]; then
+               COMPREPLY=( $(compgen -g -- $cur) )
+       else
+               COMPREPLY=( $(compgen -c -- $cur) )
+       fi
        return 0
 }
 complete -F _newgrp_module newgrp
index e9a90d3ea85b207bd3a6d5bbff24ce1bb3f09591..521b7355949b9ff3815d8e78005a8a1cbb1163e0 100644 (file)
@@ -18,7 +18,9 @@ newgrp - log in to a new group
 
 == SYNOPSIS
 
-*newgrp* [_group_]
+*newgrp* [_group_ [_command_]]
+
+*newgrp* [*-c* _command_] [_group_]
 
 == DESCRIPTION
 
@@ -26,8 +28,13 @@ newgrp - log in to a new group
 
 If no group is specified, the GID is changed to the login GID.
 
+An optional command can be specified, which is invoked after group change instead of the user's shell.
+
 == OPTIONS
 
+*-c*, *--command*=__command__::
+Pass _command_ to the user's shell with the *-c* option.
+
 include::man-common/help-version.adoc[]
 
 == FILES
index e71a9e134b9550aff1295bc0e49b124dcf502c7f..b9b620ed7526f6b98355d7788ad895ac0b2f8207 100644 (file)
@@ -172,10 +172,10 @@ static void __attribute__((__noreturn__)) usage(void)
 {
        FILE *out = stdout;
        fputs(USAGE_HEADER, out);
-       fprintf(out, _(" %s <group>\n"), program_invocation_short_name);
+       fprintf(out, _(" %s <group> [[-c] <command>]\n"), program_invocation_short_name);
 
        fputs(USAGE_SEPARATOR, out);
-       fputs(_("Log in to a new group.\n"), out);
+       fputs(_("Log in to a new group; optionally executing a shell command.\n"), out);
 
        fputs(USAGE_OPTIONS, out);
        fprintf(out, USAGE_HELP_OPTIONS(16));
@@ -187,11 +187,12 @@ int main(int argc, char *argv[])
 {
        struct passwd *pw_entry;
        struct group *gr_entry;
-       char *shell;
+       char *shell, *command = NULL;
        int ch;
        static const struct option longopts[] = {
                {"version", no_argument, NULL, 'V'},
                {"help", no_argument, NULL, 'h'},
+               {"command", required_argument, NULL, 'c'},
                {NULL, 0, NULL, 0}
        };
 
@@ -200,8 +201,11 @@ int main(int argc, char *argv[])
        textdomain(PACKAGE);
        close_stdout_atexit();
 
-       while ((ch = getopt_long(argc, argv, "Vh", longopts, NULL)) != -1)
+       while ((ch = getopt_long(argc, argv, "c:Vh", longopts, NULL)) != -1)
                switch (ch) {
+               case 'c':
+                       command = optarg;
+                       break;
                case 'V':
                        print_version(EXIT_SUCCESS);
                case 'h':
@@ -213,12 +217,12 @@ int main(int argc, char *argv[])
        if (!(pw_entry = getpwuid(getuid())))
                err(EXIT_FAILURE, _("who are you?"));
 
-       if (argc < 2) {
+       if (argc <= optind) {
                if (setgid(pw_entry->pw_gid) < 0)
                        err(EXIT_FAILURE, _("setgid failed"));
        } else {
                errno = 0;
-               if (!(gr_entry = getgrnam(argv[1]))) {
+               if (!(gr_entry = getgrnam(argv[optind++]))) {
                        if (errno)
                                err(EXIT_FAILURE, _("no such group"));
                        else
@@ -236,6 +240,8 @@ int main(int argc, char *argv[])
        fflush(NULL);
        shell = (pw_entry->pw_shell && *pw_entry->pw_shell ?
                                pw_entry->pw_shell : _PATH_BSHELL);
-       execl(shell, shell, (char *)NULL);
+       if (!command && optind < argc)
+               command = argv[optind];
+       execl(shell, shell, command ? "-c" : NULL, command, (char *)NULL);
        errexec(shell);
 }