Hello,

I'm using mathopd embedded within a larger C++ program on a Windows Cygwin 
platform. I needed C access to mathopd POST requests, so I modified a few 
snippets from different open source projects to produce this functionality. 
Here is the result. I thought these might be useful.

- Stephan

 
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include "mathopd.h"

/* Function from Paul Phillips <paulp <at> go2net.com>
  * Modified to not use global mathopd_tempfile
  Stephan Erickson 
*/

int create_temporary_file(short want_unlink, char *storage, int size)
{
  int fd;
  char *mathopd_tempfile = malloc(PATHLEN+1);
  char *tempdir = "/tmp";

  mathopd_tempfile[0]=0; 
  strcat(mathopd_tempfile, tempdir); // use strcat for constants only
  strcat(mathopd_tempfile, "/mathopd-temp.XXXXXX");
 
  // open temp file 
  fd = mkstemp(mathopd_tempfile);
  if (fd == -1) {
    log_d("mkstemp");
    return 0;
  }

  if (storage != NULL) {
    int len = strlen(mathopd_tempfile);
    if (len < size) {
      memcpy(storage, mathopd_tempfile, len + 1);
    } else {
      close(fd);
      fd = 0;
      log_d("not enough memory for memcpy in storage\n");
      want_unlink = 1;
    }   
  }
 
  if (want_unlink) {
    if (unlink(mathopd_tempfile) == -1) {
      close(fd);
      fd = 0;
      log_d("unlink temp file\n");
    } 
  }
  return (fd);
}

/*
From: Toby DiPasquale <anany <at> ece.villanova.edu>
NOTE: This function must be called AFTER process_headers(), preferably in
it's own code module, similar to how imap.c, dump.c, dummy.c, redirect.c
and cgi.c are set up.

Modified to 
  - write to temporary file
  -  use recv for multiple reads to handle large size uploads
  -  not use MSG_SEEK which is incorrectly implemented on Windows platforms. 
Stephan Erickson

*/
/* get the POST body from the stream */
int get_post_file (struct request *r, char *tempfile, int maxsize)
{
        int rv, size;
        char *input_buffer;
        int fd = 0;
        int pagesize = 100000;
        int loopcount = 0;
      
        if (r->in_content_length==0) { 
          tempfile[0]=0;
          return 0; 
        }
        size = atoi (r->in_content_length);
        input_buffer = malloc (pagesize+1);
        fcntl (r->cn->fd, F_SETFL, 0);

        do {   
                rv = recv (r->cn->fd, input_buffer, pagesize, 0);
                size -= rv; 
                if (rv == -1)
                {
                        switch (errno) {
                        default:
                                log_d (
                                "get_post_file: error reading from fd"
                                );
                                lerror ("recv");
                        case ECONNRESET:
                                r->cn->action = HC_CLOSING;
                        case EAGAIN:
                                return 0;
                        }
                }
                if (rv == 0)
                {
                        log_d ("get_post_file: body empty");
                        r->cn->action = HC_CLOSING;
                        return 0;
                }
                if (loopcount==0) {
                        fd = create_temporary_file(0, tempfile, maxsize);
                }
                if (fd) {
                        write(fd, input_buffer, rv);
                }
                loopcount++; 
        } while (size>0); 

        free(input_buffer);
        if (fd) {
          close(fd);
        }
        fcntl (r->cn->fd, F_SETFL, O_NONBLOCK);
        return 0;
}

Reply via email to