Reputation: 11890
I have the following c setuid wrapper:
#include <unistd.h>
#include <sys/types.h>
#include <pwd.h>
main( int argc, char ** argv ) {
struct passwd *pwd;
char user[] = "cvmfs-test";
pwd = getpwnam(user);
setuid(pwd->pw_uid);
system(argv[1]);
}
I can call my perl script with ./cwrapper perlscript.pl
.
I would like to do ./cwrapper perlscript.pl --option1 --option2 --option3
and elaborate all arguments inside the perl script with GetOptions. How should I change my wrapper?
Upvotes: 1
Views: 1490
Reputation: 433
There is also a nice solution which does not need any allocation, is able to deal with arbitrary long commands and does not imply running useless processes because it does not use system
. Moreover with the following solution you get the exit code of the spawned process for free.
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include <pwd.h>
#define SETUIDUSER "foobar"
int main(int argc, char **argv) {
struct passwd *pwd;
char user[] = SETUIDUSER;
pwd = getpwnam(user);
// success test needed here
setuid(pwd->pw_uid);
// success test needed here
if (argc < 2)
return 1;
execvp(argv[1], &argv[1]);
return 42;
}
Upvotes: 3
Reputation: 4384
Here is a version dealing with a variable number of arguments. Please note that your syscalls should be tested to ensure everything is going OK.
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include <pwd.h>
#define CMDMAXLGTH 4096
#define SETUIDUSER "testuser"
int main( int argc, char ** argv ) {
struct passwd *pwd;
char user[] = SETUIDUSER;
char buf[CMDMAXLGTH];
char *p = buf;
int i = 1;
pwd = getpwnam(user);
// success test needed here
setuid(pwd->pw_uid);
// success test needed here
memset (buf, 0, sizeof(buf));
while (argv[i]) {
p += sprintf(p, " %s", argv[i++]);
}
system(buf);
return 0;
}
Upvotes: 2
Reputation: 3892
Ignore the argv[0] because is the name of the c program and use all the other. You can calculate (strlen
) the required memory to assemble a new string, malloc()
the memory for the new string and then build your new string by concatenating all the argv
(strcat
). Or for a fixed length approach, follow @dan1111 answer.
Upvotes: 0
Reputation: 6566
You should use sprintf
to build a character string with your options, then pass this string to system:
char command [100];
sprintf (command, "./cwrapper %s --%s --%s --%s", program_name,option1,option2,
option3);
system(command);
Update: this approach assumes a fixed number of arguments, and looking back at your question, I see that may not be the case.
Upvotes: 0