Advertisement
C4Cypher

mfcgi.m

Aug 17th, 2014
270
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Prolog 5.60 KB | None | 0 0
  1. % Mercury-fcgi library binding
  2. % contains single thread and multi-thread parts of api
  3.  
  4. :- module mfcgi.
  5.  
  6. :- interface.
  7. :- import_module io.
  8.  
  9. :- pred main(io::di, io::uo) is det.
  10.  
  11. :- implementation.
  12. :- import_module bool, string.
  13.  
  14. % Declarations ------------------------------------------------------------------
  15.        
  16. :- pragma foreign_decl("C",
  17.   "
  18.  
  19. /* C4Cypher:
  20.  
  21.  Okay, I went through HELL getting fcgi to link properly, I finally did it with
  22.  mmc --make mfcgi -lfcgi
  23.  
  24.  That explains why you don't include something like
  25.    #include <fcgi_stdio.h>
  26.    
  27.  here, yep it compiles and runs clean, nice job man.
  28.  
  29.  END C4Cypher */  
  30.  
  31.    #include <assert.h>
  32.    #include <errno.h>
  33.    #include <fcntl.h>      /* for fcntl */
  34.    #include <math.h>
  35.    #include <memory.h>     /* for memchr() */
  36.    #include <stdarg.h>
  37.    #include <stdio.h>
  38.    #include <stdlib.h>
  39.    #include <string.h>
  40.    #include <sys/types.h>
  41.  
  42. /* C4Cypher: This method of escaping double quotes works, and I'm not calling it
  43.  wrong  but it was screwing with my syntax highlighting.  
  44.  mmc interprets "" as \".
  45.  
  46.    #include \"fcgi_config.h\"
  47. */
  48.    #include <fcgi_config.h>
  49.    
  50. /* END C4Cypher */
  51.  
  52.    #ifdef HAVE_SYS_SOCKET_H
  53.    #include <sys/socket.h> /* for getpeername */
  54.    #endif
  55.  
  56.    #ifdef HAVE_SYS_TIME_H
  57.    #include <sys/time.h>
  58.    #endif
  59.  
  60.    #ifdef HAVE_UNISTD_H
  61.    #include <unistd.h>
  62.    #endif
  63.  
  64.    #ifdef HAVE_LIMITS_H
  65.    #include <limits.h>
  66.    #endif
  67.  
  68.    #ifdef _WIN32
  69.    #define DLLAPI  __declspec(dllexport)
  70.    #endif
  71.  
  72. /* C4Cypher
  73.    #include \"fcgimisc.h\"
  74.    #include \"fastcgi.h\"
  75.    #include \"fcgios.h\"
  76.    #include \"fcgiapp.h\"
  77. */
  78.  
  79.    #include ""fcgimisc.h""
  80.    #include ""fastcgi.h""
  81.    #include ""fcgios.h""
  82.    #include ""fcgiapp.h""
  83.    
  84. /* END C4Cypher */
  85.  
  86.  
  87.    #ifdef HAVE_VA_ARG_LONG_DOUBLE_BUG
  88.    #define LONG_DOUBLE double
  89.    #else
  90.    #define LONG_DOUBLE long double
  91.    #endif
  92.  
  93.    /*
  94.     * Globals
  95.     */
  96.    static int libInitialized = 0;
  97.    static int isFastCGI = -1;
  98.    static char *webServerAddressList = NULL;
  99.    static FCGX_Request the_request;
  100.  
  101.    FCGX_Stream *in, *out, *err;
  102.    FCGX_ParamArray envp;
  103.   ").
  104.  
  105. % NOTE: make a header type
  106. :- func header = string.
  107. header = "Content-Type: text/plain\n\n".
  108.  
  109. % Single threaded demo ----------------------------------------------------------
  110.  
  111. main(!IO) :-
  112.   fcgx_accept(Success, !IO),
  113.   (Success = yes ->
  114.      (fcgx_get_param("QUERY_STRING", Str, !IO),
  115.       fcgx_puts(header, _, !IO),
  116.       fcgx_puts(Str, _, !IO),
  117.       main(!IO))
  118.  
  119.      ;
  120.      %true
  121.      % C4Cypher: Hmm, another subjective thing, my gut wants to stick a simple
  122.      % message to stdout just to verify that the program terminated cleanly,
  123.      % as opposed to comitting silent suicide.
  124.      
  125.      print("Done.\n", !IO)
  126.      
  127.      % END C4cypher
  128.      
  129.   ).
  130.  
  131. % Multi threaded demo -----------------------------------------------------------
  132.  
  133. % API ---------------------------------------------------------------------------
  134.  
  135. % get a parameter from the environment array
  136. :- pred fcgx_get_param(string::in, string::out, io::di, io::uo) is det.
  137.  
  138. :- pragma foreign_proc("C", fcgx_get_param(Name::in, Result::out,
  139.   _IO0::di, _IO::uo),
  140.   [promise_pure, will_not_call_mercury, tabled_for_io],
  141.   "
  142.    Result = FCGX_GetParam(Name, envp);
  143.   ").
  144.  
  145. % accept a request from the client
  146. :- pred fcgx_accept(bool::out, io::di, io::uo) is det.
  147.  
  148. :- pragma foreign_proc("C", fcgx_accept(Success::out, _IO0::di, _IO::uo),
  149.   [promise_pure, will_not_call_mercury, tabled_for_io],
  150.   "
  151.    Success = FCGX_Accept(&in, &out, &err, &envp) >= 0 ? MR_YES : MR_NO;
  152.   ").
  153.  
  154. % write a string to buffer
  155. :- pred fcgx_puts(string::in, bool::out, io::di, io::uo) is det.
  156.  
  157. :- pragma foreign_proc("C", fcgx_puts(Str::in, Success::out,
  158.   _IO0::di, _IO::uo),
  159.   [promise_pure, will_not_call_mercury, tabled_for_io],
  160.   "
  161.    Success = FCGX_PutStr(Str, strlen(Str), out) >= 0 ? MR_YES : MR_NO;
  162.   ").
  163.  
  164. % tests whether application is CGI or FCGI (for compatibility)
  165. % True if CGI, False if FCGI
  166. :- pred fcgx_isCGI(bool::out, io::di, io::uo) is det.
  167.  
  168. :- pragma foreign_proc("C", fcgx_isCGI(Result::out, _IO0::di, _IO::uo),
  169.   [promise_pure, will_not_call_mercury, tabled_for_io],
  170.   "
  171.    Result = FCGX_isCGI() ? MR_YES : MR_NO;
  172.   ").            
  173.  
  174. :- pred fcgx_finish(io::di, io::uo) is det.
  175.  
  176. :- pragma foreign_proc("C", fcgx_finish(_IO0::di, _IO::uo),
  177.   [promise_pure, will_not_call_mercury, tabled_for_io],
  178.   "
  179.    FCGX_Finish_r(&the_request);
  180.   ").
  181.  
  182. % thread safe
  183. % finish request accepted by previous call to fcgx_accept
  184. % also frees any storage allocated by previous call
  185. :- pred fcgx_finish_r(c_pointer::in, io::di, io::uo) is det.
  186.  
  187. :- pragma foreign_proc("C", fcgx_finish_r(ReqDataPtr::in, _IO0::di, _IO::uo),
  188.   [thread_safe, promise_pure, will_not_call_mercury, tabled_for_io],
  189.   "
  190.    FCGX_Finish_r((FCGX_Request *)ReqDataPtr);
  191.   ").
  192.  
  193. % initialize FCGX library. This is called by fcgx_accept
  194. % but should be caleld when using fcgx_accept_r
  195. :- pred fcgx_init(bool::out, io::di, io::uo) is det.
  196.  
  197. :- pragma foreign_proc("C", fcgx_init(Success::out, _IO0::di, _IO::uo),
  198.   [promise_pure, will_not_call_mercury, tabled_for_io],
  199.   "
  200.    Success = FCGX_Init() == 0 ? MR_YES : MR_NO;
  201.   ").            
  202.  
  203. % thread safe
  204. % accept new request from HTTP server
  205. % 0 is success, -1 is error.
  206. :- pred fcgx_accept_r(bool::out, io::di, io::uo) is det.
  207.  
  208. :- pragma foreign_proc("C", fcgx_accept_r(Success::out, _IO0::di, _IO::uo),
  209.   [thread_safe, promise_pure, will_not_call_mercury, tabled_for_io],
  210.   "
  211.    Success = FCGX_Accept(&in, &out, &err, &envp) >= 0 ? MR_YES : MR_NO;          
  212.   ").
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement