Ejemplo n.º 1
0
Archivo: init.c Proyecto: rudyLi/fio
/*
 * Adds a job to the list of things todo. Sanitizes the various options
 * to make sure we don't have conflicts, and initializes various
 * members of td.
 */
static int add_job(struct thread_data *td, const char *jobname, int job_add_num)
{
	const char *ddir_str[] = { NULL, "read", "write", "rw", NULL,
				   "randread", "randwrite", "randrw" };
	unsigned int i;
	char fname[PATH_MAX];
	int numjobs, file_alloced;

	/*
	 * the def_thread is just for options, it's not a real job
	 */
	if (td == &def_thread)
		return 0;

	/*
	 * if we are just dumping the output command line, don't add the job
	 */
	if (dump_cmdline) {
		put_job(td);
		return 0;
	}

	if (profile_td_init(td))
		goto err;

	if (ioengine_load(td))
		goto err;

	if (td->o.use_thread)
		nr_thread++;
	else
		nr_process++;

	if (td->o.odirect)
		td->io_ops->flags |= FIO_RAWIO;

	file_alloced = 0;
	if (!td->o.filename && !td->files_index && !td->o.read_iolog_file) {
		file_alloced = 1;

		if (td->o.nr_files == 1 && exists_and_not_file(jobname))
			add_file(td, jobname);
		else {
			for (i = 0; i < td->o.nr_files; i++) {
				sprintf(fname, "%s.%d.%d", jobname,
							td->thread_number, i);
				add_file(td, fname);
			}
		}
	}

	if (fixup_options(td))
		goto err;

	flow_init_job(td);

	/*
	 * IO engines only need this for option callbacks, and the address may
	 * change in subprocesses.
	 */
	if (td->eo)
		*(struct thread_data **)td->eo = NULL;

	if (td->io_ops->flags & FIO_DISKLESSIO) {
		struct fio_file *f;

		for_each_file(td, f, i)
			f->real_file_size = -1ULL;
	}

	td->mutex = fio_mutex_init(0);

	td->ts.clat_percentiles = td->o.clat_percentiles;
	if (td->o.overwrite_plist)
		memcpy(td->ts.percentile_list, td->o.percentile_list, sizeof(td->o.percentile_list));
	else
		memcpy(td->ts.percentile_list, def_percentile_list, sizeof(def_percentile_list));

	td->ts.clat_stat[0].min_val = td->ts.clat_stat[1].min_val = ULONG_MAX;
	td->ts.slat_stat[0].min_val = td->ts.slat_stat[1].min_val = ULONG_MAX;
	td->ts.lat_stat[0].min_val = td->ts.lat_stat[1].min_val = ULONG_MAX;
	td->ts.bw_stat[0].min_val = td->ts.bw_stat[1].min_val = ULONG_MAX;
	td->ddir_seq_nr = td->o.ddir_seq_nr;

	if ((td->o.stonewall || td->o.new_group) && prev_group_jobs) {
		prev_group_jobs = 0;
		groupid++;
	}

	td->groupid = groupid;
	prev_group_jobs++;

	if (init_random_state(td, td->rand_seeds, sizeof(td->rand_seeds))) {
		td_verror(td, errno, "init_random_state");
		goto err;
	}

	if (setup_rate(td))
		goto err;

	if (td->o.write_lat_log) {
		setup_log(&td->lat_log, td->o.log_avg_msec);
		setup_log(&td->slat_log, td->o.log_avg_msec);
		setup_log(&td->clat_log, td->o.log_avg_msec);
	}
	if (td->o.write_bw_log)
		setup_log(&td->bw_log, td->o.log_avg_msec);
	if (td->o.write_iops_log)
		setup_log(&td->iops_log, td->o.log_avg_msec);

	if (!td->o.name)
		td->o.name = strdup(jobname);

	if (!terse_output) {
		if (!job_add_num) {
			if (!strcmp(td->io_ops->name, "cpuio")) {
				log_info("%s: ioengine=cpu, cpuload=%u,"
					 " cpucycle=%u\n", td->o.name,
							td->o.cpuload,
							td->o.cpucycle);
			} else {
				char *c1, *c2, *c3, *c4;

				c1 = to_kmg(td->o.min_bs[DDIR_READ]);
				c2 = to_kmg(td->o.max_bs[DDIR_READ]);
				c3 = to_kmg(td->o.min_bs[DDIR_WRITE]);
				c4 = to_kmg(td->o.max_bs[DDIR_WRITE]);

				log_info("%s: (g=%d): rw=%s, bs=%s-%s/%s-%s,"
					 " ioengine=%s, iodepth=%u\n",
						td->o.name, td->groupid,
						ddir_str[td->o.td_ddir],
						c1, c2, c3, c4,
						td->io_ops->name,
						td->o.iodepth);

				free(c1);
				free(c2);
				free(c3);
				free(c4);
			}
		} else if (job_add_num == 1)
			log_info("...\n");
	}

	/*
	 * recurse add identical jobs, clear numjobs and stonewall options
	 * as they don't apply to sub-jobs
	 */
	numjobs = td->o.numjobs;
	while (--numjobs) {
		struct thread_data *td_new = get_new_job(0, td, 1);

		if (!td_new)
			goto err;

		td_new->o.numjobs = 1;
		td_new->o.stonewall = 0;
		td_new->o.new_group = 0;

		if (file_alloced) {
			td_new->o.filename = NULL;
			td_new->files_index = 0;
			td_new->files_size = 0;
			td_new->files = NULL;
		}

		job_add_num = numjobs - 1;

		if (add_job(td_new, jobname, job_add_num))
			goto err;
	}

	return 0;
err:
	put_job(td);
	return -1;
}
Ejemplo n.º 2
0
Archivo: init.c Proyecto: rudyLi/fio
/*
 * This is our [ini] type file parser.
 */
