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.
21 #include <libubox/blobmsg.h>
24 static LIST_HEAD(interpreters
);
26 void uh_interpreter_add(const char *ext
, const char *path
)
28 struct interpreter
*in
;
29 char *new_ext
, *new_path
;
31 in
= calloc_a(sizeof(*in
),
32 &new_ext
, strlen(ext
) + 1,
33 &new_path
, strlen(path
) + 1);
35 in
->ext
= strcpy(new_ext
, ext
);
36 in
->path
= strcpy(new_path
, path
);
37 list_add_tail(&in
->list
, &interpreters
);
40 static void cgi_main(struct client
*cl
, struct path_info
*pi
, char *url
)
42 const struct interpreter
*ip
= pi
->ip
;
46 setenv("PATH", conf
.cgi_path
, 1);
48 for (var
= uh_get_process_vars(cl
, pi
); var
->name
; var
++) {
52 setenv(var
->name
, var
->value
, 1);
55 if (!chdir(pi
->root
)) {
57 execl(ip
->path
, ip
->path
, pi
->phys
, NULL
);
59 execl(pi
->phys
, pi
->phys
, NULL
);
62 printf("Status: 500 Internal Server Error\r\n\r\n"
63 "Unable to launch the requested CGI program:\n"
64 " %s: %s\n", ip
? ip
->path
: pi
->phys
, strerror(errno
));
67 static void cgi_handle_request(struct client
*cl
, char *url
, struct path_info
*pi
)
69 unsigned int mode
= S_IFREG
| S_IXOTH
;
71 if (!pi
->ip
&& !((pi
->stat
.st_mode
& mode
) == mode
)) {
72 uh_client_error(cl
, 403, "Forbidden",
73 "You don't have permission to access %s on this server.",
78 if (!uh_create_process(cl
, pi
, url
, cgi_main
)) {
79 uh_client_error(cl
, 500, "Internal Server Error",
80 "Failed to create CGI process: %s", strerror(errno
));
87 static bool check_cgi_path(struct path_info
*pi
, const char *url
)
89 struct interpreter
*ip
;
90 const char *path
= pi
->phys
;
91 int path_len
= strlen(path
);
93 list_for_each_entry(ip
, &interpreters
, list
) {
94 int len
= strlen(ip
->ext
);
99 if (strcmp(path
+ path_len
- len
, ip
->ext
) != 0)
108 if (conf
.cgi_docroot_path
)
109 return uh_path_match(conf
.cgi_docroot_path
, pi
->phys
);
114 struct dispatch_handler cgi_dispatch
= {
116 .check_path
= check_cgi_path
,
117 .handle_request
= cgi_handle_request
,