Browse Source

Started arg parser implementation

Yann Weber 4 years ago
parent
commit
9906803b42
4 changed files with 184 additions and 1 deletions
  1. 65
    0
      include/conf.h
  2. 1
    1
      src/Makefile.am
  3. 110
    0
      src/conf.c
  4. 8
    0
      src/main.c

+ 65
- 0
include/conf.h View File

@@ -19,6 +19,9 @@
19 19
 #ifndef __CONF_H___
20 20
 #define __CONF_H___
21 21
 
22
+#include <unistd.h>
23
+#include <getopt.h>
24
+
22 25
 #include "config.h"
23 26
 /**@defgroup conf_internal PYFCGI configuration handling
24 27
  */
@@ -38,6 +41,55 @@
38 41
 /**@ingroup ret_status */
39 42
 #define PYFCGI_FATAL 128
40 43
 
44
+#define PYFCGI_NAME "spawn-fcgi [OPTIONS] -- pyfcgi"
45
+
46
+#define PYFCGI_SHORT_OPT "Ce:E:w:W:m:l:Svh"
47
+
48
+#define PYFCGI_LONG_OPT { \
49
+	{"config", required_argument, 0, 'C'},\
50
+	{"pymodule", required_argument, 0, 'e'},\
51
+	{"pyapp", required_argument, 0, 'E'},\
52
+	{"min-worker", required_argument, 0, 'w'},\
53
+	{"max-worker", required_argument, 0, 'W'},\
54
+	{"max-request", required_argument, 0, 'm'},\
55
+	{"log", required_argument, 0, 'L'},\
56
+	{"syslog", no_argument, 0, 'S'},\
57
+	{"pid-file", required_argument, 0, 'P'},\
58
+	{"version", no_argument, 0, 'v'},\
59
+	{"help", no_argument, 0, 'h' },\
60
+	{0, 0, 0, 0}\
61
+}
62
+
63
+#define PYFCGI_OPT_HELP {\
64
+	{"Load options from configuration file", "CONFIG"},\
65
+	{"Search application function in given python module", "MODULE_NAME"},\
66
+	{"Python application entrypoint function name", "FUNC_NAME"},\
67
+	{"Minimum worker in the pool", "INT"},\
68
+	{"Maximum worker in the pool", "INT"},\
69
+	{"Request count after wich the worker is restarted (if 0 never restart)", "INT"},\
70
+	{"Add a logfile using syntax : 'LOGFILE[;FILT][;FMT]'", "LOGGER_SPEC"},\
71
+	{"Use syslog for logging", NULL},\
72
+	{"Create a PID file", "FILENAME"},\
73
+	{"Print PyFCGI and Python version and exit", NULL},\
74
+	{"Display this help and exit", NULL},\
75
+}
76
+
77
+#define PYFCGI_HELP_TEXT "Logger specification format 'LOGFILE[;FILT][;FMT]' with :\n\
78
+\t- LOGFILE the log file name\n\
79
+\t- FILT a number (in decimal or hexadicimal 0xXX) indicating wich\n\
80
+\t  facility/level to log\n\
81
+\t- FMT the logline format in a special markup format using fields between { }\n\
82
+\t  supported fields are :\n\
83
+\t\t- {datetime} {datetime:SIZE} {datetime:SIZE:FMT} defines a format and a \n\
84
+\t\t  constant length for a datetime field. Default : {datetime:25:%F %T%z}\n\
85
+\t\t- {level} the loglevel \n\
86
+\t\t- {facility} the log facility\n\
87
+\t\t- {pid} the process PID\n\
88
+\t\t- {ident} the defined ident (set by process)\n\
89
+\t\t- {msg} the log message (can only appear once)\n\
90
+You can escape { and } by using {{ and }} and all field names can by\n\
91
+abbreviated to one character.\n"
92
+
41 93
 /**@brief Friendly name for @ref struct pyfcgi_conf_s
42 94
  * @see struct pyfcgi_conf_s */
43 95
 typedef struct pyfcgi_conf_s pyfcgi_conf_t;
@@ -47,6 +99,7 @@ typedef struct pyfcgi_context_s pyfcgi_context_t;
47 99
 struct pyfcgi_context_s {
48 100
 	pid_t pid;
49 101
 	pid_t ppid;
102
+	char *pidfile;
50 103
 };
51 104
 
52 105
 /**@brief Structure containing configuration
@@ -84,4 +137,16 @@ struct pyfcgi_conf_s
84 137
 /**@brief Configuration globals, inherited from parent to childs */
85 138
 pyfcgi_conf_t PyFCGI_conf;
86 139
 
140
+/**@brief Print usage on FD 2 (stdout) */
141
+void usage();
142
+
143
+/**@brief Print pyfcgi & python version on given fd */
144
+void print_version(int);
145
+
146
+/**@brief Parse arguments and store them in conf
147
+ * @return 0 if no error */
148
+int parse_args(int argc, char *argv[]);
149
+
150
+int parse_optlog(const char*);
151
+
87 152
 #endif

+ 1
- 1
src/Makefile.am View File

@@ -1,7 +1,7 @@
1 1
 bin_PROGRAMS = pyfcgi
