source: trunk/samba/source/web/statuspage.c @ 30

Last change on this file since 30 was 30, checked in by Paul Smedley, 14 years ago

Code updated to Samba 3.0.25rc2 level

File size: 12.8 KB
Line 
1/*
2   Unix SMB/CIFS implementation.
3   web status page
4   Copyright (C) Andrew Tridgell 1997-1998
5   
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2 of the License, or
9   (at your option) any later version.
10   
11   This program is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   GNU General Public License for more details.
15   
16   You should have received a copy of the GNU General Public License
17   along with this program; if not, write to the Free Software
18   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19*/
20
21#include "includes.h"
22#include "web/swat_proto.h"
23
24#define PIDMAP          struct PidMap
25
26/* how long to wait for start/stops to take effect */
27#define SLEEP_TIME 3
28
29PIDMAP {
30        PIDMAP  *next, *prev;
31        struct process_id pid;
32        char    *machine;
33};
34
35static PIDMAP   *pidmap;
36static int      PID_or_Machine;         /* 0 = show PID, else show Machine name */
37
38static struct process_id smbd_pid;
39
40/* from 2nd call on, remove old list */
41static void initPid2Machine (void)
42{
43        /* show machine name rather PID on table "Open Files"? */
44        if (PID_or_Machine) {
45                PIDMAP *p;
46
47                for (p = pidmap; p != NULL; ) {
48                        DLIST_REMOVE(pidmap, p);
49                        SAFE_FREE(p->machine);
50                        SAFE_FREE(p);
51                }
52
53                pidmap = NULL;
54        }
55}
56
57/* add new PID <-> Machine name mapping */
58static void addPid2Machine (struct process_id pid, char *machine)
59{
60        /* show machine name rather PID on table "Open Files"? */
61        if (PID_or_Machine) {
62                PIDMAP *newmap;
63
64                if ((newmap = SMB_MALLOC_P(PIDMAP)) == NULL) {
65                        /* XXX need error message for this?
66                           if malloc fails, PID is always shown */
67                        return;
68                }
69
70                newmap->pid = pid;
71                newmap->machine = SMB_STRDUP(machine);
72
73                DLIST_ADD(pidmap, newmap);
74        }
75}
76
77/* lookup PID <-> Machine name mapping */
78static char *mapPid2Machine (struct process_id pid)
79{
80        static char pidbuf [64];
81        PIDMAP *map;
82
83        /* show machine name rather PID on table "Open Files"? */
84        if (PID_or_Machine) {
85                for (map = pidmap; map != NULL; map = map->next) {
86                        if (procid_equal(&pid, &map->pid)) {
87                                if (map->machine == NULL)       /* no machine name */
88                                        break;                  /* show PID */
89
90                                return map->machine;
91                        }
92                }
93        }
94
95        /* PID not in list or machine name NULL? return pid as string */
96        snprintf (pidbuf, sizeof (pidbuf) - 1, "%s",
97                  procid_str_static(&pid));
98        return pidbuf;
99}
100
101static char *tstring(time_t t)
102{
103        static pstring buf;
104        pstrcpy(buf, time_to_asc(t));
105        all_string_sub(buf," ","&nbsp;",sizeof(buf));
106        return buf;
107}
108
109static void print_share_mode(const struct share_mode_entry *e,
110                             const char *sharepath,
111                             const char *fname,
112                             void *dummy)
113{
114        char           *utf8_fname;
115        int deny_mode;
116
117        if (!is_valid_share_mode_entry(e)) {
118                return;
119        }
120
121        deny_mode = map_share_mode_to_deny_mode(e->share_access,
122                                                    e->private_options);
123
124        printf("<tr><td>%s</td>",_(mapPid2Machine(e->pid)));
125        printf("<td>%u</td>",(unsigned int)e->uid);
126        printf("<td>");
127        switch ((deny_mode>>4)&0xF) {
128        case DENY_NONE: printf("DENY_NONE"); break;
129        case DENY_ALL:  printf("DENY_ALL   "); break;
130        case DENY_DOS:  printf("DENY_DOS   "); break;
131        case DENY_FCB:  printf("DENY_FCB   "); break;
132        case DENY_READ: printf("DENY_READ  "); break;
133        case DENY_WRITE:printf("DENY_WRITE "); break;
134        }
135        printf("</td>");
136
137        printf("<td>");
138        if (e->access_mask & (FILE_READ_DATA|FILE_WRITE_DATA)) {
139                printf("%s", _("RDWR       "));
140        } else if (e->access_mask & FILE_WRITE_DATA) {
141                printf("%s", _("WRONLY     "));
142        } else {
143                printf("%s", _("RDONLY     "));
144        }
145        printf("</td>");
146
147        printf("<td>");
148        if((e->op_type & 
149            (EXCLUSIVE_OPLOCK|BATCH_OPLOCK)) == 
150           (EXCLUSIVE_OPLOCK|BATCH_OPLOCK))
151                printf("EXCLUSIVE+BATCH ");
152        else if (e->op_type & EXCLUSIVE_OPLOCK)
153                printf("EXCLUSIVE       ");
154        else if (e->op_type & BATCH_OPLOCK)
155                printf("BATCH           ");
156        else if (e->op_type & LEVEL_II_OPLOCK)
157                printf("LEVEL_II        ");
158        else
159                printf("NONE            ");
160        printf("</td>");
161
162        push_utf8_allocate(&utf8_fname, fname);
163        printf("<td>%s</td><td>%s</td></tr>\n",
164               utf8_fname,tstring(e->time.tv_sec));
165        SAFE_FREE(utf8_fname);
166}
167
168
169/* kill off any connections chosen by the user */
170static int traverse_fn1(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void* state)
171{
172        struct connections_data crec;
173
174        if (dbuf.dsize != sizeof(crec))
175                return 0;
176
177        memcpy(&crec, dbuf.dptr, sizeof(crec));
178
179        if (crec.cnum == -1 && process_exists(crec.pid)) {
180                char buf[30];
181                slprintf(buf,sizeof(buf)-1,"kill_%s", procid_str_static(&crec.pid));
182                if (cgi_variable(buf)) {
183                        kill_pid(crec.pid);
184                        sleep(SLEEP_TIME);
185                }
186        }
187        return 0;
188}
189
190/* traversal fn for showing machine connections */
191static int traverse_fn2(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void* state)
192{
193        struct connections_data crec;
194
195        if (dbuf.dsize != sizeof(crec))
196                return 0;
197
198        memcpy(&crec, dbuf.dptr, sizeof(crec));
199       
200        if (crec.cnum == -1 || !process_exists(crec.pid) ||
201            procid_equal(&crec.pid, &smbd_pid))
202                return 0;
203
204        addPid2Machine (crec.pid, crec.machine);
205
206        printf("<tr><td>%s</td><td>%s</td><td>%s</td><td>%s</td>\n",
207               procid_str_static(&crec.pid),
208               crec.machine,crec.addr,
209               tstring(crec.start));
210        if (geteuid() == 0) {
211                printf("<td><input type=submit value=\"X\" name=\"kill_%s\"></td>\n",
212                       procid_str_static(&crec.pid));
213        }
214        printf("</tr>\n");
215
216        return 0;
217}
218
219/* traversal fn for showing share connections */
220static int traverse_fn3(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void* state)
221{
222        struct connections_data crec;
223
224        if (dbuf.dsize != sizeof(crec))
225                return 0;
226
227        memcpy(&crec, dbuf.dptr, sizeof(crec));
228
229        if (crec.cnum == -1 || !process_exists(crec.pid))
230                return 0;
231
232        printf("<tr><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>\n",
233               crec.servicename,uidtoname(crec.uid),
234               gidtoname(crec.gid),procid_str_static(&crec.pid),
235               crec.machine,
236               tstring(crec.start));
237        return 0;
238}
239
240
241/* show the current server status */
242void status_page(void)
243{
244        const char *v;
245        int autorefresh=0;
246        int refresh_interval=30;
247        TDB_CONTEXT *tdb;
248        int nr_running=0;
249        BOOL waitup = False;
250
251        smbd_pid = pid_to_procid(pidfile_pid("smbd"));
252
253        if (cgi_variable("smbd_restart") || cgi_variable("all_restart")) {
254                stop_smbd();
255                start_smbd();
256                waitup=True;
257        }
258
259        if (cgi_variable("smbd_start") || cgi_variable("all_start")) {
260                start_smbd();
261                waitup=True;
262        }
263
264        if (cgi_variable("smbd_stop") || cgi_variable("all_stop")) {
265                stop_smbd();
266                waitup=True;
267        }
268
269        if (cgi_variable("nmbd_restart") || cgi_variable("all_restart")) {
270                stop_nmbd();
271                start_nmbd();
272                waitup=True;
273        }
274        if (cgi_variable("nmbd_start") || cgi_variable("all_start")) {
275                start_nmbd();
276                waitup=True;
277        }
278
279        if (cgi_variable("nmbd_stop")|| cgi_variable("all_stop")) {
280                stop_nmbd();
281                waitup=True;
282        }
283
284#ifdef WITH_WINBIND
285        if (cgi_variable("winbindd_restart") || cgi_variable("all_restart")) {
286                stop_winbindd();
287                start_winbindd();
288                waitup=True;
289        }
290
291        if (cgi_variable("winbindd_start") || cgi_variable("all_start")) {
292                start_winbindd();
293                waitup=True;
294        }
295
296        if (cgi_variable("winbindd_stop") || cgi_variable("all_stop")) {
297                stop_winbindd();
298                waitup=True;
299        }
300#endif
301        /* wait for daemons to start/stop */
302        if (waitup)
303                sleep(SLEEP_TIME);
304       
305        if (cgi_variable("autorefresh")) {
306                autorefresh = 1;
307        } else if (cgi_variable("norefresh")) {
308                autorefresh = 0;
309        } else if (cgi_variable("refresh")) {
310                autorefresh = 1;
311        }
312
313        if ((v=cgi_variable("refresh_interval"))) {
314                refresh_interval = atoi(v);
315        }
316
317        if (cgi_variable("show_client_in_col_1")) {
318                PID_or_Machine = 1;
319        }
320
321        if (cgi_variable("show_pid_in_col_1")) {
322                PID_or_Machine = 0;
323        }
324
325        tdb = tdb_open_log(lock_path("connections.tdb"), 0, TDB_DEFAULT, O_RDONLY, 0);
326        if (tdb) tdb_traverse(tdb, traverse_fn1, NULL);
327 
328        initPid2Machine ();
329
330        printf("<H2>%s</H2>\n", _("Server Status"));
331
332        printf("<FORM method=post>\n");
333
334        if (!autorefresh) {
335                printf("<input type=submit value=\"%s\" name=\"autorefresh\">\n", _("Auto Refresh"));
336                printf("<br>%s", _("Refresh Interval: "));
337                printf("<input type=text size=2 name=\"refresh_interval\" value=\"%d\">\n", 
338                       refresh_interval);
339        } else {
340                printf("<input type=submit value=\"%s\" name=\"norefresh\">\n", _("Stop Refreshing"));
341                printf("<br>%s%d\n", _("Refresh Interval: "), refresh_interval);
342                printf("<input type=hidden name=\"refresh\" value=\"1\">\n");
343        }
344
345        printf("<p>\n");
346
347        if (!tdb) {
348                /* open failure either means no connections have been
349                   made */
350        }
351
352
353        printf("<table>\n");
354
355        printf("<tr><td>%s</td><td>%s</td></tr>", _("version:"), SAMBA_VERSION_STRING);
356
357        fflush(stdout);
358        printf("<tr><td>%s</td><td>%s</td>\n", _("smbd:"), smbd_running()?_("running"):_("not running"));
359        if (geteuid() == 0) {
360            if (smbd_running()) {
361                nr_running++;
362                printf("<td><input type=submit name=\"smbd_stop\" value=\"%s\"></td>\n", _("Stop smbd"));
363            } else {
364                printf("<td><input type=submit name=\"smbd_start\" value=\"%s\"></td>\n", _("Start smbd"));
365            }
366            printf("<td><input type=submit name=\"smbd_restart\" value=\"%s\"></td>\n", _("Restart smbd"));
367        }
368        printf("</tr>\n");
369
370        fflush(stdout);
371        printf("<tr><td>%s</td><td>%s</td>\n", _("nmbd:"), nmbd_running()?_("running"):_("not running"));
372        if (geteuid() == 0) {
373            if (nmbd_running()) {
374                nr_running++;
375                printf("<td><input type=submit name=\"nmbd_stop\" value=\"%s\"></td>\n", _("Stop nmbd"));
376            } else {
377                printf("<td><input type=submit name=\"nmbd_start\" value=\"%s\"></td>\n", _("Start nmbd"));
378            }
379            printf("<td><input type=submit name=\"nmbd_restart\" value=\"%s\"></td>\n", _("Restart nmbd"));   
380        }
381        printf("</tr>\n");
382
383#ifdef WITH_WINBIND
384        fflush(stdout);
385        printf("<tr><td>%s</td><td>%s</td>\n", _("winbindd:"), winbindd_running()?_("running"):_("not running"));
386        if (geteuid() == 0) {
387            if (winbindd_running()) {
388                nr_running++;
389                printf("<td><input type=submit name=\"winbindd_stop\" value=\"%s\"></td>\n", _("Stop winbindd"));
390            } else {
391                printf("<td><input type=submit name=\"winbindd_start\" value=\"%s\"></td>\n", _("Start winbindd"));
392            }
393            printf("<td><input type=submit name=\"winbindd_restart\" value=\"%s\"></td>\n", _("Restart winbindd"));
394        }
395        printf("</tr>\n");
396#endif
397
398        if (geteuid() == 0) {
399            printf("<tr><td></td><td></td>\n");
400            if (nr_running >= 1) {
401                /* stop, restart all */
402                printf("<td><input type=submit name=\"all_stop\" value=\"%s\"></td>\n", _("Stop All"));
403                printf("<td><input type=submit name=\"all_restart\" value=\"%s\"></td>\n", _("Restart All"));
404            }
405            else if (nr_running == 0) {
406                /* start all */
407                printf("<td><input type=submit name=\"all_start\" value=\"%s\"></td>\n", _("Start All"));
408            }
409            printf("</tr>\n");
410        }
411        printf("</table>\n");
412        fflush(stdout);
413
414        printf("<p><h3>%s</h3>\n", _("Active Connections"));
415        printf("<table border=1>\n");
416        printf("<tr><th>%s</th><th>%s</th><th>%s</th><th>%s</th>\n", _("PID"), _("Client"), _("IP address"), _("Date"));
417        if (geteuid() == 0) {
418                printf("<th>%s</th>\n", _("Kill"));
419        }
420        printf("</tr>\n");
421
422        if (tdb) tdb_traverse(tdb, traverse_fn2, NULL);
423
424        printf("</table><p>\n");
425
426        printf("<p><h3>%s</h3>\n", _("Active Shares"));
427        printf("<table border=1>\n");
428        printf("<tr><th>%s</th><th>%s</th><th>%s</th><th>%s</th><th>%s</th><th>%s</th></tr>\n\n",
429                _("Share"), _("User"), _("Group"), _("PID"), _("Client"), _("Date"));
430
431        if (tdb) tdb_traverse(tdb, traverse_fn3, NULL);
432
433        printf("</table><p>\n");
434
435        printf("<h3>%s</h3>\n", _("Open Files"));
436        printf("<table border=1>\n");
437        printf("<tr><th>%s</th><th>%s</th><th>%s</th><th>%s</th><th>%s</th><th>%s</th></tr>\n", _("PID"), _("Sharing"), _("R/W"), _("Oplock"), _("File"), _("Date"));
438
439        locking_init(1);
440        share_mode_forall(print_share_mode, NULL);
441        locking_end();
442        printf("</table>\n");
443
444        if (tdb) tdb_close(tdb);
445
446        printf("<br><input type=submit name=\"show_client_in_col_1\" value=\"%s\">\n", _("Show Client in col 1"));
447        printf("<input type=submit name=\"show_pid_in_col_1\" value=\"%s\">\n", _("Show PID in col 1"));
448
449        printf("</FORM>\n");
450
451        if (autorefresh) {
452                /* this little JavaScript allows for automatic refresh
453                   of the page. There are other methods but this seems
454                   to be the best alternative */
455                printf("<script language=\"JavaScript\">\n");
456                printf("<!--\nsetTimeout('window.location.replace(\"%s/status?refresh_interval=%d&refresh=1\")', %d)\n", 
457                       cgi_baseurl(),
458                       refresh_interval,
459                       refresh_interval*1000);
460                printf("//-->\n</script>\n");
461        }
462}
Note: See TracBrowser for help on using the repository browser.