int parse_jobs_ini(char *file, int is_buf, int stonewall_flag)
{
	unsigned int global;
	struct thread_data *td;
	char *string, *name;
	FILE *f;
	char *p;
	int ret = 0, stonewall;
	int first_sect = 1;
	int skip_fgets = 0;
	int inside_skip = 0;
	char **opts;
	int i, alloc_opts, num_opts;

	if (is_buf)
		f = NULL;
	else {
		if (!strcmp(file, "-"))
			f = stdin;
		else
			f = fopen(file, "r");

		if (!f) {
			perror("fopen job file");
			return 1;
		}
	}

	string = malloc(4096);

	/*
	 * it's really 256 + small bit, 280 should suffice
	 */
	name = malloc(280);
	memset(name, 0, 280);

	alloc_opts = 8;
	opts = malloc(sizeof(char *) * alloc_opts);
	num_opts = 0;

	stonewall = stonewall_flag;
	do {
		/*
		 * if skip_fgets is set, we already have loaded a line we
		 * haven't handled.
		 */
		if (!skip_fgets) {
			if (is_buf)
				p = strsep(&file, "\n");
			else
				p = fgets(string, 4096, f);
			if (!p)
				break;
		}

		skip_fgets = 0;
		strip_blank_front(&p);
		strip_blank_end(p);

		if (is_empty_or_comment(p))
			continue;
		if (sscanf(p, "[%255[^\n]]", name) != 1) {
			if (inside_skip)
				continue;
			log_err("fio: option <%s> outside of [] job section\n",
									p);
			break;
		}

		name[strlen(name) - 1] = '\0';

		if (skip_this_section(name)) {
			inside_skip = 1;
			continue;
		} else
			inside_skip = 0;

		global = !strncmp(name, "global", 6);

		if (dump_cmdline) {
			if (first_sect)
				log_info("fio ");
			if (!global)
				log_info("--name=%s ", name);
			first_sect = 0;
		}

		td = get_new_job(global, &def_thread, 0);
		if (!td) {
			ret = 1;
			break;
		}

		/*
		 * Seperate multiple job files by a stonewall
		 */
		if (!global && stonewall) {
			td->o.stonewall = stonewall;
			stonewall = 0;
		}

		num_opts = 0;
		memset(opts, 0, alloc_opts * sizeof(char *));

		while (1) {
			if (is_buf)
				p = strsep(&file, "\n");
			else
				p = fgets(string, 4096, f);
			if (!p)
				break;

			if (is_empty_or_comment(p))
				continue;

			strip_blank_front(&p);

			/*
			 * new section, break out and make sure we don't
			 * fgets() a new line at the top.
			 */
			if (p[0] == '[') {
				skip_fgets = 1;
				break;
			}

			strip_blank_end(p);

			if (num_opts == alloc_opts) {
				alloc_opts <<= 1;
				opts = realloc(opts,
						alloc_opts * sizeof(char *));
			}

			opts[num_opts] = strdup(p);
			num_opts++;
		}

		ret = fio_options_parse(td, opts, num_opts);
		if (!ret) {
			if (dump_cmdline)
				for (i = 0; i < num_opts; i++)
					log_info("--%s ", opts[i]);

			ret = add_job(td, name, 0);
		} else {
			log_err("fio: job %s dropped\n", name);
			put_job(td);
		}

		for (i = 0; i < num_opts; i++)
			free(opts[i]);
		num_opts = 0;
	} while (!ret);

	if (dump_cmdline)
		log_info("\n");

	i = 0;
	while (i < nr_job_sections) {
		free(job_sections[i]);
		i++;
	}

	for (i = 0; i < num_opts; i++)
		free(opts[i]);

	free(string);
	free(name);
	free(opts);
	if (!is_buf && f != stdin)
		fclose(f);
	return ret;
}
Ejemplo n.º 3
0
/* fg and bg built-ins: called only if Flag(FMONITOR) set */
int
j_resume(const char *cp, int bg)
{
	Job	*j;
	Proc	*p;
	int	ecode;
	int	running;
	int	rv = 0;
	sigset_t omask;

	sigprocmask(SIG_BLOCK, &sm_sigchld, &omask);

	if ((j = j_lookup(cp, &ecode)) == (Job *) 0) {
		sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0);
		bi_errorf("%s: %s", cp, lookup_msgs[ecode]);
		return 1;
	}

	if (j->pgrp == 0) {
		sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0);
		bi_errorf("job not job-controlled");
		return 1;
	}

	if (bg)
		shprintf("[%d] ", j->job);

	running = 0;
	for (p = j->proc_list; p != (Proc *) 0; p = p->next) {
		if (p->state == PSTOPPED) {
			p->state = PRUNNING;
			p->status = 0;
			running = 1;
		}
		shprintf("%s%s", p->command, p->next ? "| " : null);
	}
	shprintf("%s", newline);
	shf_flush(shl_stdout);
	if (running)
		j->state = PRUNNING;

	put_job(j, PJ_PAST_STOPPED);
	if (bg)
		j_set_async(j);
	else {
# ifdef JOBS
		/* attach tty to job */
		if (j->state == PRUNNING) {
			if (ttypgrp_ok && (j->flags & JF_SAVEDTTY))
				tcsetattr(tty_fd, TCSADRAIN, &j->ttystate);
			/* See comment in j_waitj regarding saved_ttypgrp. */
			if (ttypgrp_ok &&
			    tcsetpgrp(tty_fd, (j->flags & JF_SAVEDTTYPGRP) ?
			    j->saved_ttypgrp : j->pgrp) < 0) {
				if (j->flags & JF_SAVEDTTY)
					tcsetattr(tty_fd, TCSADRAIN, &tty_state);
				sigprocmask(SIG_SETMASK, &omask,
				    (sigset_t *) 0);
				bi_errorf("1st tcsetpgrp(%d, %d) failed: %s",
				    tty_fd,
				    (int) ((j->flags & JF_SAVEDTTYPGRP) ?
				    j->saved_ttypgrp : j->pgrp),
				    strerror(errno));
				return 1;
			}
		}
# endif /* JOBS */
		j->flags |= JF_FG;
		j->flags &= ~JF_KNOWN;
		if (j == async_job)
			async_job = (Job *) 0;
	}

	if (j->state == PRUNNING && killpg(j->pgrp, SIGCONT) < 0) {
		int	err = errno;

		if (!bg) {
			j->flags &= ~JF_FG;
# ifdef JOBS
			if (ttypgrp_ok && (j->flags & JF_SAVEDTTY))
				tcsetattr(tty_fd, TCSADRAIN, &tty_state);
			if (ttypgrp_ok && tcsetpgrp(tty_fd, our_pgrp) < 0) {
				warningf(true,
				    "fg: 2nd tcsetpgrp(%d, %d) failed: %s",
				    tty_fd, (int) our_pgrp,
				    strerror(errno));
			}
# endif /* JOBS */
		}
		sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0);
		bi_errorf("cannot continue job %s: %s",
		    cp, strerror(err));
		return 1;
	}
	if (!bg) {
# ifdef JOBS
		if (ttypgrp_ok) {
			j->flags &= ~(JF_SAVEDTTY | JF_SAVEDTTYPGRP);
		}
# endif /* JOBS */
		rv = j_waitj(j, JW_NONE, "jw:resume");
	}
	sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0);
	return rv;
}
Ejemplo n.º 4
0
/* execute tree in child subprocess */
int
exchild(struct op *t, int flags, volatile int *xerrok,
    int close_fd)	/* used if XPCLOSE or XCCLOSE */
{
	static Proc	*last_proc;	/* for pipelines */

	int		i;
	sigset_t	omask;
	Proc		*p;
	Job		*j;
	int		rv = 0;
	int		forksleep;
	int		ischild;

	if (flags & XEXEC)
		/* Clear XFORK|XPCLOSE|XCCLOSE|XCOPROC|XPIPEO|XPIPEI|XXCOM|XBGND
		 * (also done in another execute() below)
		 */
		return execute(t, flags & (XEXEC | XERROK), xerrok);

	/* no SIGCHLD's while messing with job and process lists */
	sigprocmask(SIG_BLOCK, &sm_sigchld, &omask);

	p = new_proc();
	p->next = (Proc *) 0;
	p->state = PRUNNING;
	p->status = 0;
	p->pid = 0;

	/* link process into jobs list */
	if (flags&XPIPEI) {	/* continuing with a pipe */
		if (!last_job)
			internal_errorf(1,
			    "exchild: XPIPEI and no last_job - pid %d",
			    (int) procpid);
		j = last_job;
		last_proc->next = p;
		last_proc = p;
	} else {
		j = new_job(); /* fills in j->job */
		/* we don't consider XXCOM's foreground since they don't get
		 * tty process group and we don't save or restore tty modes.
		 */
		j->flags = (flags & XXCOM) ? JF_XXCOM :
		    ((flags & XBGND) ? 0 : (JF_FG|JF_USETTYMODE));
		timerclear(&j->usrtime);
		timerclear(&j->systime);
		j->state = PRUNNING;
		j->pgrp = 0;
		j->ppid = procpid;
		j->age = ++njobs;
		j->proc_list = p;
		j->coproc_id = 0;
		last_job = j;
		last_proc = p;
		put_job(j, PJ_PAST_STOPPED);
	}

	snptreef(p->command, sizeof(p->command), "%T", t);

	/* create child process */
	forksleep = 1;
	while ((i = fork()) < 0 && errno == EAGAIN && forksleep < 32) {
		if (intrsig)	 /* allow user to ^C out... */
			break;
		sleep(forksleep);
		forksleep <<= 1;
	}
	if (i < 0) {
		kill_job(j, SIGKILL);
		remove_job(j, "fork failed");
		sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0);
		errorf("cannot fork - try again");
	}
	ischild = i == 0;
	if (ischild)
		p->pid = procpid = getpid();
	else
		p->pid = i;