2 2
 noinst_LIBRARIES = libpyfcgi.a
3 3
 
4
-libpyfcgi_a_SOURCES = logger.c pyworker.c responder.c
4
+libpyfcgi_a_SOURCES = logger.c pyworker.c responder.c conf.c
5 5
 libpyfcgi_a_CFLAGS = $(PYTHON_CFLAGS)
6 6
 
7 7
 

+ 110
- 0
src/conf.c View File

@@ -0,0 +1,110 @@
1
+#include "conf.h"
2
+
3
+void usage()
4
+{
5
+	static const struct option opts[] = PYFCGI_LONG_OPT;
6
+	static const char *help[][2] = PYFCGI_OPT_HELP;
7
+	size_t i;
8
+	dprintf(2, "Usage : %s -e PYMODULE -E PYFUN [OPTIONS]\n", PYFCGI_NAME);
9
+	dprintf(2, "\nOptions list :\n");
10
+	i=0;
11
+	while(opts[i].name)
12
+	{
13
+		dprintf(2, "\t-%c, --%s", opts[i].val, opts[i].name);
14
+		switch(opts[i].has_arg)
15
+		{
16
+			case required_argument:
17
+				dprintf(2, "=%s\n",
18
+					help[i][1]?help[i][1]:"ARG");
19
+				break;
20
+			case optional_argument:
21
+				dprintf(2, "[=%s]\n",
22
+					help[i][1]?help[i][1]:"ARG");
23
+				break;
24
+			default: //no_argument
25
+				dprintf(2, "\n");
26
+		}
27
+		printf("\t\t%s\n\n", help[i][0]);
28
+		i++;
29
+	}
30
+	dprintf(2, "%s", PYFCGI_HELP_TEXT);
31
+}
32
+
33
+void print_version(int fd)
34
+{
35
+
36
+}
37
+
38
+int parse_args(int argc, char *argv[])
39
+{
40
+	static const struct option long_options[] = PYFCGI_LONG_OPT;
41
+	int c, opt_i;
42
+	while(1)
43
+	{
44
+		c = getopt_long(argc, argv, PYFCGI_SHORT_OPT, long_options,
45
+			&opt_i);
46
+		if(c == -1) { break; }
47
+		switch(c)
48
+		{
49
+			case 'v':
50
+				print_version(1);
51
+				exit(0);
52
+			case 'C':
53
+				dprintf(2, "Config parser not yet implemented :'(\n");
54
+				exit(1);
55
+			case 'e':
56
+				PyFCGI_conf.py_entrymod = strdup(optarg);
57
+				break;
58
+			case 'E':
59
+				PyFCGI_conf.py_entryfun = strdup(optarg);
60
+				break;
61
+			case 'w':
62
+				PyFCGI_conf.min_wrk = atoi(optarg);
63
+				break;
64
+			case 'W':
65
+				PyFCGI_conf.max_wrk = atoi(optarg);
66
+				break;
67
+			case 'm':
68
+				PyFCGI_conf.max_reqs = atoi(optarg);
69
+				if(PyFCGI_conf.max_reqs < 0)
70
+				{
71
+					PyFCGI_conf.max_reqs = 0;
72
+				}
73
+				break;
74
+			case 'L':
75
+				if(parse_optlog(optarg))
76
+				{
77
+					exit(1);
78
+				}
79
+				break;
80
+			case 'S':
81
+				PyFCGI_conf.logs.flags |= PYFCGI_LOG_FSYSLOG;
82
+				break;
83
+			case 'P':
84
+				PyFCGI_conf.context.pidfile = strdup(optarg);
85
+				break;
86
+			case 'h':
87
+				usage();
88
+				exit(0);
89
+			default:
90
+				usage();
91
+				exit(1);
92
+		}
93
+	}
94
+	if(optind < argc)
95
+	{
96
+		for(opt_i=optind; opt_i<argc; opt_i++)
97
+		{
98
+			dprintf(2, "Unkown argument '%s'\n", argv[opt_i]);
99
+		}
100
+		usage();
101
+		exit(1);
102
+	}
103
+	return 0;
104
+}
105
+
106
+int parse_optlog(const char* logspec)
107
+{
108
+	return 0;
109
+}
110
+

+ 8
- 0
src/main.c View File

@@ -59,13 +59,21 @@ int main(int argc, char **argv)
59 59
 	unsigned int emerg_sleep = 3;
60 60
 
61 61
 	py_entrypoint = getenv("PY_ENTRYPOINT");
62
+	/*
62 63
 	if(argc > 1 || !py_entrypoint)
63 64
 	{
65
+		usage();
66
+		return 1;
64 67
 		EARLY_ERR("Usage : PY_ENTRYPOINT='PATH.py' spawn-fcgi [OPTIONS] ");
65 68
 		EARLY_ERR(argv[0]);
66 69
 		EARLY_ERR("\n");
67 70
 		return 1;
68 71
 	}
72
+	*/
73
+	if(parse_args(argc, argv))
74
+	{
75
+		return 1;
76
+	}
69 77
 
70 78
 PyFCGI_conf.context.pid = getpid();
71 79
 

Loading…
Cancel
Save