Tuesday, January 25, 2011

Guile web challenge: a mysql/php blog on sizzweb -- take 1

Today's internet challenge will be to set up a mysql/php blog on sizzweb, a webserver written entirely in Guile scheme.

Like yesterday, the blog software for today will be b2evolution version 4.0.3.

The webserver for today will be sizzweb version 1.12.

Again, why would I even want to do such a thing?  Because I find it fun.  I don't make fun of you for going golfing, and that's an even bigger waste of time.

sizzweb depends on the guile-www package.  I downloaded and installed guile-www-2.29.

A small bug in latest rev of guile-www-2.29 kept it from building on my machine guile-www bug #32244.

Part 1: getting sizzweb to run


Last time I tried to install this, it was a bit of a failure (not that I tried very hard, or at all).  The problem is that sizzweb is part of a larger package called ttn-do, and ttn-do historically has been targeted on a fork of Guile that had a more powerful set of install and configure tools that the official Guile.

I downloaded ttn-do-379.tar.gz and did ./configure and make, and the build failed with an error in a call to guile-toolsguile-tools is distributed with guile and is sort of a meta tool that calls on of a dozen other scripts that work with scheme sources. ttn-do was looking for the c2x script which is not a script in the mainline guile distribution. This is the sort of thing I thought would happen. This means I won't be able to build the modules in the ttn-do/zz directory because they rely on c2x.

Also guile-tools does not give a nice warning if it can't find a script. Guile bug #32243

So, instead I directly copied the scheme files in ttn-do and ttn-to/zzz into my my guile site directory manually.  Then, to get it to work I
  • ttn-do/zzz/filesystem.scm: changed all calls to make-shared-substring to substring
  • ttn-do/zzz/publishing.scm: use (ice-9 optargs) instead of (ice-9 optargs-kw) 
I also added my own version of the module (ttn-do zz sys linux-gnu) to replace the one function that sizzweb uses from it.

 (define-module (ttn-do zz sys linux-gnu)
  #:use-module (system foreign)
  #:use-module (rnrs bytevectors)
  #:export (sendfile/never-fewer))

;;(define libc (dynamic-link "/usr/lib64/libc.so"))
(define libc (dynamic-link))

(define sendfile
  (pointer->procedure
   long    ; really ssize_t, but, (system
           ; foreign) doesn't have a
           ; ssize_t.
   (dynamic-func "sendfile" libc)
   (list
    int
    int
    unsigned-long   ; Really this is a pointer to
                    ; an off_t, but, we always
                    ; pass it a null pointer
    size_t)))

(define errno (dynamic-pointer "errno" libc))

(define (errno-val)
  (let ((bv (pointer->bytevector errno int)))
    ;; assuming errno is a 4-byte int
    (bytevector-s32-native-ref bv 0))) 

(define (sendfile/never-fewer outfd infd unused count)
  (let loop ((count count))
    (let ((bytes-written (sendfile outfd infd 0 count)))
      (cond
       ((< bytes-written 0)
        (scm-error 'system-error
                   "sendfile/never-fewer"
                   (strerror (errno-val))
                   '()
                   (list (errno-val))))
       ((and (>= bytes-written count))
        *unspecified*)
       ((and (> bytes-written 0) (> count bytes-written))
        (loop (- count bytes-written)))))))
And with all that, I've got the webserver up and running.

Part 2: getting PHP to run

sizzweb has no native php support, but it does have a plug-in architecture called `servlets'.  Basically you create a file named servlets.scm and then write a custom responder that gets used when the input path matches a given regular expression.


The way the servlets system works is that if it matches the regex it gets passed to the handler whether or not there is actually a document at that location.  There would actually be a fair bit of work involved to get it to run PHP.  Subtasks would include
  • Adding index.php to the list of default files
  • Checking to see if the php file is actually there, is not a symlink, and is readable
  • Parsing the GET variables out of the URI
  • And calling php-cgi
But that is enough hacking fun for one day.  Tomorrow, we shall see what the future holds.

Monday, January 24, 2011

Guile web madness: a mysql/php blog on serveez-mg -- take 1

Today's internet madness will be to set up a PHP/MySQL-based weblog on top of one of the Guile webservers.

The blog software for today will be b2evolution version 4.0.3.

The webserver for today will be serveez-mg version 0.2.  serveez-mg isn't really a Guile webserver, but, it is a software that I hacked on that has some Guile features, so I'm starting with what I know.

I'm starting off on my Fedora 14 box on x86_64.  I installed the mysql and phpMyAdmin packages.

So, b2evolution first says that you should use phpMyAdmin to make a database.  I could do this using the mysql command line tool, but, I'll need to get PHP working eventually.  May as well start now.


serveez-mg lacks an SAPI to use PHP directly, so I'm going to have to use it in cgi mode.

OK.

Part 1: setting up serveez-mg as a cgi-enabled webserver

On a Fedora 14 box, /var/www comes set up for Apache.  I don't really want to overwrite it, so I'll set up a parallel directory structure.

$ su 
$ mkdir /var/serveez-www
$ mkdir /var/serveez-www/html
$ mkdir /var/serveez-www/cgi-bin

serveez-mg needs a configuration file: `serveez.cfg'.

;; === Load convenience file  
(use-modules (serveez-mg lib))

;; === Greet the user
(printsln " "
          "** Welcome to Serveez" serveez-version
          "using Guile" guile-version
          (if have-debug
              "(debugging enabled)"
              ""
           ))

;; === Control protocol server for remote control.
(define-port! 'control-port `(
                              (proto . tcp)
                              (port . 42420)
                              (ipaddr . "127.0.0.11")
                              ))