#ifdef JOBS
	/* job control set up */
	if (Flag(FMONITOR) && !(flags&XXCOM)) {
		int	dotty = 0;
		if (j->pgrp == 0) {	/* First process */
			j->pgrp = p->pid;
			dotty = 1;
		}

		/* set pgrp in both parent and child to deal with race
		 * condition
		 */
		setpgid(p->pid, j->pgrp);
		/* YYY: should this be
		   if (ttypgrp_ok && ischild && !(flags&XBGND))
			tcsetpgrp(tty_fd, j->pgrp);
		   instead? (see also YYY below)
		 */
		if (ttypgrp_ok && dotty && !(flags & XBGND))
			tcsetpgrp(tty_fd, j->pgrp);
	}
#endif /* JOBS */

	/* used to close pipe input fd */
	if (close_fd >= 0 && (((flags & XPCLOSE) && !ischild) ||
	    ((flags & XCCLOSE) && ischild)))
		close(close_fd);
	if (ischild) {		/* child */
		/* Do this before restoring signal */
		if (flags & XCOPROC)
			coproc_cleanup(false);
		sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0);
		cleanup_parents_env();
#ifdef JOBS
		/* If FMONITOR or FTALKING is set, these signals are ignored,
		 * if neither FMONITOR nor FTALKING are set, the signals have
		 * their inherited values.
		 */
		if (Flag(FMONITOR) && !(flags & XXCOM)) {
			for (i = NELEM(tt_sigs); --i >= 0; )
				setsig(&sigtraps[tt_sigs[i]], SIG_DFL,
				    SS_RESTORE_DFL|SS_FORCE);
		}
