Exemple #1
0
WebRequest *FCGIStream::getNextRequest(int timeoutsec)
{
  fd_set rfds;
  FD_ZERO(&rfds);
  FD_SET(0, &rfds);
  struct timeval timeout;
  timeout.tv_sec = timeoutsec;
  timeout.tv_usec = 0;

  for(;;) {
    int result = select(FD_SETSIZE, &rfds, 0, 0, &timeout);

    if (result == 0)
      return 0; // timeout
    else if (result == -1) {
      if (errno != EINTR) {
	perror("select");
	exit(1); // FIXME: throw exception
      } else
	; // EINTR, try again
    } else
      break;
  }

  FCGX_Request *request = new FCGX_Request();
  FCGX_InitRequest(request, 0, 0);

  if (FCGX_Accept_r(request) == 0) {
    return new FCGIRequest(request);
  } else {
    LOG_ERROR("could not FCGX_Accept ?");
    delete request;

    exit(1); // FIXME: throw exception
  }
}
Exemple #2
0
int main(int argc, char** argv){
    (void)argc;
    (void)argv;

    openlog("eqbeats", LOG_PID, LOG_USER);

    struct eqbeats_ctx eq;
    if(eqbeats_init(&eq, "", NULL, EQBEATS_INIT_SETUP) != 0){
        log("eqbeats initialization failed");
        exit(1);
    }

    setenv("EQBEATS_DIR", eq.root, 0);
    DB::setPgDatabase(eq.pg);

    if(!DB::connect((std::string)argv[0] + "-" + number(getpid()))){
        log("critical error: couldn't connect to PostgreSQL");
        exit(1);
    }

    uint32_t buf = 0;
    int urandom = open("/dev/urandom", O_RDONLY);
    if(urandom != -1) {
        read(urandom, &buf, 4);
        close(urandom);
        srand(buf);
    } else {
        log("Couldn't open /dev/urandom, random seed will be predictable.");
        srand(getpid() ^ time(NULL));
    }

    MagickWandGenesis();

    FCGX_Request request;
    FCGX_Init();
    FCGX_InitRequest(&request, 0, 0);
    FCgiIO o;

    ctemplate::AddModifier("x-irc", new IrcEscape);
    ctemplate::AddXssSafeModifier("x-email", new EmailEscape);
    ctemplate::AddXssSafeModifier("x-format", new Formatter);
    cache.SetTemplateRootDirectory(TEMPLATES_DIR);

    void (*callbacks[])(Document*) = {
        Pages::statics, Pages::home,
        Pages::track, Pages::trackMisc, Pages::tracks, Pages::oembed, Pages::trackActions, Pages::trackUpload, Pages::art, Pages::license,
        Pages::account, Pages::login, Pages::user, Pages::users, Pages::registration, Pages::passwordReset,
        Pages::playlist, Pages::playlistActions,
        Pages::comment, Pages::socialActions, Pages::favorites,
        Pages::featureActions,
#ifdef HAVE_LIBHIREDIS
        Pages::stats,
#endif
        0
    };

    struct sigaction sa;
    memset(&sa, 0, sizeof(sa));
    sa.sa_handler = &signalCatch;
    sigaction(SIGINT, &sa, NULL);
    sigaction(SIGQUIT, &sa, NULL);
    sigaction(SIGTERM, &sa, NULL);

    pid_t child;
    int rc;

    while(FCGX_Accept_r(&request) == 0){
        resetTimer();
        if(eqbeats_health_check(&eq) < 0)
            continue; /* let it return 502 */
        DB::healthCheck(); /* redis */
        headers = request.envp;
        o.attach(&request);
        try { cgi = cgicc::Cgicc(&o); }
        catch(std::runtime_error &err){
            log((std::string)"CgiCc error: " + err.what());
            //continue;
        }
        path = stripSlash(cgi.getEnvironment().getScriptName());
        Document doc;

        // Nope
        if (cgi.getElementByValue("PHPE9568F34-D428-11d2-A769-00AA001ACF42") != cgi.getElements().end() ||
            cgi.getElementByValue("PHPE9568F35-D428-11d2-A769-00AA001ACF42") != cgi.getElements().end() ||
            cgi.getElementByValue("PHPE9568F36-D428-11d2-A769-00AA001ACF42") != cgi.getElements().end()){
            doc.redirect("http://youtu.be/gvdf5n-zI14");
        }

        if (getenv("EQBEATS_HTTPS") && !cgi.getEnvironment().usingHTTPS() && cgi.getElements().size() == 0)
            doc.moved(eqbeatsUrl() + path);

        Session::start();

        for(int i=0; !doc && callbacks[i]; i++)
            callbacks[i](&doc);

        Session::fill(doc.rootDict());
        o << doc.generate();

        Session::destroy();
        FCGX_Finish_r(&request);
        while((child = waitpid(-1, &rc, WNOHANG)) > 0) // wait for zombies
            syslog(WIFEXITED(rc) ? LOG_NOTICE : LOG_ERR, "%d exited with %d.", child, WEXITSTATUS(rc));
    }

    MagickWandTerminus();
    DB::close();
    eqbeats_end(&eq);
    return 0;
}
Exemple #3
0
static VALUE fcgi_s_accept(VALUE self)
{
  int status;
  FCGX_Request *req;
  fd_set readfds;

  req = ALLOC(FCGX_Request);

  status = FCGX_InitRequest(req,0,0);
  if (status != 0) {
    rb_raise(eFCGIError, "FCGX_Init() failed");
    return Qnil;
  }

  FD_ZERO(&readfds);
  FD_SET(req->listen_sock, &readfds);
  if (select(req->listen_sock+1, &readfds, NULL, NULL, NULL) < 1) {
    return Qnil;
  }

  status = FCGX_Accept_r(req);
  if (status >= 0) {
    fcgi_data *data;
    fcgi_stream_data *stream_data;
    char      **env;
    VALUE     obj,key, value;
    char      *pkey,*pvalue;
    int       flags, fd;

    /* Unset NONBLOCKING */
    fd = ((FCGX_Request*) req)->ipcFd;
    flags = fcntl(fd, F_GETFL);

    if (flags & O_NONBLOCK) {
       fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
    }

    obj = Data_Make_Struct(self, fcgi_data, fcgi_mark, fcgi_free_req, data);
    data->req = req;
    data->in = Data_Make_Struct(cFCGIStream, fcgi_stream_data, fcgi_stream_mark, fcgi_stream_free, stream_data);
    stream_data->stream = req->in;
    stream_data->req = obj;
    data->out = Data_Make_Struct(cFCGIStream, fcgi_stream_data, fcgi_stream_mark, fcgi_stream_free, stream_data);
    stream_data->stream = req->out;
    stream_data->req = obj;
    data->err = Data_Make_Struct(cFCGIStream, fcgi_stream_data, fcgi_stream_mark, fcgi_stream_free, stream_data);
    stream_data->stream = req->err;
    stream_data->req = obj;
    data->env = rb_hash_new();
    env = req->envp;
    for (; *env; env++) {
      int size = 0;
      pkey = *env;
      pvalue = pkey;
      while( *(pvalue++) != '=') size++;
      key   = rb_str_new(pkey, size);
      value = rb_str_new2(pvalue);
      OBJ_TAINT(key);
      OBJ_TAINT(value);
      rb_hash_aset(data->env, key, value);
    }

    return obj;
  } else {
    FCGX_Free(req, 1);
    free(req);
    return Qnil;
  }
}
Exemple #4
0
/* TODO: Comment */
static void *doit(void *a){
  int rc, thread_id = (pthread_t) a;
  FCGX_Request request;
  apr_pool_t* pool;
  struct range_request* rr;
  struct libcrange *lr;
  char *config_file = NULL;
  char * r_query;		/* range query */
  int r_status = 0;

  apr_initialize();
  atexit(apr_terminate);
  apr_pool_create(&pool, NULL);

  config_file = LIBCRANGE_CONF;

  lr = libcrange_new(pool, config_file);

  /* malloc for query */
  r_query = (char *)malloc(QUERY_STR_SIZE);

  FCGX_InitRequest(&request, 0, 0);

  for (;;)
    {
      static pthread_mutex_t accept_mutex = PTHREAD_MUTEX_INITIALIZER;

      apr_pool_t* sub_pool;

      apr_pool_create(&sub_pool, pool);

      /* zero it out */
      bzero(r_query, QUERY_STR_SIZE);
      r_status = 0;
	

      /* Some platforms require accept() serialization, some don't.. */
      pthread_mutex_lock(&accept_mutex);
      rc = FCGX_Accept_r(&request);
      pthread_mutex_unlock(&accept_mutex);

      if (rc < 0)
	break;

      
      r_status = get_range_query(&request, r_query);
      rr = range_expand(lr, sub_pool, r_query);

      FCGX_FPrintF(request.out, "Content-type: text/plain\r\n");
      
      /* set headers */
      if (range_request_has_warnings(rr)) {
      	const char *warnings = range_request_warnings(rr);
      	FCGX_FPrintF(request.out,
      		     "RangeException: %s\r\nRange_FCGI_Thread_Id: %d\r\n",
      		     warnings, thread_id);
      }

      /* End Delimiter */
      FCGX_FPrintF(request.out, "\r\n");

      /* r_status == 1, then wants list */
      if (r_status == 1) {
      	const char **nodes = range_request_nodes(rr);
      	while(*nodes) {
      	  FCGX_FPrintF(request.out, "%s\n", *nodes++);
      	}
      } else if (r_status == 0) {
      	FCGX_FPrintF(request.out, "%s\n", range_request_compressed(rr));
      }
      
      apr_pool_destroy(sub_pool);

      FCGX_Finish_r(&request);

    } /* for (;;) */

  /* free, what I hogged :-) */
  free(r_query);

  apr_pool_destroy(pool);

  return NULL;
}
Exemple #5
0
		Worker4CloseThread() {
			FCGX_InitRequest(&request, 0, 0);
		}
