示例#1
0
PUBLIC int
mime_run_command(const char *cmd, FILE *fo)
{
	sigset_t nset;
	FILE *nfo;
	pid_t pid;
	int p[2];
	int flags;

	if (cmd == NULL)
		return 0;

	flags = get_cmd_flags(cmd, &cmd);
	if (fo == NULL)		/* no output file, just return the flags! */
		return flags;

	if ((flags & CMD_FLAG_SHELLCMD) != 0) {	/* run command under the shell */
		char *cp;
		char *shellcmd;
		if ((shellcmd = value(ENAME_SHELL)) == NULL)
			shellcmd = __UNCONST(_PATH_CSHELL);
		(void)sasprintf(&cp, "%s -c '%s'", shellcmd, cmd);
		cmd = cp;
	}
	if (prepare_pipe(&nset, p) != 0) {
		warn("mime_run_command: prepare_pipe");
		return flags;	/* XXX - this or -1? */
	}
	flush_files(fo, 0); /* flush fo, all registered files, and stdout */

	switch (pid = start_command(cmd, &nset, p[READ], fileno(fo), NULL)) {
	case -1:	/* error */
		/* start_command already did a warn(). */
		warnx("mime_run_command: %s", cmd); /* tell a bit more */
		(void)close(p[READ]);
		(void)close(p[WRITE]);
		return flags;			/* XXX - this or -1? */

	case 0:		/* child */
		assert(/*CONSTCOND*/ 0);	/* a real coding error! */
		/* NOTREACHED */

	default:	/* parent */
		(void)close(p[READ]);

		nfo = fdopen(p[WRITE], "w");
		if (nfo == NULL) {
			warn("mime_run_command: fdopen");
			(void)close(p[WRITE]);
			warn("fdopen");
			return flags;
		}
		register_file(nfo, 1, pid);
		return flags;
	}
}
示例#2
0
PUBLIC void
mime_run_function(void (*fn)(FILE *, FILE *, void *), FILE *fo, void *cookie)
{
	sigset_t nset;
	FILE *nfo;
	pid_t pid;
	int p[2];

	if (prepare_pipe(&nset, p) != 0) {
		warn("mime_run_function: pipe");
		return;
	}
	flush_files(fo, 0); /* flush fo, all registered files, and stdout */

	switch (pid = fork()) {
	case -1:	/* error */
		warn("mime_run_function: fork");
		(void)close(p[READ]);
		(void)close(p[WRITE]);
		return;

	case 0:		/* child */
		(void)close(p[WRITE]);
		prepare_child(&nset, p[READ], fileno(fo));
		fn(stdin, stdout, cookie);
		(void)fflush(stdout);
		_exit(0);
		/* NOTREACHED */

	default:	/* parent */
		(void)close(p[READ]);
		nfo = fdopen(p[WRITE], "w");
		if (nfo == NULL) {
			warn("run_function: fdopen");
			(void)close(p[WRITE]);
			return;
		}
		register_file(nfo, 1, pid);
		return;
	}
}
示例#3
0
/**
 * \param[in] argc argument count
 * \param[in] argv argument array
 * \return 0 on success, 1 on error
 *
 * \attention In daemon mode, it finishes immediately.
 */