#endif /* JOBS */
		if (Flag(FBGNICE) && (flags & XBGND))
			nice(4);
		if ((flags & XBGND) && !Flag(FMONITOR)) {
			setsig(&sigtraps[SIGINT], SIG_IGN,
			    SS_RESTORE_IGN|SS_FORCE);
			setsig(&sigtraps[SIGQUIT], SIG_IGN,
			    SS_RESTORE_IGN|SS_FORCE);
			if (!(flags & (XPIPEI | XCOPROC))) {
				int fd = open("/dev/null", 0);
				if (fd != 0) {
					(void) ksh_dup2(fd, 0, true);
					close(fd);
				}
			}
		}
		remove_job(j, "child");	/* in case of `jobs` command */
		nzombie = 0;
#ifdef JOBS
		ttypgrp_ok = 0;
		Flag(FMONITOR) = 0;
#endif /* JOBS */
		Flag(FTALKING) = 0;
		tty_close();
		cleartraps();
		execute(t, (flags & XERROK) | XEXEC, NULL); /* no return */
		internal_errorf(0, "exchild: execute() returned");
		unwind(LLEAVE);
		/* NOTREACHED */
	}

	/* shell (parent) stuff */
	/* Ensure next child gets a (slightly) different $RANDOM sequence */
	change_random();
	if (!(flags & XPIPEO)) {	/* last process in a job */
#ifdef JOBS
		/* YYY: Is this needed? (see also YYY above)
		   if (Flag(FMONITOR) && !(flags&(XXCOM|XBGND)))
			tcsetpgrp(tty_fd, j->pgrp);
		*/
#endif /* JOBS */
		j_startjob(j);
		if (flags & XCOPROC) {
			j->coproc_id = coproc.id;
			coproc.njobs++; /* n jobs using co-process output */
			coproc.job = (void *) j; /* j using co-process input */
		}
		if (flags & XBGND) {
			j_set_async(j);
			if (Flag(FTALKING)) {
				shf_fprintf(shl_out, "[%d]", j->job);
				for (p = j->proc_list; p; p = p->next)
					shf_fprintf(shl_out, " %d", p->pid);
				shf_putchar('\n', shl_out);
				shf_flush(shl_out);
			}
		} else
			rv = j_waitj(j, JW_NONE, "jw:last proc");
	}

	sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0);

	return rv;
}
Ejemplo n.º 5
0
/*
 * Called only when a process in j has exited/stopped (ie, called only
 * from j_sigchld()).  If no processes are running, the job status
 * and state are updated, asynchronous job notification is done and,
 * if unneeded, the job is removed.
 *
 * If jobs are compiled in then this routine expects sigchld to be blocked.
 */
