When writing CLI tools or system utilities, you might need to modify program behavior based on whether it's executed with sudo privileges. A classic example is MacPorts' output - when suggesting follow-up commands, it should include 'sudo' if the original command used it.
The most reliable method checks the SUDO_UID
environment variable:
#include <stdlib.h>
#include <stdio.h>
int is_sudo() {
return getenv("SUDO_UID") != NULL;
}
int main() {
if (is_sudo()) {
printf("Running with sudo privileges\n");
} else {
printf("Running as normal user\n");
}
return 0;
}
For shell scripts, you can use:
#!/bin/bash
if [ -n "$SUDO_USER" ]; then
PREFIX="sudo "
else
PREFIX=""
fi
echo "Run this command: ${PREFIX}port upgrade outdated"
Another approach compares user IDs:
#include <unistd.h>
int is_sudo() {
return geteuid() == 0 && getuid() != 0;
}
This works because sudo changes the effective UID to root (0) while maintaining the original UID.
Be aware of these scenarios:
- Direct root login (both UIDs are 0)
- Programs with setuid bit set
- Different sudo configurations that might not set environment variables
Here's how MacPorts could implement this:
#!/usr/bin/env tclsh
if {[info exists env(SUDO_USER)]} {
set prefix "sudo "
} else {
set prefix ""
}
puts "Run: ${prefix}port upgrade outdated"
For Python implementation:
import os
def is_sudo():
return 'SUDO_USER' in os.environ or os.geteuid() == 0
if is_sudo():
print("Command to run: sudo port upgrade outdated")
else:
print("Command to run: port upgrade outdated")
When implementing sudo detection:
- Never rely solely on environment variables
- Always verify using multiple methods
- Consider using capabilities instead of full root when possible
In Unix-like systems, processes executed with sudo
inherit different environment characteristics than regular processes. When building CLI tools or system utilities, we often need to adapt behavior based on execution context.
Here are several robust approaches to detect sudo context programmatically:
1. Checking Environment Variables
def is_sudo():
return 'SUDO_USER' in os.environ or os.geteuid() == 0
# Example usage:
if is_sudo():
print("Running with elevated privileges")
2. Examining Process UID/GID
# C implementation
#include
int is_sudo_context() {
return (geteuid() == 0) && (getuid() != 0);
}
3. Checking Parent Process Information
# Bash implementation
if [[ $(ps -o comm= -p $PPID) =~ "sudo" ]]; then
echo "Running under sudo"
fi
MacOS handles sudo slightly differently than Linux:
# MacOS-specific check
if [[ $(sysctl -n kern.superuser) -eq 1 ]]; then
echo "Running as superuser"
fi
Extending the original MacPorts use case:
#!/bin/bash
is_sudo() {
[ "$(id -u)" -eq 0 ] && [ -n "$SUDO_USER" ]
}
if is_sudo; then
echo "sudo port upgrade outdated"
else
echo "port upgrade outdated"
fi
Always validate:
- Check both effective and real UIDs
- Verify environment variables aren't spoofed
- Use multiple detection methods for reliability
For Python applications:
import os, pwd
def is_sudo():
try:
return os.geteuid() == 0 and pwd.getpwuid(os.getuid()).pw_name != 'root'
except:
return False