summaryrefslogtreecommitdiff
path: root/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'main.c')
-rw-r--r--main.c58
1 files changed, 58 insertions, 0 deletions
diff --git a/main.c b/main.c
new file mode 100644
index 0000000..7af7c55
--- /dev/null
+++ b/main.c
@@ -0,0 +1,58 @@
+#define _GNU_SOURCE
+
+#include <assert.h>
+#include <errno.h>
+#include <grp.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+int main( int argc, char *argv[] ) {
+
+ if ( argc < 4 ) {
+ fprintf( stderr, "Usage: %s user group cmd [args..]\n", argv[0] );
+ return 1;
+ };
+
+ char *user = argv[1];
+ char *group = argv[2];
+ char *cmd = argv[3];
+ char **args = argv + 3;
+
+ char *end;
+ unsigned long tmp;
+
+ struct passwd *userpw;
+ struct group *grouppw;
+
+ tmp = strtoul( user, &end, 10 );
+ if ( end != user && ! *end ) {
+ userpw = getpwuid( tmp );
+ } else {
+ userpw = getpwnam( user );
+ };
+ assert( userpw != NULL );
+
+ tmp = strtoul( group, &end, 10 );
+ if ( end != user && ! *end ) {
+ grouppw = getgrgid( tmp );
+ } else {
+ grouppw = getgrnam( group );
+ };
+ assert( grouppw != NULL );
+
+ if ( setgroups( 0, NULL ) != 0 )
+ assert_perror( errno );
+
+ if ( setregid( grouppw->gr_gid, grouppw->gr_gid ) != 0 )
+ assert_perror( errno );
+
+ if ( setreuid( userpw->pw_uid, userpw->pw_uid ) != 0 )
+ assert_perror( errno );
+
+ execv( cmd, args );
+ assert_perror( errno );
+
+}