Advertisement
C4Cypher

mfcgi.m

Aug 17th, 2014
249
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Prolog 5.67 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.  I don't have my own fcgi_config.h, so I'm going with the default.
  47.  
  48.    #include \"fcgi_config.h\"
  49. */
  50.    #include <fcgi_config.h>
  51.    
  52. /* END C4Cypher */
  53.  
  54.    #ifdef HAVE_SYS_SOCKET_H
  55.    #include <sys/socket.h> /* for getpeername */
  56.    #endif
  57.  
  58.    #ifdef HAVE_SYS_TIME_H
  59.    #include <sys/time.h>
  60.    #endif
  61.  
  62.    #ifdef HAVE_UNISTD_H
  63.    #include <unistd.h>
  64.    #endif
  65.  
  66.    #ifdef HAVE_LIMITS_H
  67.    #include <limits.h>
  68.    #endif
  69.  
  70.    #ifdef _WIN32
  71.    #define DLLAPI  __declspec(dllexport)
  72.    #endif
  73.  
  74. /* C4Cypher
  75.    #include \"fcgimisc.h\"
  76.    #include \"fastcgi.h\"
  77.    #include \"fcgios.h\"
  78.    #include \"fcgiapp.h\"
  79. */
  80.  
  81.    #include ""fcgimisc.h""
  82.    #include ""fastcgi.h""
  83.    #include ""fcgios.h""
  84.    #include ""fcgiapp.h""
  85.    
  86. /* END C4Cypher */
  87.  
  88.  
  89.    #ifdef HAVE_VA_ARG_LONG_DOUBLE_BUG
  90.    #define LONG_DOUBLE double
  91.    #else
  92.    #define LONG_DOUBLE long double
  93.    #endif
  94.  
  95.    /*
  96.     * Globals
  97.     */
  98.    static int libInitialized = 0;
  99.    static int isFastCGI = -1;
  100.    static char *webServerAddressList = NULL;
  101.    static FCGX_Request the_request;
  102.  
  103.    FCGX_Stream *in, *out, *err;
  104.    FCGX_ParamArray envp;
  105.   ").
  106.  
  107. % NOTE: make a header type
  108. :- func header = string.
  109. header = "Content-Type: text/plain\n\n".
  110.  
  111. % Single threaded demo ----------------------------------------------------------
  112.  
  113. main(!IO) :-
  114.   fcgx_accept(Success, !IO),
  115.   (Success = yes ->
  116.      (fcgx_get_param("QUERY_STRING", Str, !IO),
  117.       fcgx_puts(header, _, !IO),
  118.       fcgx_puts(Str, _, !IO),
  119.       main(!IO))
  120.  
  121.      ;
  122.      %true
  123.      % C4Cypher: Hmm, another subjective thing, my gut wants to stick a simple
  124.      % message to stdout just to verify that the program terminated cleanly,
  125.      % as opposed to comitting silent suicide.
  126.      
  127.      print("Done.\n", !IO)
  128.      
  129.      % END C4cypher
  130.      
  131.   ).
  132.  
  133. % Multi threaded demo -----------------------------------------------------------
  134.  
  135. % API ---------------------------------------------------------------------------
  136.  
  137. % get a parameter from the environment array
  138. :- pred fcgx_get_param(string::in, string::out, io::di, io::uo) is det.
  139.  
  140. :- pragma foreign_proc("C", fcgx_get_param(Name::in, Result::out,
  141.   _IO0::di, _IO::uo),
  142.   [promise_pure, will_not_call_mercury, tabled_for_io],
  143.   "
  144.    Result = FCGX_GetParam(Name, envp);
  145.   ").
  146.  
  147. % accept a request from the client
  148. :- pred fcgx_accept(bool::out, io::di, io::uo) is det.
  149.  
  150. :- pragma foreign_proc("C", fcgx_accept(Success::out, _IO0::di, _IO::uo),
  151.   [promise_pure, will_not_call_mercury, tabled_for_io],
  152.   "
  153.    Success = FCGX_Accept(&in, &out, &err, &envp) >= 0 ? MR_YES : MR_NO;
  154.   ").
  155.  
  156. % write a string to buffer
  157. :- pred fcgx_puts(string::in, bool::out, io::di, io::uo) is det.
  158.  
  159. :- pragma foreign_proc("C", fcgx_puts(Str::in, Success::out,
  160.   _IO0::di, _IO::uo),
  161.   [promise_pure, will_not_call_mercury, tabled_for_io],
  162.   "
  163.    Success = FCGX_PutStr(Str, strlen(Str), out) >= 0 ? MR_YES : MR_NO;
  164.   ").
  165.  
  166. % tests whether application is CGI or FCGI (for compatibility)
  167. % True if CGI, False if FCGI
  168. :- pred fcgx_isCGI(bool::out, io::di, io::uo) is det.
  169.  
  170. :- pragma foreign_proc("C", fcgx_isCGI(Result::out, _IO0::di, _IO::uo),
  171.   [promise_pure, will_not_call_mercury, tabled_for_io],
  172.   "
  173.    Result = FCGX_isCGI() ? MR_YES : MR_NO;
  174.   ").            
  175.  
  176. :- pred fcgx_finish(io::di, io::uo) is det.
  177.  
  178. :- pragma foreign_proc("C", fcgx_finish(_IO0::di, _IO::uo),
  179.   [promise_pure, will_not_call_mercury, tabled_for_io],
  180.   "
  181.    FCGX_Finish_r(&the_request);
  182.   ").
  183.  
  184. % thread safe
  185. % finish request accepted by previous call to fcgx_accept
  186. % also frees any storage allocated by previous call
  187. :- pred fcgx_finish_r(c_pointer::in, io::di, io::uo) is det.
  188.  
  189. :- pragma foreign_proc("C", fcgx_finish_r(ReqDataPtr::in, _IO0::di, _IO::uo),
  190.   [thread_safe, promise_pure, will_not_call_mercury, tabled_for_io],
  191.   "
  192.    FCGX_Finish_r((FCGX_Request *)ReqDataPtr);
  193.   ").
  194.  
  195. % initialize FCGX library. This is called by fcgx_accept
  196. % but should be caleld when using fcgx_accept_r
  197. :- pred fcgx_init(bool::out, io::di, io::uo) is det.
  198.  
  199. :- pragma foreign_proc("C", fcgx_init(Success::out, _IO0::di, _IO::uo),
  200.   [promise_pure, will_not_call_mercury, tabled_for_io],
  201.   "
  202.    Success = FCGX_Init() == 0 ? MR_YES : MR_NO;
  203.   ").            
  204.  
  205. % thread safe
  206. % accept new request from HTTP server
  207. % 0 is success, -1 is error.
  208. :- pred fcgx_accept_r(bool::out, io::di, io::uo) is det.
  209.  
  210. :- pragma foreign_proc("C", fcgx_accept_r(Success::out, _IO0::di, _IO::uo),
  211.   [thread_safe, promise_pure, will_not_call_mercury, tabled_for_io],
  212.   "
  213.    Success = FCGX_Accept(&in, &out, &err, &envp) >= 0 ? MR_YES : MR_NO;          
  214.   ").
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement