simplified relocation handling
deleted qse_httpd_entaskredir() and related definitions added virtual(function pointer) cgi support. improved pio to read /dev/fd implemented QSE_PIO_FNCCMD for qse_pio_t
This commit is contained in:
parent
bf25f92704
commit
b7d14da21e
@ -357,6 +357,33 @@ static int daemonize (int devnull)
|
|||||||
|
|
||||||
/* --------------------------------------------------------------------- */
|
/* --------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
int xxxx (void* ctx, qse_env_char_t** envir)
|
||||||
|
{
|
||||||
|
extern char** environ;
|
||||||
|
char buf[1000];
|
||||||
|
char* cl;
|
||||||
|
int cl_i = 0;
|
||||||
|
environ = envir;
|
||||||
|
printf ("Content-Type: text/html\n\n");
|
||||||
|
printf ("<html><body><pre>\n");
|
||||||
|
system ("ls -laF /tmp");
|
||||||
|
printf ("--------------------\n");
|
||||||
|
system ("printenv");
|
||||||
|
cl = getenv("CONTENT_LENGTH");
|
||||||
|
if (cl) cl_i = atoi(cl);
|
||||||
|
//if (cl_i)
|
||||||
|
//{
|
||||||
|
while (fgets (buf, sizeof(buf), stdin) != NULL)
|
||||||
|
{
|
||||||
|
printf ("%s", buf);
|
||||||
|
}
|
||||||
|
//}
|
||||||
|
// system ("while read xxx; do echo $xxx; done; echo 123 456 789");
|
||||||
|
printf ("</pre></body></html>\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int make_resource (
|
static int make_resource (
|
||||||
qse_httpd_t* httpd, qse_httpd_client_t* client,
|
qse_httpd_t* httpd, qse_httpd_client_t* client,
|
||||||
qse_htre_t* req, qse_httpd_rsrc_t* rsrc)
|
qse_htre_t* req, qse_httpd_rsrc_t* rsrc)
|
||||||
@ -708,10 +735,10 @@ found:
|
|||||||
if (qse_mbscmp (qse_htre_getqpath(qinfo->req), QSE_MT("/version")) == 0)
|
if (qse_mbscmp (qse_htre_getqpath(qinfo->req), QSE_MT("/version")) == 0)
|
||||||
{
|
{
|
||||||
/* return static text without inspecting further */
|
/* return static text without inspecting further */
|
||||||
((qse_httpd_serverstd_root_t*)result)->type = QSE_HTTPD_SERVERSTD_ROOT_TEXT;
|
|
||||||
|
/*((qse_httpd_serverstd_root_t*)result)->type = QSE_HTTPD_SERVERSTD_ROOT_TEXT;
|
||||||
((qse_httpd_serverstd_root_t*)result)->u.text.ptr = QSE_MT(QSE_PACKAGE_NAME " " QSE_PACKAGE_VERSION);
|
((qse_httpd_serverstd_root_t*)result)->u.text.ptr = QSE_MT(QSE_PACKAGE_NAME " " QSE_PACKAGE_VERSION);
|
||||||
((qse_httpd_serverstd_root_t*)result)->u.text.mime = QSE_MT("text/plain");
|
((qse_httpd_serverstd_root_t*)result)->u.text.mime = QSE_MT("text/plain");*/
|
||||||
}
|
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -724,7 +751,10 @@ found:
|
|||||||
|
|
||||||
((qse_httpd_serverstd_realm_t*)result)->name = loccfg->xcfg[XCFG_REALM];
|
((qse_httpd_serverstd_realm_t*)result)->name = loccfg->xcfg[XCFG_REALM];
|
||||||
|
|
||||||
|
/* qinfo->xpath is not available for the REALM query in the std implementation.
|
||||||
|
* let me check if it's available in case the implementation changes */
|
||||||
apath = qinfo->xpath? qinfo->xpath: qse_htre_getqpath (qinfo->req);
|
apath = qinfo->xpath? qinfo->xpath: qse_htre_getqpath (qinfo->req);
|
||||||
|
printf ("apth in READM QUERY [%s]\n", apath);
|
||||||
if (apath)
|
if (apath)
|
||||||
{
|
{
|
||||||
const qse_mchar_t* base;
|
const qse_mchar_t* base;
|
||||||
@ -803,12 +833,30 @@ found:
|
|||||||
qse_size_t i;
|
qse_size_t i;
|
||||||
qse_httpd_serverstd_cgi_t* scgi;
|
qse_httpd_serverstd_cgi_t* scgi;
|
||||||
const qse_mchar_t* xpath_base;
|
const qse_mchar_t* xpath_base;
|
||||||
|
qse_mchar_t* qpath;
|
||||||
|
|
||||||
xpath_base = qse_mbsbasename (qinfo->xpath);
|
qpath = qse_htre_getqpath(qinfo->req);
|
||||||
|
|
||||||
scgi = (qse_httpd_serverstd_cgi_t*)result;
|
scgi = (qse_httpd_serverstd_cgi_t*)result;
|
||||||
qse_memset (scgi, 0, QSE_SIZEOF(*scgi));
|
qse_memset (scgi, 0, QSE_SIZEOF(*scgi));
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
printf ("qinfo->xpath ####### [%s] %d [%s]\n", qinfo->xpath, qinfo->xpath_nx, qpath);
|
||||||
|
//if (qse_mbscmp (qinfo->xpath, QSE_MT("/tmp/version.cgi")) == 0)
|
||||||
|
if (qse_mbscmp (qpath, QSE_MT("/local/version.cgi")) == 0)
|
||||||
|
{
|
||||||
|
scgi->cgi = 1;
|
||||||
|
scgi->nph = 0;
|
||||||
|
scgi->fncptr = xxxx;
|
||||||
|
scgi->shebang = QSE_NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
if (!qinfo->xpath_nx)
|
||||||
|
{
|
||||||
|
xpath_base = qse_mbsbasename (qinfo->xpath);
|
||||||
for (i = 0; i < QSE_COUNTOF(loccfg->cgi); i++)
|
for (i = 0; i < QSE_COUNTOF(loccfg->cgi); i++)
|
||||||
{
|
{
|
||||||
struct cgi_t* cgi;
|
struct cgi_t* cgi;
|
||||||
@ -825,6 +873,7 @@ found:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -59,6 +59,10 @@ enum qse_pio_flag_t
|
|||||||
* them to prevent inheritance. */
|
* them to prevent inheritance. */
|
||||||
QSE_PIO_NOCLOEXEC = (1 << 5),
|
QSE_PIO_NOCLOEXEC = (1 << 5),
|
||||||
|
|
||||||
|
/** indidate that the command to qse_pio_open() is a pointer to
|
||||||
|
* #qse_pio_fnc_t. supported on unix/linux only */
|
||||||
|
QSE_PIO_FNCCMD = (1 << 6),
|
||||||
|
|
||||||
/** write to stdin of a child process */
|
/** write to stdin of a child process */
|
||||||
QSE_PIO_WRITEIN = (1 << 8),
|
QSE_PIO_WRITEIN = (1 << 8),
|
||||||
/** read stdout of a child process */
|
/** read stdout of a child process */
|
||||||
@ -113,6 +117,16 @@ enum qse_pio_hid_t
|
|||||||
};
|
};
|
||||||
typedef enum qse_pio_hid_t qse_pio_hid_t;
|
typedef enum qse_pio_hid_t qse_pio_hid_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef int (*qse_pio_fncptr_t) (void* ctx, qse_env_char_t** envir);
|
||||||
|
|
||||||
|
typedef struct qse_pio_fnc_t qse_pio_fnc_t;
|
||||||
|
struct qse_pio_fnc_t
|
||||||
|
{
|
||||||
|
qse_pio_fncptr_t ptr;
|
||||||
|
void* ctx;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The qse_pio_errnum_t type defines error numbers.
|
* The qse_pio_errnum_t type defines error numbers.
|
||||||
*/
|
*/
|
||||||
@ -177,6 +191,7 @@ struct qse_pio_pin_t
|
|||||||
qse_pio_t* self;
|
qse_pio_t* self;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The qse_pio_t type defines a structure to store status for piped I/O
|
* The qse_pio_t type defines a structure to store status for piped I/O
|
||||||
* to a child process. The qse_pio_xxx() funtions are written around this
|
* to a child process. The qse_pio_xxx() funtions are written around this
|
||||||
|
@ -28,6 +28,8 @@
|
|||||||
#include <qse/cmn/nwad.h>
|
#include <qse/cmn/nwad.h>
|
||||||
#include <qse/cmn/time.h>
|
#include <qse/cmn/time.h>
|
||||||
#include <qse/cmn/tmr.h>
|
#include <qse/cmn/tmr.h>
|
||||||
|
#include <qse/cmn/env.h>
|
||||||
|
|
||||||
|
|
||||||
typedef struct qse_httpd_t qse_httpd_t;
|
typedef struct qse_httpd_t qse_httpd_t;
|
||||||
typedef struct qse_httpd_mate_t qse_httpd_mate_t;
|
typedef struct qse_httpd_mate_t qse_httpd_mate_t;
|
||||||
@ -689,6 +691,19 @@ struct qse_httpd_urs_t
|
|||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* ensure to define qse_httpd_fncptr_t to the same as
|
||||||
|
* qse_pio_fncptr_t in <qse/cmn/pio.h> */
|
||||||
|
typedef int (*qse_httpd_fncptr_t) (void* ctx, qse_env_char_t** envir);
|
||||||
|
|
||||||
|
typedef struct qse_httpd_fnc_t qse_httpd_fnc_t;
|
||||||
|
struct qse_httpd_fnc_t
|
||||||
|
{
|
||||||
|
qse_httpd_fncptr_t ptr;
|
||||||
|
void* ctx;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The qse_httpd_rsrc_type_t defines the resource type than can
|
* The qse_httpd_rsrc_type_t defines the resource type than can
|
||||||
* be entasked with qse_httpd_entaskrsrc().
|
* be entasked with qse_httpd_entaskrsrc().
|
||||||
@ -702,7 +717,6 @@ enum qse_httpd_rsrc_type_t
|
|||||||
QSE_HTTPD_RSRC_FILE,
|
QSE_HTTPD_RSRC_FILE,
|
||||||
QSE_HTTPD_RSRC_PROXY,
|
QSE_HTTPD_RSRC_PROXY,
|
||||||
QSE_HTTPD_RSRC_RELOC,
|
QSE_HTTPD_RSRC_RELOC,
|
||||||
QSE_HTTPD_RSRC_REDIR,
|
|
||||||
QSE_HTTPD_RSRC_TEXT
|
QSE_HTTPD_RSRC_TEXT
|
||||||
};
|
};
|
||||||
typedef enum qse_httpd_rsrc_type_t qse_httpd_rsrc_type_t;
|
typedef enum qse_httpd_rsrc_type_t qse_httpd_rsrc_type_t;
|
||||||
@ -711,16 +725,39 @@ enum qse_httpd_rsrc_flag_t
|
|||||||
{
|
{
|
||||||
QSE_HTTPD_RSRC_100_CONTINUE = (1 << 0)
|
QSE_HTTPD_RSRC_100_CONTINUE = (1 << 0)
|
||||||
};
|
};
|
||||||
|
typedef enum qse_httpd_rsrc_flag_t qse_httpd_rsrc_flag_t;
|
||||||
|
|
||||||
|
enum qse_httpd_rsrc_cgi_flag_t
|
||||||
|
{
|
||||||
|
/* non-parsed header */
|
||||||
|
QSE_HTTPD_RSRC_CGI_NPH = (1 << 0),
|
||||||
|
|
||||||
|
/* 'path' points to qse_httpd_fncptr_t && 'shebang' points to its context */
|
||||||
|
QSE_HTTPD_RSRC_CGI_FNC = (1 << 1)
|
||||||
|
};
|
||||||
|
typedef enum qse_httpd_rsrc_cgi_flag_t qse_httpd_rsrc_cgi_flag_t;
|
||||||
|
|
||||||
|
|
||||||
typedef struct qse_httpd_rsrc_cgi_t qse_httpd_rsrc_cgi_t;
|
typedef struct qse_httpd_rsrc_cgi_t qse_httpd_rsrc_cgi_t;
|
||||||
struct qse_httpd_rsrc_cgi_t
|
struct qse_httpd_rsrc_cgi_t
|
||||||
{
|
{
|
||||||
|
/* bitwised-ORed of #qse_httpd_rsrc_cgi_flag_t */
|
||||||
|
int flags;
|
||||||
|
|
||||||
|
/* script path resolved against file system */
|
||||||
const qse_mchar_t* path;
|
const qse_mchar_t* path;
|
||||||
|
|
||||||
|
/* script path as in qpath */
|
||||||
const qse_mchar_t* script;
|
const qse_mchar_t* script;
|
||||||
|
|
||||||
|
/* trailing part of qpath excluding the script path.
|
||||||
|
* for a qpath of /tmp/abc.cgi/a/b/c, if /tmp/abc.cgi is a script path,
|
||||||
|
* /a/b/c forms the suffix.*/
|
||||||
const qse_mchar_t* suffix;
|
const qse_mchar_t* suffix;
|
||||||
|
|
||||||
const qse_mchar_t* root;
|
const qse_mchar_t* root;
|
||||||
|
|
||||||
const qse_mchar_t* shebang;
|
const qse_mchar_t* shebang;
|
||||||
int nph;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum qse_httpd_rsrc_proxy_flag_t
|
enum qse_httpd_rsrc_proxy_flag_t
|
||||||
@ -733,6 +770,7 @@ enum qse_httpd_rsrc_proxy_flag_t
|
|||||||
QSE_HTTPD_RSRC_PROXY_DNS_SERVER = (1 << 5), /* dns address specified */
|
QSE_HTTPD_RSRC_PROXY_DNS_SERVER = (1 << 5), /* dns address specified */
|
||||||
QSE_HTTPD_RSRC_PROXY_URS_SERVER = (1 << 6), /* urs address specified */
|
QSE_HTTPD_RSRC_PROXY_URS_SERVER = (1 << 6), /* urs address specified */
|
||||||
};
|
};
|
||||||
|
typedef enum qse_httpd_rsrc_proxy_flag_t qse_httpd_rsrc_proxy_flag_t;
|
||||||
|
|
||||||
typedef struct qse_httpd_rsrc_proxy_t qse_httpd_rsrc_proxy_t;
|
typedef struct qse_httpd_rsrc_proxy_t qse_httpd_rsrc_proxy_t;
|
||||||
struct qse_httpd_rsrc_proxy_t
|
struct qse_httpd_rsrc_proxy_t
|
||||||
@ -774,6 +812,21 @@ struct qse_httpd_rsrc_dir_t
|
|||||||
const qse_mchar_t* foot;
|
const qse_mchar_t* foot;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum qse_httpd_rsrc_reloc_flag_t
|
||||||
|
{
|
||||||
|
QSE_HTTPD_RSRC_RELOC_PERMANENT = (1 << 0),
|
||||||
|
QSE_HTTPD_RSRC_RELOC_KEEPMETHOD = (1 << 1),
|
||||||
|
QSE_HTTPD_RSRC_RELOC_APPENDSLASH = (1 << 2)
|
||||||
|
};
|
||||||
|
typedef enum qse_httpd_rsrc_reloc_flag_t qse_httpd_rsrc_reloc_flag_t;
|
||||||
|
|
||||||
|
typedef struct qse_httpd_rsrc_reloc_t qse_httpd_rsrc_reloc_t;
|
||||||
|
struct qse_httpd_rsrc_reloc_t
|
||||||
|
{
|
||||||
|
int flags;
|
||||||
|
const qse_mchar_t* dst;
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct qse_httpd_rsrc_t qse_httpd_rsrc_t;
|
typedef struct qse_httpd_rsrc_t qse_httpd_rsrc_t;
|
||||||
struct qse_httpd_rsrc_t
|
struct qse_httpd_rsrc_t
|
||||||
{
|
{
|
||||||
@ -802,15 +855,7 @@ struct qse_httpd_rsrc_t
|
|||||||
|
|
||||||
qse_httpd_rsrc_proxy_t proxy;
|
qse_httpd_rsrc_proxy_t proxy;
|
||||||
|
|
||||||
struct
|
qse_httpd_rsrc_reloc_t reloc;
|
||||||
{
|
|
||||||
const qse_mchar_t* dst;
|
|
||||||
} reloc;
|
|
||||||
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
const qse_mchar_t* dst;
|
|
||||||
} redir;
|
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
@ -1074,19 +1119,10 @@ QSE_EXPORT qse_httpd_task_t* qse_httpd_entaskreloc (
|
|||||||
qse_httpd_t* httpd,
|
qse_httpd_t* httpd,
|
||||||
qse_httpd_client_t* client,
|
qse_httpd_client_t* client,
|
||||||
qse_httpd_task_t* pred,
|
qse_httpd_task_t* pred,
|
||||||
const qse_mchar_t* dst,
|
const qse_httpd_rsrc_reloc_t* reloc,
|
||||||
qse_htre_t* req
|
qse_htre_t* req
|
||||||
);
|
);
|
||||||
|
|
||||||
QSE_EXPORT qse_httpd_task_t* qse_httpd_entaskredir (
|
|
||||||
qse_httpd_t* httpd,
|
|
||||||
qse_httpd_client_t* client,
|
|
||||||
qse_httpd_task_t* pred,
|
|
||||||
const qse_mchar_t* dst,
|
|
||||||
qse_htre_t* req
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
QSE_EXPORT qse_httpd_task_t* qse_httpd_entasknomod (
|
QSE_EXPORT qse_httpd_task_t* qse_httpd_entasknomod (
|
||||||
qse_httpd_t* httpd,
|
qse_httpd_t* httpd,
|
||||||
qse_httpd_client_t* client,
|
qse_httpd_client_t* client,
|
||||||
|
@ -90,9 +90,17 @@ struct qse_httpd_serverstd_auth_t
|
|||||||
typedef struct qse_httpd_serverstd_cgi_t qse_httpd_serverstd_cgi_t;
|
typedef struct qse_httpd_serverstd_cgi_t qse_httpd_serverstd_cgi_t;
|
||||||
struct qse_httpd_serverstd_cgi_t
|
struct qse_httpd_serverstd_cgi_t
|
||||||
{
|
{
|
||||||
int cgi: 1;
|
unsigned int cgi: 1;
|
||||||
int nph: 1;
|
unsigned int nph: 1;
|
||||||
const qse_mchar_t* shebang; /* optional, can be #QSE_NULL */
|
|
||||||
|
/* optional, can be #QSE_NULL. */
|
||||||
|
qse_httpd_fncptr_t fncptr;
|
||||||
|
|
||||||
|
/* optional, can be #QSE_NULL. if fncptr not #QSE_NULL, shebang is
|
||||||
|
* interpreted as void* and used as a context pointer to fnc.
|
||||||
|
* if fncptr is #QSE_NULL, it provides a pointer to the path
|
||||||
|
* to the program interpreter for executing a cgi script. */
|
||||||
|
const qse_mchar_t* shebang;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct qse_httpd_serverstd_index_t qse_httpd_serverstd_index_t;
|
typedef struct qse_httpd_serverstd_index_t qse_httpd_serverstd_index_t;
|
||||||
@ -135,7 +143,22 @@ struct qse_httpd_serverstd_query_info_t
|
|||||||
{
|
{
|
||||||
qse_httpd_client_t* client;
|
qse_httpd_client_t* client;
|
||||||
qse_htre_t* req;
|
qse_htre_t* req;
|
||||||
qse_mchar_t* xpath; /* query path combined with document root */
|
|
||||||
|
/**
|
||||||
|
* set to a query path combined with document root for these query types.
|
||||||
|
* - #QSE_HTTPD_SERVERSTD_CGI
|
||||||
|
* - #QSE_HTTPD_SERVERSTD_MIME
|
||||||
|
* - #QSE_HTTPD_SERVERSTD_DIRACC
|
||||||
|
* - #QSE_HTTPD_SERVERSTD_FILEACC
|
||||||
|
* - #QSE_HTTPD_SERVERSTD_DIRHEAD
|
||||||
|
* - #QSE_HTTPD_SERVERSTD_DIRFOOT
|
||||||
|
*
|
||||||
|
* set to #QSE_NULL for other query types.
|
||||||
|
*/
|
||||||
|
qse_mchar_t* xpath;
|
||||||
|
|
||||||
|
/** indiates that stat() failed over xpath when it's not #QSE_NULL. */
|
||||||
|
int xpath_nx;
|
||||||
};
|
};
|
||||||
typedef struct qse_httpd_serverstd_query_info_t qse_httpd_serverstd_query_info_t;
|
typedef struct qse_httpd_serverstd_query_info_t qse_httpd_serverstd_query_info_t;
|
||||||
|
|
||||||
|
@ -639,7 +639,6 @@ done:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
@ -376,8 +376,8 @@ static int close_unneeded_fds_using_proc (int* excepts, qse_size_t count)
|
|||||||
qse_mchar_t buf[64];
|
qse_mchar_t buf[64];
|
||||||
qse_mbsxfmt (buf, QSE_COUNTOF(buf), QSE_MT("/proc/%d/fd"), QSE_GETPID());
|
qse_mbsxfmt (buf, QSE_COUNTOF(buf), QSE_MT("/proc/%d/fd"), QSE_GETPID());
|
||||||
d = QSE_OPENDIR (buf);
|
d = QSE_OPENDIR (buf);
|
||||||
|
if (!d) d = QSE_OPENDIR (QSE_MT("/dev/fd")); /* Darwin, FreeBSD */
|
||||||
}
|
}
|
||||||
/* TODO: try /dev/fd - FreeBSD, Darwin, OS X*/
|
|
||||||
|
|
||||||
if (d)
|
if (d)
|
||||||
{
|
{
|
||||||
@ -438,10 +438,9 @@ static int get_highest_fd (void)
|
|||||||
qse_mchar_t buf[64];
|
qse_mchar_t buf[64];
|
||||||
qse_mbsxfmt (buf, QSE_COUNTOF(buf), QSE_MT("/proc/%d/fd"), QSE_GETPID());
|
qse_mbsxfmt (buf, QSE_COUNTOF(buf), QSE_MT("/proc/%d/fd"), QSE_GETPID());
|
||||||
d = QSE_OPENDIR (buf);
|
d = QSE_OPENDIR (buf);
|
||||||
|
if (!d) d = QSE_OPENDIR (QSE_MT("/dev/fd")); /* Darwin, FreeBSD */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: try /dev/fd - FreeBSD, Darwin, OS X*/
|
|
||||||
|
|
||||||
if (d)
|
if (d)
|
||||||
{
|
{
|
||||||
int maxfd = -1;
|
int maxfd = -1;
|
||||||
@ -476,7 +475,7 @@ static int get_highest_fd (void)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else fd = rlim.rlim_max;
|
else fd = rlim.rlim_max;
|
||||||
if (fd == -1) fd = 1024; /* fallback */
|
if (fd <= -1) fd = 1024; /* fallback */
|
||||||
|
|
||||||
/* F_MAXFD is the highest fd. but RLIMIT_NOFILE and
|
/* F_MAXFD is the highest fd. but RLIMIT_NOFILE and
|
||||||
* _SC_OPEN_MAX returnes the maximum number of file
|
* _SC_OPEN_MAX returnes the maximum number of file
|
||||||
@ -486,6 +485,152 @@ static int get_highest_fd (void)
|
|||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static qse_pio_pid_t standard_fork_and_exec (qse_pio_t* pio, int pipes[], param_t* param, qse_env_t* env)
|
||||||
|
{
|
||||||
|
qse_pio_pid_t pid;
|
||||||
|
|
||||||
|
#if defined(HAVE_CRT_EXTERNS_H)
|
||||||
|
# define environ (*(_NSGetEnviron()))
|
||||||
|
#else
|
||||||
|
extern char** environ;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
pid = QSE_FORK();
|
||||||
|
if (pid <= -1)
|
||||||
|
{
|
||||||
|
pio->errnum = QSE_PIO_EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pid == 0)
|
||||||
|
{
|
||||||
|
/* child */
|
||||||
|
qse_pio_hnd_t devnull = -1;
|
||||||
|
|
||||||
|
if (!(pio->flags & QSE_PIO_NOCLOEXEC))
|
||||||
|
{
|
||||||
|
if (close_unneeded_fds_using_proc (pipes, 6) <= -1)
|
||||||
|
{
|
||||||
|
int fd = get_highest_fd ();
|
||||||
|
|
||||||
|
/* close all other unknown open handles except
|
||||||
|
* stdin/out/err and the pipes. */
|
||||||
|
while (fd > 2)
|
||||||
|
{
|
||||||
|
if (fd != pipes[0] && fd != pipes[1] &&
|
||||||
|
fd != pipes[2] && fd != pipes[3] &&
|
||||||
|
fd != pipes[4] && fd != pipes[5])
|
||||||
|
{
|
||||||
|
QSE_CLOSE (fd);
|
||||||
|
}
|
||||||
|
fd--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pio->flags & QSE_PIO_WRITEIN)
|
||||||
|
{
|
||||||
|
/* child should read */
|
||||||
|
QSE_CLOSE (pipes[1]);
|
||||||
|
pipes[1] = QSE_PIO_HND_NIL;
|
||||||
|
if (QSE_DUP2 (pipes[0], 0) <= -1) goto child_oops;
|
||||||
|
QSE_CLOSE (pipes[0]);
|
||||||
|
pipes[0] = QSE_PIO_HND_NIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pio->flags & QSE_PIO_READOUT)
|
||||||
|
{
|
||||||
|
/* child should write */
|
||||||
|
QSE_CLOSE (pipes[2]);
|
||||||
|
pipes[2] = QSE_PIO_HND_NIL;
|
||||||
|
if (QSE_DUP2 (pipes[3], 1) <= -1) goto child_oops;
|
||||||
|
|
||||||
|
if (pio->flags & QSE_PIO_ERRTOOUT)
|
||||||
|
{
|
||||||
|
if (QSE_DUP2 (pipes[3], 2) <= -1) goto child_oops;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSE_CLOSE (pipes[3]);
|
||||||
|
pipes[3] = QSE_PIO_HND_NIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pio->flags & QSE_PIO_READERR)
|
||||||
|
{
|
||||||
|
/* child should write */
|
||||||
|
QSE_CLOSE (pipes[4]);
|
||||||
|
pipes[4] = QSE_PIO_HND_NIL;
|
||||||
|
if (QSE_DUP2 (pipes[5], 2) <= -1) goto child_oops;
|
||||||
|
|
||||||
|
if (pio->flags & QSE_PIO_OUTTOERR)
|
||||||
|
{
|
||||||
|
if (QSE_DUP2 (pipes[5], 1) <= -1) goto child_oops;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSE_CLOSE (pipes[5]);
|
||||||
|
pipes[5] = QSE_PIO_HND_NIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((pio->flags & QSE_PIO_INTONUL) ||
|
||||||
|
(pio->flags & QSE_PIO_OUTTONUL) ||
|
||||||
|
(pio->flags & QSE_PIO_ERRTONUL))
|
||||||
|
{
|
||||||
|
#if defined(O_LARGEFILE)
|
||||||
|
devnull = QSE_OPEN (QSE_MT("/dev/null"), O_RDWR|O_LARGEFILE, 0);
|
||||||
|
#else
|
||||||
|
devnull = QSE_OPEN (QSE_MT("/dev/null"), O_RDWR, 0);
|
||||||
|
#endif
|
||||||
|
if (devnull <= -1) goto child_oops;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((pio->flags & QSE_PIO_INTONUL) &&
|
||||||
|
QSE_DUP2(devnull,0) <= -1) goto child_oops;
|
||||||
|
if ((pio->flags & QSE_PIO_OUTTONUL) &&
|
||||||
|
QSE_DUP2(devnull,1) <= -1) goto child_oops;
|
||||||
|
if ((pio->flags & QSE_PIO_ERRTONUL) &&
|
||||||
|
QSE_DUP2(devnull,2) <= -1) goto child_oops;
|
||||||
|
|
||||||
|
if ((pio->flags & QSE_PIO_INTONUL) ||
|
||||||
|
(pio->flags & QSE_PIO_OUTTONUL) ||
|
||||||
|
(pio->flags & QSE_PIO_ERRTONUL))
|
||||||
|
{
|
||||||
|
QSE_CLOSE (devnull);
|
||||||
|
devnull = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pio->flags & QSE_PIO_DROPIN) QSE_CLOSE(0);
|
||||||
|
if (pio->flags & QSE_PIO_DROPOUT) QSE_CLOSE(1);
|
||||||
|
if (pio->flags & QSE_PIO_DROPERR) QSE_CLOSE(2);
|
||||||
|
|
||||||
|
|
||||||
|
if (pio->flags & QSE_PIO_FNCCMD)
|
||||||
|
{
|
||||||
|
/* -----------------------------------------------
|
||||||
|
* the function pointer to execute has been given.
|
||||||
|
* -----------------------------------------------*/
|
||||||
|
qse_pio_fnc_t* fnc = (qse_pio_fnc_t*)param;
|
||||||
|
int retx;
|
||||||
|
|
||||||
|
retx = fnc->ptr (fnc->ctx, (env? qse_env_getarr(env): environ));
|
||||||
|
if (devnull >= 0) QSE_CLOSE (devnull);
|
||||||
|
QSE_EXIT (retx);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
QSE_EXECVE (param->argv[0], param->argv, (env? qse_env_getarr(env): environ));
|
||||||
|
|
||||||
|
/* if exec fails, free 'param' parameter which is an inherited pointer */
|
||||||
|
free_param (pio, param);
|
||||||
|
}
|
||||||
|
|
||||||
|
child_oops:
|
||||||
|
if (devnull >= 0) QSE_CLOSE (devnull);
|
||||||
|
QSE_EXIT (128);
|
||||||
|
}
|
||||||
|
|
||||||
|
return pid;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int set_pipe_nonblock (qse_pio_t* pio, qse_pio_hnd_t fd, int enabled)
|
static int set_pipe_nonblock (qse_pio_t* pio, qse_pio_hnd_t fd, int enabled)
|
||||||
@ -1205,7 +1350,8 @@ create_process:
|
|||||||
pio->errnum = QSE_PIO_ENOIMPL;
|
pio->errnum = QSE_PIO_ENOIMPL;
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
#elif defined(HAVE_POSIX_SPAWN) && !(defined(QSE_SYSCALL0) && defined(SYS_vfork))
|
#else
|
||||||
|
|
||||||
if (flags & QSE_PIO_WRITEIN)
|
if (flags & QSE_PIO_WRITEIN)
|
||||||
{
|
{
|
||||||
if (QSE_PIPE(&handle[0]) <= -1)
|
if (QSE_PIPE(&handle[0]) <= -1)
|
||||||
@ -1244,6 +1390,18 @@ create_process:
|
|||||||
goto oops;
|
goto oops;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pio->flags & QSE_PIO_FNCCMD)
|
||||||
|
{
|
||||||
|
/* i know i'm abusing typecasting here.
|
||||||
|
* cmd is supposed to be qse_pio_fnc_t*, anyway */
|
||||||
|
pid = standard_fork_and_exec (pio, handle, (param_t*)cmd, env);
|
||||||
|
if (pid <= -1) goto oops;
|
||||||
|
pio->child = pid;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#if defined(HAVE_POSIX_SPAWN) && !(defined(QSE_SYSCALL0) && defined(SYS_vfork))
|
||||||
|
|
||||||
if ((pserr = posix_spawn_file_actions_init (&fa)) != 0)
|
if ((pserr = posix_spawn_file_actions_init (&fa)) != 0)
|
||||||
{
|
{
|
||||||
pio->errnum = syserr_to_errnum (pserr);
|
pio->errnum = syserr_to_errnum (pserr);
|
||||||
@ -1409,6 +1567,7 @@ create_process:
|
|||||||
}
|
}
|
||||||
|
|
||||||
posix_spawnattr_init (&psattr);
|
posix_spawnattr_init (&psattr);
|
||||||
|
|
||||||
#if defined(__linux)
|
#if defined(__linux)
|
||||||
#if !defined(POSIX_SPAWN_USEVFORK)
|
#if !defined(POSIX_SPAWN_USEVFORK)
|
||||||
# define POSIX_SPAWN_USEVFORK 0x40
|
# define POSIX_SPAWN_USEVFORK 0x40
|
||||||
@ -1437,60 +1596,8 @@ create_process:
|
|||||||
}
|
}
|
||||||
|
|
||||||
pio->child = pid;
|
pio->child = pid;
|
||||||
if (flags & QSE_PIO_WRITEIN)
|
|
||||||
{
|
|
||||||
QSE_CLOSE (handle[0]);
|
|
||||||
handle[0] = QSE_PIO_HND_NIL;
|
|
||||||
}
|
|
||||||
if (flags & QSE_PIO_READOUT)
|
|
||||||
{
|
|
||||||
QSE_CLOSE (handle[3]);
|
|
||||||
handle[3] = QSE_PIO_HND_NIL;
|
|
||||||
}
|
|
||||||
if (flags & QSE_PIO_READERR)
|
|
||||||
{
|
|
||||||
QSE_CLOSE (handle[5]);
|
|
||||||
handle[5] = QSE_PIO_HND_NIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
#elif defined(QSE_SYSCALL0) && defined(SYS_vfork)
|
#elif defined(QSE_SYSCALL0) && defined(SYS_vfork)
|
||||||
if (flags & QSE_PIO_WRITEIN)
|
|
||||||
{
|
|
||||||
if (QSE_PIPE(&handle[0]) <= -1)
|
|
||||||
{
|
|
||||||
pio->errnum = syserr_to_errnum (errno);
|
|
||||||
goto oops;
|
|
||||||
}
|
|
||||||
minidx = 0; maxidx = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags & QSE_PIO_READOUT)
|
|
||||||
{
|
|
||||||
if (QSE_PIPE(&handle[2]) <= -1)
|
|
||||||
{
|
|
||||||
pio->errnum = syserr_to_errnum (errno);
|
|
||||||
goto oops;
|
|
||||||
}
|
|
||||||
if (minidx == -1) minidx = 2;
|
|
||||||
maxidx = 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags & QSE_PIO_READERR)
|
|
||||||
{
|
|
||||||
if (QSE_PIPE(&handle[4]) <= -1)
|
|
||||||
{
|
|
||||||
pio->errnum = syserr_to_errnum (errno);
|
|
||||||
goto oops;
|
|
||||||
}
|
|
||||||
if (minidx == -1) minidx = 4;
|
|
||||||
maxidx = 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (maxidx == -1)
|
|
||||||
{
|
|
||||||
pio->errnum = QSE_PIO_EINVAL;
|
|
||||||
goto oops;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (make_param (pio, cmd, flags, ¶m) <= -1) goto oops;
|
if (make_param (pio, cmd, flags, ¶m) <= -1) goto oops;
|
||||||
|
|
||||||
@ -1587,9 +1694,7 @@ create_process:
|
|||||||
QSE_SYSCALL1 (dummy, SYS_close, handle[5]);
|
QSE_SYSCALL1 (dummy, SYS_close, handle[5]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((flags & QSE_PIO_INTONUL) ||
|
if (flags & (QSE_PIO_INTONUL | QSE_PIO_OUTTONUL | QSE_PIO_ERRTONUL))
|
||||||
(flags & QSE_PIO_OUTTONUL) ||
|
|
||||||
(flags & QSE_PIO_ERRTONUL))
|
|
||||||
{
|
{
|
||||||
#if defined(O_LARGEFILE)
|
#if defined(O_LARGEFILE)
|
||||||
QSE_SYSCALL3 (devnull, SYS_open, QSE_MT("/dev/null"), O_RDWR|O_LARGEFILE, 0);
|
QSE_SYSCALL3 (devnull, SYS_open, QSE_MT("/dev/null"), O_RDWR|O_LARGEFILE, 0);
|
||||||
@ -1615,9 +1720,7 @@ create_process:
|
|||||||
if (dummy <= -1) goto child_oops;
|
if (dummy <= -1) goto child_oops;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((flags & QSE_PIO_INTONUL) ||
|
if (flags & (QSE_PIO_INTONUL | QSE_PIO_OUTTONUL | QSE_PIO_ERRTONUL))
|
||||||
(flags & QSE_PIO_OUTTONUL) ||
|
|
||||||
(flags & QSE_PIO_ERRTONUL))
|
|
||||||
{
|
{
|
||||||
QSE_SYSCALL1 (dummy, SYS_close, devnull);
|
QSE_SYSCALL1 (dummy, SYS_close, devnull);
|
||||||
devnull = -1;
|
devnull = -1;
|
||||||
@ -1639,63 +1742,8 @@ create_process:
|
|||||||
free_param (pio, ¶m);
|
free_param (pio, ¶m);
|
||||||
pio->child = pid;
|
pio->child = pid;
|
||||||
|
|
||||||
if (flags & QSE_PIO_WRITEIN)
|
|
||||||
{
|
|
||||||
QSE_CLOSE (handle[0]);
|
|
||||||
handle[0] = QSE_PIO_HND_NIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags & QSE_PIO_READOUT)
|
|
||||||
{
|
|
||||||
QSE_CLOSE (handle[3]);
|
|
||||||
handle[3] = QSE_PIO_HND_NIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags & QSE_PIO_READERR)
|
|
||||||
{
|
|
||||||
QSE_CLOSE (handle[5]);
|
|
||||||
handle[5] = QSE_PIO_HND_NIL;
|
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
if (flags & QSE_PIO_WRITEIN)
|
|
||||||
{
|
|
||||||
if (QSE_PIPE(&handle[0]) <= -1)
|
|
||||||
{
|
|
||||||
pio->errnum = syserr_to_errnum (errno);
|
|
||||||
goto oops;
|
|
||||||
}
|
|
||||||
minidx = 0; maxidx = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags & QSE_PIO_READOUT)
|
|
||||||
{
|
|
||||||
if (QSE_PIPE(&handle[2]) <= -1)
|
|
||||||
{
|
|
||||||
pio->errnum = syserr_to_errnum (errno);
|
|
||||||
goto oops;
|
|
||||||
}
|
|
||||||
if (minidx == -1) minidx = 2;
|
|
||||||
maxidx = 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags & QSE_PIO_READERR)
|
|
||||||
{
|
|
||||||
if (QSE_PIPE(&handle[4]) <= -1)
|
|
||||||
{
|
|
||||||
pio->errnum = syserr_to_errnum (errno);
|
|
||||||
goto oops;
|
|
||||||
}
|
|
||||||
if (minidx == -1) minidx = 4;
|
|
||||||
maxidx = 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (maxidx == -1)
|
|
||||||
{
|
|
||||||
pio->errnum = QSE_PIO_EINVAL;
|
|
||||||
goto oops;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (make_param (pio, cmd, flags, ¶m) <= -1) goto oops;
|
if (make_param (pio, cmd, flags, ¶m) <= -1) goto oops;
|
||||||
|
|
||||||
/* check if the command(the command requested or /bin/sh) is
|
/* check if the command(the command requested or /bin/sh) is
|
||||||
@ -1707,125 +1755,19 @@ create_process:
|
|||||||
goto oops;
|
goto oops;
|
||||||
}
|
}
|
||||||
|
|
||||||
pid = QSE_FORK();
|
pid = standard_fork_and_exec (pio, handle, ¶m, env);
|
||||||
if (pid <= -1)
|
if (pid <= -1)
|
||||||
{
|
{
|
||||||
pio->errnum = QSE_PIO_EINVAL;
|
|
||||||
free_param (pio, ¶m);
|
free_param (pio, ¶m);
|
||||||
goto oops;
|
goto oops;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pid == 0)
|
|
||||||
{
|
|
||||||
/* child */
|
|
||||||
qse_pio_hnd_t devnull = -1;
|
|
||||||
|
|
||||||
if (!(flags & QSE_PIO_NOCLOEXEC))
|
|
||||||
{
|
|
||||||
if (close_unneeded_fds_using_proc (handle, 6) <= -1)
|
|
||||||
{
|
|
||||||
int fd = get_highest_fd ();
|
|
||||||
|
|
||||||
/* close all other unknown open handles except
|
|
||||||
* stdin/out/err and the pipes. */
|
|
||||||
while (fd > 2)
|
|
||||||
{
|
|
||||||
if (fd != handle[0] && fd != handle[1] &&
|
|
||||||
fd != handle[2] && fd != handle[3] &&
|
|
||||||
fd != handle[4] && fd != handle[5])
|
|
||||||
{
|
|
||||||
QSE_CLOSE (fd);
|
|
||||||
}
|
|
||||||
fd--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags & QSE_PIO_WRITEIN)
|
|
||||||
{
|
|
||||||
/* child should read */
|
|
||||||
QSE_CLOSE (handle[1]);
|
|
||||||
handle[1] = QSE_PIO_HND_NIL;
|
|
||||||
if (QSE_DUP2 (handle[0], 0) <= -1) goto child_oops;
|
|
||||||
QSE_CLOSE (handle[0]);
|
|
||||||
handle[0] = QSE_PIO_HND_NIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags & QSE_PIO_READOUT)
|
|
||||||
{
|
|
||||||
/* child should write */
|
|
||||||
QSE_CLOSE (handle[2]);
|
|
||||||
handle[2] = QSE_PIO_HND_NIL;
|
|
||||||
if (QSE_DUP2 (handle[3], 1) <= -1) goto child_oops;
|
|
||||||
|
|
||||||
if (flags & QSE_PIO_ERRTOOUT)
|
|
||||||
{
|
|
||||||
if (QSE_DUP2 (handle[3], 2) <= -1) goto child_oops;
|
|
||||||
}
|
|
||||||
|
|
||||||
QSE_CLOSE (handle[3]);
|
|
||||||
handle[3] = QSE_PIO_HND_NIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags & QSE_PIO_READERR)
|
|
||||||
{
|
|
||||||
/* child should write */
|
|
||||||
QSE_CLOSE (handle[4]);
|
|
||||||
handle[4] = QSE_PIO_HND_NIL;
|
|
||||||
if (QSE_DUP2 (handle[5], 2) <= -1) goto child_oops;
|
|
||||||
|
|
||||||
if (flags & QSE_PIO_OUTTOERR)
|
|
||||||
{
|
|
||||||
if (QSE_DUP2 (handle[5], 1) <= -1) goto child_oops;
|
|
||||||
}
|
|
||||||
|
|
||||||
QSE_CLOSE (handle[5]);
|
|
||||||
handle[5] = QSE_PIO_HND_NIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((flags & QSE_PIO_INTONUL) ||
|
|
||||||
(flags & QSE_PIO_OUTTONUL) ||
|
|
||||||
(flags & QSE_PIO_ERRTONUL))
|
|
||||||
{
|
|
||||||
#if defined(O_LARGEFILE)
|
|
||||||
devnull = QSE_OPEN (QSE_MT("/dev/null"), O_RDWR|O_LARGEFILE, 0);
|
|
||||||
#else
|
|
||||||
devnull = QSE_OPEN (QSE_MT("/dev/null"), O_RDWR, 0);
|
|
||||||
#endif
|
|
||||||
if (devnull <= -1) goto child_oops;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((flags & QSE_PIO_INTONUL) &&
|
|
||||||
QSE_DUP2(devnull,0) <= -1) goto child_oops;
|
|
||||||
if ((flags & QSE_PIO_OUTTONUL) &&
|
|
||||||
QSE_DUP2(devnull,1) <= -1) goto child_oops;
|
|
||||||
if ((flags & QSE_PIO_ERRTONUL) &&
|
|
||||||
QSE_DUP2(devnull,2) <= -1) goto child_oops;
|
|
||||||
|
|
||||||
if ((flags & QSE_PIO_INTONUL) ||
|
|
||||||
(flags & QSE_PIO_OUTTONUL) ||
|
|
||||||
(flags & QSE_PIO_ERRTONUL))
|
|
||||||
{
|
|
||||||
QSE_CLOSE (devnull);
|
|
||||||
devnull = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags & QSE_PIO_DROPIN) QSE_CLOSE(0);
|
|
||||||
if (flags & QSE_PIO_DROPOUT) QSE_CLOSE(1);
|
|
||||||
if (flags & QSE_PIO_DROPERR) QSE_CLOSE(2);
|
|
||||||
|
|
||||||
/*if (make_param (pio, cmd, flags, ¶m) <= -1) goto child_oops;*/
|
|
||||||
QSE_EXECVE (param.argv[0], param.argv, (env? qse_env_getarr(env): environ));
|
|
||||||
free_param (pio, ¶m);
|
|
||||||
|
|
||||||
child_oops:
|
|
||||||
if (devnull >= 0) QSE_CLOSE (devnull);
|
|
||||||
QSE_EXIT (128);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* parent */
|
/* parent */
|
||||||
free_param (pio, ¶m);
|
free_param (pio, ¶m);
|
||||||
pio->child = pid;
|
pio->child = pid;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if (flags & QSE_PIO_WRITEIN)
|
if (flags & QSE_PIO_WRITEIN)
|
||||||
{
|
{
|
||||||
@ -1862,7 +1804,6 @@ create_process:
|
|||||||
QSE_CLOSE (handle[5]);
|
QSE_CLOSE (handle[5]);
|
||||||
handle[5] = QSE_PIO_HND_NIL;
|
handle[5] = QSE_PIO_HND_NIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (((flags & QSE_PIO_INNOBLOCK) && set_pipe_nonblock(pio, handle[1], 1) <= -1) ||
|
if (((flags & QSE_PIO_INNOBLOCK) && set_pipe_nonblock(pio, handle[1], 1) <= -1) ||
|
||||||
|
@ -316,7 +316,7 @@ qse_task_slice_t* qse_task_create (
|
|||||||
tmp = ((qse_uint8_t*)(slice + 1)) + stksize - QSE_SIZEOF(void*);
|
tmp = ((qse_uint8_t*)(slice + 1)) + stksize - QSE_SIZEOF(void*);
|
||||||
|
|
||||||
tmp = (qse_uint8_t*)tmp - QSE_SIZEOF(void*);
|
tmp = (qse_uint8_t*)tmp - QSE_SIZEOF(void*);
|
||||||
*(void**)tmp = NULL; /* t1 */
|
*(void**)tmp = QSE_NULL; /* t1 */
|
||||||
|
|
||||||
tmp = (qse_uint8_t*)tmp - QSE_SIZEOF(void*);
|
tmp = (qse_uint8_t*)tmp - QSE_SIZEOF(void*);
|
||||||
*(void**)tmp = slice; /* t2 */
|
*(void**)tmp = slice; /* t2 */
|
||||||
|
@ -56,6 +56,7 @@ const qse_mchar_t* qse_httpstatustombs (int code)
|
|||||||
case 304: msg = QSE_MT("Not Modified"); break;
|
case 304: msg = QSE_MT("Not Modified"); break;
|
||||||
case 305: msg = QSE_MT("Use Proxy"); break;
|
case 305: msg = QSE_MT("Use Proxy"); break;
|
||||||
case 307: msg = QSE_MT("Temporary Redirect"); break;
|
case 307: msg = QSE_MT("Temporary Redirect"); break;
|
||||||
|
case 308: msg = QSE_MT("Permanent Redirect"); break;
|
||||||
|
|
||||||
case 400: msg = QSE_MT("Bad Request"); break;
|
case 400: msg = QSE_MT("Bad Request"); break;
|
||||||
case 401: msg = QSE_MT("Unauthorized"); break;
|
case 401: msg = QSE_MT("Unauthorized"); break;
|
||||||
|
@ -44,6 +44,7 @@ struct task_cgi_arg_t
|
|||||||
qse_mcstr_t root;
|
qse_mcstr_t root;
|
||||||
qse_mcstr_t shebang;
|
qse_mcstr_t shebang;
|
||||||
int nph;
|
int nph;
|
||||||
|
qse_httpd_fnc_t fnc;
|
||||||
qse_htre_t* req;
|
qse_htre_t* req;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -63,6 +64,7 @@ struct task_cgi_t
|
|||||||
qse_http_version_t version;
|
qse_http_version_t version;
|
||||||
int keepalive; /* taken from the request */
|
int keepalive; /* taken from the request */
|
||||||
int nph;
|
int nph;
|
||||||
|
qse_pio_fnc_t fnc;
|
||||||
|
|
||||||
qse_htrd_t* script_htrd;
|
qse_htrd_t* script_htrd;
|
||||||
qse_env_t* env;
|
qse_env_t* env;
|
||||||
@ -733,6 +735,12 @@ static int task_init_cgi (
|
|||||||
cgi->keepalive = (arg->req->flags & QSE_HTRE_ATTR_KEEPALIVE);
|
cgi->keepalive = (arg->req->flags & QSE_HTRE_ATTR_KEEPALIVE);
|
||||||
cgi->nph = arg->nph;
|
cgi->nph = arg->nph;
|
||||||
cgi->req = QSE_NULL;
|
cgi->req = QSE_NULL;
|
||||||
|
if (arg->fnc.ptr)
|
||||||
|
{
|
||||||
|
/* the function pointer is set */
|
||||||
|
cgi->fnc.ptr = arg->fnc.ptr;
|
||||||
|
cgi->fnc.ctx = arg->fnc.ctx;
|
||||||
|
}
|
||||||
|
|
||||||
content_length = 0;
|
content_length = 0;
|
||||||
if (arg->req->state & QSE_HTRE_DISCARDED) goto done;
|
if (arg->req->state & QSE_HTRE_DISCARDED) goto done;
|
||||||
@ -1432,6 +1440,7 @@ static int task_main_cgi (
|
|||||||
cgi_script_htrd_xtn_t* xtn;
|
cgi_script_htrd_xtn_t* xtn;
|
||||||
cgi->script_htrd = qse_htrd_open (httpd->mmgr, QSE_SIZEOF(cgi_script_htrd_xtn_t));
|
cgi->script_htrd = qse_htrd_open (httpd->mmgr, QSE_SIZEOF(cgi_script_htrd_xtn_t));
|
||||||
if (cgi->script_htrd == QSE_NULL) goto oops;
|
if (cgi->script_htrd == QSE_NULL) goto oops;
|
||||||
|
|
||||||
xtn = (cgi_script_htrd_xtn_t*) qse_htrd_getxtn (cgi->script_htrd);
|
xtn = (cgi_script_htrd_xtn_t*) qse_htrd_getxtn (cgi->script_htrd);
|
||||||
xtn->cgi = cgi;
|
xtn->cgi = cgi;
|
||||||
xtn->task = task;
|
xtn->task = task;
|
||||||
@ -1460,6 +1469,13 @@ static int task_main_cgi (
|
|||||||
if (httpd->opt.trait & QSE_HTTPD_CGINOCLOEXEC)
|
if (httpd->opt.trait & QSE_HTTPD_CGINOCLOEXEC)
|
||||||
pio_options |= QSE_PIO_NOCLOEXEC;
|
pio_options |= QSE_PIO_NOCLOEXEC;
|
||||||
|
|
||||||
|
if (cgi->fnc.ptr)
|
||||||
|
{
|
||||||
|
xpath = (qse_mchar_t*)&cgi->fnc;
|
||||||
|
pio_options |= QSE_PIO_FNCCMD;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
if (cgi->shebang[0] != QSE_MT('\0'))
|
if (cgi->shebang[0] != QSE_MT('\0'))
|
||||||
{
|
{
|
||||||
const qse_mchar_t* tmp[4];
|
const qse_mchar_t* tmp[4];
|
||||||
@ -1471,11 +1487,12 @@ static int task_main_cgi (
|
|||||||
if (xpath == QSE_NULL) goto oops;
|
if (xpath == QSE_NULL) goto oops;
|
||||||
}
|
}
|
||||||
else xpath = cgi->path;
|
else xpath = cgi->path;
|
||||||
|
}
|
||||||
|
|
||||||
x = qse_pio_init (
|
x = qse_pio_init (
|
||||||
&cgi->pio, httpd->mmgr, (const qse_char_t*)xpath,
|
&cgi->pio, httpd->mmgr, (const qse_char_t*)xpath,
|
||||||
cgi->env, pio_options);
|
cgi->env, pio_options);
|
||||||
if (xpath != cgi->path) QSE_MMGR_FREE (httpd->mmgr, xpath);
|
if (xpath != cgi->path && xpath != &cgi->fnc) QSE_MMGR_FREE (httpd->mmgr, xpath);
|
||||||
|
|
||||||
if (x <= -1)
|
if (x <= -1)
|
||||||
{
|
{
|
||||||
@ -1539,6 +1556,12 @@ static int task_main_cgi (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* no forwarding buffer. the request should not send any contents
|
||||||
|
* to the cgi script. close the input to the script */
|
||||||
|
qse_pio_end (&cgi->pio, QSE_PIO_IN);
|
||||||
|
}
|
||||||
|
|
||||||
task->main = cgi->nph? task_main_cgi_4_nph: task_main_cgi_2;
|
task->main = cgi->nph? task_main_cgi_4_nph: task_main_cgi_2;
|
||||||
return 1;
|
return 1;
|
||||||
@ -1575,11 +1598,35 @@ qse_httpd_task_t* qse_httpd_entaskcgi (
|
|||||||
task_cgi_arg_t arg;
|
task_cgi_arg_t arg;
|
||||||
qse_httpd_rsrc_cgi_t rsrc;
|
qse_httpd_rsrc_cgi_t rsrc;
|
||||||
|
|
||||||
|
QSE_MEMSET (&arg, 0, QSE_SIZEOF(arg));
|
||||||
|
|
||||||
rsrc = *cgi;
|
rsrc = *cgi;
|
||||||
|
if (rsrc.flags & QSE_HTTPD_RSRC_CGI_FNC)
|
||||||
|
{
|
||||||
|
/* rsrc.script must carry a pointer to qse_pio_fnc_t */
|
||||||
|
if (rsrc.script == QSE_NULL || ((qse_pio_fnc_t*)rsrc.script)->ptr == QSE_NULL)
|
||||||
|
{
|
||||||
|
httpd->errnum = QSE_HTTPD_EINVAL;
|
||||||
|
return QSE_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
arg.fnc.ptr = (qse_httpd_fncptr_t)rsrc.path;
|
||||||
|
arg.fnc.ctx = (void*)rsrc.shebang;
|
||||||
|
|
||||||
|
/* reset the script to an empty string for less interference
|
||||||
|
* with code handling normal script */
|
||||||
|
rsrc.path = QSE_MT("");
|
||||||
|
rsrc.shebang = QSE_MT("");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
QSE_ASSERT (rsrc.path != QSE_NULL);
|
||||||
|
if (rsrc.shebang == QSE_NULL) rsrc.shebang = QSE_MT("");
|
||||||
|
}
|
||||||
|
|
||||||
if (rsrc.script == QSE_NULL) rsrc.script = qse_htre_getqpath(req);
|
if (rsrc.script == QSE_NULL) rsrc.script = qse_htre_getqpath(req);
|
||||||
if (rsrc.suffix == QSE_NULL) rsrc.suffix = QSE_MT("");
|
if (rsrc.suffix == QSE_NULL) rsrc.suffix = QSE_MT("");
|
||||||
if (rsrc.root == QSE_NULL) rsrc.root = QSE_MT("");
|
if (rsrc.root == QSE_NULL) rsrc.root = QSE_MT("");
|
||||||
if (rsrc.shebang == QSE_NULL) rsrc.shebang = QSE_MT("");
|
|
||||||
|
|
||||||
arg.path.ptr = (qse_mchar_t*)rsrc.path;
|
arg.path.ptr = (qse_mchar_t*)rsrc.path;
|
||||||
arg.path.len = qse_mbslen(rsrc.path);
|
arg.path.len = qse_mbslen(rsrc.path);
|
||||||
@ -1589,7 +1636,7 @@ qse_httpd_task_t* qse_httpd_entaskcgi (
|
|||||||
arg.suffix.len = qse_mbslen(rsrc.suffix);
|
arg.suffix.len = qse_mbslen(rsrc.suffix);
|
||||||
arg.root.ptr = (qse_mchar_t*)rsrc.root;
|
arg.root.ptr = (qse_mchar_t*)rsrc.root;
|
||||||
arg.root.len = qse_mbslen(rsrc.root);
|
arg.root.len = qse_mbslen(rsrc.root);
|
||||||
arg.nph = rsrc.nph;
|
arg.nph = ((rsrc.flags & QSE_HTTPD_RSRC_CGI_NPH) != 0);
|
||||||
arg.shebang.ptr = (qse_mchar_t*)rsrc.shebang;
|
arg.shebang.ptr = (qse_mchar_t*)rsrc.shebang;
|
||||||
arg.shebang.len = qse_mbslen(rsrc.shebang);
|
arg.shebang.len = qse_mbslen(rsrc.shebang);
|
||||||
arg.req = req;
|
arg.req = req;
|
||||||
|
@ -1983,7 +1983,7 @@ printf ("XXXXXXXXXXXXXXXXXXXXXXXXXX URL REWRITTEN TO [%s].....\n", new_url);
|
|||||||
{
|
{
|
||||||
/* check if it begins with redirection code followed by a colon */
|
/* check if it begins with redirection code followed by a colon */
|
||||||
int redir_code = 0;
|
int redir_code = 0;
|
||||||
qse_httpd_status_reloc_t reloc;
|
qse_httpd_rsrc_reloc_t reloc;
|
||||||
const qse_mchar_t* nuptr = new_url;
|
const qse_mchar_t* nuptr = new_url;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
@ -1996,11 +1996,14 @@ printf ("XXXXXXXXXXXXXXXXXXXXXXXXXX URL REWRITTEN TO [%s].....\n", new_url);
|
|||||||
/* no colon is found after digits. it's probably a normal url */
|
/* no colon is found after digits. it's probably a normal url */
|
||||||
goto normal_url;
|
goto normal_url;
|
||||||
}
|
}
|
||||||
if (redir_code != 301 && redir_code != 302 && redir_code != 307) redir_code = 301;
|
if (redir_code != 301 && redir_code != 302 && redir_code != 303 &&
|
||||||
|
redir_code != 307 && redir_code != 308) redir_code = 302;
|
||||||
nuptr++;
|
nuptr++;
|
||||||
|
|
||||||
|
/* relocation code is given explictly, no slash appending is needed.
|
||||||
|
* use qse_httpd_entask_status() rather than qse_httpd_entaskreloc(). */
|
||||||
|
reloc.flags = 0;
|
||||||
reloc.dst = nuptr;
|
reloc.dst = nuptr;
|
||||||
reloc.redir = 0; /* don't want to append extra / */
|
|
||||||
|
|
||||||
if (qse_httpd_entask_status (
|
if (qse_httpd_entask_status (
|
||||||
httpd, proxy->client, proxy->task, redir_code, &reloc,
|
httpd, proxy->client, proxy->task, redir_code, &reloc,
|
||||||
|
@ -2444,10 +2444,13 @@ static void free_resource (
|
|||||||
QSE_MMGR_FREE (httpd->mmgr, (qse_mchar_t*)target->u.cgi.suffix);
|
QSE_MMGR_FREE (httpd->mmgr, (qse_mchar_t*)target->u.cgi.suffix);
|
||||||
if (target->u.cgi.script != qpath)
|
if (target->u.cgi.script != qpath)
|
||||||
QSE_MMGR_FREE (httpd->mmgr, (qse_mchar_t*)target->u.cgi.script);
|
QSE_MMGR_FREE (httpd->mmgr, (qse_mchar_t*)target->u.cgi.script);
|
||||||
|
if (!(target->u.cgi.flags & QSE_HTTPD_RSRC_CGI_FNC))
|
||||||
|
{
|
||||||
if (target->u.cgi.path != qpath)
|
if (target->u.cgi.path != qpath)
|
||||||
QSE_MMGR_FREE (httpd->mmgr, (qse_mchar_t*)target->u.cgi.path);
|
QSE_MMGR_FREE (httpd->mmgr, (qse_mchar_t*)target->u.cgi.path);
|
||||||
if (target->u.cgi.shebang)
|
if (target->u.cgi.shebang)
|
||||||
QSE_MMGR_FREE (httpd->mmgr, (qse_mchar_t*)target->u.cgi.shebang);
|
QSE_MMGR_FREE (httpd->mmgr, (qse_mchar_t*)target->u.cgi.shebang);
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -2457,8 +2460,8 @@ static void free_resource (
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case QSE_HTTPD_RSRC_FILE:
|
case QSE_HTTPD_RSRC_FILE:
|
||||||
if (target->u.cgi.path != qpath)
|
if (target->u.file.path != qpath)
|
||||||
QSE_MMGR_FREE (httpd->mmgr, (qse_mchar_t*)target->u.cgi.path);
|
QSE_MMGR_FREE (httpd->mmgr, (qse_mchar_t*)target->u.file.path);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case QSE_HTTPD_RSRC_RELOC:
|
case QSE_HTTPD_RSRC_RELOC:
|
||||||
@ -2466,11 +2469,6 @@ static void free_resource (
|
|||||||
QSE_MMGR_FREE (httpd->mmgr, (qse_mchar_t*)target->u.reloc.dst);
|
QSE_MMGR_FREE (httpd->mmgr, (qse_mchar_t*)target->u.reloc.dst);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case QSE_HTTPD_RSRC_REDIR:
|
|
||||||
if (target->u.redir.dst != qpath)
|
|
||||||
QSE_MMGR_FREE (httpd->mmgr, (qse_mchar_t*)target->u.redir.dst);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
/* nothing to do */
|
/* nothing to do */
|
||||||
break;
|
break;
|
||||||
@ -2573,22 +2571,19 @@ static int attempt_cgi (
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* create a relocation resource */
|
/* create a relocation resource */
|
||||||
|
QSE_MEMSET (target, 0, QSE_SIZEOF(*target));
|
||||||
target->type = QSE_HTTPD_RSRC_RELOC;
|
target->type = QSE_HTTPD_RSRC_RELOC;
|
||||||
target->u.reloc.dst = merge_paths (httpd, tmp->qpath, tmp->idxfile);
|
target->u.reloc.dst = merge_paths (httpd, tmp->qpath, tmp->idxfile);
|
||||||
if (target->u.reloc.dst == QSE_NULL) goto oops;
|
if (target->u.reloc.dst == QSE_NULL) goto oops;
|
||||||
|
|
||||||
/* free tmp->xpath here upon success since it's not used for relocation.
|
/* free tmp->xpath here upon success since it's not used for relocation.
|
||||||
* it is freed by the called upon failure so the 'oops' part don't free it */
|
* upon failure, it is freed by the caller. so the 'oops' part
|
||||||
|
* of this function doesn't free it. */
|
||||||
QSE_MMGR_FREE (httpd->mmgr, tmp->xpath);
|
QSE_MMGR_FREE (httpd->mmgr, tmp->xpath);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
else script = (qse_mchar_t*)tmp->qpath;
|
else script = (qse_mchar_t*)tmp->qpath;
|
||||||
|
|
||||||
if (cgi.shebang)
|
|
||||||
{
|
|
||||||
shebang = qse_mbsdup (cgi.shebang, httpd->mmgr);
|
|
||||||
if (shebang == QSE_NULL) goto oops;
|
|
||||||
}
|
|
||||||
|
|
||||||
goto bingo;
|
goto bingo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2623,10 +2618,9 @@ static int attempt_cgi (
|
|||||||
stx = stat_file (httpd, tmp->xpath, &st, 0);
|
stx = stat_file (httpd, tmp->xpath, &st, 0);
|
||||||
if (stx <= -1)
|
if (stx <= -1)
|
||||||
{
|
{
|
||||||
/* stop at the current segment if stating fails.
|
/* instead of stopping here, let's give a non-existent
|
||||||
* if the current semgment can't be stat-ed, it's not likely that
|
* segment to be a virtual cgi script(function pointer). */
|
||||||
* the next segment can be successfully stat-ed */
|
st.isdir = 0;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!st.isdir)
|
if (!st.isdir)
|
||||||
@ -2636,9 +2630,16 @@ static int attempt_cgi (
|
|||||||
QSE_MEMSET (&qinfo, 0, QSE_SIZEOF(qinfo));
|
QSE_MEMSET (&qinfo, 0, QSE_SIZEOF(qinfo));
|
||||||
qinfo.req = req;
|
qinfo.req = req;
|
||||||
qinfo.xpath = tmp->xpath;
|
qinfo.xpath = tmp->xpath;
|
||||||
|
qinfo.xpath_nx = (stx <= -1);
|
||||||
|
|
||||||
if (server_xtn->query (httpd, client->server, QSE_HTTPD_SERVERSTD_CGI, &qinfo, &cgi) >= 0 && cgi.cgi)
|
if (server_xtn->query (httpd, client->server, QSE_HTTPD_SERVERSTD_CGI, &qinfo, &cgi) >= 0 && cgi.cgi)
|
||||||
{
|
{
|
||||||
|
if (cgi.fncptr == QSE_NULL && stx <= -1)
|
||||||
|
{
|
||||||
|
/* normal cgi script must exist. */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* the script name is composed of the orginal query path.
|
/* the script name is composed of the orginal query path.
|
||||||
* the pointer held in 'slash' is valid for tmp->qpath as
|
* the pointer held in 'slash' is valid for tmp->qpath as
|
||||||
* tmp->qpath_rp is at most the tail part of tmp->qpath. */
|
* tmp->qpath_rp is at most the tail part of tmp->qpath. */
|
||||||
@ -2646,23 +2647,57 @@ static int attempt_cgi (
|
|||||||
suffix = qse_mbsdup (slash, httpd->mmgr);
|
suffix = qse_mbsdup (slash, httpd->mmgr);
|
||||||
if (!script || !suffix) goto oops;
|
if (!script || !suffix) goto oops;
|
||||||
|
|
||||||
if (cgi.shebang)
|
|
||||||
{
|
|
||||||
shebang = qse_mbsdup (cgi.shebang, httpd->mmgr);
|
|
||||||
if (shebang == QSE_NULL) goto oops;
|
|
||||||
}
|
|
||||||
|
|
||||||
goto bingo;
|
goto bingo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (stx <= -1)
|
||||||
|
{
|
||||||
|
/* stop at the current segment if stat() fails.
|
||||||
|
* if the current segment can't be stat-ed, it's not likely that
|
||||||
|
* the next segment can be stat-ed successfully */
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ptr = slash + 1;
|
ptr = slash + 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* no more slash is found. the last segement doesn't have to be checked
|
/* no more slash is found. this is the last segment.
|
||||||
* here since it's attempted by the caller. */
|
* the caller has called stat() against the last segment
|
||||||
|
* before having called this function. so it's known
|
||||||
|
* that the path disn't exist.
|
||||||
|
*
|
||||||
|
* however, a virtual cgi script may not exist. a check
|
||||||
|
* for it is still required here */
|
||||||
|
|
||||||
|
qse_httpd_serverstd_query_info_t qinfo;
|
||||||
|
|
||||||
|
if (xpath_changed)
|
||||||
|
{
|
||||||
|
/* restore the tmp->xpath to the original value by
|
||||||
|
* combining the full path with the document root. */
|
||||||
|
merge_paths_to_buf (httpd, tmp->root.u.path.val, tmp->qpath_rp, (qse_size_t)-1, tmp->xpath);
|
||||||
|
xpath_changed = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSE_MEMSET (&qinfo, 0, QSE_SIZEOF(qinfo));
|
||||||
|
qinfo.req = req;
|
||||||
|
qinfo.xpath = tmp->xpath;
|
||||||
|
qinfo.xpath_nx = 1;
|
||||||
|
|
||||||
|
if (server_xtn->query (httpd, client->server, QSE_HTTPD_SERVERSTD_CGI, &qinfo, &cgi) >= 0 && cgi.cgi && cgi.fncptr)
|
||||||
|
{
|
||||||
|
/* virtual cgi script */
|
||||||
|
script = qse_mbsdup (tmp->qpath, httpd->mmgr);
|
||||||
|
if (!script) goto oops;
|
||||||
|
suffix = QSE_NULL;
|
||||||
|
|
||||||
|
goto bingo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* not a virtual cgi script. just break */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2675,12 +2710,32 @@ static int attempt_cgi (
|
|||||||
|
|
||||||
bingo:
|
bingo:
|
||||||
target->type = QSE_HTTPD_RSRC_CGI;
|
target->type = QSE_HTTPD_RSRC_CGI;
|
||||||
target->u.cgi.nph = cgi.nph;
|
target->u.cgi.flags = 0;
|
||||||
|
if (cgi.nph) target->u.cgi.flags |= QSE_HTTPD_RSRC_CGI_NPH;
|
||||||
|
|
||||||
|
if (cgi.fncptr)
|
||||||
|
{
|
||||||
|
/* the type casting here is guly */
|
||||||
|
target->u.cgi.path = (qse_mchar_t*)cgi.fncptr;
|
||||||
|
target->u.cgi.shebang = cgi.shebang;
|
||||||
|
target->u.cgi.flags |= QSE_HTTPD_RSRC_CGI_FNC;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (cgi.shebang)
|
||||||
|
{
|
||||||
|
shebang = qse_mbsdup (cgi.shebang, httpd->mmgr);
|
||||||
|
if (shebang == QSE_NULL) goto oops;
|
||||||
|
}
|
||||||
|
|
||||||
target->u.cgi.path = tmp->xpath;
|
target->u.cgi.path = tmp->xpath;
|
||||||
|
target->u.cgi.shebang = shebang;
|
||||||
|
}
|
||||||
|
|
||||||
target->u.cgi.script = script;
|
target->u.cgi.script = script;
|
||||||
target->u.cgi.suffix = suffix;
|
target->u.cgi.suffix = suffix;
|
||||||
target->u.cgi.root = tmp->root.u.path.val;
|
target->u.cgi.root = tmp->root.u.path.val;
|
||||||
target->u.cgi.shebang = shebang;
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
oops:
|
oops:
|
||||||
@ -2739,6 +2794,13 @@ static int make_resource (
|
|||||||
/* handle the request locally */
|
/* handle the request locally */
|
||||||
QSE_ASSERT (tmp.root.type == QSE_HTTPD_SERVERSTD_ROOT_PATH);
|
QSE_ASSERT (tmp.root.type == QSE_HTTPD_SERVERSTD_ROOT_PATH);
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
* BUG BUG BUG !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1
|
||||||
|
* TODO: calling the realm query here is wrong especially if the prefix path is resolved to a cgi.
|
||||||
|
* for example, /abc/def/test.cgi/x/y/z,
|
||||||
|
* when this function queries for REALM, it's not known that /abc/def/test.cgi is a cgi script.
|
||||||
|
|
||||||
|
*****************************************************************************/
|
||||||
if (server_xtn->query (httpd, client->server, QSE_HTTPD_SERVERSTD_REALM, &qinfo, &tmp.realm) <= -1 ||
|
if (server_xtn->query (httpd, client->server, QSE_HTTPD_SERVERSTD_REALM, &qinfo, &tmp.realm) <= -1 ||
|
||||||
server_xtn->query (httpd, client->server, QSE_HTTPD_SERVERSTD_INDEX, &qinfo, &tmp.index) <= -1)
|
server_xtn->query (httpd, client->server, QSE_HTTPD_SERVERSTD_INDEX, &qinfo, &tmp.index) <= -1)
|
||||||
{
|
{
|
||||||
@ -2898,8 +2960,9 @@ auth_ok:
|
|||||||
{
|
{
|
||||||
/* the query path doesn't end with a slash. so redirect it */
|
/* the query path doesn't end with a slash. so redirect it */
|
||||||
qse_htre_discardcontent (req);
|
qse_htre_discardcontent (req);
|
||||||
target->type = QSE_HTTPD_RSRC_REDIR;
|
target->type = QSE_HTTPD_RSRC_RELOC;
|
||||||
target->u.redir.dst = tmp.qpath;
|
target->u.reloc.flags = QSE_HTTPD_RSRC_RELOC_APPENDSLASH | QSE_HTTPD_RSRC_RELOC_PERMANENT;
|
||||||
|
target->u.reloc.dst = tmp.qpath;
|
||||||
/* free xpath since it won't be used */
|
/* free xpath since it won't be used */
|
||||||
QSE_MMGR_FREE (httpd->mmgr, tmp.xpath);
|
QSE_MMGR_FREE (httpd->mmgr, tmp.xpath);
|
||||||
}
|
}
|
||||||
@ -2929,7 +2992,16 @@ auth_ok:
|
|||||||
QSE_MMGR_FREE (httpd->mmgr, tmp.xpath);
|
QSE_MMGR_FREE (httpd->mmgr, tmp.xpath);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (n >= 1) return 0;
|
if (n >= 1)
|
||||||
|
{
|
||||||
|
if (target->u.cgi.flags & QSE_HTTPD_RSRC_CGI_FNC)
|
||||||
|
{
|
||||||
|
/* tmp.xpath is not set to target->u.cgi.path when
|
||||||
|
* this flag is set. it must be deallocated */
|
||||||
|
QSE_MMGR_FREE (httpd->mmgr, tmp.xpath);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
qinfo.xpath = tmp.xpath;
|
qinfo.xpath = tmp.xpath;
|
||||||
|
|
||||||
@ -3015,8 +3087,8 @@ struct cgi_tab_t
|
|||||||
};
|
};
|
||||||
static struct cgi_tab_t cgitab[] =
|
static struct cgi_tab_t cgitab[] =
|
||||||
{
|
{
|
||||||
{ QSE_MT(".cgi"), { 1, 0, QSE_NULL } },
|
{ QSE_MT(".cgi"), { 1, 0, QSE_NULL, QSE_NULL } },
|
||||||
{ QSE_MT(".nph"), { 1, 1, QSE_NULL } },
|
{ QSE_MT(".nph"), { 1, 1, QSE_NULL, QSE_NULL } },
|
||||||
};
|
};
|
||||||
|
|
||||||
static int query_server (
|
static int query_server (
|
||||||
@ -3071,6 +3143,11 @@ static int query_server (
|
|||||||
case QSE_HTTPD_SERVERSTD_CGI:
|
case QSE_HTTPD_SERVERSTD_CGI:
|
||||||
{
|
{
|
||||||
qse_httpd_serverstd_cgi_t* cgi = (qse_httpd_serverstd_cgi_t*)result;
|
qse_httpd_serverstd_cgi_t* cgi = (qse_httpd_serverstd_cgi_t*)result;
|
||||||
|
|
||||||
|
if (!qinfo->xpath_nx)
|
||||||
|
{
|
||||||
|
/* this standard implementation supports a normal cgi script only */
|
||||||
|
|
||||||
for (i = 0; i < QSE_COUNTOF(cgitab); i++)
|
for (i = 0; i < QSE_COUNTOF(cgitab); i++)
|
||||||
{
|
{
|
||||||
if (qse_mbsend (qinfo->xpath, cgitab[i].suffix))
|
if (qse_mbsend (qinfo->xpath, cgitab[i].suffix))
|
||||||
@ -3079,6 +3156,7 @@ static int query_server (
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QSE_MEMSET (cgi,0, QSE_SIZEOF(*cgi));
|
QSE_MEMSET (cgi,0, QSE_SIZEOF(*cgi));
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -178,14 +178,16 @@ qse_httpd_task_t* qse_httpd_entask_status (
|
|||||||
msg = qse_httpstatustombs (code);
|
msg = qse_httpstatustombs (code);
|
||||||
switch (code)
|
switch (code)
|
||||||
{
|
{
|
||||||
case 301:
|
case 301: /* Moved Permanently */
|
||||||
case 302:
|
case 302: /* Found */
|
||||||
case 307:
|
case 303: /* See Other (since HTTP/1.1) */
|
||||||
|
case 307: /* Temporary Redirect (since HTTP/1.1) */
|
||||||
|
case 308: /* Permanent Redirect (Experimental RFC; RFC 7238) */
|
||||||
{
|
{
|
||||||
qse_httpd_status_reloc_t* reloc;
|
qse_httpd_rsrc_reloc_t* reloc;
|
||||||
reloc = (qse_httpd_status_reloc_t*)extra;
|
reloc = (qse_httpd_rsrc_reloc_t*)extra;
|
||||||
extrapre = QSE_MT("Location: ");
|
extrapre = QSE_MT("Location: ");
|
||||||
extrapst = reloc->redir? QSE_MT("/\r\n"): QSE_MT("\r\n");
|
extrapst = (reloc->flags & QSE_HTTPD_RSRC_RELOC_APPENDSLASH)? QSE_MT("/\r\n"): QSE_MT("\r\n");
|
||||||
extraval = reloc->dst;
|
extraval = reloc->dst;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -276,31 +278,22 @@ qse_httpd_task_t* qse_httpd_entaskauth (
|
|||||||
|
|
||||||
qse_httpd_task_t* qse_httpd_entaskreloc (
|
qse_httpd_task_t* qse_httpd_entaskreloc (
|
||||||
qse_httpd_t* httpd, qse_httpd_client_t* client,
|
qse_httpd_t* httpd, qse_httpd_client_t* client,
|
||||||
qse_httpd_task_t* pred, const qse_mchar_t* dst, qse_htre_t* req)
|
qse_httpd_task_t* pred, const qse_httpd_rsrc_reloc_t* reloc, qse_htre_t* req)
|
||||||
{
|
{
|
||||||
qse_httpd_status_reloc_t reloc;
|
int code;
|
||||||
|
|
||||||
reloc.dst = dst;
|
if (reloc->flags & QSE_HTTPD_RSRC_RELOC_KEEPMETHOD)
|
||||||
reloc.redir = 0;
|
{
|
||||||
|
code = (reloc->flags & QSE_HTTPD_RSRC_RELOC_PERMANENT)? 308: 307;
|
||||||
return qse_httpd_entask_status (
|
}
|
||||||
httpd, client, pred, 301, (void*)&reloc,
|
else
|
||||||
qse_htre_getqmethodtype(req),
|
{
|
||||||
qse_htre_getversion(req),
|
/* NOTE: 302 can be 303 for HTTP/1.1 */
|
||||||
(req->flags & QSE_HTRE_ATTR_KEEPALIVE));
|
code = (reloc->flags & QSE_HTTPD_RSRC_RELOC_PERMANENT)? 301: 302;
|
||||||
}
|
}
|
||||||
|
|
||||||
qse_httpd_task_t* qse_httpd_entaskredir (
|
|
||||||
qse_httpd_t* httpd, qse_httpd_client_t* client,
|
|
||||||
qse_httpd_task_t* pred, const qse_mchar_t* dst, qse_htre_t* req)
|
|
||||||
{
|
|
||||||
qse_httpd_status_reloc_t reloc;
|
|
||||||
|
|
||||||
reloc.dst = dst;
|
|
||||||
reloc.redir = 1;
|
|
||||||
|
|
||||||
return qse_httpd_entask_status (
|
return qse_httpd_entask_status (
|
||||||
httpd, client, pred, 301, (void*)&reloc,
|
httpd, client, pred, code, (void*)reloc,
|
||||||
qse_htre_getqmethodtype(req),
|
qse_htre_getqmethodtype(req),
|
||||||
qse_htre_getversion(req),
|
qse_htre_getversion(req),
|
||||||
(req->flags & QSE_HTRE_ATTR_KEEPALIVE));
|
(req->flags & QSE_HTRE_ATTR_KEEPALIVE));
|
||||||
@ -403,11 +396,7 @@ qse_httpd_task_t* qse_httpd_entaskrsrc (
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case QSE_HTTPD_RSRC_RELOC:
|
case QSE_HTTPD_RSRC_RELOC:
|
||||||
task = qse_httpd_entaskreloc (httpd, client, pred, rsrc->u.reloc.dst, req);
|
task = qse_httpd_entaskreloc (httpd, client, pred, &rsrc->u.reloc, req);
|
||||||
break;
|
|
||||||
|
|
||||||
case QSE_HTTPD_RSRC_REDIR:
|
|
||||||
task = qse_httpd_entaskredir (httpd, client, pred, rsrc->u.redir.dst, req);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case QSE_HTTPD_RSRC_TEXT:
|
case QSE_HTTPD_RSRC_TEXT:
|
||||||
|
@ -100,13 +100,6 @@ struct qse_httpd_real_task_t
|
|||||||
qse_httpd_real_task_t* next;
|
qse_httpd_real_task_t* next;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct qse_httpd_status_reloc_t qse_httpd_status_reloc_t;
|
|
||||||
struct qse_httpd_status_reloc_t
|
|
||||||
{
|
|
||||||
const qse_mchar_t* dst;
|
|
||||||
int redir;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define MAX_SEND_SIZE 4096
|
#define MAX_SEND_SIZE 4096
|
||||||
#define MAX_RECV_SIZE 4096
|
#define MAX_RECV_SIZE 4096
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user