Beispiel #1
0
static void
msg_trashed( int sts, void *aux )
{
	DECL_SVARS;

	if (sts == DRV_MSG_BAD)
		sts = DRV_BOX_BAD;
	if (check_ret( sts, aux ))
		return;
	INIT_SVARS(aux);
	svars->trash_done[t]++;
	stats( svars );
	sync_close( svars, t );
}
Beispiel #2
0
static int
msgs_flags_set( sync_vars_t *svars, int t )
{
	message_t *tmsg;
	copy_vars_t *cv;

	if (!(svars->state[t] & ST_SENT_FLAGS) || svars->flags_done[t] < svars->flags_total[t])
		return 0;

	if ((svars->chan->ops[t] & OP_EXPUNGE) &&
	    (svars->ctx[t]->conf->trash || (svars->ctx[1-t]->conf->trash && svars->ctx[1-t]->conf->trash_remote_new))) {
		debug( "trashing in %s\n", str_ms[t] );
		for (tmsg = svars->ctx[t]->msgs; tmsg; tmsg = tmsg->next)
			if (tmsg->flags & F_DELETED) {
				if (svars->ctx[t]->conf->trash) {
					if (!svars->ctx[t]->conf->trash_only_new || !tmsg->srec || tmsg->srec->uid[1-t] < 0) {
						debug( "%s: trashing message %d\n", str_ms[t], tmsg->uid );
						svars->trash_total[t]++;
						stats( svars );
						sync_ref( svars );
						svars->drv[t]->trash_msg( svars->ctx[t], tmsg, msg_trashed, AUX );
						if (deref_check_cancel( svars ))
							return -1;
					} else
						debug( "%s: not trashing message %d - not new\n", str_ms[t], tmsg->uid );
				} else {
					if (!tmsg->srec || tmsg->srec->uid[1-t] < 0) {
						if (!svars->ctx[1-t]->conf->max_size || tmsg->size <= svars->ctx[1-t]->conf->max_size) {
							debug( "%s: remote trashing message %d\n", str_ms[t], tmsg->uid );
							svars->trash_total[t]++;
							stats( svars );
							cv = nfmalloc( sizeof(*cv) );
							cv->cb = msg_rtrashed;
							cv->aux = INV_AUX;
							cv->srec = 0;
							cv->msg = tmsg;
							if (copy_msg( cv ))
								return -1;
						} else
							debug( "%s: not remote trashing message %d - too big\n", str_ms[t], tmsg->uid );
					} else
						debug( "%s: not remote trashing message %d - not new\n", str_ms[t], tmsg->uid );
				}
			}
	}
	svars->state[t] |= ST_SENT_TRASH;
	sync_close( svars, t );
	return 0;
}
Beispiel #3
0
static void
msg_rtrashed( int sts, int uid, copy_vars_t *vars )
{
	SVARS_CHECK_CANCEL_RET;
	(void)uid;
	switch (sts) {
	case SYNC_OK:
	case SYNC_NOGOOD: /* the message is gone or heavily busted */
		break;
	default:
		cancel_sync( svars );
		free( vars );
		return;
	}
	free( vars );
	t ^= 1;
	svars->trash_done[t]++;
	stats( svars );
	sync_close( svars, t );
}
Beispiel #4
0
dr_main()
{
	register int n;
	register struct ship *sp;
	int nat[NNATION];
	int value = 0;

	(void) signal(SIGINT, SIG_IGN);
	(void) signal(SIGQUIT, SIG_IGN);
	(void) signal(SIGTSTP, SIG_IGN);
	if (issetuid)
		(void) setuid(geteuid());
	if (game < 0 || game >= NSCENE) {
		fprintf(stderr, "DRIVER: Bad game number %d\n", game);
		exit(1);
	}
	cc = &scene[game];
	ls = SHIP(cc->vessels);
	if (sync_open() < 0) {
		perror("driver: syncfile");
		exit(1);
	}
	for (n = 0; n < NNATION; n++)
		nat[n] = 0;
	foreachship(sp) {
		if (sp->file == NULL &&
		    (sp->file = (struct File *)calloc(1, sizeof (struct File))) == NULL) {
			(void) fprintf(stderr, "DRIVER: Out of memory.\n");
			exit(1);
		}
		sp->file->index = sp - SHIP(0);
		sp->file->loadL = L_ROUND;
		sp->file->loadR = L_ROUND;
		sp->file->readyR = R_LOADED|R_INITIAL;
		sp->file->readyL = R_LOADED|R_INITIAL;
		sp->file->stern = nat[sp->nationality]++;
		sp->file->dir = sp->shipdir;
		sp->file->row = sp->shiprow;
		sp->file->col = sp->shipcol;
	}
	windspeed = cc->windspeed;
	winddir = cc->winddir;
	people = 0;
	for (;;) {
		sleep(7);
		if (Sync() < 0) {
			value = 1;
			break;
		}
		if (next() < 0)
			break;
		unfoul();
		checkup();
		prizecheck();
		moveall();
		thinkofgrapples();
		boardcomp();
		compcombat();
		resolve();
		reload();
		checksails();
		if (Sync() < 0) {
			value = 1;
			break;
		}
	}
	sync_close(1);
	return value;
}
Beispiel #5
0
/*
 * If we get here before a ship is chosen, then ms == 0 and
 * we don't want to update the score file, or do any Write's either.
 * We can assume the sync file is already created and may need
 * to be removed.
 * Of course, we don't do any more Sync()'s if we got here
 * because of a Sync() failure.
 */
