我有以下c setuid包装器:
#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]);
}
我可以使用./cwrapper perlscript.pl
调用我的perl脚本。
我想做./cwrapper perlscript.pl --option1 --option2 --option3
并使用GetOptions详细说明perl脚本中的所有参数。我该如何更换我的包装?
答案 0 :(得分:3)
还有一个不需要任何分配的好解决方案,能够处理任意长命令,并不意味着运行无用的进程,因为它不使用system
。此外,通过以下解决方案,您可以免费获得衍生过程的退出代码。
#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;
}
答案 1 :(得分:2)
这是一个处理可变数量参数的版本。请注意,您的系统调用应该进行测试,以确保一切正常。
#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;
}
答案 2 :(得分:0)
您应该使用sprintf
使用您的选项构建字符串,然后将此字符串传递给system:
char command [100];
sprintf (command, "./cwrapper %s --%s --%s --%s", program_name,option1,option2,
option3);
system(command);
更新:这种方法采用固定数量的参数,回顾你的问题,我发现可能并非如此。
答案 3 :(得分:0)
忽略argv [0]因为是c程序的名称并使用所有其他程序。您可以计算(strlen
)所需内存以组合新字符串,malloc()
新字符串的内存,然后通过连接所有argv
(strcat
来构建新字符串})。或者对于固定长度的方法,请关注@ dan1111 answer。