2 * uhttpd - Tiny single-threaded httpd
4 * Copyright (C) 2010-2013 Jo-Philipp Wich <xm@subsignal.org>
5 * Copyright (C) 2013 Felix Fietkau <nbd@openwrt.org>
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 #include <libubox/blobmsg.h>
23 static LIST_HEAD(interpreters
);
25 void uh_interpreter_add(const char *ext
, const char *path
)
27 struct interpreter
*in
;
28 char *new_ext
, *new_path
;
30 in
= calloc_a(sizeof(*in
),
31 &new_ext
, strlen(ext
) + 1,
32 &new_path
, strlen(path
) + 1);
34 in
->ext
= strcpy(new_ext
, ext
);
35 in
->path
= strcpy(new_path
, path
);
36 list_add_tail(&in
->list
, &interpreters
);
39 static void cgi_main(struct client
*cl
, struct path_info
*pi
, char *url
)
41 const struct interpreter
*ip
= pi
->ip
;
45 setenv("PATH", conf
.cgi_path
, 1);
47 for (var
= uh_get_process_vars(cl
, pi
); var
->name
; var
++) {
51 setenv(var
->name
, var
->value
, 1);
57 execl(ip
->path
, ip
->path
, pi
->phys
, NULL
);
59 execl(pi
->phys
, pi
->phys
, NULL
);
61 printf("Status: 500 Internal Server Error\r\n\r\n"
62 "Unable to launch the requested CGI program:\n"
63 " %s: %s\n", ip
? ip
->path
: pi
->phys
, strerror(errno
));
66 static void cgi_handle_request(struct client
*cl
, char *url
, struct path_info
*pi
)
68 unsigned int mode
= S_IFREG
| S_IXOTH
;
70 if (!pi
->ip
&& !((pi
->stat
.st_mode
& mode
) == mode
)) {
71 uh_client_error(cl
, 403, "Forbidden",
72 "You don't have permission to access %s on this server.",
77 if (!uh_create_process(cl
, pi
, url
, cgi_main
)) {
78 uh_client_error(cl
, 500, "Internal Server Error",
79 "Failed to create CGI process: %s", strerror(errno
));
86 static bool check_cgi_path(struct path_info
*pi
, const char *url
)
88 struct interpreter
*ip
;
89 const char *path
= pi
->phys
;
90 int path_len
= strlen(path
);
92 list_for_each_entry(ip
, &interpreters
, list
) {
93 int len
= strlen(ip
->ext
);
98 if (strcmp(path
+ path_len
- len
, ip
->ext
) != 0)
106 return uh_path_match(conf
.cgi_prefix
, url
);
109 struct dispatch_handler cgi_dispatch
= {
110 .check_path
= check_cgi_path
,
111 .handle_request
= cgi_handle_request
,