(name: &str)
| 51 | } |
| 52 | |
| 53 | pub fn create_system_user(name: &str) -> Result<(), Error> { |
| 54 | let mut list_users = Command::new("dscl"); |
| 55 | list_users.args([".", "-list", "/Users", "UniqueID"]); |
| 56 | let output = command_output(&mut list_users, "dscl -list /Users UniqueID")?; |
| 57 | let stdout = String::from_utf8_lossy(&output.stdout); |
| 58 | let used_uids: Vec<u32> = stdout |
| 59 | .lines() |
| 60 | .filter_map(|line| line.split_whitespace().last()?.parse().ok()) |
| 61 | .collect(); |
| 62 | let uid = (400..500) |
| 63 | .rev() |
| 64 | .find(|u| !used_uids.contains(u)) |
| 65 | .ok_or(Error::NoAvailableSystemUid)?; |
| 66 | |
| 67 | let user_path = format!("/Users/{name}"); |
| 68 | let uid_str = uid.to_string(); |
| 69 | |
| 70 | let dscl = |args: &[&str], command_name: &'static str| -> Result<(), Error> { |
| 71 | let mut command = Command::new("dscl"); |
| 72 | command.args(args); |
| 73 | command_status(&mut command, command_name) |
| 74 | }; |
| 75 | |
| 76 | dscl(&[".", "-create", &user_path], "dscl create user record")?; |
| 77 | dscl( |
| 78 | &[".", "-create", &user_path, "UniqueID", &uid_str], |
| 79 | "dscl set user UID", |
| 80 | )?; |
| 81 | dscl( |
| 82 | &[".", "-create", &user_path, "PrimaryGroupID", "20"], |
| 83 | "dscl set user GID", |
| 84 | )?; |
| 85 | dscl( |
| 86 | &[".", "-create", &user_path, "UserShell", "/usr/bin/false"], |
| 87 | "dscl set user shell", |
| 88 | )?; |
| 89 | dscl( |
| 90 | &[".", "-create", &user_path, "RealName", "ClawShell Service"], |
| 91 | "dscl set user real name", |
| 92 | )?; |
| 93 | dscl( |
| 94 | &[".", "-create", &user_path, "NFSHomeDirectory", "/var/empty"], |
| 95 | "dscl set user home directory", |
| 96 | )?; |
| 97 | |
| 98 | let mut hide_user = Command::new("dscl"); |
| 99 | hide_user.args([".", "-create", &user_path, "IsHidden", "1"]); |
| 100 | command_status(&mut hide_user, "dscl hide user")?; |
| 101 | |
| 102 | Ok(()) |
| 103 | } |
| 104 | |
| 105 | pub fn delete_system_user(name: &str) -> Result<(), Error> { |
| 106 | let mut command = Command::new("dscl"); |
nothing calls this directly
no test coverage detected