lwsws cgi integration

Signed-off-by: Andy Green <andy@warmcat.com>
This commit is contained in:
Andy Green 2016-04-13 11:49:07 +08:00
parent 6e7b79b263
commit a5e73a1a4b
12 changed files with 282 additions and 207 deletions

View file

@ -140,8 +140,56 @@ Mounts
Where mounts are given in the vhost definition, then directory contents may
be auto-served if it matches the mountpoint.
Currently only file:// mount protocol and a fixed set of mimetypes are
supported.
Mount protocols are used to control what kind of translation happens
- file:// serve the uri using the remainder of the url past the mountpoint based on the origin directory.
Eg, with this mountpoint
```
{
"mountpoint": "/",
"origin": "file:///var/www/mysite.com",
"default": "/"
}
```
The uri /file.jpg would serve /var/www/mysite.com/file.jpg, since / matched.
- ^http:// or ^https:// these cause any url matching the mountpoint to issue a redirect to the origin url
- cgi:// this causes any matching url to be given to the named cgi, eg
```
{
"mountpoint": "/git",
"origin": "cgi:///var/www/cgi-bin/cgit",
"default": "/"
}, {
"mountpoint": "/cgit-data",
"origin": "file:///usr/share/cgit",
"default": "/"
},
```
would cause the url /git/myrepo to pass "myrepo" to the cgi /var/www/cgi-bin/cgit and send the results to the client.
When using a cgi:// protcol origin at a mountpoint, you may also give cgi environment variables specific to the mountpoint like this
```
{
"mountpoint": "/git",
"origin": "cgi:///var/www/cgi-bin/cgit",
"default": "/",
"cgi-env": [{
"CGIT_CONFIG": "/etc/cgitrc/libwebsockets.org"
}]
}
```
This allows you to customize one cgi depending on the mountpoint (and / or vhost).
Currently only a fixed set of mimetypes are supported.
Plugins

View file

