a sandboxed Lua backend for FastCGI
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.

171 lines
3.4 KiB

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <stdint.h>
  4. #include <string.h>
  5. #include <errno.h>
  6. #include <time.h>
  7. #include <fcgi_config.h>
  8. #include <fcgiapp.h>
  9. #include <lua5.1/lua.h>
  10. #include <pthread.h>
  11. #include "lua.h"
  12. #include "config.h"
  13. #include "lua-fastcgi.h"
  14. static char *http_status_strings[] = {
  15. [200] = "OK",
  16. [403] = "Forbidden",
  17. [404] = "Not Found",
  18. [500] = "Internal Server Error"
  19. };
  20. #define senderror(status_code,error_string) \
  21. if(!response.committed){ \
  22. FCGX_FPrintF(request.out, "Status: %d %s\r\n", status_code, http_status_strings[status_code]); \
  23. FCGX_FPrintF(request.out, "Content-Type: %s\r\n\r\n", config->content_type); \
  24. response.committed = 1; \
  25. } \
  26. FCGX_PutS(error_string, response.out);
  27. #ifdef DEBUG
  28. static void printcfg(LF_config *cfg)
  29. {
  30. printf("Listen: %s\n", cfg->listen);
  31. printf("Backlog: %d\n", cfg->backlog);
  32. printf("Threads: %d\n", cfg->threads);
  33. printf("Sandbox: %d\n", cfg->sandbox);
  34. printf("Max Memory: %zu\n", cfg->mem_max);
  35. printf("Max Output: %zu\n", cfg->output_max);
  36. printf("CPU usec: %lu\n", cfg->cpu_usec);
  37. printf("CPU sec: %lu\n", cfg->cpu_sec);
  38. printf("Default Content Type: %s\n", cfg->content_type);
  39. printf("\n");
  40. }
  41. static void printvars(FCGX_Request *request)
  42. {
  43. for(int i=0; request->envp[i] != NULL; i++){
  44. printf("%s\n", request->envp[i]);
  45. }
  46. printf("\n");
  47. }
  48. #endif
  49. void *thread_run(void *arg)
  50. {
  51. LF_params *params = arg;
  52. LF_config *config = params->config;
  53. LF_limits *limits = LF_newlimits();
  54. LF_response response;
  55. lua_State *l;
  56. FCGX_Request request;
  57. FCGX_InitRequest(&request, params->socket, 0);
  58. for(;;){
  59. LF_setlimits(
  60. limits, config->mem_max, config->output_max,
  61. config->cpu_sec, config->cpu_usec
  62. );
  63. l = LF_newstate(config->sandbox, config->content_type);
  64. if(FCGX_Accept_r(&request)){
  65. printf("FCGX_Accept_r() failure\n");
  66. LF_closestate(l);
  67. continue;
  68. }
  69. #ifdef DEBUG
  70. printvars(&request);
  71. #endif
  72. LF_parserequest(l, &request, &response);
  73. LF_enablelimits(l, limits);
  74. switch(LF_loadfile(l)){
  75. case 0:
  76. if(lua_pcall(l, 0, 0, 0)){
  77. senderror(500, lua_tostring(l, -1));
  78. } else if(!response.committed){
  79. senderror(200, "");
  80. }
  81. break;
  82. case EACCES:
  83. senderror(403, lua_tostring(l, -1));
  84. break;
  85. case ENOENT:
  86. senderror(404, lua_tostring(l, -1));
  87. break;
  88. default:
  89. senderror(500, lua_tostring(l, -1));
  90. break;
  91. }
  92. FCGX_Finish_r(&request);
  93. LF_closestate(l);
  94. }
  95. }
  96. int main()
  97. {
  98. if(FCGX_Init() != 0){
  99. printf("FCGX_Init() failure\n");
  100. exit(EXIT_FAILURE);
  101. }
  102. LF_config *config = LF_createconfig();
  103. if(config == NULL){
  104. printf("LF_createconfig(): memory allocation error\n");
  105. exit(EXIT_FAILURE);
  106. }
  107. if(LF_loadconfig(config, "./lua-fastcgi.lua")){
  108. printf("Error loading lua-fastcgi.lua\n");
  109. }
  110. #ifdef DEBUG
  111. printcfg(config);
  112. #endif
  113. int socket = FCGX_OpenSocket(config->listen, config->backlog);
  114. if(socket < 0){
  115. printf("FCGX_OpenSocket() failure: could not open %s\n", config->listen);
  116. exit(EXIT_FAILURE);
  117. }
  118. LF_params *params = malloc(sizeof(LF_params));
  119. params->socket = socket;
  120. params->config = config;
  121. if(config->threads == 1){
  122. thread_run(params);
  123. } else {
  124. pthread_attr_t attr;
  125. pthread_attr_init(&attr);
  126. pthread_t threads[config->threads];
  127. for(int i=0; i < config->threads; i++){
  128. int r = pthread_create(&threads[i], &attr, &thread_run, params);
  129. if(r){
  130. printf("Thread creation error: %d\n", r);
  131. exit(EXIT_FAILURE);
  132. }
  133. }
  134. pthread_join(threads[0], NULL);
  135. }
  136. return 0;
  137. }