int main(int argc, char** argv)
{
    openlog(INCRON_DAEMON_NAME, INCRON_LOG_OPTS, INCRON_LOG_FACIL);

    syslog(LOG_NOTICE, "starting service (version %s, built on %s %s)", INCRON_VERSION, __DATE__, __TIME__);

    try {
        Inotify in;
        in.SetNonBlock(true);

        EventDispatcher ed(&in);

        try {
            load_tables(&in, &ed);
        } catch (InotifyException e) {
            int err = e.GetErrorNumber();
            syslog(LOG_CRIT, "%s: (%i) %s", e.GetMessage().c_str(), err, strerror(err));
            syslog(LOG_NOTICE, "stopping service");
            closelog();
            return 1;
        }

        if (DAEMON)
            daemon(0, 0);

        prepare_pipe();

        signal(SIGTERM, on_signal);
        signal(SIGINT, on_signal);
        signal(SIGCHLD, on_signal);

        uint32_t wm = IN_CLOSE_WRITE | IN_DELETE | IN_MOVE | IN_DELETE_SELF | IN_UNMOUNT;
        InotifyWatch watch(INCRON_TABLE_BASE, wm);
        in.Add(watch);

        syslog(LOG_NOTICE, "ready to process filesystem events");

        InotifyEvent e;

        struct pollfd pfd[2];
        pfd[0].fd = in.GetDescriptor();
        pfd[0].events = (short) POLLIN;
        pfd[0].revents = (short) 0;
        pfd[1].fd = g_cldPipe[0];
        pfd[1].events = (short) POLLIN;
        pfd[1].revents = (short) 0;

        while (!g_fFinish) {

            int res = poll(pfd, 2, -1);

            if (res > 0) {
                if (pfd[1].revents & ((short) POLLIN)) {
                    char c;
                    while (read(pfd[1].fd, &c, 1) > 0) {}
                    UserTable::FinishDone();
                }
                else {
                    in.WaitForEvents(true);
                }
            }
            else if (res < 0) {
                if (errno != EINTR)
                    throw InotifyException("polling failed", errno, NULL);
            }

            while (in.GetEvent(e)) {

                if (e.GetWatch() == &watch) {
                    if (e.IsType(IN_DELETE_SELF) || e.IsType(IN_UNMOUNT)) {
                        syslog(LOG_CRIT, "base directory destroyed, exitting");
                        g_fFinish = true;
                    }
                    else if (!e.GetName().empty()) {
                        SUT_MAP::iterator it = g_ut.find(e.GetName());
                        if (it != g_ut.end()) {
                            UserTable* pUt = (*it).second;
                            if (e.IsType(IN_CLOSE_WRITE) || e.IsType(IN_MOVED_TO)) {
                                syslog(LOG_INFO, "table for user %s changed, reloading", e.GetName().c_str());
                                pUt->Dispose();
                                pUt->Load();
                            }
                            else if (e.IsType(IN_MOVED_FROM) || e.IsType(IN_DELETE)) {
                                syslog(LOG_INFO, "table for user %s destroyed, removing", e.GetName().c_str());
                                delete pUt;
                                g_ut.erase(it);
                            }
                        }
                        else if (e.IsType(IN_CLOSE_WRITE) || e.IsType(IN_MOVED_TO)) {
                            if (check_user(e.GetName().c_str())) {
                                syslog(LOG_INFO, "table for user %s created, loading", e.GetName().c_str());
                                UserTable* pUt = new UserTable(&in, &ed, e.GetName());
                                g_ut.insert(SUT_MAP::value_type(e.GetName(), pUt));
                                pUt->Load();
                            }
                        }
                    }
                }
                else {
                    ed.DispatchEvent(e);
                }

            }
        }

        if (g_cldPipe[0] != -1)
            close(g_cldPipe[0]);
        if (g_cldPipe[1] != -1)
            close(g_cldPipe[1]);
    } catch (InotifyException e) {
        int err = e.GetErrorNumber();
        syslog(LOG_CRIT, "*** unhandled exception occurred ***");
        syslog(LOG_CRIT, "  %s", e.GetMessage().c_str());
        syslog(LOG_CRIT, "  error: (%i) %s", err, strerror(err));
    }

    syslog(LOG_NOTICE, "stopping service");

    closelog();

    return 0;
}
示例#4
0
文件: job.c 项目: UNGLinux/Obase
/*-
 *-----------------------------------------------------------------------
 * JobExec --
 *	Execute the shell for the given job. Called from JobStart
 *
 * Side Effects:
 *	A shell is executed, outputs is altered and the Job structure added
 *	to the job table.
 *-----------------------------------------------------------------------
 */
