Skip to content

feat: Add newgrp command (#94)#117

Open
Niloyyy wants to merge 2 commits into
microsoft:mainfrom
Niloyyy:feature/add-newgrp
Open

feat: Add newgrp command (#94)#117
Niloyyy wants to merge 2 commits into
microsoft:mainfrom
Niloyyy:feature/add-newgrp

Conversation

@Niloyyy

@Niloyyy Niloyyy commented Jun 9, 2026

Copy link
Copy Markdown

-This PR implements the newgrp command requested in #94.

-It uses LookupAccountNameW and SetTokenInformation to modify the primary group of the process token, then spawns a new shell (%SHELL% or cmd.exe), conforming to standard POSIX-like expectations on Windows.

-It is implemented as a local workspace crate (uu_newgrp) since GNU coreutils does not natively provide it.

@Niloyyy

Niloyyy commented Jun 9, 2026

Copy link
Copy Markdown
Author

@microsoft-github-policy-service agree

lionelconswork

This comment was marked as off-topic.

@lionelconswork

This comment was marked as off-topic.

@lhecker

This comment was marked as off-topic.

@lionelconswork

This comment was marked as off-topic.

@lhecker

This comment was marked as off-topic.

Comment thread deps/newgrp/src/lib.rs
Comment on lines +15 to +24
pub fn uu_app() -> Command {
Command::new("newgrp")
.about("Log in to a new group")
.arg(
Arg::new("group")
.help("The group to log into")
.index(1)
.required(false),
)
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The -c/--command arg is missing.

Comment thread deps/newgrp/src/lib.rs Outdated
}

// Spawn the shell
let shell = std::env::var("SHELL").unwrap_or_else(|_| "cmd.exe".to_string());

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The original newgrp command does not respect a SHELL environment variable. Where did you find this behavior?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The original newgrp command does not respect a SHELL environment variable. Where did you find this behavior?

Cygwin/MSYS2

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit conflicted on whether we should port that behavior. Other tools so far have generally followed the GNU coreutils behavior, so I would assume that newgrp would follow the util-linux behavior. But we don't have login(1), so...

Comment thread deps/newgrp/src/lib.rs Outdated
Comment on lines +94 to +97
let mut token: HANDLE = std::ptr::null_mut();
if OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_DEFAULT, &mut token) == 0 {
return Err(format!("OpenProcessToken failed: {}", GetLastError()));
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't want to change the token of newgrp but the token of the created process. I believe CreateProcessAsUserW would be the appropriate API for that.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't want to change the token of newgrp but the token of the created process. I believe CreateProcessAsUserW would be the appropriate API for that.

That should be fine, because the token is then inherited by the new process.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, but I prefer the suggested approach because it expresses the intent better. I think it's a good idea if we treat this like Microsoft reference code to at least a certain extent. And at least conceptually speaking, newgrp does not really modify its own group, right?

I.e.:

duplicate = DuplicateTokenEx(TokenPrimary)
SetTokenInformation(duplicate, TokenPrimaryGroup)
CreateProcessAsUserW(duplicate, shell + command)

Comment thread deps/newgrp/src/lib.rs Outdated
)
}

pub fn uumain(args: impl uucore::Args) -> i32 {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check how grep handles this. You're missing #[uucore::main(no_signals)] and should be returning an UResult<()>. Same for the function below. You can use an io::Error to GetLastError.

@lionelconswork

This comment was marked as off-topic.

@lhecker

This comment was marked as off-topic.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants