If URI is not found, before to send 404, check if a plugins on stage 40 would like...
[MonkeyD.git] / src / plugins / cheetah / cheetah.c
blob1e21534a97e28b732772e248036af43c4cc8e28c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
3 /* Monkey HTTP Daemon
4 * ------------------
5 * Copyright (C) 2001-2009, Eduardo Silva P.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Library General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <sys/types.h>
26 #include <unistd.h>
27 #include <pwd.h>
28 #include <time.h>
30 #include "monkey.h"
31 #include "config.h"
32 #include "scheduler.h"
33 #include "info.h"
34 #include "request.h"
35 #include "str.h"
36 #include "plugin.h"
37 #include "worker.h"
39 #define MK_CHEETAH_STATUS "status"
40 #define MK_CHEETAH_STATUS_SC "\\s"
42 #define MK_CHEETAH_HELP "help"
43 #define MK_CHEETAH_HELP_SC "\\h"
45 #define MK_CHEETAH_UPTIME "uptime"
46 #define MK_CHEETAH_UPTIME_SC "\\u"
48 #define MK_CHEETAH_PLUGINS "plugins"
49 #define MK_CHEETAH_PLUGINS_SC "\\g"
51 #define MK_CHEETAH_VHOSTS "vhosts"
52 #define MK_CHEETAH_VHOSTS_SC "\\v"
54 #define MK_CHEETAH_WORKERS "workers"
55 #define MK_CHEETAH_WORKERS_SC "\\w"
57 #define MK_CHEETAH_QUIT "quit"
58 #define MK_CHEETAH_QUIT_SC "\\q"
60 #define MK_CHEETAH_PROMPT "cheetah> "
61 #define MK_CHEETAH_PROC_TASK "/proc/%i/task/%i/stat"
62 #define MK_CHEETAH_ONEDAY 86400
63 #define MK_CHEETAH_ONEHOUR 3600
64 #define MK_CHEETAH_ONEMINUTE 60
66 /* Plugin data for register */
67 mk_plugin_data_t _name = "Cheetah";
68 mk_plugin_data_t _version = "1.0";
69 mk_plugin_stage_t _stages = MK_PLUGIN_STAGE_10;
71 time_t init_time;
72 struct plugin_api *mk_api;
74 void mk_cheetah_print_worker_memory_usage(pid_t pid)
76 int last, init, n, c = 0;
77 int s = 1024;
78 char *buf;
79 char *value;
80 pid_t ppid;
81 FILE *f;
83 ppid = getpid();
84 buf = mk_api->mem_alloc(s);
85 sprintf(buf, MK_CHEETAH_PROC_TASK, ppid, pid);
87 f = fopen(buf, "r");
88 if(!f){
89 printf("Cannot get details\n");
90 return;
93 buf = fgets(buf, s, f);
94 if(!buf){
95 printf("Cannot format details\n");
96 return;
98 fclose(f);
100 last = 0;
101 init = 0;
103 printf("\n");
104 return;
106 while((n = mk_string_search(buf+last, " ")) > 0){
107 if(c == 23){
108 value = mk_string_copy_substr(buf, init, last+n);
109 printf("%s\n", value);
110 mk_mem_free(buf);
111 mk_mem_free(value);
112 return;
114 init = last+n+1;
115 last += n +1;
116 c++;
120 void mk_cheetah_print_running_user()
122 struct passwd pwd;
123 struct passwd *result;
124 char *buf;
125 size_t bufsize;
126 uid_t uid;
128 bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
129 if (bufsize == -1){
130 bufsize = 16384;
133 buf = malloc(bufsize);
134 uid = getuid();
135 getpwuid_r(uid, &pwd, buf, bufsize, &result);
137 printf("%s\n", pwd.pw_name);
138 free(buf);
141 void mk_cheetah_cmd_uptime()
143 int days; int hours; int minutes; int seconds;
144 long int upmind;
145 long int upminh;
146 long int uptime;
148 /* uptime in seconds */
149 uptime = time(NULL) - init_time;
151 /* days */
152 days = uptime / MK_CHEETAH_ONEDAY;
153 upmind = uptime - (days * MK_CHEETAH_ONEDAY);
155 /* hours */
156 hours = upmind / MK_CHEETAH_ONEHOUR;
157 upminh = upmind - hours * MK_CHEETAH_ONEHOUR;
159 /* minutes */
160 minutes = upminh / MK_CHEETAH_ONEMINUTE;
161 seconds = upminh - minutes * MK_CHEETAH_ONEMINUTE;
163 printf("Server has been running: %i day%s, %i hour%s, %i minute%s and %i second%s\n",
164 days, (days > 1) ? "s" : "",
165 hours, (hours > 1) ? "s" : "",
166 minutes, (minutes > 1) ? "s" : "",
167 seconds, (seconds > 1) ? "s" : "");
170 void mk_cheetah_cmd_plugins_print(struct plugin *list, const char *stage)
172 struct plugin *p;
174 if(!list){
175 return;
178 p = list;
179 printf("* %s", stage);
180 printf("\n Loaded plugins on this stage");
181 printf("\n ----------------------------");
182 while(p){
183 printf("\n %s v%s on \"%s\"", p->name, p->version, p->path);
184 p = p->next;
187 printf("\n\n");
190 void mk_cheetah_cmd_plugins()
192 struct plugin_stages *p = mk_api->config->plugins;
194 mk_cheetah_cmd_plugins_print(p->stage_10, "STAGE_10");
195 mk_cheetah_cmd_plugins_print(p->stage_20, "STAGE_20");
196 mk_cheetah_cmd_plugins_print(p->stage_30, "STAGE_30");
197 mk_cheetah_cmd_plugins_print(p->stage_40, "STAGE_40");
198 mk_cheetah_cmd_plugins_print(p->stage_50, "STAGE_50");
199 mk_cheetah_cmd_plugins_print(p->stage_60, "STAGE_60");
202 void mk_cheetah_cmd_vhosts()
204 struct host *host;
206 host = mk_api->config->hosts;
208 while(host){
209 printf("* VHost '%s'\n", host->servername);
210 printf(" - Configuration Path : %s\n",
211 host->file);
212 printf(" - Document Root : %s\n",
213 host->documentroot.data);
214 printf(" - Access Log : %s\n",
215 host->access_log_path);
216 printf(" - Error Log : %s\n",
217 host->error_log_path);
218 printf(" - List Directory Content : %s",
219 (host->getdir == VAR_ON) ? "Yes" : "No");
220 host = host->next;
224 void mk_cheetah_cmd_workers()
226 struct sched_list_node *sl;
227 sl = *mk_api->sched_list;
229 while(sl){
230 printf("* Worker %i\n", sl->idx);
231 printf(" - Task ID : %i\n", sl->pid);
233 /* Memory Usage */
234 printf(" - Memory usage : ");
235 mk_cheetah_print_worker_memory_usage(sl->pid);
237 printf(" - Active Requests : %i\n",
238 sl->active_requests);
239 printf(" - Closed Requests : %i\n",
240 sl->closed_requests);
241 sl = sl->next;
245 void mk_cheetah_cmd_quit()
247 printf("Cheeta says: Good Bye!\n");
248 fflush(stdout);
249 pthread_exit(NULL);
252 void mk_cheetah_cmd_help()
254 printf("\nList of available commands for Cheetah Shell\n");
255 printf("\ncommand shortcut description");
256 printf("\n----------------------------------------------------");
257 printf("\nhelp (\\h) Print this help");
258 printf("\nstatus (\\s) Display general web server information");
259 printf("\nuptime (\\u) Display how long the web server has been running");
260 printf("\nplugins (\\g) List loaded plugins and associated stages");
261 printf("\nvhosts (\\v) List virtual hosts configured");
262 printf("\nworkers (\\w) Show thread workers information");
263 printf("\nquit (\\q) Exit Cheetah shell :_(\n");
266 void mk_cheetah_cmd(char *cmd)
268 int nthreads = 0;
269 struct sched_list_node *sl;
272 sl = *mk_api->sched_list;
273 while(sl){
274 nthreads++;
275 sl = sl->next;
278 if(strcmp(cmd, MK_CHEETAH_STATUS) == 0 ||
279 strcmp(cmd, MK_CHEETAH_STATUS_SC) == 0){
280 printf("\nMonkey Version : %s\n", VERSION);
281 printf("Configutarion path : %s\n", mk_api->config->serverconf);
282 printf("Process ID : %i\n", getpid());
284 printf("Process User : ");
285 mk_cheetah_print_running_user();
287 printf("Server Port : %i\n", mk_api->config->serverport);
288 printf("Worker Threads : %i (per configuration: %i)\n",
289 nthreads,
290 mk_api->config->workers);
292 else if(strcmp(cmd, MK_CHEETAH_UPTIME) == 0 ||
293 strcmp(cmd, MK_CHEETAH_UPTIME_SC) == 0){
294 mk_cheetah_cmd_uptime();
296 else if(strcmp(cmd, MK_CHEETAH_PLUGINS) == 0 ||
297 strcmp(cmd, MK_CHEETAH_PLUGINS_SC) == 0){
298 mk_cheetah_cmd_plugins();
300 else if(strcmp(cmd, MK_CHEETAH_WORKERS) == 0 ||
301 strcmp(cmd, MK_CHEETAH_WORKERS_SC) == 0){
302 mk_cheetah_cmd_workers();
304 else if(strcmp(cmd, MK_CHEETAH_VHOSTS) == 0 ||
305 strcmp(cmd, MK_CHEETAH_VHOSTS_SC) == 0){
306 mk_cheetah_cmd_vhosts();
308 else if(strcmp(cmd, MK_CHEETAH_HELP) == 0 ||
309 strcmp(cmd, MK_CHEETAH_HELP_SC) == 0){
310 mk_cheetah_cmd_help();
312 else if(strcmp(cmd, MK_CHEETAH_QUIT) == 0 ||
313 strcmp(cmd, MK_CHEETAH_QUIT_SC) == 0){
314 mk_cheetah_cmd_quit();
316 else if(strlen(cmd) == 0){
317 return;
319 else{
320 printf("Invalid command, type 'help' for a list of available commands\n");
323 printf("\n");
324 fflush(stdout);
327 void mk_cheetah_loop()
329 int len;
330 char cmd[200];
331 char line[200];
332 char *rcmd;
334 printf("\n*** Welcome to Cheetah!, the Monkey Shell :) ***\n");
335 printf("\nType 'help' for a list of available commands\n\n");
336 fflush(stdout);
338 while(1){
339 printf("%s", MK_CHEETAH_PROMPT);
340 rcmd = fgets(line, sizeof(line), stdin);
342 len = strlen(line);
343 strncpy(cmd, line, len-1);
344 cmd[len-1] = '\0';
346 mk_cheetah_cmd(cmd);
347 bzero(line, sizeof(line));
351 void *mk_cheetah_init(void *args)
353 init_time = time(NULL);
354 mk_cheetah_loop();
355 return 0;
358 /* This function is called when the plugin is loaded, it must
359 * return
361 int _mk_plugin_init(void **api)
363 mk_api = *api;
364 return 0;
367 int _mk_plugin_stage_10(struct server_config *config)
369 pthread_t tid;
370 pthread_attr_t thread_attr;
372 pthread_attr_init(&thread_attr);
373 pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
374 if(pthread_create(&tid, &thread_attr, (void *) mk_cheetah_init, config)<0)
376 perror("pthread_create");
377 exit(1);
380 return 0;