static void
check_job(Job *j)
{
	int	jstate;
	Proc	*p;

	/* XXX debugging (nasty - interrupt routine using shl_out) */
	if (!(j->flags & JF_STARTED)) {
		internal_errorf(0, "check_job: job started (flags 0x%x)",
		    j->flags);
		return;
	}

	jstate = PRUNNING;
	for (p=j->proc_list; p != (Proc *) 0; p = p->next) {
		if (p->state == PRUNNING)
			return;	/* some processes still running */
		if (p->state > jstate)
			jstate = p->state;
	}
	j->state = jstate;

	switch (j->last_proc->state) {
	case PEXITED:
		j->status = WEXITSTATUS(j->last_proc->status);
		break;
	case PSIGNALLED:
		j->status = 128 + WTERMSIG(j->last_proc->status);
		break;
	default:
		j->status = 0;
		break;
	}

	/* Note when co-process dies: can't be done in j_wait() nor
	 * remove_job() since neither may be called for non-interactive
	 * shells.
	 */
	if (j->state == PEXITED || j->state == PSIGNALLED) {
		/* No need to keep co-process input any more
		 * (at least, this is what ksh93d thinks)
		 */
		if (coproc.job == j) {
			coproc.job = (void *) 0;
			/* XXX would be nice to get the closes out of here
			 * so they aren't done in the signal handler.
			 * Would mean a check in coproc_getfd() to
			 * do "if job == 0 && write >= 0, close write".
			 */
			coproc_write_close(coproc.write);
		}
		/* Do we need to keep the output? */
		if (j->coproc_id && j->coproc_id == coproc.id &&
		    --coproc.njobs == 0)
			coproc_readw_close(coproc.read);
	}

	j->flags |= JF_CHANGED;
#ifdef JOBS
	if (Flag(FMONITOR) && !(j->flags & JF_XXCOM)) {
		/* Only put stopped jobs at the front to avoid confusing
		 * the user (don't want finished jobs effecting %+ or %-)
		 */
		if (j->state == PSTOPPED)
			put_job(j, PJ_ON_FRONT);
		if (Flag(FNOTIFY) &&
		    (j->flags & (JF_WAITING|JF_W_ASYNCNOTIFY)) != JF_WAITING) {
			/* Look for the real file descriptor 2 */
			{
				struct env *ep;
				int fd = 2;

				for (ep = e; ep; ep = ep->oenv)
					if (ep->savefd && ep->savefd[2])
						fd = ep->savefd[2];
				shf_reopen(fd, SHF_WR, shl_j);
			}
			/* Can't call j_notify() as it removes jobs.  The job
			 * must stay in the job list as j_waitj() may be
			 * running with this job.
			 */
			j_print(j, JP_MEDIUM, shl_j);
			shf_flush(shl_j);
			if (!(j->flags & JF_WAITING) && j->state != PSTOPPED)
				remove_job(j, "notify");
		}
	}
#endif /* JOBS */
	if (!Flag(FMONITOR) && !(j->flags & (JF_WAITING|JF_FG)) &&
	    j->state != PSTOPPED) {
		if (j == async_job || (j->flags & JF_KNOWN)) {
			j->flags |= JF_ZOMBIE;
			j->job = -1;
			nzombie++;
		} else
			remove_job(j, "checkjob");
	}
}
Ejemplo n.º 6
0
Archivo: jobs.c Proyecto: adtools/abcsh
int
exchild(struct op *t, int flags,
        int close_fd)       /* used if XPCLOSE or XCCLOSE */
{
        static Proc     *last_proc;     /* for pipelines */

        int             i;
        sigset_t        omask;
        Proc            *p;
        Job             *j;
        int             rv = 0;
        int             forksleep;
        int             ischild;

        if (flags & XEXEC)
                /* Clear XFORK|XPCLOSE|XCCLOSE|XCOPROC|XPIPEO|XPIPEI|XXCOM|XBGND
                 * (also done in another execute() below)
                 */
                return execute(t, flags & (XEXEC | XERROK));

        p = new_proc();
        p->next = (Proc *) 0;
        p->state = PRUNNING;
        p->status = 0;
        p->pid = 0;

        /* link process into jobs list */
        if (flags&XPIPEI) {     /* continuing with a pipe */
                if (!last_job)
                        internal_errorf(1,
                                "exchild: XPIPEI and no last_job - pid %d",
                                (int) procpid);
                j = last_job;
                last_proc->next = p;
                last_proc = p;
        } else {
                j = new_job(); /* fills in j->job */
                /* we don't consider XXCOM's foreground since they don't get
                 * tty process group and we don't save or restore tty modes.
                 */
                j->flags = (flags & XXCOM) ? JF_XXCOM :
                        ((flags & XBGND) ? 0 : (JF_FG|JF_USETTYMODE));
                j->usrtime = j->systime = 0;
                j->state = PRUNNING;
                j->pgrp = 0;
                j->ppid = procpid;
                j->age = ++njobs;
                j->proc_list = p;
                j->coproc_id = 0;
                last_job = j;
                last_proc = p;
                put_job(j, PJ_PAST_STOPPED);
        }

        snptreef(p->command, sizeof(p->command), "%T", t);

        /* create child process */
        forksleep = 1;
        while ((i = fork()) < 0 && errno == EAGAIN && forksleep < 32) {
                if (intrsig)     /* allow user to ^C out... */
                        break;
                sleep(forksleep);
                forksleep <<= 1;
        }
        if (i < 0) {
                kill_job(j, SIGKILL);
                remove_job(j, "fork failed");
                sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0);
                errorf("cannot fork - try again");
        }
        ischild = i == 0;
        if (ischild)
                p->pid = procpid = getpid();
        else
                p->pid = i;

        /* used to close pipe input fd */
        if (close_fd >= 0 && (((flags & XPCLOSE) && !ischild) ||
                ((flags & XCCLOSE) && ischild)))
                        close(close_fd);
        if (ischild) {          /* child */
                /* Do this before restoring signal */
                if (flags & XCOPROC)
                        coproc_cleanup(false);
                sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0);
		cleanup_parents_env();
                if ((flags & XBGND)) {
                        setsig(&sigtraps[SIGINT], SIG_IGN,
                                SS_RESTORE_IGN|SS_FORCE);
                        setsig(&sigtraps[SIGQUIT], SIG_IGN,
                                SS_RESTORE_IGN|SS_FORCE);
                        if (!(flags & (XPIPEI | XCOPROC))) {
                                int fd = open("/dev/null", 0);
                                if (fd != 0) {
				        (void) ksh_dup2(fd, 0, true);
                                        close(fd);
                                }

                        }
                }
                remove_job(j, "child"); /* in case of `jobs` command */
                nzombie = 0;
                Flag(FTALKING) = 0;
                tty_close();
                cleartraps();
                execute(t, (flags & XERROK) | XEXEC); /* no return */
                internal_errorf(0, "exchild: execute() returned");
                unwind(LLEAVE);
                /* NOTREACHED */
        }

        /* shell (parent) stuff */
        /* Ensure next child gets a (slightly) different $RANDOM sequence */
        change_random();
        if (!(flags & XPIPEO)) {        /* last process in a job */
                j_startjob(j);
                if (flags & XCOPROC) {
                        j->coproc_id = coproc.id;
                        coproc.njobs++; /* n jobs using co-process output */
                        coproc.job = (void *) j; /* j using co-process input */
                }
                if (flags & XBGND) {
                        j_set_async(j);
                        if (Flag(FTALKING)) {
                                shf_fprintf(shl_out, "[%d]", j->job);
                                for (p = j->proc_list; p; p = p->next)
                                        shf_fprintf(shl_out, " %d", p->pid);
                                shf_putchar('\n', shl_out);
                                shf_flush(shl_out);
                        }
                } else
                        rv = j_waitj(j, JW_NONE, "jw:last proc");
        }

        sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0);

        return rv;
}
Ejemplo n.º 7
0
static gsize request_gstreamill_admin (HTTPMgmt *httpmgmt, RequestData *request_data, gchar **buf)
{
        gchar *path, *http_header, *p;
        gsize buf_size;
        GError *err = NULL;

        path = NULL;
        if (g_strcmp0 (request_data->uri, "/admin/") == 0) {
                path = g_strdup_printf ("%s/gstreamill/admin/index.html", DATADIR);

        } else if (g_str_has_prefix (request_data->uri, "/admin/start")) {
                p = start_job (httpmgmt, request_data);
                *buf = g_strdup_printf (http_200, PACKAGE_NAME, PACKAGE_VERSION, "application/json", strlen (p), NO_CACHE, p);
                g_free (p);

        } else if (g_str_has_prefix (request_data->uri, "/admin/stop")) {
                p = stop_job (httpmgmt, request_data);
                *buf = g_strdup_printf (http_200, PACKAGE_NAME, PACKAGE_VERSION, "application/json", strlen (p), NO_CACHE, p);
                g_free (p);

        } else if (g_strcmp0 (request_data->uri, "/admin/networkinterfaces") == 0) {
                p = network_interfaces ();
                *buf = g_strdup_printf (http_200, PACKAGE_NAME, PACKAGE_VERSION, "application/json", strlen (p), NO_CACHE, p);
                g_free (p);

        } else if (g_strcmp0 (request_data->uri, "/admin/setnetworkinterfaces") == 0) {
                p = set_network_interfaces (request_data);
                *buf = g_strdup_printf (http_200, PACKAGE_NAME, PACKAGE_VERSION, "application/json", strlen (p), NO_CACHE, p);
                g_free (p);

        } else if (g_strcmp0 (request_data->uri, "/admin/networkdevices") == 0) {
                p = network_devices ();
                *buf = g_strdup_printf (http_200, PACKAGE_NAME, PACKAGE_VERSION, "application/json", strlen (p), NO_CACHE, p);
                g_free (p);

        } else if (g_strcmp0 (request_data->uri, "/admin/audiodevices") == 0) {
                p = list_files ("/dev/snd/pcmC*c", NULL);
                *buf = g_strdup_printf (http_200, PACKAGE_NAME, PACKAGE_VERSION, "application/json", strlen (p), NO_CACHE, p);
                g_free (p);

        } else if (g_strcmp0 (request_data->uri, "/admin/videodevices") == 0) {
                p = list_files ("/dev/video*", NULL);
                *buf = g_strdup_printf (http_200, PACKAGE_NAME, PACKAGE_VERSION, "application/json", strlen (p), NO_CACHE, p);
                g_free (p);

        } else if (g_strcmp0 (request_data->uri, "/admin/getconf") == 0) {
                p = get_conf ();
                *buf = g_strdup_printf (http_200, PACKAGE_NAME, PACKAGE_VERSION, "application/json", strlen (p), NO_CACHE, p);
                g_free (p);

        } else if ((request_data->method == HTTP_POST) && (g_strcmp0 (request_data->uri, "/admin/putconf") == 0)) {
                p = put_conf (request_data);
                *buf = g_strdup_printf (http_200, PACKAGE_NAME, PACKAGE_VERSION, "application/json", strlen (p), NO_CACHE, p);
                g_free (p);

        } else if (g_strcmp0 (request_data->uri, "/admin/listlivejob") == 0) {
                p = list_files ("/etc/gstreamill.d/*.job", "/etc/gstreamill.d/%[^.].job");
                *buf = g_strdup_printf (http_200, PACKAGE_NAME, PACKAGE_VERSION, "application/json", strlen (p), NO_CACHE, p);
                g_free (p);

        } else if (g_strcmp0 (request_data->uri, "/admin/listrunningjob") == 0) {
                p = gstreamill_list_running_job (httpmgmt->gstreamill);
                *buf = g_strdup_printf (http_200, PACKAGE_NAME, PACKAGE_VERSION, "application/json", strlen (p), NO_CACHE, p);
                g_free (p);

        } else if (g_str_has_prefix (request_data->uri, "/admin/getjob/")) {
                p = get_job (request_data->uri);
                if (p != NULL) {
                        *buf = g_strdup_printf (http_200, PACKAGE_NAME, PACKAGE_VERSION, "application/json", strlen (p), NO_CACHE, p);
                        g_free (p);

                } else {
                        *buf = g_strdup_printf (http_404, PACKAGE_NAME, PACKAGE_VERSION);
                }

        } else if (g_str_has_prefix (request_data->uri, "/admin/rmjob/")) {
                p = rm_job (request_data->uri);
                *buf = g_strdup_printf (http_200, PACKAGE_NAME, PACKAGE_VERSION, "application/json", strlen (p), NO_CACHE, p);
                g_free (p);

        } else if ((request_data->method == HTTP_POST) && (g_str_has_prefix (request_data->uri, "/admin/putjob/"))) {
                p = put_job (request_data);
                *buf = g_strdup_printf (http_200, PACKAGE_NAME, PACKAGE_VERSION, "application/json", strlen (p), NO_CACHE, p);
                g_free (p);

        } else if (g_str_has_prefix (request_data->uri, "/admin/jobmanage.html")) {
                if (g_str_has_prefix (request_data->parameters, "name=")) {
                        path = g_strdup_printf ("%s/gstreamill/admin/jobmanage.html", DATADIR);

                } else {
                        *buf = g_strdup_printf (http_400, PACKAGE_NAME, PACKAGE_VERSION);
                }

        } else {
                /* static content, prepare file path */
                path = g_strdup_printf ("%s/gstreamill%s", DATADIR, request_data->uri);
        }

        if (path == NULL) {
                /* not static content */
                buf_size = strlen (*buf);

        } else if (!g_file_get_contents (path, buf, &buf_size, &err)) {
                GST_ERROR ("read file %s failure: %s", p, err->message);
                *buf = g_strdup_printf (http_404, PACKAGE_NAME, PACKAGE_VERSION);
                buf_size = strlen (*buf);
                g_error_free (err);

        } else {
                /* jobmanage.html? process name parameter */
                if (g_str_has_suffix (path, "jobmanage.html")) {
                        gchar name[32], *temp_buf;

                        sscanf (request_data->parameters, "name=%s", name);
                        temp_buf = g_strdup_printf (*buf, name);
                        g_free (*buf);
                        *buf = temp_buf;
                }
                /* html file? add top and bottom */
                if (g_str_has_suffix (path, ".html")) {
                        gchar *body;

                        body = *buf;
                        *buf = add_header_footer (body);
                        g_free (body);
                        buf_size = strlen (*buf);
                }
                http_header = gen_http_header (path, buf_size);
                p = g_malloc (buf_size + strlen (http_header));
                memcpy (p, http_header, strlen (http_header));
                memcpy (p + strlen (http_header), *buf, buf_size);
                g_free (*buf);
                *buf = p;
                buf_size += strlen (http_header);
                g_free (http_header);
        }

        if (path != NULL) {
                g_free (path);
        }

        return buf_size;
}