static void
JobExec(Job *job)
{
	pid_t cpid; 	/* ID of new child */
	struct job_pid *p;
	int fds[4];
	int *fdout = fds;
	int *fderr = fds+2;
	int i;

	banner(job, stdout);

	setup_engine(1);

	/* Create the pipe by which we'll get the shell's output.
	 */
	if (pipe(fdout) == -1)
		Punt("Cannot create pipe: %s", strerror(errno));

	if (pipe(fderr) == -1)
		Punt("Cannot create pipe: %s", strerror(errno));

	block_signals();
	if ((cpid = fork()) == -1) {
		Punt("Cannot fork");
		unblock_signals();
	} else if (cpid == 0) {
		supervise_jobs = false;
		/* standard pipe code to route stdout and stderr */
		close(fdout[0]);
		if (dup2(fdout[1], 1) == -1)
			Punt("Cannot dup2(outPipe): %s", strerror(errno));
		if (fdout[1] != 1)
			close(fdout[1]);
		close(fderr[0]);
		if (dup2(fderr[1], 2) == -1)
			Punt("Cannot dup2(errPipe): %s", strerror(errno));
		if (fderr[1] != 2)
			close(fderr[1]);

		/*
		 * We want to switch the child into a different process family
		 * so we can kill it and all its descendants in one fell swoop,
		 * by killing its process family, but not commit suicide.
		 */
		(void)setpgid(0, getpid());

		if (random_delay)
			if (!(nJobs == 1 && no_jobs_left()))
				usleep(random() % random_delay);

		setup_all_signals(SigHandler, SIG_DFL);
		unblock_signals();
		/* this exits directly */
		run_gnode_parallel(job->node);
		/*NOTREACHED*/
	} else {
		supervise_jobs = true;
		job->pid = cpid;

		/* we set the current position in the buffers to the beginning
		 * and mark another stream to watch in the outputs mask
		 */
		for (i = 0; i < 2; i++)
			prepare_pipe(&job->in[i], fds+2*i);
	}
	/*
	 * Now the job is actually running, add it to the table.
	 */
	nJobs++;
	Lst_AtEnd(&runningJobs, job);
	if (job->flags & JOB_IS_EXPENSIVE)
		expensive_job = true;
	p = emalloc(sizeof(struct job_pid));
	p->pid = cpid;
	Lst_AtEnd(&job_pids, p);
	job->p = Lst_Last(&job_pids);

	unblock_signals();
	if (DEBUG(JOB)) {
		LstNode ln;

		(void)fprintf(stdout, "Running %ld (%s)\n", (long)cpid,
		    job->node->name);
		for (ln = Lst_First(&job->node->commands); ln != NULL ;
		    ln = Lst_Adv(ln))
		    	fprintf(stdout, "\t%s\n", (char *)Lst_Datum(ln));
		(void)fflush(stdout);
	}

}
示例#5
0
/**
 * \param[in] argc argument count
 * \param[in] argv argument array
 * \return 0 on success, 1 on error
 * 
 * \attention In daemon mode, it finishes immediately.
 */
