通过C setuid包装器将命令行参数传递给另一个脚本

时间:2012-08-18 08:35:05

标签: c perl wrapper

我有以下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脚本中的所有参数。我该如何更换我的包装?

4 个答案:

答案 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()新字符串的内存,然后通过连接所有argvstrcat来构建新字符串})。或者对于固定长度的方法,请关注@ dan1111 answer。