1

我有以下 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.

我想./cwrapper perlscript.pl --option1 --option2 --option3用 GetOptions 来详细说明 perl 脚本中的所有参数。我应该如何改变我的包装?

4

4 回答 4

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;
}
于 2012-08-18T11:36:43.840 回答
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;
}
于 2012-08-18T09:43:45.973 回答
0

您应该使用sprintf您的选项构建一个字符串,然后将此字符串传递给系统:

 char command [100];
 sprintf (command, "./cwrapper %s --%s --%s --%s", program_name,option1,option2,
     option3);
 system(command);

更新:这种方法假设有固定数量的参数,回头看看你的问题,我发现情况可能并非如此。

于 2012-08-18T08:42:02.467 回答
0

忽略 argv[0] 因为是 c 程序的名称并使用所有其他名称。您可以计算 ( strlen) 组装新字符串所需malloc()的内存,新字符串的内存,然后通过连接所有argv( strcat) 来构建新字符串。或者对于固定长度的方法,请按照@dan1111 回答。

于 2012-08-18T09:07:28.260 回答