Added support for suPHP_UserGroup directive
[vhostgen.git] / vhostgen.c
blob824733441b94743bb6e0b715c3c3a48e795243a5
1 /*
2 * Copyright (c) 2007 Svante Kvarnström <sjk@ankeborg.nu>
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 #include <stdlib.h>
19 #include <stdio.h>
20 #include <time.h>
21 #include <string.h>
23 #include "mysql.h"
25 #define MAX_BUFF 512
27 struct config_list {
28 char *username; /* Mysql username */
29 char *password; /* Mysql password */
30 char *host; /* Mysql hostname */
31 char *vhosttable; /* Mysql vhost table */
32 char *db; /* Mysql database */
33 char *outfile; /* Vhost config file to write */
34 char *logpath; /* basepath for logfiles */
37 int load_config_file(const char *, struct config_list *);
38 char *mkdate(void);
40 int
41 main(int argc, char *argv[])
43 MYSQL sql_conn;
44 MYSQL_ROW sqlrow;
45 MYSQL_RES *res_ptr;
47 res_ptr = NULL;
49 int res;
50 char *query; /* Points at a mysql (INSERT/DELETE/SELECT/WHATEVER) query */
51 int qlen; /* Length of query string */
52 FILE *out; /* File handler for vhost config file (/var/www/conf/vhosts.conf or so) */
54 struct config_list *clist;
55 clist = malloc(sizeof(struct config_list));
57 /* Populate the clist struct with information taken from CONFIG_FILE */
58 /* If we can't open the config file, exit. */
59 if (load_config_file(CONFIG_FILE, clist)) {
60 exit(1);
63 /* Initialize mysql database connection, select database, etc */
64 mysql_init(&sql_conn);
66 if (!mysql_real_connect(&sql_conn, clist->host, clist->username, clist->password, clist->db, 0, NULL, 0)) {
67 if (mysql_errno(&sql_conn)) {
68 fprintf(stderr, "Connection error %d: %s\n", mysql_errno(&sql_conn), mysql_error(&sql_conn));
69 exit(1);
74 * Since mysql_query doesn't support printf's %s/%d/whatever format, we'll
75 * have to craft the exact SELECT message with snprintf first, and then send
76 * that to mysql_query. snprintf wants the length of the string, so we start
77 * of by getting that.
79 qlen = strlen("SELECT * FROM ") + strlen(clist->vhosttable) + 1;
81 /* Next we allocate enough memory for our sql query. */
82 query = malloc(sizeof(char) * qlen);
85 * And now we put the query into "query" (or well, we put it into memory and
86 * have query direct us to it :)
88 snprintf(query, qlen, "SELECT * FROM %s", clist->vhosttable);
90 res = mysql_query(&sql_conn, query);
92 if (res)
93 fprintf(stderr, "SELECT error: %s\n", mysql_error(&sql_conn));
94 else {
95 res_ptr = mysql_use_result(&sql_conn);
96 if (res_ptr) {
98 * Alright, we've got stuff from the database. Now we need to write it
99 * to the vhost config file. Let's see if we can open the config file for
100 * writing. If not we're screwed.
102 if ((out = fopen(clist->outfile, "w")) == NULL) {
103 fprintf(stderr, "ERROR: %s could not be opened for writing\n", clist->outfile);
104 exit(1);
107 fprintf(out, "# This file was generated by vhostgen %s.\n"
108 "# DO NOT EDIT THIS FILE MANUALLY AS ANY CHANGES WILL BE"
109 " LOST. \n# Make any changes to the database instead.\n \n\n", mkdate());
111 while ((sqlrow = mysql_fetch_row(res_ptr))) {
112 if (sqlrow[2] && *sqlrow[2] != '\0')
113 fprintf(out,"# %d - %s (%s), maintained by %s\n",
114 atoi(sqlrow[0]), sqlrow[1], sqlrow[2], sqlrow[4]);
115 else
116 fprintf(out, "\n# %d - %s, maintained by %s\n",
117 atoi(sqlrow[0]), sqlrow[1], sqlrow[4]);
118 fprintf(out, "<VirtualHost *>\n\tServerName %s\n", sqlrow[1]);
119 if (sqlrow[2] && *sqlrow[2] != '\0')
120 fprintf(out, "\tServerAlias %s\n", sqlrow[2]);
121 fprintf(out, "\tDocumentRoot %s\n", sqlrow[3]);
122 fprintf(out, "\tCustomLog %s%s.log combined\n", clist->logpath, sqlrow[1]);
123 fprintf(out, "\tErrorLog %s%s.error.log\n", clist->logpath, sqlrow[1]);
125 if (sqlrow[5] && *sqlrow[5] != '\0' && sqlrow[6] && sqlrow[6] != '\0')
126 fprintf(out, "\tsuPHP_UserGroup %s %s\n", sqlrow[5], sqlrow[6]);
128 fprintf(out, "</VirtualHost>\n\n");
130 if (mysql_errno(&sql_conn))
131 fprintf(stderr, "Retrieve error: %s\n", mysql_error(&sql_conn));
135 mysql_free_result(res_ptr);
136 return(0);
139 void
140 chk_alloc_mem(char **dest, char *from)
142 /* strip trailing \n */
143 int length = strlen(from) - 1;
144 *dest = malloc(length);
145 if (*dest == NULL) {
146 printf("ERROR: Couldn't allocate memory\n");
147 exit(1);
149 strncpy(*dest, from, length);
150 (*dest)[length] = '\0';
154 load_config_file(const char *file_name, struct config_list *clist)
156 FILE *fp;
157 char line[MAX_BUFF];
158 char option;
159 char *value;
161 if ((fp = fopen(file_name, "r")) == NULL) {
162 fprintf(stderr, "Couldn't open configuration file %s\n", file_name);
163 return 1;
166 while (fgets(line, sizeof(line), fp)) {
167 if (line[0] == '#') /* Ignore comments */
168 continue;
170 if (strchr(line, '\n') == NULL) { /* Got huge line, ignore it. */
171 fprintf(stderr, "Got huge config line. This can't be right, please "
172 "fix your config.\n");
173 exit(1);
176 if (*line == '\0' || *line == '\n')
177 continue;
179 if (line[1] == ':') {
180 option = *line;
181 value = line+2;
182 } else
183 fprintf(stderr, "Invalid line in config file:\n%s", line);
185 switch(option) {
186 case 'u':
187 chk_alloc_mem(&clist->username, value);
188 break;
189 case 'p':
190 chk_alloc_mem(&clist->password, value);
191 break;
192 case 'o':
193 chk_alloc_mem(&clist->outfile, value);
194 break;
195 case 'h':
196 chk_alloc_mem(&clist->host, value);
197 break;
198 case 'd':
199 chk_alloc_mem(&clist->db, value);
200 break;
201 case 't':
202 chk_alloc_mem(&clist->vhosttable, value);
203 break;
204 case 'l':
205 chk_alloc_mem(&clist->logpath, value);
206 break;
207 default:
208 fprintf(stderr, "Invalid option '%c' given.\n", option);
209 exit(1);
210 break;
214 return 0;
218 * This function returns a pointer to a malloced string containing the current
219 * date, month, date, hour, minute and second in format
220 * YYYY-MM-DD HH:SS UTC(+/-)HH.
222 char
223 *mkdate(void)
225 struct tm *tm_ptr;
226 time_t the_time;
227 char buf[256];
228 char *our_date;
230 (void) time(&the_time);
231 tm_ptr = gmtime(&the_time);
233 strftime(buf, sizeof(buf), "%y-%m-%d %H:%M UTC%z", tm_ptr);
235 our_date = malloc(strlen(buf) + 1);
237 if (our_date == NULL) {
238 printf("ERROR: Couldn't allocate memory\n");
239 exit(1);
242 strcpy(our_date, buf);
244 return our_date;