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;
}