int main(int argc, char** argv)
{
  AppArgs::Init();

  if (!(  AppArgs::AddOption("about",       '?', AAT_NO_VALUE, false)
      &&  AppArgs::AddOption("help",        'h', AAT_NO_VALUE, false)
      &&  AppArgs::AddOption("foreground",  'n', AAT_NO_VALUE, false)
      &&  AppArgs::AddOption("kill",        'k', AAT_NO_VALUE, false)
      &&  AppArgs::AddOption("config",      'f', AAT_MANDATORY_VALUE, false)
      &&  AppArgs::AddOption("version",     'V', AAT_NO_VALUE, false)))
  {
    fprintf(stderr, "error while initializing application");
    return 1;
  }
  
  AppArgs::Parse(argc, argv);
  
  if (AppArgs::ExistsOption("help")) {
    fprintf(stderr, "%s\n", INCROND_HELP);
    return 0;
  }
  
  if (AppArgs::ExistsOption("about")) {
    fprintf(stderr, "%s\n", INCROND_DESCRIPTION);
    return 0;
  }
  
  if (AppArgs::ExistsOption("version")) {
    fprintf(stderr, "%s\n", INCROND_VERSION);
    return 0;
  }
  
  IncronCfg::Init();
  
  std::string cfg;
  if (!AppArgs::GetOption("config", cfg))
    cfg = INCRON_CONFIG;
  IncronCfg::Load(cfg);
  
  std::string lckdir;
  IncronCfg::GetValue("lockfile_dir", lckdir);
  std::string lckfile;
  IncronCfg::GetValue("lockfile_name", lckfile);
  AppInstance app(lckfile, lckdir);
  
  if (AppArgs::ExistsOption("kill")) {
    fprintf(stderr, "attempting to terminate a running instance of incrond...\n");
    if (app.Terminate()) {
      fprintf(stderr, "the instance notified, going down\n");
      return 0;
    }
    else { 
      fprintf(stderr, "error - incrond probably not running\n");
      return 1;
    }
  }
  
  if (AppArgs::ExistsOption("foreground"))
    g_daemon = false;
  
  
  openlog(INCROND_NAME, INCRON_LOG_OPTS, INCRON_LOG_FACIL);
  
  syslog(LOG_NOTICE, "starting service (version %s, built on %s %s)", INCRON_VERSION, __DATE__, __TIME__);
  
  AppArgs::Destroy();
  
  int ret = 0;
  
  std::string sysBase;
  std::string userBase;
  
  if (!IncronCfg::GetValue("system_table_dir", sysBase))
    throw InotifyException("configuration is corrupted", EINVAL);
  
  if (access(sysBase.c_str(), R_OK) != 0) {
    syslog(LOG_CRIT, "cannot read directory for system tables (%s): (%i) %s", sysBase.c_str(), errno, strerror(errno));
    if (!g_daemon)
        fprintf(stderr, "cannot read directory for system tables (%s): (%i) %s", sysBase.c_str(), errno, strerror(errno));
    ret = 1;
    goto error;
  }
  
  if (!IncronCfg::GetValue("user_table_dir", userBase))
    throw InotifyException("configuration is corrupted", EINVAL);
  
  if (access(userBase.c_str(), R_OK) != 0) {
    syslog(LOG_CRIT, "cannot read directory for user tables (%s): (%i) %s", userBase.c_str(), errno, strerror(errno));
    if (!g_daemon)
        fprintf(stderr, "cannot read directory for user tables (%s): (%i) %s", userBase.c_str(), errno, strerror(errno));
    ret = 1;
    goto error;
  }
  
  try {
    if (g_daemon)
      if (daemon(0, 0) == -1) {
        syslog(LOG_CRIT, "daemonizing failed: (%i) %s", errno, strerror(errno));
        fprintf(stderr, "daemonizing failed: (%i) %s\n", errno, strerror(errno));
        ret = 1;
        goto error;
      }
  
    try {
    if (!app.Lock()) {
      syslog(LOG_CRIT, "another instance of incrond already running");
      if (!g_daemon)
        fprintf(stderr, "another instance of incrond already running\n");
      ret = 1;
      goto error;
      }
    } catch (AppInstException e) {
      syslog(LOG_CRIT, "instance lookup failed: (%i) %s", e.GetErrorNumber(), strerror(e.GetErrorNumber()));
      if (!g_daemon)
        fprintf(stderr, "instance lookup failed: (%i) %s\n", e.GetErrorNumber(), strerror(e.GetErrorNumber()));
      ret = 1;
      goto error;
    }
    
    prepare_pipe();
    
    Inotify in;
    in.SetNonBlock(true);
    in.SetCloseOnExec(true);
    
    uint32_t wm = IN_CREATE | IN_CLOSE_WRITE | IN_DELETE | IN_MOVE | IN_DELETE_SELF | IN_UNMOUNT;
    InotifyWatch stw(sysBase, wm);
    in.Add(stw);
    InotifyWatch utw(userBase, wm);
    in.Add(utw);
    
    EventDispatcher ed(g_cldPipe[0], &in, &stw, &utw);
    
    try {
      load_tables(&ed);
    } catch (InotifyException e) {
      int err = e.GetErrorNumber();
      syslog(LOG_CRIT, "%s: (%i) %s", e.GetMessage().c_str(), err, strerror(err));
      ret = 1;
      goto error;
    }
    
    ed.Rebuild(); // not too efficient, but simple 
    
    signal(SIGTERM, on_signal);
    signal(SIGINT, on_signal);
    signal(SIGCHLD, on_signal);
    
    syslog(LOG_NOTICE, "ready to process filesystem events");
    
    while (!g_fFinish) {
      
      int res = poll(ed.GetPollData(), ed.GetSize(), -1);
      
      if (res > 0) {
        if (ed.ProcessEvents())
          UserTable::FinishDone();
      }
      else if (res < 0) {
        switch (errno) {
          case EINTR:   // syscall interrupted - continue polling
            break;
          case EAGAIN:  // not enough resources - wait a moment and try again
            syslog(LOG_WARNING, "polling failed due to resource shortage, retrying later...");
            sleep(POLL_EAGAIN_WAIT);
            break;
          default:
            throw InotifyException("polling failed", errno, NULL);
        } 
      }
      
    }
    
    free_tables(&ed);
    
    if (g_cldPipe[0] != -1)
      close(g_cldPipe[0]);
    if (g_cldPipe[1] != -1)
      close(g_cldPipe[1]);
  } catch (InotifyException e) {
    int err = e.GetErrorNumber();
    syslog(LOG_CRIT, "*** unhandled exception occurred ***");
    syslog(LOG_CRIT, "  %s", e.GetMessage().c_str());
    syslog(LOG_CRIT, "  error: (%i) %s", err, strerror(err));
    ret = 1;
  }

error:

  syslog(LOG_NOTICE, "stopping service");
  
  closelog();
  
  return ret;
}