/* * 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; }
/* * 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; }
/* 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; }
/* 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; }
/* * 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"); } }
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; }
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; }