This patch addes the "inlcude_dir" keyword for httpd.conf. Which works
just like "include" but it includes all the files in a directory, for
example: include "/etc/httpd.d"
The diff file is attatched.
Index: httpd.conf.5
===================================================================
RCS file: /cvs/src/usr.sbin/httpd/httpd.conf.5,v
retrieving revision 1.121
diff -u -p -u -p -r1.121 httpd.conf.5
--- httpd.conf.5 9 Mar 2022 13:50:41 -0000 1.121
+++ httpd.conf.5 2 Jun 2022 09:02:22 -0000
@@ -84,6 +84,12 @@ keyword, for example:
.Bd -literal -offset indent
include "/etc/httpd.conf.local"
.Ed
+A directory with configuration files can be included with the
+.Ic include_dir
+keyword, for example:
+.Bd -literal -offset indent
+include_dir "/etc/httpd.conf.d"
+.Ed
.Sh MACROS
Macros can be defined that will later be expanded in context.
Macro names must start with a letter, digit, or underscore,
Index: parse.y
===================================================================
RCS file: /cvs/src/usr.sbin/httpd/parse.y,v
retrieving revision 1.128
diff -u -p -u -p -r1.128 parse.y
--- parse.y 27 Feb 2022 20:30:30 -0000 1.128
+++ parse.y 2 Jun 2022 09:02:22 -0000
@@ -52,6 +52,7 @@
#include <string.h>
#include <ifaddrs.h>
#include <syslog.h>
+#include <dirent.h>
#include "httpd.h"
#include "http.h"
@@ -139,7 +140,7 @@ typedef struct {
%token LISTEN LOCATION LOG LOGDIR MATCH MAXIMUM NO NODELAY OCSP ON PORT PREFORK
%token PROTOCOLS REQUESTS ROOT SACK SERVER SOCKET STRIP STYLE SYSLOG TCP TICKET
%token TIMEOUT TLS TYPE TYPES HSTS MAXAGE SUBDOMAINS DEFAULT PRELOAD REQUEST
-%token ERROR INCLUDE AUTHENTICATE WITH BLOCK DROP RETURN PASS REWRITE
+%token ERROR INCLUDE INCLUDE_DIR AUTHENTICATE WITH BLOCK DROP RETURN PASS
REWRITE
%token CA CLIENT CRL OPTIONAL PARAM FORWARDED FOUND NOT
%token ERRDOCS GZIPSTATIC
%token <v.string> STRING
@@ -155,6 +156,7 @@ typedef struct {
grammar : /* empty */
| grammar include '\n'
+ | grammar include_dir '\n'
| grammar '\n'
| grammar varset '\n'
| grammar main '\n'
@@ -165,7 +167,6 @@ grammar : /* empty */
include : INCLUDE STRING {
struct file *nfile;
-
if ((nfile = pushfile($2, 0)) == NULL) {
yyerror("failed to include file %s", $2);
free($2);
@@ -178,6 +179,46 @@ include : INCLUDE STRING {
}
;
+include_dir : INCLUDE_DIR STRING {
+ char absolute_path[PATH_MAX];
+ char dir[PATH_MAX];
+ struct file *nfile;
+ DIR *opened_dir = opendir($2);
+ struct dirent *entry;
+
+ if(opened_dir == NULL) {
+ free($2);
+ yyerror("Failed to open directory %s", $2);
+ YYERROR;
+ }
+
+ size_t len = strlcpy(dir, $2, PATH_MAX);
+
+ if(len >= sizeof(dir)) {
+ free($2);
+ yyerror("too long");
+ YYERROR;
+ }
+
+ while((entry = readdir(opened_dir))) {
+ if(entry->d_name[0] == '.')
+ continue;
+ len =
snprintf(absolute_path,PATH_MAX,"%s%s",dir, entry->d_name);
+ if(len < 0|| len >= sizeof(absolute_path)) {
+ yyerror("too long");
+ YYERROR;
+ }
+ if((nfile = pushfile(absolute_path, 0)) ==
NULL) {
+ yyerror("failed to include file %s",
$2);
+ YYERROR;
+ }
+ }
+
+ file = nfile;
+ lungetc('\n');
+ }
+ ;
+
varset : STRING '=' STRING {
char *s = $1;
while (*s++) {
@@ -1453,6 +1494,7 @@ lookup(char *s)
{ "gzip-static", GZIPSTATIC },
{ "hsts", HSTS },
{ "include", INCLUDE },
+ { "include_dir", INCLUDE_DIR},
{ "index", INDEX },
{ "ip", IP },
{ "key", KEY },