X-Git-Url: http://git.linux-vserver.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=util-vserver%2Fsrc%2Fvcontext.c;h=a26b0c73695becfb4db9704561513cf545cf5979;hb=c379a190b0c8f633c6daca9586cc44b5bc4f4c28;hp=efed109b0a6444d0796b12aee61a89e9448157f4;hpb=088775aa3aee3851124fd282b435338a696496c4;p=util-vserver.git diff --git a/util-vserver/src/vcontext.c b/util-vserver/src/vcontext.c index efed109..a26b0c7 100644 --- a/util-vserver/src/vcontext.c +++ b/util-vserver/src/vcontext.c @@ -27,11 +27,15 @@ #include #include #include +#include +#include #define ENSC_WRAPPERS_PREFIX "vcontext: " #define ENSC_WRAPPERS_UNISTD 1 #define ENSC_WRAPPERS_VSERVER 1 #define ENSC_WRAPPERS_FCNTL 1 +#define ENSC_WRAPPERS_SOCKET 1 +#define ENSC_WRAPPERS_IOSOCK 1 #include #define CMD_HELP 0x1000 @@ -44,6 +48,9 @@ #define CMD_UID 0x4005 #define CMD_CHROOT 0x4006 #define CMD_SILENT 0x4007 +#define CMD_SYNCSOCK 0x4008 +#define CMD_SYNCMSG 0x4009 +#define CMD_MIGRATESELF 0x4010 struct option const CMDLINE_OPTIONS[] = { @@ -53,23 +60,29 @@ CMDLINE_OPTIONS[] = { { "xid", required_argument, 0, CMD_XID }, { "create", no_argument, 0, CMD_CREATE }, { "migrate", no_argument, 0, CMD_MIGRATE }, - { "fakeinit", no_argument, 0, CMD_FAKEINIT }, - { "disconnect", no_argument, 0, CMD_DISCONNECT }, - { "silent", no_argument, 0, CMD_SILENT }, - { "uid", no_argument, 0, CMD_UID }, - { "chroot", no_argument, 0, CMD_CHROOT }, + { "migrate-self", no_argument, 0, CMD_MIGRATESELF }, + { "fakeinit", no_argument, 0, CMD_FAKEINIT }, + { "disconnect", no_argument, 0, CMD_DISCONNECT }, + { "silent", no_argument, 0, CMD_SILENT }, + { "uid", no_argument, 0, CMD_UID }, + { "chroot", no_argument, 0, CMD_CHROOT }, + { "syncsock", required_argument, 0, CMD_SYNCSOCK }, + { "syncmsg", required_argument, 0, CMD_SYNCMSG }, { 0,0,0,0 }, }; struct Arguments { bool do_create; bool do_migrate; + bool do_migrateself; bool do_disconnect; bool is_fakeinit; int verbosity; bool do_chroot; uid_t uid; xid_t xid; + char const * sync_sock; + char const * sync_msg; }; int wrapper_exit_code = 255; @@ -83,14 +96,24 @@ showHelp(int fd, char const *cmd, int res) " --create [--xid ] * [--] *\n "); WRITE_STR(fd, cmd); WRITE_MSG(fd, - " --migrate --xid * [--] *\n" + " [(--migrate --xid )|--migrate-self] * [--] *\n" "\n" " can be:\n" " --chroot ... chroot into current directory\n" " --uid ... change uid\n" " --fakeinit ... set current process as general process reaper\n" " for ctx (possible for --migrate only)\n" + " --disconnect ... start program in background\n" " --silent ... be silent\n" + " --syncsock \n" + " ... before executing the program, send a message\n" + " to the socket and wait until it closes.\n" + " must be a SOCK_STREAM unix socket\n" + " --syncmsg \n" + " ... use as synchronization message; by\n" + " default, 'ok' will be used\n" + "\n" + "'vcontext --create' exits with code 254 iff the context exists already.\n" "\n" "Please report bugs to " PACKAGE_BUGREPORT "\n"); @@ -169,6 +192,40 @@ tellContext(xid_t ctx, bool do_it) WRITE_MSG(2, "\n"); } +static int +connectExternalSync(char const *filename) +{ + int fd; + struct sockaddr_un addr; + + if (filename==0) return -1; + + ENSC_INIT_UNIX_SOCK(addr, filename); + + fd = Esocket(PF_UNIX, SOCK_STREAM, 0); + Econnect(fd, &addr, sizeof(addr)); + + return fd; +} + +static void +doExternalSync(int fd, char const *msg) +{ + char c; + + if (fd==-1) return; + + if (msg) EsendAll(fd, msg, strlen(msg)); + Eshutdown(fd, SHUT_WR); + + if (TEMP_FAILURE_RETRY(recv(fd, &c, 1, MSG_NOSIGNAL))!=0) { + WRITE_MSG(2, "vcontext: unexpected external synchronization event\n"); + exit(255); + } + + Eclose(fd); +} + static inline ALWAYSINLINE int doit(struct Arguments const *args, char *argv[]) { @@ -177,8 +234,17 @@ doit(struct Arguments const *args, char *argv[]) if (pid==0) { xid_t xid; + int ext_sync_fd = connectExternalSync(args->sync_sock); + if (args->do_create) { - xid = Evc_create_context(args->xid); + xid = vc_create_context(args->xid); + if (xid==VC_NOCTX) { + if (errno==EEXIST) return 254; + else { + perror(ENSC_WRAPPERS_PREFIX "vc_create_context()"); + return wrapper_exit_code; + } + } tellContext(xid, args->verbosity>=1); } else @@ -196,19 +262,25 @@ doit(struct Arguments const *args, char *argv[]) } if (args->is_fakeinit) { - struct vc_ctx_flags flags; - Evc_get_flags(xid, &flags); -#warning !!! IMPLEMENT ME !!! - //if (flags.mask - if (0) { + struct vc_ctx_flags test_flags; + struct vc_ctx_flags flags = { + .flagword = S_CTX_INFO_INIT, + .mask = S_CTX_INFO_INIT + }; + + Evc_get_flags(xid, &test_flags); + if ((flags.mask & S_CTX_INFO_INIT)==0) { WRITE_MSG(2, "vcontext: context has already a fakeinit-process\n"); exit(255); } + + Evc_set_flags(xid, &flags); } - if (args->do_migrate) + if (args->do_migrate && !args->do_migrateself) Evc_migrate_context(xid); + doExternalSync(ext_sync_fd, args->sync_msg); doSyncStage1(p, args->do_disconnect); execvp (argv[optind],argv+optind); doSyncStage2(p, args->do_disconnect); @@ -224,13 +296,15 @@ doit(struct Arguments const *args, char *argv[]) int main (int argc, char *argv[]) { struct Arguments args = { - .do_create = false, - .do_migrate = false, - .do_disconnect = false, - .is_fakeinit = false, - .verbosity = 1, - .uid = -1, - .xid = VC_DYNAMIC_XID, + .do_create = false, + .do_migrate = false, + .do_migrateself = false, + .do_disconnect = false, + .is_fakeinit = false, + .verbosity = 1, + .uid = -1, + .xid = VC_DYNAMIC_XID, + .sync_msg = "ok", }; while (1) { @@ -248,6 +322,12 @@ int main (int argc, char *argv[]) case CMD_SILENT : --args.verbosity; break; case CMD_XID : args.xid = atol(optarg); break; case CMD_UID : args.uid = atol(optarg); break; + case CMD_SYNCSOCK : args.sync_sock = optarg; break; + case CMD_SYNCMSG : args.sync_msg = optarg; break; + case CMD_MIGRATESELF : + args.do_migrate = true; + args.do_migrateself = true; + break; default : WRITE_MSG(2, "Try '"); @@ -258,6 +338,9 @@ int main (int argc, char *argv[]) } } + if (args.do_migrateself) + args.xid = Evc_get_task_xid(0); + if (!args.do_create && !args.do_migrate) WRITE_MSG(2, "Neither '--create' nor '--migrate specified; try '--help' for more information\n"); else if (args.do_create && args.do_migrate)