Exemple #6
0
static void *doit(int id, Config &conf)
{
    
    FCGX_Request request;
	
    if(FCGX_InitRequest(&request, socketId.load(), 0) != 0)
    {
        //ошибка при инициализации структуры запроса
        printf("Can not init request\n");
        return NULL;
    }

	Router router(&request, &conf);
	
	router.addHandler("OPTIONS",	"/users/login", 		&OptUsersLogin);
	router.addHandler("GET",		"/users/login", 		&UsersInfo);
	router.addHandler("POST",		"/users/login", 		&PostUsersLogin);
	
	router.addHandler("OPTIONS",	"/users/add", 			&OptUsersAdd);
	router.addHandler("POST",		"/users/add", 			&PostUsersAdd);
	
	router.addHandler("OPTIONS",	".*", 					&OptDirs);
	router.addHandler("OPTIONS",	"/dirs/(?<id>\\d+)",	&OptDirs);
	
	router.addHandler("POST",		"/dirs", 				&PostCreateDir);
	router.addHandler("GET",		"/dirs/(\\d+)",			&GetDir);
	router.addHandler("DELETE",		"/dirs/(\\d+)",			&DelDir);
	
	router.addHandler("POST",		"/files/(\\d+)/(.+)",	&PutFile);
	router.addHandler("GET",		"/files/(\\d+)",		&GetFile);
	router.addHandler("DELETE",		"/files/(\\d+)",		&DelFile);


    for(;;)
    {
        static pthread_mutex_t accept_mutex = PTHREAD_MUTEX_INITIALIZER;

        pthread_mutex_lock(&accept_mutex);
        int rc = FCGX_Accept_r(&request);
		
		pthread_mutex_unlock(&accept_mutex);
        
        if(rc < 0)
        {
            //ошибка при получении запроса
            printf("Can not accept new request\n");
            break;
        }

	   	std::streambuf * cin_streambuf  = std::cin.rdbuf();
	    std::streambuf * cout_streambuf = std::cout.rdbuf();
	    std::streambuf * cerr_streambuf = std::cerr.rdbuf();    


        fcgi_streambuf cin_fcgi_streambuf(request.in);
        fcgi_streambuf cout_fcgi_streambuf(request.out);
        fcgi_streambuf cerr_fcgi_streambuf(request.err);

        std::cin.rdbuf(&cin_fcgi_streambuf);
        std::cout.rdbuf(&cout_fcgi_streambuf);
        std::cerr.rdbuf(&cerr_fcgi_streambuf);
		try
		{	
			router.Run();
		}
		catch (Error &e)
		{
			router.SetStatus(e.http_code());
			router.AddHeader("Content-Type", "application/json; charset=utf-8");
			router.AddContent(e.what());
			router.AcceptContent();
		}
		catch (std::exception &e)
		{
			std::cerr << e.what();
			router.SetStatus(Httpstatus::InternalServerError);
			router.AddHeader("Content-Type", "text/plain; charset=utf-8");
			router.AddContent(e.what());
			router.AcceptContent();
		}
		
		FCGX_Finish_r(&request);
		
        //завершающие действия - запись статистики, логгирование ошибок и т.п.

		router.Cleanup();


	    std::cin.rdbuf(cin_streambuf);
	    std::cout.rdbuf(cout_streambuf);
	    std::cerr.rdbuf(cerr_streambuf);

    }


    return NULL;
}
Exemple #7
0
			void init() override { FCGX_InitRequest(&m_request, 0, 0); }