(define-server! 'control-server)

(bind-server! 'control-port 'control-server)

(serveez-passwd "qruo5rZkLyu22")

;; === Web Server.
(define-port! 'http-port '(
                           ("proto"  . "tcp")
                           ("port"   . 80)
                           ("ipaddr" . "*")))

(define-server! 'http-server '(
              ;; standard properties                                           
              ("admin"        . "spike@xxxxxx.dyndns.org")
              ("host"         . "xxxxxx.dyndns.org")
              ("logfile"      . "http-access.log")
              ("logformat"    . "%h %i %u [%t] \"%R\" %c %l")
              ("indexfile"    . "index.html")
              ("docs"         . "/var/serveez-www/html")
              ("userdir"      . "public_html")
              ("type-file"    . "/etc/mime.types")             
              ("default-type" . "text/plain")
              ("nslookup"     . on)
              ("ident"        . yes)

              ;; cgi interface                                                 
              ("cgi-url"         . "/cgi-bin")
              ("cgi-dir"         . "/var/serveez-www/cgi-bin")
              ("cgi-application" . (("php"  . "php-cgi")))
                                   

Note in the last line how php applications are supposed to be associated with
the php-cgi interpreter.  This will be the source of some comedy in about four paragraphs.

(Wow, the default index file in serveez-mg tries to use the image internal-gopher-menu.  That's some old mojo.)

Part 2: making phpMyAdmin work

Fedora 14 installs phpMyAdmin to work gracefully with Apache and uses Apache aliases to translate paths to where it is installed.  That is not what I need.  So, I'm going to have to install phpMyAdmin by hand into serveez-mg's tree.

So I downloaded phpMyAdmin-3.3.9, unpacked it into the directory /var/serveez-www/cgi-bin/phpMyAdmin

In phpMyAdmin's manual, it tells you to unpack it, and then navigate to the setup folder.  I dutifully point my browser to http://127.0.0.1/cgi-bin/phpMyAdmin/setup and give it a try.  No joy.  So with about 20 minutes of debugging, I learn three important facts.
  1. serveez-mg only supports one default index file, which I've currently set to index.html.  I need to add support for multiple files so that I can put index.php as an alternate index file.
  2. That cgi-application alist in the serveez.cfg -- the one that is supposed to associate php files to the php-cgi executable -- does absolutely nothing.
  3. Thus, the only thing that would work in the cgi-bin directory are executable programs and shell scripts.
And, with dinner-time fast approaching, thus ends today's lesson.