@ -52,7 +52,7 @@ static const char * const mount_protocols[] = {
LWS_VISIBLE LWS_EXTERN int
lws_write_http_mount(struct lws_http_mount *next, struct lws_http_mount **res,
void *store, const char *mountpoint, const char *origin,
const char *def)
const char *def, struct lws_protocol_vhost_options *cgienv)
{
struct lws_http_mount *m;
void *orig = store;
@ -70,6 +70,7 @@ lws_write_http_mount(struct lws_http_mount *next, struct lws_http_mount **res,
m->mountpoint = mountpoint;
m->mountpoint_len = (unsigned char)strlen(mountpoint);
m->mount_next = NULL;
m->cgienv = cgienv;
if (next)
next->mount_next = m;

View file

@ -51,11 +51,14 @@ lws_uv_idle(uv_idle_t *handle
/* still somebody left who wants forced service? */
if (!lws_service_adjust_timeout(pt->context, 1, pt->tid))
/* yes... come back again later */
lwsl_debug("%s: done again\n", __func__);
return;
}
/* there is nobody who needs service forcing, shut down idle */
uv_idle_stop(handle);
lwsl_debug("%s: done stop\n", __func__);
}
static void
@ -272,7 +275,7 @@ lws_libuv_io(struct lws *wsi, int flags)
if (!LWS_LIBUV_ENABLED(context))
return;
lwsl_debug("%s: wsi: %p, flags:%d\n", __func__, wsi, flags);
lwsl_debug("%s: wsi: %p, flags:0x%x\n", __func__, wsi, flags);
if (!pt->io_loop_uv) {
lwsl_info("%s: no io loop yet\n", __func__);

View file

@ -176,10 +176,11 @@ lws_close_free_wsi(struct lws *wsi, enum lws_close_status reason)
if (wsi->mode == LWSCM_CGI) {
/* we are not a network connection, but a handler for CGI io */
if (wsi->parent && wsi->parent->cgi)
/* end the binding between us and master */
wsi->parent->cgi->stdwsi[(int)wsi->cgi_channel] = NULL;
/* end the binding between us and master */
wsi->parent->cgi->stdwsi[(int)wsi->cgi_channel] = NULL;
wsi->socket_is_permanently_unusable = 1;
lwsl_debug("------ %s: detected cgi fdhandler wsi %p\n", __func__, wsi);
goto just_kill_connection;
}
@ -496,6 +497,7 @@ just_kill_connection:
#ifdef LWS_USE_LIBUV
if (LWS_LIBUV_ENABLED(context)) {
lwsl_debug("%s: lws_libuv_closehandle: wsi %p\n", __func__, wsi);
/* libuv has to do his own close handle processing asynchronously */
lws_libuv_closehandle(wsi);
@ -1534,7 +1536,7 @@ lws_urlencode(const char *in, int inlen, char *out, int outlen)
const char *hex = "0123456789ABCDEF";
char *start = out, *end = out + outlen;
while (inlen-- && out > end - 4) {
while (inlen-- && out < end - 4) {
if ((*in >= 'A' && *in <= 'Z') ||
(*in >= 'a' && *in <= 'z') ||
(*in >= '0' && *in <= '9') ||
@ -1635,12 +1637,12 @@ lws_create_basic_wsi(struct lws_context *context, int tsi)
*/
LWS_VISIBLE LWS_EXTERN int
lws_cgi(struct lws *wsi, char * const *exec_array, int script_uri_path_len,
int timeout_secs)
lws_cgi(struct lws *wsi, const char * const *exec_array, int script_uri_path_len,
int timeout_secs, struct lws_protocol_vhost_options *mp_cgienv)
{
struct lws_context_per_thread *pt = &wsi->context->pt[(int)wsi->tsi];
char *env_array[30], cgi_path[400], e[1024], *p = e,
*end = p + sizeof(e) - 1, tok[256];
*end = p + sizeof(e) - 1, tok[256], *t;
struct lws_cgi *cgi;
int n, m, i;
@ -1670,12 +1672,15 @@ lws_cgi(struct lws *wsi, char * const *exec_array, int script_uri_path_len,
if (!cgi->stdwsi[n])
goto bail2;
cgi->stdwsi[n]->cgi_channel = n;
cgi->stdwsi[n]->vhost = wsi->vhost;
/* read side is 0, stdin we want the write side, others read */
cgi->stdwsi[n]->sock = cgi->pipe_fds[n][!!(n == 0)];
fcntl(cgi->pipe_fds[n][!!(n == 0)], F_SETFL, O_NONBLOCK);
}
for (n = 0; n < 3; n++) {
lws_libuv_accept(cgi->stdwsi[n], cgi->stdwsi[n]->sock);
if (insert_wsi_socket_into_fds(wsi->context, cgi->stdwsi[n]))
goto bail3;
cgi->stdwsi[n]->parent = wsi;
@ -1725,9 +1730,16 @@ lws_cgi(struct lws *wsi, char * const *exec_array, int script_uri_path_len,
WSI_TOKEN_HTTP_URI_ARGS, m);
if (i < 0)
break;
i = lws_urlencode(tok, i, p, end - p);
p += i;
*p++ = '&';
t = tok;
while (*t && *t != '=' && p < end - 4)
*p++ = *t++;
if (*t == '=')
*p++ = *t++;
i = lws_urlencode(t, i- (t - tok), p, end - p);
if (i > 0) {
p += i;
*p++ = '&';
}
m++;
}
if (m)
@ -1759,13 +1771,23 @@ lws_cgi(struct lws *wsi, char * const *exec_array, int script_uri_path_len,
p++;
}
env_array[n++] = p;
p += snprintf(p, end - p, "SCRIPT_PATH=%s", exec_array[2]) + 1;
p += snprintf(p, end - p, "SCRIPT_PATH=%s", exec_array[0]) + 1;
while (mp_cgienv) {
env_array[n++] = p;
p += snprintf(p, end - p, "%s=%s", mp_cgienv->name,
mp_cgienv->value);
lwsl_notice(" Applying mount-specific cgi env '%s'\n",
env_array[n - 1]);
p++;
mp_cgienv = mp_cgienv->next;
}
env_array[n++] = "SERVER_SOFTWARE=libwebsockets";
env_array[n++] = "PATH=/bin:/usr/bin:/usr/local/bin:/var/www/cgi-bin";
env_array[n] = NULL;
#if 0
#if 1
for (m = 0; m < n; m++)
lwsl_err(" %s\n", env_array[m]);
#endif
@ -1785,6 +1807,10 @@ lws_cgi(struct lws *wsi, char * const *exec_array, int script_uri_path_len,
/* we are the parent process */
return 0;
/* somewhere we can at least read things and enter it */
if (chdir("/"))
lwsl_notice("%s: Failed to chdir\n", __func__);
/* We are the forked process, redirect and kill inherited things.
*
* Because of vfork(), we cannot do anything that changes pages in
@ -1806,9 +1832,9 @@ lws_cgi(struct lws *wsi, char * const *exec_array, int script_uri_path_len,
*p++ = '\0';
setenv(env_array[m], p, 1);
}
execvp(exec_array[0], &exec_array[0]);
execvp(exec_array[0], (char * const *)&exec_array[0]);
#else
execvpe(exec_array[0], &exec_array[0], &env_array[0]);
execvpe(exec_array[0], (char * const *)&exec_array[0], &env_array[0]);
#endif
exit(1);
@ -1948,6 +1974,8 @@ lws_cgi_kill(struct lws *wsi)
struct lws_cgi_args args;
int n, status, do_close = 0;
lwsl_debug("!!!!! %s: %p\n", __func__, wsi);
if (!wsi->cgi)
return 0;
@ -1986,17 +2014,20 @@ lws_cgi_kill(struct lws *wsi)
pcgi = &(*pcgi)->cgi_list;
}
for (n = 0 ; n < 3; n++) {
if (wsi->cgi->pipe_fds[n][!!(n == 0)] >= 0) {
close(wsi->cgi->pipe_fds[n][!!(n == 0)]);
wsi->cgi->pipe_fds[n][!!(n == 0)] = -1;
if (!do_close)
for (n = 0 ; n < 3; n++) {
if (wsi->cgi->pipe_fds[n][!!(n == 0)] >= 0) {
close(wsi->cgi->pipe_fds[n][!!(n == 0)]);
wsi->cgi->pipe_fds[n][!!(n == 0)] = -1;
}
}
}
lws_free_set_NULL(wsi->cgi);
if (do_close)
if (do_close) {
lwsl_debug("!!!!! %s: do_close\n", __func__);
lws_close_free_wsi(wsi, 0);
}
return 0;
}

View file

@ -1538,10 +1538,20 @@ struct lws_client_connect_info {
struct lws_http_mount;
enum {
LWSMPRO_HTTP,
LWSMPRO_HTTPS,
LWSMPRO_FILE,
LWSMPRO_CGI,
LWSMPRO_REDIR_HTTP,
LWSMPRO_REDIR_HTTPS,
};
LWS_VISIBLE LWS_EXTERN int
lws_write_http_mount(struct lws_http_mount *next, struct lws_http_mount **res,
void *store, const char *mountpoint, const char *origin,
const char *def);
const char *def,
struct lws_protocol_vhost_options *cgienv);
LWS_VISIBLE LWS_EXTERN void
lws_set_log_level(int level,
@ -2012,8 +2022,9 @@ struct lws_cgi_args {
};
LWS_VISIBLE LWS_EXTERN int
lws_cgi(struct lws *wsi, char * const *exec_array, int script_uri_path_len,
int timeout_secs);
lws_cgi(struct lws *wsi, const char * const *exec_array,
int script_uri_path_len, int timeout_secs,
struct lws_protocol_vhost_options *mp_cgienv);
LWS_VISIBLE LWS_EXTERN int
lws_cgi_write_split_stdout_headers(struct lws *wsi);

View file

@ -441,8 +441,10 @@ next:
static void
sigpipe_handler(int x)
sigabrt_handler(int x)
{
printf("%s\n", __func__);
//*(char *)0 = 0;
}
LWS_VISIBLE int
@ -456,7 +458,9 @@ lws_plat_context_early_init(void)
sigprocmask(SIG_BLOCK, &mask, NULL);
signal(SIGPIPE, sigpipe_handler);
signal(SIGPIPE, SIG_IGN);
signal(SIGABRT, sigabrt_handler);
return 0;
}

View file

@ -621,6 +621,8 @@ struct lws_http_mount {
const char *origin; /* path to be mounted, eg, "/var/www/warmcat.com" */
const char *def; /* default target, eg, "index.html" */
struct lws_protocol_vhost_options *cgienv;
unsigned char origin_protocol;
unsigned char mountpoint_len;
};

View file

@ -218,17 +218,48 @@ static const char * get_mimetype(const char *file)
int lws_http_serve(struct lws *wsi, char *uri, const char *origin)
{
const char *mimetype;
char path[256];
int n;
struct stat st;
char path[256], sym[256];
int n, spin = 0;
lwsl_notice("%s: %s %s\n", __func__, uri, origin);
snprintf(path, sizeof(path) - 1, "%s/%s", origin, uri);
do {
spin++;
if (stat(path, &st)) {
lwsl_err("unable to stat %s\n", path);
goto bail;
}
lwsl_debug(" %s mode %d\n", path, S_IFMT & st.st_mode);
if ((S_IFMT & st.st_mode) == S_IFLNK) {
if (readlink(path, sym, sizeof(sym))) {
lwsl_err("Failed to read link %s\n", path);
goto bail;
}
lwsl_debug("symlink %s -> %s\n", path, sym);
snprintf(path, sizeof(path) - 1, "%s", sym);
}
if ((S_IFMT & st.st_mode) == S_IFDIR) {
lwsl_debug("default filename append to dir\n");
snprintf(path, sizeof(path) - 1, "%s/%s/index.html",
origin, uri);
}
} while ((S_IFMT & st.st_mode) != S_IFREG && spin < 5);
if (spin == 5) {
lwsl_err("symlink loop %s \n", path);
}
mimetype = get_mimetype(path);
if (!mimetype) {
lwsl_err("unknown mimetype for %s", path);
lws_return_http_status(wsi, HTTP_STATUS_NOT_FOUND, NULL);
return -1;
goto bail;
}
n = lws_serve_http_file(wsi, path, mimetype, NULL, 0);
@ -237,6 +268,10 @@ int lws_http_serve(struct lws *wsi, char *uri, const char *origin)
return -1; /* error or can't reuse connection: close the socket */
return 0;
bail:
lws_return_http_status(wsi, HTTP_STATUS_NOT_FOUND, NULL);
return -1;
}
int
@ -403,7 +438,11 @@ lws_http_action(struct lws *wsi)
hm = wsi->vhost->mount_list;
while (hm) {
if (uri_len >= hm->mountpoint_len &&
!strncmp(uri_ptr, hm->mountpoint, hm->mountpoint_len)) {
!strncmp(uri_ptr, hm->mountpoint, hm->mountpoint_len) &&
(uri_ptr[hm->mountpoint_len] == '\0' ||
uri_ptr[hm->mountpoint_len] == '/' ||
hm->mountpoint_len == 1)
) {
if (hm->mountpoint_len > best) {
best = hm->mountpoint_len;
hit = hm;
@ -414,7 +453,8 @@ lws_http_action(struct lws *wsi)
if (hit) {
char *s = uri_ptr + hit->mountpoint_len;
lwsl_err("*** hit %d %d %s\n", hit->mountpoint_len, hit->origin_protocol , hit->origin);
lwsl_debug("*** hit %d %d %s\n", hit->mountpoint_len,
hit->origin_protocol , hit->origin);
/*
* if we have a mountpoint like https://xxx.com/yyy
@ -431,50 +471,87 @@ lws_http_action(struct lws *wsi)
* / at the end, we must redirect to add it so the browser
* understands he is one "directory level" down.
*/
if (hit->mountpoint_len > 1 || (hit->origin_protocol & 4))
if (*s != '/' || (hit->origin_protocol & 4)) {
unsigned char *start = pt->serv_buf + LWS_PRE,
if ((hit->mountpoint_len > 1 || (hit->origin_protocol & 4)) &&
(*s != '/' || (hit->origin_protocol & 4))) {
unsigned char *start = pt->serv_buf + LWS_PRE,
*p = start, *end = p + 512;
static const char *oprot[] = {
"http://", "https://"
};
static const char *oprot[] = {
"http://", "https://"
};
if (!lws_hdr_total_length(wsi, WSI_TOKEN_HOST))
goto bail_nuke_ah;
if (lws_add_http_header_status(wsi, 301, &p, end))
goto bail_nuke_ah;
if (!lws_hdr_total_length(wsi, WSI_TOKEN_HOST))
goto bail_nuke_ah;
if (lws_add_http_header_status(wsi, 301, &p, end))
goto bail_nuke_ah;
lwsl_err("**** %s", hit->origin);
lwsl_debug("**** %s", hit->origin);
/* > at start indicates deal with by redirect */
if (hit->origin_protocol & 4)
n = snprintf((char *)end, 256, "%s%s",
oprot[hit->origin_protocol & 1],
hit->origin);
else
n = snprintf((char *)end, 256,
"https://%s/%s/",
lws_hdr_simple_ptr(wsi, WSI_TOKEN_HOST),
uri_ptr);
if (lws_add_http_header_by_token(wsi,
WSI_TOKEN_HTTP_LOCATION,
end, n, &p, end))
goto bail_nuke_ah;
if (lws_finalize_http_header(wsi, &p, end))
goto bail_nuke_ah;
n = lws_write(wsi, start, p - start,
LWS_WRITE_HTTP_HEADERS);
if ((int)n < 0)
goto bail_nuke_ah;
/* > at start indicates deal with by redirect */
if (hit->origin_protocol & 4)
n = snprintf((char *)end, 256, "%s%s",
oprot[hit->origin_protocol & 1],
hit->origin);
else
n = snprintf((char *)end, 256,
"https://%s/%s/",
lws_hdr_simple_ptr(wsi, WSI_TOKEN_HOST),
uri_ptr);
if (lws_add_http_header_by_token(wsi,
WSI_TOKEN_HTTP_LOCATION,
end, n, &p, end))
goto bail_nuke_ah;
if (lws_finalize_http_header(wsi, &p, end))
goto bail_nuke_ah;
n = lws_write(wsi, start, p - start,
LWS_WRITE_HTTP_HEADERS);
if ((int)n < 0)
goto bail_nuke_ah;
return lws_http_transaction_completed(wsi);
return lws_http_transaction_completed(wsi);
}
#ifdef LWS_WITH_CGI
/* did we hit something with a cgi:// origin? */
if (hit->origin_protocol == LWSMPRO_CGI) {
const char *cmd[] = {
NULL, /* replace with cgi path */
NULL
};
unsigned char *p, *end, buffer[256];
lwsl_debug("%s: cgi\n", __func__);
cmd[0] = hit->origin;
n = lws_cgi(wsi, cmd, hit->mountpoint_len, 5,
hit->cgienv);
if (n) {
lwsl_err("%s: cgi failed\n");
return -1;
}
p = buffer + LWS_PRE;
end = p + sizeof(buffer) - LWS_PRE;
if (s[0] == '\0' || (s[0] == '/' && s[1] == '\0'))
if (lws_add_http_header_status(wsi, 200, &p, end))
return 1;
if (lws_add_http_header_by_token(wsi, WSI_TOKEN_CONNECTION,
(unsigned char *)"close", 5, &p, end))
return 1;
n = lws_write(wsi, buffer + LWS_PRE,
p - (buffer + LWS_PRE),
LWS_WRITE_HTTP_HEADERS);
return 0;
}
#endif
n = strlen(s);
if (s[0] == '\0' || (n == 1 && s[n - 1] == '/'))
s = (char *)hit->def;
if (!s)
s = "index.html";
n = lws_http_serve(wsi, s, hit->origin);
} else
n = wsi->protocol->callback(wsi, LWS_CALLBACK_HTTP,
@ -992,18 +1069,21 @@ lws_adopt_socket_vhost(struct lws_vhost *vh, lws_sockfd_type accept_fd)
lws_libuv_accept(new_wsi, new_wsi->sock);
if (!LWS_SSL_ENABLED(new_wsi->vhost)) {
if (insert_wsi_socket_into_fds(context, new_wsi))
if (insert_wsi_socket_into_fds(context, new_wsi)) {
lwsl_err("%s: fail inserting socket\n", __func__);
goto fail;
}
} else {
new_wsi->mode = LWSCM_SSL_INIT;
if (lws_server_socket_service_ssl(new_wsi, accept_fd))
if (lws_server_socket_service_ssl(new_wsi, accept_fd)) {
lwsl_err("%s: fail ssl negotiation\n", __func__);
goto fail;
}
}
return new_wsi;
fail:
lwsl_err("%s: fail\n", __func__);
lws_close_free_wsi(new_wsi, LWS_CLOSE_STATUS_NOSTATUS);
return NULL;

View file

@ -178,7 +178,8 @@ lws_ssl_server_name_cb(SSL *ssl, int *ad, void *arg)
if (servername) {
vhost = lws_select_vhost(context, port, servername);
if (vhost) {
lwsl_notice("SNI: Found: %s (port %d)\n", servername, port);
lwsl_debug("SNI: Found: %s (port %d)\n",
servername, port);
SSL_set_SSL_CTX(ssl, vhost->ssl_ctx);
return SSL_TLSEXT_ERR_OK;
}

View file

@ -48,6 +48,7 @@ static const char * const paths_vhosts[] = {
"vhosts[].mounts[].mountpoint",
"vhosts[].mounts[].origin",
"vhosts[].mounts[].default",
"vhosts[].mounts[].cgi-env[].*",
"vhosts[].ws-protocols[].*.*",
"vhosts[].ws-protocols[].*",
"vhosts[].ws-protocols[]",
@ -64,6 +65,7 @@ enum lejp_vhost_paths {
LEJPVP_MOUNTPOINT,
LEJPVP_ORIGIN,
LEJPVP_DEFAULT,
LEJPVP_CGI_ENV,
LEJPVP_PROTOCOL_NAME_OPT,
LEJPVP_PROTOCOL_NAME,
LEJPVP_PROTOCOL,
@ -78,6 +80,7 @@ struct jpargs {
struct lws_http_mount *head, *last;
char *mountpoint, *origin, *def;
struct lws_protocol_vhost_options *pvo;
struct lws_protocol_vhost_options *mp_cgienv;
};
static void *
@ -144,13 +147,15 @@ static char
lejp_vhosts_cb(struct lejp_ctx *ctx, char reason)
{
struct jpargs *a = (struct jpargs *)ctx->user;
struct lws_protocol_vhost_options *pvo;
struct lws_protocol_vhost_options *pvo, *mp_cgienv;
struct lws_http_mount *m;
int n;
// lwsl_notice(" %d: %s (%d)\n", reason, ctx->path, ctx->path_match);
// for (n = 0; n < ctx->wildcount; n++)
// lwsl_notice(" %d\n", ctx->wild[n]);
#if 0
lwsl_notice(" %d: %s (%d)\n", reason, ctx->path, ctx->path_match);
for (n = 0; n < ctx->wildcount; n++)
lwsl_notice(" %d\n", ctx->wild[n]);
#endif
if (reason == LEJPCB_OBJECT_START && ctx->path_match == LEJPVP + 1) {
/* set the defaults for this vhost */
@ -186,6 +191,7 @@ lejp_vhosts_cb(struct lejp_ctx *ctx, char reason)
a->mountpoint = NULL;
a->origin = NULL;
a->def = NULL;
a->mp_cgienv = NULL;
}
/* this catches, eg, vhosts[].ws-protocols[].xxx-protocol */
@ -235,7 +241,7 @@ lejp_vhosts_cb(struct lejp_ctx *ctx, char reason)
}
n = lws_write_http_mount(a->last, &m, a->p, a->mountpoint,
a->origin, a->def);
a->origin, a->def, a->mp_cgienv);
if (!n)
return 1;
a->p += n;
@ -274,7 +280,25 @@ lejp_vhosts_cb(struct lejp_ctx *ctx, char reason)
case LEJPVP_DEFAULT:
a->def = a->p;
break;
case LEJPVP_CGI_ENV:
mp_cgienv = lwsws_align(a);
a->p += sizeof(*a->mp_cgienv);
mp_cgienv->next = a->mp_cgienv;
a->mp_cgienv = mp_cgienv;
n = lejp_get_wildcard(ctx, 0, a->p, a->end - a->p);
mp_cgienv->name = a->p;
a->p += n;
mp_cgienv->value = a->p;
mp_cgienv->options = NULL;
a->p += snprintf(a->p, a->end - a->p, "%s", ctx->buf);
*(a->p)++ = '\0';
lwsl_notice(" adding cgi-env '%s' = '%s'\n", mp_cgienv->name,
mp_cgienv->value);
break;
case LEJPVP_PROTOCOL_NAME_OPT:
/* this catches, eg,
* vhosts[].ws-protocols[].xxx-protocol.yyy-option
@ -435,7 +459,7 @@ lwsws_get_config_globals(struct lws_context_creation_info *info, const char *d,
a.info = info;
a.p = *cs;
a.end = a.p + *len;
a.end = (a.p + *len) - 1;
a.valid = 0;
if (lwsws_get_config(&a, "/etc/lwsws/conf", paths_global,

View file

@ -152,42 +152,6 @@ int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user,
}
#endif
#ifdef LWS_WITH_CGI
if (!strncmp(in, "/cgitest", 8)) {
static char *cmd[] = {
"/bin/sh",
"-c",
INSTALL_DATADIR"/libwebsockets-test-server/lws-cgi-test.sh",
// "/var/www/cgi-bin/cgit",
NULL
};
lwsl_notice("%s: cgitest\n", __func__);
n = lws_cgi(wsi, cmd, 8, 5);
if (n) {
lwsl_err("%s: cgi failed\n");
return -1;
}
p = buffer + LWS_PRE;
end = p + sizeof(buffer) - LWS_PRE;
if (lws_add_http_header_status(wsi, 200, &p, end))
return 1;
if (lws_add_http_header_by_token(wsi, WSI_TOKEN_CONNECTION,
(unsigned char *)"close", 5, &p, end))
return 1;
n = lws_write(wsi, buffer + LWS_PRE,
p - (buffer + LWS_PRE),
LWS_WRITE_HTTP_HEADERS);
/* the cgi starts by outputting headers, we can't
* finalize the headers until we see the end of that
*/
break;
}
#endif
/* if a legal POST URL, let it continue and accept data */
if (lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI))
return 0;

View file

@ -215,42 +215,6 @@ int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user,
}
#endif
#ifdef LWS_WITH_CGI
if (!strncmp(in, "/cgitest", 8)) {
static char *cmd[] = {
"/bin/sh",
"-c",
INSTALL_DATADIR"/libwebsockets-test-server/lws-cgi-test.sh",
// "/var/www/cgi-bin/cgit",
NULL
};
lwsl_notice("%s: cgitest\n", __func__);
n = lws_cgi(wsi, cmd, 8, 5);
if (n) {
lwsl_err("%s: cgi failed\n");
return -1;
}
p = buffer + LWS_PRE;
end = p + sizeof(buffer) - LWS_PRE;
if (lws_add_http_header_status(wsi, 200, &p, end))
return 1;
if (lws_add_http_header_by_token(wsi, WSI_TOKEN_CONNECTION,
(unsigned char *)"close", 5, &p, end))
return 1;
n = lws_write(wsi, buffer + LWS_PRE,
p - (buffer + LWS_PRE),
LWS_WRITE_HTTP_HEADERS);
/* the cgi starts by outputting headers, we can't
* finalize the headers until we see the end of that
*/
break;
}
#endif
/* if a legal POST URL, let it continue and accept data */
if (lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI))
return 0;
@ -423,15 +387,7 @@ int callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user,
if (pss->fd == LWS_INVALID_FILE)
goto try_to_reuse;
#ifdef LWS_WITH_CGI
if (pss->reason_bf & 1) {
if (lws_cgi_write_split_stdout_headers(wsi) < 0)
goto bail;
pss->reason_bf &= ~1;
break;
}
#endif
#ifndef LWS_NO_CLIENT
if (pss->reason_bf & 2) {
char *px = buf + LWS_PRE;
@ -601,56 +557,6 @@ bail:
break;
#endif
#ifdef LWS_WITH_CGI
/* CGI IO events (POLLIN/OUT) appear here our demo user code policy is
*
* - POST data goes on subprocess stdin
* - subprocess stdout goes on http via writeable callback
* - subprocess stderr goes to the logs
*/
case LWS_CALLBACK_CGI:
pss->args = *((struct lws_cgi_args *)in);
//lwsl_notice("LWS_CALLBACK_CGI: ch %d\n", pss->args.ch);
switch (pss->args.ch) { /* which of stdin/out/err ? */
case LWS_STDIN:
/* TBD stdin rx flow control */
break;
case LWS_STDOUT:
pss->reason_bf |= 1;
/* when writing to MASTER would not block */
lws_callback_on_writable(wsi);
break;
case LWS_STDERR:
n = read(lws_get_socket_fd(pss->args.stdwsi[LWS_STDERR]),
buf, 127);
//lwsl_notice("stderr reads %d\n", n);
if (n > 0) {
if (buf[n - 1] != '\n')
buf[n++] = '\n';
buf[n] = '\0';
lwsl_notice("CGI-stderr: %s\n", buf);
}
break;
}
break;
case LWS_CALLBACK_CGI_TERMINATED:
//lwsl_notice("LWS_CALLBACK_CGI_TERMINATED\n");
/* because we sent on openended http, close the connection */
return -1;
case LWS_CALLBACK_CGI_STDIN_DATA: /* POST body for stdin */
//lwsl_notice("LWS_CALLBACK_CGI_STDIN_DATA\n");
pss->args = *((struct lws_cgi_args *)in);
n = write(lws_get_socket_fd(pss->args.stdwsi[LWS_STDIN]),
pss->args.data, pss->args.len);
//lwsl_notice("LWS_CALLBACK_CGI_STDIN_DATA: write says %d", n);
if (n < pss->args.len)
lwsl_notice("LWS_CALLBACK_CGI_STDIN_DATA: sent %d only %d went",
n, pss->args.len);
return n;
#endif
/*
* callbacks for managing the external poll() array appear in
* protocol 0 callback