Exemple #8
0
void* Rok4Server::thread_loop ( void* arg ) {
    Rok4Server* server = ( Rok4Server* ) ( arg );
    FCGX_Request fcgxRequest;
    if ( FCGX_InitRequest ( &fcgxRequest, server->sock, FCGI_FAIL_ACCEPT_ON_INTR ) !=0 ) {
        LOGGER_FATAL ( _ ( "Le listener FCGI ne peut etre initialise" ) );
    }

    while ( server->isRunning() ) {
        std::string content;
        bool postRequest;

        int rc;
        if ( ( rc=FCGX_Accept_r ( &fcgxRequest ) ) < 0 ) {
            if ( rc != -4 ) { // Cas différent du redémarrage
                LOGGER_ERROR ( _ ( "FCGX_InitRequest renvoie le code d'erreur" ) << rc );
            }
            //std::cerr <<"FCGX_InitRequest renvoie le code d'erreur" << rc << std::endl;
            break;
        }
        //DEBUG: La boucle suivante permet de lister les valeurs dans fcgxRequest.envp
        /*char **p;
        for (p = fcgxRequest.envp; *p; ++p) {
            LOGGER_DEBUG((char*)*p);
        }*/

        Request* request;



        postRequest = ( server->servicesConf.isPostEnabled() ?strcmp ( FCGX_GetParam ( "REQUEST_METHOD",fcgxRequest.envp ),"POST" ) ==0:false );

        if ( postRequest ) { // Post Request
            char* contentBuffer = ( char* ) malloc ( sizeof ( char ) *200 );
            while ( FCGX_GetLine ( contentBuffer,200,fcgxRequest.in ) ) {
                content.append ( contentBuffer );
            }
            free ( contentBuffer );
            contentBuffer= NULL;
            LOGGER_DEBUG ( _ ( "Request Content :" ) << std::endl << content );
            request = new Request ( FCGX_GetParam ( "QUERY_STRING", fcgxRequest.envp ),
                                    FCGX_GetParam ( "HTTP_HOST", fcgxRequest.envp ),
                                    FCGX_GetParam ( "SCRIPT_NAME", fcgxRequest.envp ),
                                    FCGX_GetParam ( "HTTPS", fcgxRequest.envp ),
                                    content );



        } else { // Get Request

            /* On espère récupérer le nom du host tel qu'il est exprimé dans la requete avec HTTP_HOST.
             * De même, on espère récupérer le path tel qu'exprimé dans la requête avec SCRIPT_NAME.
             */

            request = new Request ( FCGX_GetParam ( "QUERY_STRING", fcgxRequest.envp ),
                                    FCGX_GetParam ( "HTTP_HOST", fcgxRequest.envp ),
                                    FCGX_GetParam ( "SCRIPT_NAME", fcgxRequest.envp ),
                                    FCGX_GetParam ( "HTTPS", fcgxRequest.envp )
                                  );
        }
        server->processRequest ( request, fcgxRequest );
        delete request;

        FCGX_Finish_r ( &fcgxRequest );
        FCGX_Free ( &fcgxRequest,1 );
    }
    LOGGER_DEBUG ( _ ( "Extinction du thread" ) );
    Logger::stopLogger();
    return 0;
}
Exemple #9
0
void WebInterface::worker() {
	/* Backup the stdio streambufs */
	std::streambuf * cin_streambuf  = std::cin.rdbuf();
	std::streambuf * cout_streambuf = std::cout.rdbuf();
	std::streambuf * cerr_streambuf = std::cerr.rdbuf();

	const std::string kw_title(KW_TITLE);
	const std::string kw_head(KW_HEAD);
	const std::string kw_menu(KW_MENU);
	const std::string kw_content(KW_CONTENT);

	FCGX_Request request;

	/* Initialize FastCGI library and request */
	FCGX_Init();
	FCGX_InitRequest(&request, 0, FCGI_FAIL_ACCEPT_ON_INTR);

	LOG_DBG("FastCGI initialization success!");

	while (!stop_flag_) {
		if(FCGX_Accept_r(&request) >= 0) {

			fcgi_streambuf cin_fcgi_streambuf(request.in);
			fcgi_streambuf cout_fcgi_streambuf(request.out);
			fcgi_streambuf cerr_fcgi_streambuf(request.err);

			std::cin.rdbuf(&cin_fcgi_streambuf);
			std::cout.rdbuf(&cout_fcgi_streambuf);
			std::cerr.rdbuf(&cerr_fcgi_streambuf);

			/* getting the uri from the request */
			std::string uri;
			const char *uri_param = FCGX_GetParam("REQUEST_URI", request.envp);
			if(!uri_param) {
				LOG_ERR("Failed to retrieve the request URI environment value!");
				uri = URI_PAGE_ERROR;
			} else {
				uri = uri_param;
			}

			LOG_DBG("Request received: %s", uri.c_str());

			/* Check if URI is a file in the home folder and get the mime of
			 * that file (by extension) */
			std::string path;
			std::string mime = if_file_get_mime(uri, &path);

			if (!mime.empty()) {
				/* This is a file we need to serve */
				StringPtr file_data = Utils::read_file(path);
				std::cout << "Content-type: " << mime << "\r\n\r\n";
				std::cout << *(file_data);

				file_data.reset();
			} else {
				/* Parse the URI */
				std::map<std::string, std::string> uri_data = parseURI(uri);

				LOG_DBG("URI Parsed, page requested: %s",
						uri_data[URI_PAGE].c_str());

				/* Generate and serve the page depending on the URI */
				StringPtr page;
				std::string content_type = "text/html";

				/* Main page requested */
				if (uri_data[URI_PAGE].compare(URI_PAGE_MAIN) == 0) {
					bool success = false;

					/* Check if a command was sent from the client. */
					if (uri_data.find(URI_PAGE_COMMAND) != uri_data.end()) {
						success = add_command(uri_data[URI_PAGE_COMMAND]);
					}

					std::string s;
					/* Check if the request was sent from javascript or pure HTML */
					if(uri_data.find(URI_PAGE_SOURCE) != uri_data.end()) {
						LOG_DBG("This query's source IS javascript: %s, Source: %s",
								uri.c_str(), (uri_data[URI_PAGE_SOURCE]).c_str());
						content_type = "application/json";
						page = generate_command_json(success);
					} else {
						LOG_DBG("This query's source IS NOT javascript: %s", uri.c_str());
						/* Just generate a standard main page */
						page = generate_main_page();
					}
				/* Log page requested */
				} else if (uri_data[URI_PAGE].compare(URI_PAGE_LOG) == 0) {
					page = generate_log_page();

				/* Status page requested */
				} else if (uri_data[URI_PAGE].compare(URI_PAGE_STATUS) == 0) {
					page = generate_status_page();

				/* Console lines JSON page requested */
				} else if (uri_data[URI_PAGE].compare(URI_PAGE_CL) == 0) {
					if (uri_data.find(URI_PAGE_BEFORE) != uri_data.end()) {
						content_type = "application/json";
						page = generate_cljson_before(
								uri_data[URI_PAGE_BEFORE]);
					} else if (uri_data.find(URI_PAGE_AFTER)
							!= uri_data.end()) {
						content_type = "application/json";
						page = generate_cljson_after(uri_data[URI_PAGE_AFTER]);
					} else {
						page = generate_error_page();
					}

				/* Log lines JSON page requested */
				} else if (uri_data[URI_PAGE].compare(URI_PAGE_LL) == 0) {
					if (uri_data.find(URI_PAGE_BEFORE) != uri_data.end()) {
						content_type = "application/json";
						page = generate_lljson_before(
								uri_data[URI_PAGE_BEFORE]);
					} else if (uri_data.find(URI_PAGE_AFTER)
							!= uri_data.end()) {
						content_type = "application/json";
						page = generate_lljson_after(uri_data[URI_PAGE_AFTER]);
					} else {
						page = generate_error_page();
					}
				} else {
					page = generate_error_page();
				}

				/* Output the generated page with the correct content type */
				std::cout << "Content-type: " << content_type << "\r\n\r\n";
				std::cout << *(page.get());
			}

		}
		else {
			LOG_TRC("FCGX_Aceept_r returned less than 0!");
		}
	}

	LOG_TRC("Out of accept request loop!");

	// Free request strucure
	FCGX_Finish_r(&request);

	// Flag the thread as not running anymore.
	running_ = false;

	// restore stdio streambufs
	std::cin.rdbuf(cin_streambuf);
	std::cout.rdbuf(cout_streambuf);
	std::cerr.rdbuf(cerr_streambuf);
}
Exemple #10
0
int main(void)
{
    unsigned int        count   = 0;
    int                 socket_fdescriptor = 0;

    char                *buf    = NULL;

    FCGX_Request        request;
    Request_t           req;


    // Initialize all the elements of the structures to NULL
    memset(&request, 0, sizeof(FCGX_Request) );
    memset(&req, 0, sizeof(Request_t) );

    if ( FCGX_Init() != 0 )
    {
        return (1);
    }

    socket_fdescriptor = FCGX_OpenSocket(PORT_FCGI, 500);

    if ( socket_fdescriptor < 0 )
    {
        return (2);
    }

    buf = (char *) malloc(50 * sizeof(char) );
    sprintf(buf, "The file descriptor of the socket is : %d", socket_fdescriptor);

    logger("main.c", buf);

    if ( buf )
    {
        free(buf);
    }

    if ( FCGX_InitRequest(&request, socket_fdescriptor, 0) < 0 )
    {
        return (3);
    }


    /* Response loop. */
    while ( FCGX_Accept_r(&request) == 0 )
    {
        request_fill(request, &req);
        request_display(req, ++count);

        FCGX_FPrintF(request.out,
                     "Content-type: text/html\r\n"
                     "\r\n"
                     "<title>FastCGI Hello! (C, fcgi_stdio library)</title>"
                         "<h1>FastCGI Hello! (C, fcgi_stdio library)</h1>"
                             "Request number %d",
                     count);
        FCGX_Finish_r(&request);
    }

    fprintf(stderr, "Error FCGX_Accept_r");

    return (0);
}
Exemple #11
0
int main(int argc, char* argv[], char* envp[])
{
	if(argc < 7)
		usage(argv);

	char* root = argv[1];
	char* thumbnail_root = argv[2];
	char* listen_addr = argv[3];
	num_workers = atoi(argv[6]);

	if(num_workers < 1)
		usage(argv);

	struct passwd* pwd = getpwnam(argv[4]);
	if (pwd == NULL)
			error_errno("getpwnam_r failed", EXIT_FAILURE);

	struct group* grp = getgrnam(argv[5]);
	if (grp == NULL)
			error_errno("getgrnam_r failed", EXIT_FAILURE);

	int userid = pwd->pw_uid;
	int groupid = grp->gr_gid;

	if(root[strlen(root) - 1] != '/' || thumbnail_root[strlen(thumbnail_root) - 1] != '/')
		error("Did you forget the ending slash in the (thumbnail) root directory path?", EXIT_FAILURE);

	// TODO Some more error checking

	// Initialize syslog
	syslog(LOG_INFO, "Starting up\n");
	#if defined(DEBUG)
		setlogmask(LOG_UPTO(LOG_DEBUG));
		openlog("fastresize", LOG_CONS | LOG_NDELAY | LOG_PERROR | LOG_PID, LOG_USER);
	#else
		setlogmask(LOG_UPTO(LOG_INFO));
		openlog("fastresize", LOG_CONS, LOG_USER);
	#endif

	// Change the working directory
	if((chdir(root)) < 0)
		error("Couldn't change working directory\n", EXIT_FAILURE);

	// Initialize FastCGI
	syslog(LOG_INFO, "Initializing FastCGI\n");
	if(FCGX_Init())
		error("Could not initialize FastCGI (during FCGX_Init())", EXIT_FAILURE);

	int listen_socket = FCGX_OpenSocket(listen_addr, 400);
	if(listen_socket < 0)
		error("Couldn't bind to FastCGI socket", EXIT_FAILURE);

	// Now that we've got our socket, drop root privileges
	if (getuid() == 0) {
		if (setgid(groupid) != 0)
			error_errno("setgid: Unable to drop group privileges", EXIT_FAILURE);
		if (setuid(userid) != 0)
			error_errno("setuid: Unable to drop user privileges", EXIT_FAILURE);
	}

	FCGX_Request request;
	if(FCGX_InitRequest(&request, listen_socket, 0))
		error("Couldn't initialize FastCGI request handler", EXIT_FAILURE);

	// Initialize ImageMagick
	syslog(LOG_INFO, "Initializing ImageMagick\n");
	MagickWandGenesis();
	atexit(MagickWandTerminus);

	/* Fork a new master process to daemonize and exit the old one. We use
	 * _Exit here to not trigger the atexit that terminates ImageMagick.
	 */
	if(fork())
		_Exit(EXIT_SUCCESS);

	// Fork worker processes
	syslog(LOG_INFO, "Forking workers\n");

	worker_pids = calloc(num_workers, sizeof(pid_t));
	if(!worker_pids)
		error_errno("worker_pids: Could not allocate", 1);

	for(worker_id = 0; worker_id <= num_workers; worker_id++)
	{
		worker_pids[worker_id] = fork();

		// Exit the loop if we're the forked process
		if(worker_pids[worker_id] == 0)
			break;

		syslog(LOG_INFO, "Forked worker with PID %d\n", worker_pids[worker_id]);
	}

	// The following code is only executed in the master process.
	if(worker_id > num_workers)
	{
		syslog(LOG_INFO, "master (PID %d): Sleeping until I receive a signal.\n", getpid());

		/* Sleep a little until we get a SIG{TERM,HUP,INT} or one of our
		 * workers died (not cool).
		 */
		struct sigaction exit_action;
		exit_action.sa_handler = &exit_signal;
		exit_action.sa_sigaction = &exit_signal;

		struct sigaction worker_died_action;
		worker_died_action.sa_handler = &worker_died;
		worker_died_action.sa_sigaction = &worker_died;

		sigaction(SIGTERM, &exit_action, NULL);
		sigaction(SIGHUP, &exit_action, NULL);
		sigaction(SIGINT, &exit_action, NULL);
		sigaction(SIGCHLD, &worker_died_action, NULL);
		pause();

		// This should never™ be reached unless something funny happens.
		exit(EXIT_FAILURE);
	}

	syslog(LOG_INFO, "Worker #%d is now listening for requests on 127.0.0.1:9000\n", worker_id);

	while(FCGX_Accept_r(&request) == 0)
		handle_request(&request, root, thumbnail_root);

	// Exit
	exit(EXIT_SUCCESS);
}
Exemple #12
0
foreign_t
fcgi_accept(control_t h)
{
  FCGX_Request *req;
  fd_set fds;
  fcgi_context *ctxt;
  int status;

  FCGI_debug("fcgi_accept()");

  if ( FCGX_IsCGI() )
  { return TRUE;
  }

  ctxt = pthread_getspecific(key);

  if ( !ctxt )
  { ctxt = malloc(sizeof(*ctxt));
    memset(ctxt, 0, sizeof(*ctxt));
  }

  if ( ctxt->req )
  { fcgi_finish();
  }

  req = malloc(sizeof(*req));
  memset(req, 0, sizeof(*req));

  status = FCGX_InitRequest(req, 0, 0);
  if ( status != FCGI_SUCCESS )
  { return fcgi_raise_error(status, "FCGX_InitRequest() failed");
  }

  FD_ZERO(&fds);
  FD_SET(req->listen_sock, &fds);
  if ( select(req->listen_sock+1, &fds, NULL, NULL, NULL) < 1 )
  { return FALSE;
  }

  status = FCGX_Accept_r(req);
  if ( status != FCGI_SUCCESS )
  { return fcgi_raise_error(status, "FCGX_Accept_r() failed");
  }

  FCGI_debug("REMOTE_ADDR: %s, REQUEST_METHOD: %s, REQUEST_URI: %s",
             FCGX_GetParam("REMOTE_ADDR", req->envp),
             FCGX_GetParam("REQUEST_METHOD", req->envp),
             FCGX_GetParam("REQUEST_URI", req->envp));

  if ( !ctxt )
  { ctxt = malloc(sizeof(*ctxt));
    memset(ctxt, 0, sizeof(*ctxt));
  }

  ctxt->req = req;

  ctxt->pl_in = Suser_input;
  ctxt->h_in = Suser_input->handle;
  ctxt->fn_in = Suser_input->functions;
  ctxt->fcgi_in = req->in;

  ctxt->pl_out = Suser_output;
  ctxt->h_out = Suser_output->handle;
  ctxt->fn_out = Suser_output->functions;
  ctxt->fcgi_out = req->out;

  ctxt->pl_err = Suser_error;
  ctxt->h_err = Suser_error->handle;
  ctxt->fn_err = Suser_error->functions;
  ctxt->fcgi_err = req->err;

  ctxt->env = req->envp;

  pthread_setspecific(key, ctxt);

  Suser_input->handle = req->in;
  Suser_input->functions = &fcgi_functions;

  Suser_output->handle = req->out;
  Suser_output->functions = &fcgi_functions;

  Suser_error->handle = req->err;
  Suser_error->functions = &fcgi_functions;

  PL_retry(0);
}