Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
M
mongoose
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
esp
mongoose
Commits
5425b94f
Commit
5425b94f
authored
Jun 25, 2010
by
Sergey Lyubka
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
introduced struct mg_config. Fixed Range response.
parent
9a5f96e7
Changes
4
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
351 additions
and
564 deletions
+351
-564
main.c
main.c
+111
-37
mongoose.c
mongoose.c
+187
-460
mongoose.h
mongoose.h
+50
-64
test.pl
test/test.pl
+3
-3
No files found.
main.c
View file @
5425b94f
...
@@ -32,6 +32,7 @@
...
@@ -32,6 +32,7 @@
#include <string.h>
#include <string.h>
#include <errno.h>
#include <errno.h>
#include <limits.h>
#include <limits.h>
#include <stddef.h>
#include "mongoose.h"
#include "mongoose.h"
...
@@ -70,16 +71,6 @@ signal_handler(int sig_num)
...
@@ -70,16 +71,6 @@ signal_handler(int sig_num)
}
}
}
}
/*
* Show usage string and exit.
*/
static
void
show_usage_and_exit
(
void
)
{
mg_show_usage_string
(
stderr
);
exit
(
EXIT_FAILURE
);
}
/*
/*
* Edit the passwords file.
* Edit the passwords file.
*/
*/
...
@@ -88,18 +79,89 @@ mg_edit_passwords(const char *fname, const char *domain,
...
@@ -88,18 +79,89 @@ mg_edit_passwords(const char *fname, const char *domain,
const
char
*
user
,
const
char
*
pass
)
const
char
*
user
,
const
char
*
pass
)
{
{
struct
mg_context
*
ctx
;
struct
mg_context
*
ctx
;
struct
mg_config
config
;
int
retval
;
int
retval
;
ctx
=
mg_start
();
memset
(
&
config
,
0
,
sizeof
(
config
));
(
void
)
mg_set_option
(
ctx
,
"auth_realm"
,
domain
);
config
.
auth_domain
=
(
char
*
)
domain
;
config
.
num_threads
=
"0"
;
config
.
listening_ports
=
""
;
ctx
=
mg_start
(
&
config
);
retval
=
mg_modify_passwords_file
(
ctx
,
fname
,
user
,
pass
);
retval
=
mg_modify_passwords_file
(
ctx
,
fname
,
user
,
pass
);
mg_stop
(
ctx
);
mg_stop
(
ctx
);
return
(
retval
);
return
(
retval
);
}
}
#define OFFSET(x) offsetof(struct mg_config, x)
static
struct
option_descriptor
{
const
char
*
name
;
const
char
*
description
;
size_t
offset
;
}
known_options
[]
=
{
{
"root"
,
"
\t
Web root directory"
,
OFFSET
(
document_root
)},
{
"index_files"
,
"Index files"
,
OFFSET
(
index_files
)},
{
"ssl_cert"
,
"SSL certificate file"
,
OFFSET
(
ssl_certificate
)},
{
"ports"
,
"Listening ports"
,
OFFSET
(
listening_ports
)},
{
"dir_list"
,
"Directory listing"
,
OFFSET
(
enable_directory_listing
)},
{
"protect"
,
"URI to htpasswd mapping"
,
OFFSET
(
protect
)},
{
"cgi_ext"
,
"CGI extensions"
,
OFFSET
(
cgi_extensions
)},
{
"cgi_interp"
,
"CGI interpreter to use"
,
OFFSET
(
cgi_interpreter
)},
{
"cgi_env"
,
"Custom CGI enviroment variables"
,
OFFSET
(
cgi_environment
)},
{
"ssi_ext"
,
"SSI extensions"
,
OFFSET
(
ssi_extensions
)},
{
"auth_realm"
,
"Authentication domain name"
,
OFFSET
(
auth_domain
)},
{
"auth_gpass"
,
"Global passwords file"
,
OFFSET
(
global_passwords_file
)},
{
"auth_PUT"
,
"PUT,DELETE auth file"
,
OFFSET
(
put_delete_passwords_file
)},
{
"uid"
,
"
\t
Run as user"
,
OFFSET
(
uid
)},
{
"access_log"
,
"Access log file"
,
OFFSET
(
access_log_file
)},
{
"error_log"
,
"Error log file"
,
OFFSET
(
error_log_file
)},
{
"acl"
,
"
\t
Allow/deny IP addresses/subnets"
,
OFFSET
(
acl
)},
{
"num_threads"
,
"Threads to spawn"
,
OFFSET
(
num_threads
)},
{
"mime_types"
,
"Extra mime types to use"
,
OFFSET
(
mime_types
)},
{
NULL
,
NULL
,
0
}
};
static
void
show_usage_and_exit
(
const
struct
mg_config
*
config
)
{
const
struct
option_descriptor
*
o
;
const
char
*
value
;
(
void
)
fprintf
(
stderr
,
"Mongoose version %s (c) Sergey Lyubka
\n
"
"usage: mongoose [options] [config_file]
\n
"
,
mg_version
());
fprintf
(
stderr
,
" -A <htpasswd_file> <realm> <user> <passwd>
\n
"
);
for
(
o
=
known_options
;
o
->
name
!=
NULL
;
o
++
)
{
(
void
)
fprintf
(
stderr
,
" -%s
\t
%s"
,
o
->
name
,
o
->
description
);
value
=
*
(
char
**
)
((
char
*
)
config
+
o
->
offset
);
if
(
value
!=
NULL
)
fprintf
(
stderr
,
" (default:
\"
%s
\"
)"
,
value
);
fputc
(
'\n'
,
stderr
);
}
exit
(
EXIT_FAILURE
);
}
static
void
static
void
process_command_line_arguments
(
struct
mg_context
*
ctx
,
char
*
argv
[])
set_option
(
struct
mg_config
*
config
,
const
char
*
name
,
char
*
value
)
{
const
struct
option_descriptor
*
o
;
for
(
o
=
known_options
;
o
->
name
!=
NULL
;
o
++
)
if
(
strcmp
(
name
,
o
->
name
)
==
0
)
{
*
(
char
**
)
((
char
*
)
config
+
o
->
offset
)
=
value
;
break
;
}
if
(
o
->
name
==
NULL
)
show_usage_and_exit
(
config
);
}
static
void
process_command_line_arguments
(
struct
mg_config
*
config
,
char
*
argv
[])
{
{
const
char
*
config_file
=
CONFIG_FILE
;
const
char
*
config_file
=
CONFIG_FILE
;
char
line
[
512
],
opt
[
512
],
*
vals
[
100
],
char
line
[
512
],
opt
[
512
],
*
vals
[
100
],
...
@@ -110,11 +172,11 @@ process_command_line_arguments(struct mg_context *ctx, char *argv[])
...
@@ -110,11 +172,11 @@ process_command_line_arguments(struct mg_context *ctx, char *argv[])
/* First find out, which config file to open */
/* First find out, which config file to open */
for
(
i
=
1
;
argv
[
i
]
!=
NULL
&&
argv
[
i
][
0
]
==
'-'
;
i
+=
2
)
for
(
i
=
1
;
argv
[
i
]
!=
NULL
&&
argv
[
i
][
0
]
==
'-'
;
i
+=
2
)
if
(
argv
[
i
+
1
]
==
NULL
)
if
(
argv
[
i
+
1
]
==
NULL
)
show_usage_and_exit
();
show_usage_and_exit
(
config
);
if
(
argv
[
i
]
!=
NULL
&&
argv
[
i
+
1
]
!=
NULL
)
{
if
(
argv
[
i
]
!=
NULL
&&
argv
[
i
+
1
]
!=
NULL
)
{
/* More than one non-option arguments are given */
/* More than one non-option arguments are given */
show_usage_and_exit
();
show_usage_and_exit
(
config
);
}
else
if
(
argv
[
i
]
!=
NULL
)
{
}
else
if
(
argv
[
i
]
!=
NULL
)
{
/* Just one non-option argument is given, this is config file */
/* Just one non-option argument is given, this is config file */
config_file
=
argv
[
i
];
config_file
=
argv
[
i
];
...
@@ -140,7 +202,8 @@ process_command_line_arguments(struct mg_context *ctx, char *argv[])
...
@@ -140,7 +202,8 @@ process_command_line_arguments(struct mg_context *ctx, char *argv[])
(
void
)
memset
(
vals
,
0
,
sizeof
(
vals
));
(
void
)
memset
(
vals
,
0
,
sizeof
(
vals
));
if
(
fp
!=
NULL
)
{
if
(
fp
!=
NULL
)
{
(
void
)
printf
(
"Loading config file %s
\n
"
,
config_file
);
(
void
)
printf
(
"Loading config file %s, "
"ignoring command line arguments
\n
"
,
config_file
);
/* Loop over the lines in config file */
/* Loop over the lines in config file */
while
(
fgets
(
line
,
sizeof
(
line
),
fp
)
!=
NULL
)
{
while
(
fgets
(
line
,
sizeof
(
line
),
fp
)
!=
NULL
)
{
...
@@ -156,56 +219,67 @@ process_command_line_arguments(struct mg_context *ctx, char *argv[])
...
@@ -156,56 +219,67 @@ process_command_line_arguments(struct mg_context *ctx, char *argv[])
config_file
,
(
int
)
line_no
);
config_file
,
(
int
)
line_no
);
exit
(
EXIT_FAILURE
);
exit
(
EXIT_FAILURE
);
}
}
if
(
mg_set_option
(
ctx
,
opt
,
val
)
!=
1
)
/* TODO(lsm): free this at some point */
exit
(
EXIT_FAILURE
);
p
=
malloc
(
strlen
(
val
)
+
1
);
(
void
)
strcpy
(
p
,
val
);
set_option
(
config
,
opt
,
p
);
}
}
(
void
)
fclose
(
fp
);
(
void
)
fclose
(
fp
);
}
}
else
{
/* Now pass through the command line options */
for
(
i
=
1
;
argv
[
i
]
!=
NULL
&&
argv
[
i
][
0
]
==
'-'
;
i
+=
2
)
for
(
i
=
1
;
argv
[
i
]
!=
NULL
&&
argv
[
i
][
0
]
==
'-'
;
i
+=
2
)
if
(
mg_set_option
(
ctx
,
&
argv
[
i
][
1
],
argv
[
i
+
1
])
!=
1
)
set_option
(
config
,
&
argv
[
i
][
1
],
argv
[
i
+
1
]);
exit
(
EXIT_FAILURE
);
}
}
}
int
int
main
(
int
argc
,
char
*
argv
[])
main
(
int
argc
,
char
*
argv
[])
{
{
struct
mg_config
config
;
struct
mg_context
*
ctx
;
struct
mg_context
*
ctx
;
char
ports
[
1024
],
web_root
[
1024
];
/* Initialize configuration with default values */
(
void
)
memset
(
&
config
,
0
,
sizeof
(
config
));
config
.
document_root
=
"."
;
config
.
enable_directory_listing
=
"yes"
;
config
.
auth_domain
=
"mydomain.com"
;
config
.
num_threads
=
"20"
;
config
.
index_files
=
"index.html,index.htm,index.cgi"
;
config
.
cgi_extensions
=
".cgi,.pl,.php"
;
config
.
ssi_extensions
=
".shtml,.shtm"
;
config
.
listening_ports
=
"8080"
;
/* Edit passwords file if -A option is specified */
if
(
argc
>
1
&&
argv
[
1
][
0
]
==
'-'
&&
argv
[
1
][
1
]
==
'A'
)
{
if
(
argc
>
1
&&
argv
[
1
][
0
]
==
'-'
&&
argv
[
1
][
1
]
==
'A'
)
{
if
(
argc
!=
6
)
if
(
argc
!=
6
)
show_usage_and_exit
();
show_usage_and_exit
(
&
config
);
exit
(
mg_edit_passwords
(
argv
[
2
],
argv
[
3
],
argv
[
4
],
argv
[
5
])
==
exit
(
mg_edit_passwords
(
argv
[
2
],
argv
[
3
],
argv
[
4
],
argv
[
5
])
==
MG_SUCCESS
?
EXIT_SUCCESS
:
EXIT_FAILURE
);
MG_SUCCESS
?
EXIT_SUCCESS
:
EXIT_FAILURE
);
}
}
/* Show usage if -h or --help options are specified */
if
(
argc
==
2
&&
(
!
strcmp
(
argv
[
1
],
"-h"
)
||
!
strcmp
(
argv
[
1
],
"--help"
)))
if
(
argc
==
2
&&
(
!
strcmp
(
argv
[
1
],
"-h"
)
||
!
strcmp
(
argv
[
1
],
"--help"
)))
show_usage_and_exit
();
show_usage_and_exit
(
&
config
);
/* Update config based on command line arguments */
process_command_line_arguments
(
&
config
,
argv
);
/* Setup signal handler: quit on Ctrl-C */
#ifndef _WIN32
#ifndef _WIN32
(
void
)
signal
(
SIGCHLD
,
signal_handler
);
(
void
)
signal
(
SIGCHLD
,
signal_handler
);
#endif
/* _WIN32 */
#endif
/* _WIN32 */
(
void
)
signal
(
SIGTERM
,
signal_handler
);
(
void
)
signal
(
SIGTERM
,
signal_handler
);
(
void
)
signal
(
SIGINT
,
signal_handler
);
(
void
)
signal
(
SIGINT
,
signal_handler
);
if
((
ctx
=
mg_start
())
==
NULL
)
{
/* Start Mongoose */
if
((
ctx
=
mg_start
(
&
config
))
==
NULL
)
{
(
void
)
printf
(
"%s
\n
"
,
"Cannot initialize Mongoose context"
);
(
void
)
printf
(
"%s
\n
"
,
"Cannot initialize Mongoose context"
);
exit
(
EXIT_FAILURE
);
exit
(
EXIT_FAILURE
);
}
}
process_command_line_arguments
(
ctx
,
argv
);
(
void
)
printf
(
"Mongoose %s started on port(s) %s "
(
void
)
mg_get_option
(
ctx
,
"ports"
,
ports
,
sizeof
(
ports
));
"with web root [%s]
\n
"
,
if
(
ports
[
0
]
==
'\0'
&&
mg_version
(),
config
.
listening_ports
,
config
.
document_root
);
mg_set_option
(
ctx
,
"ports"
,
"8080"
)
!=
MG_SUCCESS
)
exit
(
EXIT_FAILURE
);
(
void
)
mg_get_option
(
ctx
,
"ports"
,
ports
,
sizeof
(
ports
));
(
void
)
mg_get_option
(
ctx
,
"root"
,
web_root
,
sizeof
(
web_root
));
(
void
)
printf
(
"Mongoose %s started on port(s)
\"
%s
\"
, "
"serving directory
\"
%s
\"\n
"
,
mg_version
(),
ports
,
web_root
);
fflush
(
stdout
);
fflush
(
stdout
);
while
(
exit_flag
==
0
)
while
(
exit_flag
==
0
)
...
...
mongoose.c
View file @
5425b94f
This diff is collapsed.
Click to expand it.
mongoose.h
View file @
5425b94f
...
@@ -59,8 +59,21 @@ struct mg_request_info {
...
@@ -59,8 +59,21 @@ struct mg_request_info {
/*
/*
* Error codes for all functions that return 'int'.
* User-defined handler function. It must return MG_SUCCESS or MG_ERROR.
*
* If handler returns MG_SUCCESS, that means that handler has processed the
* request by sending appropriate HTTP reply to the client. Mongoose treats
* the request as served.
*
* If callback returns MG_ERROR, that means that callback has not processed
* the request. Handler must not send any data to the client in this case.
* Mongoose proceeds with request handling as if nothing happened.
*
* NOTE: ssl_password_handler must have the following prototype:
* int (*)(char *, int, int, void *)
* Refer to OpenSSL documentation for more details.
*/
*/
enum
mg_error_t
{
enum
mg_error_t
{
MG_ERROR
,
MG_ERROR
,
MG_SUCCESS
,
MG_SUCCESS
,
...
@@ -68,15 +81,48 @@ enum mg_error_t {
...
@@ -68,15 +81,48 @@ enum mg_error_t {
MG_BUFFER_TOO_SMALL
MG_BUFFER_TOO_SMALL
};
};
typedef
enum
mg_error_t
(
*
mg_callback_t
)(
struct
mg_connection
*
,
const
struct
mg_request_info
*
);
/*
* This structure describes Mongoose configuration.
*/
struct
mg_config
{
char
*
document_root
;
char
*
index_files
;
char
*
ssl_certificate
;
char
*
listening_ports
;
char
*
cgi_extensions
;
char
*
cgi_interpreter
;
char
*
cgi_environment
;
char
*
ssi_extensions
;
char
*
auth_domain
;
char
*
protect
;
char
*
global_passwords_file
;
char
*
put_delete_passwords_file
;
char
*
access_log_file
;
char
*
error_log_file
;
char
*
acl
;
char
*
uid
;
char
*
mime_types
;
char
*
enable_directory_listing
;
char
*
num_threads
;
mg_callback_t
new_request_handler
;
mg_callback_t
http_error_handler
;
mg_callback_t
event_log_handler
;
mg_callback_t
ssl_password_handler
;
};
/*
/*
* Start the web server.
* Start the web server.
*
*
* This must be the first function called by the application.
* This must be the first function called by the application.
* It creates a serving thread, and returns a context structure that
* It creates a serving thread, and returns a context structure that
* can be used to
alter the configuration, and
stop the server.
* can be used to stop the server.
*/
*/
struct
mg_context
*
mg_start
(
void
);
struct
mg_context
*
mg_start
(
struct
mg_config
*
);
/*
/*
...
@@ -89,32 +135,6 @@ struct mg_context *mg_start(void);
...
@@ -89,32 +135,6 @@ struct mg_context *mg_start(void);
void
mg_stop
(
struct
mg_context
*
);
void
mg_stop
(
struct
mg_context
*
);
/*
* Get the current value of a particular option.
*
* Return:
* MG_SUCCESS, MG_NOT_FOUND, MG_BUFFER_TOO_SMALL
*/
enum
mg_error_t
mg_get_option
(
struct
mg_context
*
,
const
char
*
option_name
,
char
*
buf
,
size_t
buf_len
);
/*
* Set a value for a particular option.
*
* Mongoose makes an internal copy of the option value string, which must be
* valid nul-terminated ASCII or UTF-8 string. It is safe to change any option
* at any time. The order of setting various options is also irrelevant with
* one exception: if "ports" option contains SSL listening ports, a "ssl_cert"
* option must be set BEFORE the "ports" option.
*
* Return:
* MG_ERROR, MG_SUCCESS, or MG_NOT_FOUND if option is unknown.
*/
enum
mg_error_t
mg_set_option
(
struct
mg_context
*
,
const
char
*
name
,
const
char
*
value
);
/*
/*
* Add, edit or delete the entry in the passwords file.
* Add, edit or delete the entry in the passwords file.
*
*
...
@@ -133,36 +153,6 @@ enum mg_error_t mg_modify_passwords_file(struct mg_context *ctx,
...
@@ -133,36 +153,6 @@ enum mg_error_t mg_modify_passwords_file(struct mg_context *ctx,
const
char
*
file_name
,
const
char
*
user
,
const
char
*
password
);
const
char
*
file_name
,
const
char
*
user
,
const
char
*
password
);
/*
* Attach a callback function to certain event.
* Callback must return MG_SUCCESS or MG_ERROR.
*
* If callback returns MG_SUCCESS, that means that callback has processed the
* request by sending appropriate HTTP reply to the client. Mongoose treats
* the request as served.
*
* If callback returns MG_ERROR, that means that callback has not processed
* the request. Callback must not send any data to client in this case.
* Mongoose proceeds with request handling.
*
* NOTE: for MG_EVENT_SSL_PASSWORD event the callback must have
* int (*)(char *, int, int, void *) prototype. Refer to OpenSSL documentation
* for more details about the SSL password callback.
*/
enum
mg_event_t
{
MG_EVENT_NEW_REQUEST
,
/* New HTTP request has arrived */
MG_EVENT_HTTP_ERROR
,
/* Mongoose is about to send HTTP error */
MG_EVENT_LOG
,
/* Mongoose is about to log a message */
MG_EVENT_SSL_PASSWORD
,
/* SSL certificate needs verification */
NUM_EVENTS
};
typedef
enum
mg_error_t
(
*
mg_callback_t
)(
struct
mg_connection
*
,
const
struct
mg_request_info
*
);
void
mg_set_callback
(
struct
mg_context
*
,
enum
mg_event_t
,
mg_callback_t
);
/*
/*
* Send data to the client.
* Send data to the client.
*/
*/
...
@@ -185,6 +175,7 @@ int mg_printf(struct mg_connection *, const char *fmt, ...);
...
@@ -185,6 +175,7 @@ int mg_printf(struct mg_connection *, const char *fmt, ...);
*/
*/
int
mg_read
(
struct
mg_connection
*
,
void
*
buf
,
size_t
len
);
int
mg_read
(
struct
mg_connection
*
,
void
*
buf
,
size_t
len
);
/*
/*
* Get the value of particular HTTP header.
* Get the value of particular HTTP header.
*
*
...
@@ -247,11 +238,6 @@ const char *mg_version(void);
...
@@ -247,11 +238,6 @@ const char *mg_version(void);
void
mg_md5
(
char
*
buf
,
...);
void
mg_md5
(
char
*
buf
,
...);
/*
* Print command line usage string.
*/
void
mg_show_usage_string
(
FILE
*
fp
);
#ifdef __cplusplus
#ifdef __cplusplus
}
}
#endif
/* __cplusplus */
#endif
/* __cplusplus */
...
...
test/test.pl
View file @
5425b94f
...
@@ -13,12 +13,11 @@ sub on_windows { $^O =~ /win32/i; }
...
@@ -13,12 +13,11 @@ sub on_windows { $^O =~ /win32/i; }
my
$port
=
23456
;
my
$port
=
23456
;
my
$pid
=
undef
;
my
$pid
=
undef
;
my
$num_requests
;
my
$num_requests
;
my
$root
=
'test'
;
my
$dir_separator
=
on_windows
()
?
'\\'
:
'/'
;
my
$dir_separator
=
on_windows
()
?
'\\'
:
'/'
;
my
$copy_cmd
=
on_windows
()
?
'copy'
:
'cp'
;
my
$copy_cmd
=
on_windows
()
?
'copy'
:
'cp'
;
my
$test_dir_uri
=
"test_dir"
;
my
$test_dir_uri
=
"test_dir"
;
my
$root
=
'test'
;
my
$test_dir
=
$root
.
$dir_separator
.
$test_dir_uri
;
my
$test_dir
=
$root
.
$dir_separator
.
$test_dir_uri
;
my
$alias
=
"/aliased=/etc/,/ta=$test_dir"
;
my
$config
=
'mongoose.conf'
;
my
$config
=
'mongoose.conf'
;
my
$exe
=
'.'
.
$dir_separator
.
'mongoose'
;
my
$exe
=
'.'
.
$dir_separator
.
'mongoose'
;
my
$embed_exe
=
'.'
.
$dir_separator
.
'embed'
;
my
$embed_exe
=
'.'
.
$dir_separator
.
'embed'
;
...
@@ -89,6 +88,7 @@ sub o {
...
@@ -89,6 +88,7 @@ sub o {
# Spawn a server listening on specified port
# Spawn a server listening on specified port
sub
spawn
{
sub
spawn
{
my
(
$cmdline
)
=
@_
;
my
(
$cmdline
)
=
@_
;
print
'Executing: '
,
@_
,
"\n"
;
if
(
on_windows
())
{
if
(
on_windows
())
{
my
@args
=
split
/\s+/
,
$cmdline
;
my
@args
=
split
/\s+/
,
$cmdline
;
my
$executable
=
$args
[
0
];
my
$executable
=
$args
[
0
];
...
@@ -159,7 +159,7 @@ kill_spawned_child();
...
@@ -159,7 +159,7 @@ kill_spawned_child();
my
$cmd
=
"$exe -ports $port -access_log access.log -error_log debug.log "
.
my
$cmd
=
"$exe -ports $port -access_log access.log -error_log debug.log "
.
"-cgi_env CGI_FOO=foo,CGI_BAR=bar,CGI_BAZ=baz "
.
"-cgi_env CGI_FOO=foo,CGI_BAR=bar,CGI_BAZ=baz "
.
"-mime_types .bar=foo/bar,.tar.gz=blah,.baz=foo "
.
"-mime_types .bar=foo/bar,.tar.gz=blah,.baz=foo "
.
"-root
test -aliases $alias -admin_uri /hh
"
;
"-root
$root,/aiased=/etc/,/ta=$test_dir
"
;
$cmd
.=
' -cgi_interp perl'
if
on_windows
();
$cmd
.=
' -cgi_interp perl'
if
on_windows
();
spawn
(
$cmd
);
spawn
(
$cmd
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment