- int ret = -1;
- int i;
- int nbctx = 0;
- int ctxs[16];
- int disconnect = 0;
- int silent = 0;
- int flags = 0;
- unsigned remove_cap = 0;
- unsigned add_cap = 0;
- unsigned long secure = (1<<CAP_LINUX_IMMUTABLE)
- |(1<<CAP_NET_BROADCAST)
- |(1<<CAP_NET_ADMIN)
- |(1<<CAP_NET_RAW)
- |(1<<CAP_IPC_LOCK)
- |(1<<CAP_IPC_OWNER)
- |(1<<CAP_SYS_MODULE)
- |(1<<CAP_SYS_RAWIO)
- |(1<<CAP_SYS_PACCT)
- |(1<<CAP_SYS_ADMIN)
- |(1<<CAP_SYS_BOOT)
- |(1<<CAP_SYS_NICE)
- |(1<<CAP_SYS_RESOURCE)
- |(1<<CAP_SYS_TIME)
- |(1<<CAP_MKNOD)
- |(1<<CAP_QUOTACTL);
- const char *hostname=NULL, *domainname=NULL;
-
- for (i=1; i<argc; i++){
- const char *arg = argv[i];
- const char *opt = argv[i+1];
- if (strcmp(arg,"--ctx")==0){
- if (nbctx >= 16){
- fprintf (stderr,"Too many context, max 16, ignored.\n");
- }else{
- ctxs[nbctx++] = atoi(opt);
- }
- i++;
- }else if (strcmp(arg,"--disconnect")==0){
- disconnect = 1;
- }else if (strcmp(arg,"--silent")==0){
- silent = 1;
- }else if (strcmp(arg,"--flag")==0){
- if (strcmp(opt,"lock")==0){
- flags |= 1;
- }else if (strcmp(opt,"sched")==0){
- flags |= 2;
- }else if (strcmp(opt,"nproc")==0){
- flags |= 4;
- }else if (strcmp(opt,"private")==0){
- flags |= 8;
- }else if (strcmp(opt,"fakeinit")==0){
- flags |= 16;
- }else if (strcmp(opt,"hideinfo")==0){
- flags |= 32;
- }else if (strcmp(opt,"ulimit")==0){
- flags |= 64;
- }else{
- fprintf (stderr,"Unknown flag %s\n",opt);
- }
- i++;
- }else if (strcmp(arg,"--cap")==0){
- static struct {
- const char *option;
- int bit;
- }tbcap[]={
- // The following capabilities are normally available
- // to vservers administrator, but are place for
- // completeness
- {"CAP_CHOWN",CAP_CHOWN},
- {"CAP_DAC_OVERRIDE",CAP_DAC_OVERRIDE},
- {"CAP_DAC_READ_SEARCH",CAP_DAC_READ_SEARCH},
- {"CAP_FOWNER",CAP_FOWNER},
- {"CAP_FSETID",CAP_FSETID},
- {"CAP_KILL",CAP_KILL},
- {"CAP_SETGID",CAP_SETGID},
- {"CAP_SETUID",CAP_SETUID},
- {"CAP_SETPCAP",CAP_SETPCAP},
- {"CAP_SYS_TTY_CONFIG",CAP_SYS_TTY_CONFIG},
- {"CAP_LEASE",CAP_LEASE},
- {"CAP_SYS_CHROOT",CAP_SYS_CHROOT},
-
- // Those capabilities are not normally available
- // to vservers because they are not needed and
- // may represent a security risk
- {"CAP_LINUX_IMMUTABLE",CAP_LINUX_IMMUTABLE},
- {"CAP_NET_BIND_SERVICE",CAP_NET_BIND_SERVICE},
- {"CAP_NET_BROADCAST",CAP_NET_BROADCAST},
- {"CAP_NET_ADMIN", CAP_NET_ADMIN},
- {"CAP_NET_RAW", CAP_NET_RAW},
- {"CAP_IPC_LOCK", CAP_IPC_LOCK},
- {"CAP_IPC_OWNER", CAP_IPC_OWNER},
- {"CAP_SYS_MODULE",CAP_SYS_MODULE},
- {"CAP_SYS_RAWIO", CAP_SYS_RAWIO},
- {"CAP_SYS_PACCT", CAP_SYS_PACCT},
- {"CAP_SYS_ADMIN", CAP_SYS_ADMIN},
- {"CAP_SYS_BOOT", CAP_SYS_BOOT},
- {"CAP_SYS_NICE", CAP_SYS_NICE},
- {"CAP_SYS_RESOURCE",CAP_SYS_RESOURCE},
- {"CAP_SYS_TIME", CAP_SYS_TIME},
- {"CAP_MKNOD", CAP_MKNOD},
- {"CAP_QUOTACTL", CAP_QUOTACTL},
- {NULL,0}
- };
- int j;
- unsigned *cap = &add_cap;
- if (opt[0] == '!'){
- cap = &remove_cap;
- opt++;
- }
- for (j=0; tbcap[j].option != NULL; j++){
- if (strcasecmp(tbcap[j].option,opt)==0){
- *cap |= (1<<tbcap[j].bit);
- break;
- }
- }
- if (tbcap[j].option == NULL){
- fprintf (stderr,"Unknown capability %s\n",opt);
- }
- i++;
- }else if (strcmp(arg,"--secure")==0){
- remove_cap |= secure;
- }else if (strcmp(arg,"--hostname")==0){
- hostname = opt;
- i++;
- }else if (strcmp(arg,"--domainname")==0){
- if (opt != NULL && strcmp(opt,"none")==0) opt = "";
- domainname = opt;
- i++;
- }else{
- break;
- }
- }
- if (i == argc){
- usage();
- }else if (argv[i][0] == '-'){
- usage();
- }else{
- /*
- We must fork early because fakeinit set the current
- process as the special init process
- */
- if (disconnect == 0 || fork()==0){
- int newctx;
- int xflags = flags & 16;
-
- if (nbctx == 0) ctxs[nbctx++] = -1;
- newctx = vc_new_s_context(ctxs[0],0,flags&~16);
- if (newctx != -1){
- if (hostname != NULL){
- if (sethostname (hostname,strlen(hostname))==-1){
- fprintf (stderr,"Can't set the host name (%s)\n"
- ,strerror(errno));
- }else if (!silent){
- printf ("Host name is now %s\n",hostname);
- }
- }
- if (domainname != NULL){
- setdomainname (domainname,strlen(domainname));
- if (!silent){
- printf ("Domain name is now %s\n",domainname);
- }
- }
- remove_cap &= (~add_cap);
- if (remove_cap!=0 || xflags!=0)
- vc_new_s_context (-2,remove_cap,xflags);
- if (!silent){
- printf ("New security context is %d\n"
- ,ctxs[0] == -1 ? newctx : ctxs[0]);
- }
- execvp (argv[i],argv+i);
- fprintf (stderr,"Can't exec %s (%s)\n",argv[i]
- ,strerror(errno));
- }else{
- perror ("Can't set the new security context\n");
- }
- if (disconnect != 0) _exit(0);
- }
+ struct Arguments args = {
+ .nbctx = 0,
+ .do_disconnect = false,
+ .do_silent = false,
+ .flags = 0,
+ .remove_caps = 0,
+ .add_caps = 0,
+ .hostname = 0,
+ .domainname = 0
+ };
+
+#if defined(VC_ENABLE_API_COMPAT) || defined(VC_ENABLE_API_LEGACY)
+ xid_t newctx;
+ int xflags;
+ int p[2][2];
+ pid_t pid;
+#endif
+
+ global_args = &args;
+ signal(SIGCHLD, SIG_DFL);
+
+ while (1) {
+ int c = getopt_long(argc, argv, "+", CMDLINE_OPTIONS, 0);
+ if (c==-1) break;
+
+ switch (c) {
+ case CMD_HELP : showHelp(1, argv[0], 0);
+ case CMD_VERSION : showVersion();
+ case CMD_DISCONNECT : args.do_disconnect = true; break;
+ case CMD_SILENT : args.do_silent = true; break;
+ case CMD_DOMAINNAME : args.domainname = optarg; break;
+ case CMD_HOSTNAME : args.hostname = optarg; break;
+
+#if defined(VC_ENABLE_API_COMPAT) || defined(VC_ENABLE_API_LEGACY)
+ case CMD_CAP :
+ setCap(optarg, &args.add_caps, &args.remove_caps);
+ break;
+ case CMD_SECURE :
+ args.remove_caps |= vc_get_insecurebcaps();
+ break;
+ case CMD_FLAG :
+ setFlags(optarg, &args.flags);
+ break;
+ case CMD_CTX :
+ if (args.nbctx>0)
+ WRITE_MSG(2, "WARNING: More than one ctx not supported by this version\n");
+ if (args.nbctx>=DIM_OF(args.ctxs)) {
+ WRITE_MSG(2, "Too many contexts given\n");
+ exit(255);