void
leave(int conditions)
{
	signal(SIGHUP, SIG_IGN);
	signal(SIGINT, SIG_IGN);
	signal(SIGQUIT, SIG_IGN);
	signal(SIGALRM, SIG_IGN);
	signal(SIGCHLD, SIG_IGN);

	if (done_curses) {
		Signal("It looks like you've had it!",
			NULL);
		switch (conditions) {
		case LEAVE_QUIT:
			break;
		case LEAVE_CAPTURED:
			Signal("Your ship was captured.",
				NULL);
			break;
		case LEAVE_HURRICAN:
			Signal("Hurricane!  All ships destroyed.",
				NULL);
			break;
		case LEAVE_DRIVER:
			Signal("The driver died.", NULL);
			break;
		case LEAVE_SYNC:
			Signal("Synchronization error.", NULL);
			break;
		default:
			Signal("A funny thing happened (%d).",
				NULL, conditions);
		}
	} else {
		switch (conditions) {
		case LEAVE_QUIT:
			break;
		case LEAVE_DRIVER:
			printf("The driver died.\n");
			break;
		case LEAVE_FORK:
			perror("fork");
			break;
		case LEAVE_SYNC:
			printf("Synchronization error\n.");
			break;
		default:
			printf("A funny thing happened (%d).\n",
				conditions);
		}
	}

	if (ms != 0) {
		write_log(ms);
		if (conditions != LEAVE_SYNC) {
			makesignal(ms, "Captain %s relinquishing.",
				NULL, mf->captain);
			Write(W_END, ms, 0, 0, 0, 0);
			Sync();
		}
	}
	sync_close(!hasdriver);
	cleanupscreen();
	exit(0);
}
Beispiel #6
0
initialize()
{
	register struct File *fp;
	register struct ship *sp;
	char captain[80];
	char message[60];
	int load;
	register int n;
	char *nameptr;
	int nat[NNATION];

	if (game < 0) {
		(void) puts("Choose a scenario:\n");
		(void) puts("\n\tNUMBER\tSHIPS\tIN PLAY\tTITLE");
		for (n = 0; n < NSCENE; n++) {
			/* ( */
			printf("\t%d):\t%d\t%s\t%s\n", n, scene[n].vessels,
				sync_exists(n) ? "YES" : "no",
				scene[n].name);
		}
reprint:
		printf("\nScenario number? ");
		(void) fflush(stdout);
		(void) scanf("%d", &game);
		while (getchar() != '\n')
			;
	}
	if (game < 0 || game >= NSCENE) {
		(void) puts("Very funny.");
		exit(1);
	}
	cc = &scene[game];
	ls = SHIP(cc->vessels);

	for (n = 0; n < NNATION; n++)
		nat[n] = 0;
	foreachship(sp) {
		if (sp->file == NULL &&
		    (sp->file = (struct File *)calloc(1, sizeof (struct File))) == NULL) {
			(void) puts("OUT OF MEMORY");
			exit(1);
		}
		sp->file->index = sp - SHIP(0);
		sp->file->stern = nat[sp->nationality]++;
		sp->file->dir = sp->shipdir;
		sp->file->row = sp->shiprow;
		sp->file->col = sp->shipcol;
	}
	windspeed = cc->windspeed;
	winddir = cc->winddir;

	(void) signal(SIGHUP, choke);
	(void) signal(SIGINT, choke);

	hasdriver = sync_exists(game);
	if (sync_open() < 0) {
		perror("sail: syncfile");
		exit(1);
	}

	if (hasdriver) {
		(void) puts("Synchronizing with the other players...");
		(void) fflush(stdout);
		if (Sync() < 0)
			leave(LEAVE_SYNC);
	}
	for (;;) {
		foreachship(sp)
			if (sp->file->captain[0] == 0 && !sp->file->struck
			    && sp->file->captured == 0)
				break;
		if (sp >= ls) {
			(void) puts("All ships taken in that scenario.");
			foreachship(sp)
				free((char *)sp->file);
			sync_close(0);
			people = 0;
			goto reprint;
		}
		if (randomize) {
			player = sp - SHIP(0);
		} else {
			printf("%s\n\n", cc->name);
			foreachship(sp)
				printf("  %2d:  %-10s %-15s  (%-2d pts)   %s\n",
					sp->file->index,
					countryname[sp->nationality],
					sp->shipname,
					sp->specs->pts,
					saywhat(sp, 1));
			printf("\nWhich ship (0-%d)? ", cc->vessels-1);
			(void) fflush(stdout);
			if (scanf("%d", &player) != 1 || player < 0
			    || player >= cc->vessels) {
				while (getchar() != '\n')
					;
				(void) puts("Say what?");
				player = -1;
			} else
				while (getchar() != '\n')
					;
		}
		if (player < 0)
			continue;
		if (Sync() < 0)
			leave(LEAVE_SYNC);
		fp = SHIP(player)->file;
		if (fp->captain[0] || fp->struck || fp->captured != 0)
			(void) puts("That ship is taken.");
		else
			break;
	}

	ms = SHIP(player);
	mf = ms->file;
	mc = ms->specs;

	Write(W_BEGIN, ms, 0, 0, 0, 0, 0);
	if (Sync() < 0)
		leave(LEAVE_SYNC);

	(void) signal(SIGCHLD, child);
	if (!hasdriver)
		switch (fork()) {
		case 0:
			longjmp(restart, MODE_DRIVER);
			/*NOTREACHED*/
		case -1:
			perror("fork");
			leave(LEAVE_FORK);
			break;
		default:
			hasdriver++;
		}

	printf("Your ship is the %s, a %d gun %s (%s crew).\n",
		ms->shipname, mc->guns, classname[mc->class],
		qualname[mc->qual]);
	if ((nameptr = (char *) getenv("SAILNAME")) && *nameptr)
		(void) strncpy(captain, nameptr, sizeof captain);
	else {
		(void) printf("Your name, Captain? ");
		(void) fflush(stdout);
		(void) gets(captain);
		if (!*captain)
			(void) strcpy(captain, "no name");
	}
	captain[sizeof captain - 1] = '\0';
	Write(W_CAPTAIN, ms, 1, (int)captain, 0, 0, 0);
	for (n = 0; n < 2; n++) {
		char buf[10];

		printf("\nInitial broadside %s (grape, chain, round, double): ",
			n ? "right" : "left");
		(void) fflush(stdout);
		(void) scanf("%s", buf);
		switch (*buf) {
		case 'g':
			load = L_GRAPE;
			break;
		case 'c':
			load = L_CHAIN;
			break;
		case 'r':
			load = L_ROUND;
			break;
		case 'd':
			load = L_DOUBLE;
			break;
		default:
			load = L_ROUND;
		}
		if (n) {
			mf->loadR = load;
			mf->readyR = R_LOADED|R_INITIAL;
		} else {
			mf->loadL = load;
			mf->readyL = R_LOADED|R_INITIAL;
		}
	}

	initscreen();
	draw_board();
	(void) sprintf(message, "Captain %s assuming command", captain);
	Write(W_SIGNAL, ms, 1, (int)message, 0, 0, 0);
	newturn();
}
Beispiel #7
0
static void
msgs_new_done( sync_vars_t *svars, int t )
{
	svars->state[t] |= ST_FOUND_NEW;
	sync_close( svars, t );
}
Beispiel #8
0
int main(int argc, char *argv[]) {
    int rc, sync[2];

    pid_t pid = -1;

    siginfo_t status;

    struct mount *mounts = NULL;
    struct netif *netifs = NULL;
    struct cgroup *cgroups = NULL;
    struct user *users = NULL;
#if HAVE_LIBCAP_NG
    struct capability *caps = NULL;
#endif

    char *master;
    _close_ int master_fd = -1;

    char ephemeral_dir[] = "/tmp/pflask-ephemeral-XXXXXX";

    int clone_flags = CLONE_NEWNS  |
                          CLONE_NEWIPC |
                          CLONE_NEWPID |
#ifdef CLONE_NEWCGROUP
                          CLONE_NEWCGROUP |
#endif
                          CLONE_NEWUTS;

    struct gengetopt_args_info args;

    if (cmdline_parser(argc, argv, &args) != 0)
        return 1;

    for (unsigned int i = 0; i < args.mount_given; i++) {
        validate_optlist("--mount", args.mount_arg[i]);
        mount_add_from_spec(&mounts, args.mount_arg[i]);
    }

    for (unsigned int i = 0; i < args.netif_given; i++) {
        clone_flags |= CLONE_NEWNET;

        if (args.netif_arg != NULL) {
            validate_optlist("--netif", args.netif_arg[i]);
            netif_add_from_spec(&netifs, args.netif_arg[i]);
        }
    }

    if (args.user_given && !args.user_map_given) {
        uid_t uid;
        gid_t gid;

        clone_flags |= CLONE_NEWUSER;

        if (user_get_uid_gid(args.user_arg, &uid, &gid)) {
            user_add_map(&users, 'u', uid, uid, 1);
            user_add_map(&users, 'g', gid, gid, 1);
        }
    }

    for (unsigned int i = 0; i < args.user_map_given; i++) {
        size_t count;
        uid_t id, host_id;

        char *start = args.user_map_arg[i], *end = NULL;

        validate_optlist("--user-map", args.user_map_arg[i]);

        clone_flags |= CLONE_NEWUSER;

        id = strtoul(start, &end, 10);
        if (*end != ':')
            fail_printf("Invalid value '%s' for --user-map",
                        args.user_map_arg[i]);

        start = end + 1;

        host_id = strtoul(start, &end, 10);
        if (*end != ':')
            fail_printf("Invalid value '%s' for --user-map",
                        args.user_map_arg[i]);

        start = end + 1;

        count = strtoul(start, &end, 10);
        if (*end != '\0')
            fail_printf("Invalid value '%s' for --user-map",
                        args.user_map_arg[i]);

        user_add_map(&users, 'u', id, host_id, count);
        user_add_map(&users, 'g', id, host_id, count);
    }

    for (unsigned int i = 0; i < args.cgroup_given; i++)
        cgroup_add(&cgroups, args.cgroup_arg[i]);

#if HAVE_LIBCAP_NG
    for (unsigned int i = 0; i < args.caps_given; i++)
        capability_add(&caps, args.caps_arg[i]);
#endif

    if (args.no_userns_flag)
        clone_flags &= ~(CLONE_NEWUSER);

    if (args.no_mountns_flag)
        clone_flags &= ~(CLONE_NEWNS);

    if (args.no_netns_flag)
        clone_flags &= ~(CLONE_NEWNET);

    if (args.no_ipcns_flag)
        clone_flags &= ~(CLONE_NEWIPC);

    if (args.no_utsns_flag)
        clone_flags &= ~(CLONE_NEWUTS);

    if (args.no_pidns_flag)
        clone_flags &= ~(CLONE_NEWPID);

    if (args.attach_given) {
        master_fd = recv_pty(args.attach_arg);
        fail_if(master_fd < 0, "Invalid PID '%u'", args.attach_arg);

        process_pty(master_fd);
        return 0;
    }

    open_master_pty(&master_fd, &master);

    if (args.detach_flag)
        do_daemonize();

    sync_init(sync);

    if (args.ephemeral_flag) {
        if (!mkdtemp(ephemeral_dir))
            sysf_printf("mkdtemp()");
    }

    pid = do_clone(&clone_flags);

    if (!pid) {
        closep(&master_fd);

        rc = prctl(PR_SET_PDEATHSIG, SIGKILL);
        sys_fail_if(rc < 0, "prctl(PR_SET_PDEATHSIG)");

        rc = setsid();
        sys_fail_if(rc < 0, "setsid()");

        sync_barrier_parent(sync, SYNC_START);

        sync_close(sync);

        open_slave_pty(master);

        setup_user(args.user_arg);

        if (args.hostname_given) {
            rc = sethostname(args.hostname_arg,
                             strlen(args.hostname_arg));
            sys_fail_if(rc < 0, "Error setting hostname");
        }

        setup_mount(mounts, args.chroot_arg, args.ephemeral_flag ?
                                               ephemeral_dir : NULL);

        if (args.chroot_given) {
            setup_nodes(args.chroot_arg);

            setup_ptmx(args.chroot_arg);

            setup_symlinks(args.chroot_arg);

            setup_console(args.chroot_arg, master);

            do_chroot(args.chroot_arg);
        }

        if (clone_flags & CLONE_NEWNET)
            config_netif();

        umask(0022);

#if HAVE_LIBCAP_NG
        setup_capabilities(caps);
#endif

        if (args.chdir_given) {
            rc = chdir(args.chdir_arg);
            sys_fail_if(rc < 0, "Error changing cwd");
        }

        if (args.chroot_given) {
            char *term = getenv("TERM");

            if (!args.keepenv_flag)
                clearenv();

            setenv("PATH", "/usr/sbin:/usr/bin:/sbin:/bin", 1);
            setenv("USER", args.user_arg, 1);
            setenv("LOGNAME", args.user_arg, 1);
            if (term)
                setenv("TERM", term, 1);
        }

        for (unsigned int i = 0; i < args.setenv_given; i++) {
            rc = putenv(strdup(args.setenv_arg[i]));
            sys_fail_if(rc != 0, "Error setting environment");
        }

        setenv("container", "pflask", 1);

        if (argc > optind)
            rc = execvpe(argv[optind], argv + optind, environ);
        else
            rc = execle("/bin/bash", "-bash", NULL, environ);

        sys_fail_if(rc < 0, "Error executing command");
    }

    sync_wait_child(sync, SYNC_START);

    if (args.chroot_given && (clone_flags & CLONE_NEWUSER))
        setup_console_owner(master, users);

    setup_cgroup(cgroups, pid);

    setup_netif(netifs, pid);

#ifdef HAVE_DBUS
    register_machine(pid, args.chroot_given ? args.chroot_arg : "");
#endif

    if (clone_flags & CLONE_NEWUSER)
        setup_user_map(users, pid);

    sync_wake_child(sync, SYNC_DONE);

    sync_close(sync);

    if (args.detach_flag)
        serve_pty(master_fd);
    else
        process_pty(master_fd);

    kill(pid, SIGKILL);

    rc = waitid(P_PID, pid, &status, WEXITED);
    sys_fail_if(rc < 0, "Error waiting for child");

    switch (status.si_code) {
    case CLD_EXITED:
        if (status.si_status != 0)
            err_printf("Child failed with code '%d'",
                       status.si_status);
        else
            ok_printf("Child exited");
        break;

    case CLD_KILLED:
        err_printf("Child was terminated by signal '%d'",
                   status.si_status);
        break;

    default:
        err_printf("Child failed");
        break;
    }

    sync_close(sync);

    clean_cgroup(cgroups);

    if (args.ephemeral_flag) {
        rc = rmdir(ephemeral_dir);
        sys_fail_if(rc != 0, "Error deleting ephemeral directory: %s",
                             ephemeral_dir);
    }

    cmdline_parser_free(&args);

    return status.si_status;
}