~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source3/web/statuspage.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 3 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, see <http://www.gnu.org/licenses/>.
 
18
*/
 
19
 
 
20
#include "includes.h"
 
21
#include "web/swat_proto.h"
 
22
 
 
23
#define _(x) lang_msg_rotate(talloc_tos(),x)
 
24
 
 
25
#define PIDMAP          struct PidMap
 
26
 
 
27
/* how long to wait for start/stops to take effect */
 
28
#define SLEEP_TIME 3
 
29
 
 
30
PIDMAP {
 
31
        PIDMAP  *next, *prev;
 
32
        struct server_id pid;
 
33
        char    *machine;
 
34
};
 
35
 
 
36
static PIDMAP   *pidmap;
 
37
static int      PID_or_Machine;         /* 0 = show PID, else show Machine name */
 
38
 
 
39
static struct server_id smbd_pid;
 
40
 
 
41
/* from 2nd call on, remove old list */
 
42
static void initPid2Machine (void)
 
43
{
 
44
        /* show machine name rather PID on table "Open Files"? */
 
45
        if (PID_or_Machine) {
 
46
                PIDMAP *p, *next;
 
47
 
 
48
                for (p = pidmap; p != NULL; p = next) {
 
49
                        next = p->next;
 
50
                        DLIST_REMOVE(pidmap, p);
 
51
                        SAFE_FREE(p->machine);
 
52
                        SAFE_FREE(p);
 
53
                }
 
54
 
 
55
                pidmap = NULL;
 
56
        }
 
57
}
 
58
 
 
59
/* add new PID <-> Machine name mapping */
 
60
static void addPid2Machine (struct server_id pid, const char *machine)
 
61
{
 
62
        /* show machine name rather PID on table "Open Files"? */
 
63
        if (PID_or_Machine) {
 
64
                PIDMAP *newmap;
 
65
 
 
66
                if ((newmap = SMB_MALLOC_P(PIDMAP)) == NULL) {
 
67
                        /* XXX need error message for this?
 
68
                           if malloc fails, PID is always shown */
 
69
                        return;
 
70
                }
 
71
 
 
72
                newmap->pid = pid;
 
73
                newmap->machine = SMB_STRDUP(machine);
 
74
 
 
75
                DLIST_ADD(pidmap, newmap);
 
76
        }
 
77
}
 
78
 
 
79
/* lookup PID <-> Machine name mapping */
 
80
static char *mapPid2Machine (struct server_id pid)
 
81
{
 
82
        static char pidbuf [64];
 
83
        PIDMAP *map;
 
84
 
 
85
        /* show machine name rather PID on table "Open Files"? */
 
86
        if (PID_or_Machine) {
 
87
                for (map = pidmap; map != NULL; map = map->next) {
 
88
                        if (procid_equal(&pid, &map->pid)) {
 
89
                                if (map->machine == NULL)       /* no machine name */
 
90
                                        break;                  /* show PID */
 
91
 
 
92
                                return map->machine;
 
93
                        }
 
94
                }
 
95
        }
 
96
 
 
97
        /* PID not in list or machine name NULL? return pid as string */
 
98
        snprintf (pidbuf, sizeof (pidbuf) - 1, "%s",
 
99
                  procid_str_static(&pid));
 
100
        return pidbuf;
 
101
}
 
102
 
 
103
static const char *tstring(TALLOC_CTX *ctx, time_t t)
 
104
{
 
105
        char *buf;
 
106
        buf = talloc_strdup(ctx, time_to_asc(t));
 
107
        if (!buf) {
 
108
                return "";
 
109
        }
 
110
        buf = talloc_all_string_sub(ctx,
 
111
                        buf,
 
112
                        " ",
 
113
                        "&nbsp;");
 
114
        if (!buf) {
 
115
                return "";
 
116
        }
 
117
        return buf;
 
118
}
 
119
 
 
120
static void print_share_mode(const struct share_mode_entry *e,
 
121
                             const char *sharepath,
 
122
                             const char *fname,
 
123
                             void *dummy)
 
124
{
 
125
        char           *utf8_fname;
 
126
        int deny_mode;
 
127
        size_t converted_size;
 
128
 
 
129
        if (!is_valid_share_mode_entry(e)) {
 
130
                return;
 
131
        }
 
132
 
 
133
        deny_mode = map_share_mode_to_deny_mode(e->share_access,
 
134
                                                    e->private_options);
 
135
 
 
136
        printf("<tr><td>%s</td>",_(mapPid2Machine(e->pid)));
 
137
        printf("<td>%u</td>",(unsigned int)e->uid);
 
138
        printf("<td>");
 
139
        switch ((deny_mode>>4)&0xF) {
 
140
        case DENY_NONE: printf("DENY_NONE"); break;
 
141
        case DENY_ALL:  printf("DENY_ALL   "); break;
 
142
        case DENY_DOS:  printf("DENY_DOS   "); break;
 
143
        case DENY_FCB:  printf("DENY_FCB   "); break;
 
144
        case DENY_READ: printf("DENY_READ  "); break;
 
145
        case DENY_WRITE:printf("DENY_WRITE "); break;
 
146
        }
 
147
        printf("</td>");
 
148
 
 
149
        printf("<td>");
 
150
        if (e->access_mask & (FILE_READ_DATA|FILE_WRITE_DATA)) {
 
151
                printf("%s", _("RDWR       "));
 
152
        } else if (e->access_mask & FILE_WRITE_DATA) {
 
153
                printf("%s", _("WRONLY     "));
 
154
        } else {
 
155
                printf("%s", _("RDONLY     "));
 
156
        }
 
157
        printf("</td>");
 
158
 
 
159
        printf("<td>");
 
160
        if((e->op_type & 
 
161
            (EXCLUSIVE_OPLOCK|BATCH_OPLOCK)) == 
 
162
           (EXCLUSIVE_OPLOCK|BATCH_OPLOCK))
 
163
                printf("EXCLUSIVE+BATCH ");
 
164
        else if (e->op_type & EXCLUSIVE_OPLOCK)
 
165
                printf("EXCLUSIVE       ");
 
166
        else if (e->op_type & BATCH_OPLOCK)
 
167
                printf("BATCH           ");
 
168
        else if (e->op_type & LEVEL_II_OPLOCK)
 
169
                printf("LEVEL_II        ");
 
170
        else
 
171
                printf("NONE            ");
 
172
        printf("</td>");
 
173
 
 
174
        push_utf8_allocate(&utf8_fname, fname, &converted_size);
 
175
        printf("<td>%s</td><td>%s</td></tr>\n",
 
176
               utf8_fname,tstring(talloc_tos(),e->time.tv_sec));
 
177
        SAFE_FREE(utf8_fname);
 
178
}
 
179
 
 
180
 
 
181
/* kill off any connections chosen by the user */
 
182
static int traverse_fn1(struct db_record *rec,
 
183
                        const struct connections_key *key,
 
184
                        const struct connections_data *crec,
 
185
                        void *private_data)
 
186
{
 
187
        if (crec->cnum == -1 && process_exists(crec->pid)) {
 
188
                char buf[30];
 
189
                slprintf(buf,sizeof(buf)-1,"kill_%s", procid_str_static(&crec->pid));
 
190
                if (cgi_variable(buf)) {
 
191
                        kill_pid(crec->pid);
 
192
                        sleep(SLEEP_TIME);
 
193
                }
 
194
        }
 
195
        return 0;
 
196
}
 
197
 
 
198
/* traversal fn for showing machine connections */
 
199
static int traverse_fn2(struct db_record *rec,
 
200
                        const struct connections_key *key,
 
201
                        const struct connections_data *crec,
 
202
                        void *private_data)
 
203
{
 
204
        if (crec->cnum == -1 || !process_exists(crec->pid) ||
 
205
            procid_equal(&crec->pid, &smbd_pid))
 
206
                return 0;
 
207
 
 
208
        addPid2Machine (crec->pid, crec->machine);
 
209
 
 
210
        printf("<tr><td>%s</td><td>%s</td><td>%s</td><td>%s</td>\n",
 
211
               procid_str_static(&crec->pid),
 
212
               crec->machine, crec->addr,
 
213
               tstring(talloc_tos(),crec->start));
 
214
        if (geteuid() == 0) {
 
215
                printf("<td><input type=submit value=\"X\" name=\"kill_%s\"></td>\n",
 
216
                       procid_str_static(&crec->pid));
 
217
        }
 
218
        printf("</tr>\n");
 
219
 
 
220
        return 0;
 
221
}
 
222
 
 
223
/* traversal fn for showing share connections */
 
224
static int traverse_fn3(struct db_record *rec,
 
225
                        const struct connections_key *key,
 
226
                        const struct connections_data *crec,
 
227
                        void *private_data)
 
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(talloc_tos(),crec->start));
 
237
        return 0;
 
238
}
 
239
 
 
240
 
 
241
/* show the current server status */
 
242
void status_page(void)
 
243
{
 
244
        const char *v;
 
245
        int autorefresh=0;
 
246
        int refresh_interval=30;
 
247
        int nr_running=0;
 
248
        bool waitup = False;
 
249
        TALLOC_CTX *ctx = talloc_stackframe();
 
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
        connections_forall(traverse_fn1, NULL);
 
326
 
 
327
        initPid2Machine ();
 
328
 
 
329
        printf("<H2>%s</H2>\n", _("Server Status"));
 
330
 
 
331
        printf("<FORM method=post>\n");
 
332
 
 
333
        if (!autorefresh) {
 
334
                printf("<input type=submit value=\"%s\" name=\"autorefresh\">\n", _("Auto Refresh"));
 
335
                printf("<br>%s", _("Refresh Interval: "));
 
336
                printf("<input type=text size=2 name=\"refresh_interval\" value=\"%d\">\n", 
 
337
                       refresh_interval);
 
338
        } else {
 
339
                printf("<input type=submit value=\"%s\" name=\"norefresh\">\n", _("Stop Refreshing"));
 
340
                printf("<br>%s%d\n", _("Refresh Interval: "), refresh_interval);
 
341
                printf("<input type=hidden name=\"refresh\" value=\"1\">\n");
 
342
        }
 
343
 
 
344
        printf("<p>\n");
 
345
 
 
346
        printf("<table>\n");
 
347
 
 
348
        printf("<tr><td>%s</td><td>%s</td></tr>", _("version:"), samba_version_string());
 
349
 
 
350
        fflush(stdout);
 
351
        printf("<tr><td>%s</td><td>%s</td>\n", _("smbd:"), smbd_running()?_("running"):_("not running"));
 
352
        if (geteuid() == 0) {
 
353
            if (smbd_running()) {
 
354
                nr_running++;
 
355
                printf("<td><input type=submit name=\"smbd_stop\" value=\"%s\"></td>\n", _("Stop smbd"));
 
356
            } else {
 
357
                printf("<td><input type=submit name=\"smbd_start\" value=\"%s\"></td>\n", _("Start smbd"));
 
358
            }
 
359
            printf("<td><input type=submit name=\"smbd_restart\" value=\"%s\"></td>\n", _("Restart smbd"));
 
360
        }
 
361
        printf("</tr>\n");
 
362
 
 
363
        fflush(stdout);
 
364
        printf("<tr><td>%s</td><td>%s</td>\n", _("nmbd:"), nmbd_running()?_("running"):_("not running"));
 
365
        if (geteuid() == 0) {
 
366
            if (nmbd_running()) {
 
367
                nr_running++;
 
368
                printf("<td><input type=submit name=\"nmbd_stop\" value=\"%s\"></td>\n", _("Stop nmbd"));
 
369
            } else {
 
370
                printf("<td><input type=submit name=\"nmbd_start\" value=\"%s\"></td>\n", _("Start nmbd"));
 
371
            }
 
372
            printf("<td><input type=submit name=\"nmbd_restart\" value=\"%s\"></td>\n", _("Restart nmbd"));    
 
373
        }
 
374
        printf("</tr>\n");
 
375
 
 
376
#ifdef WITH_WINBIND
 
377
        fflush(stdout);
 
378
        printf("<tr><td>%s</td><td>%s</td>\n", _("winbindd:"), winbindd_running()?_("running"):_("not running"));
 
379
        if (geteuid() == 0) {
 
380
            if (winbindd_running()) {
 
381
                nr_running++;
 
382
                printf("<td><input type=submit name=\"winbindd_stop\" value=\"%s\"></td>\n", _("Stop winbindd"));
 
383
            } else {
 
384
                printf("<td><input type=submit name=\"winbindd_start\" value=\"%s\"></td>\n", _("Start winbindd"));
 
385
            }
 
386
            printf("<td><input type=submit name=\"winbindd_restart\" value=\"%s\"></td>\n", _("Restart winbindd"));
 
387
        }
 
388
        printf("</tr>\n");
 
389
#endif
 
390
 
 
391
        if (geteuid() == 0) {
 
392
            printf("<tr><td></td><td></td>\n");
 
393
            if (nr_running >= 1) {
 
394
                /* stop, restart all */
 
395
                printf("<td><input type=submit name=\"all_stop\" value=\"%s\"></td>\n", _("Stop All"));
 
396
                printf("<td><input type=submit name=\"all_restart\" value=\"%s\"></td>\n", _("Restart All"));
 
397
            }
 
398
            else if (nr_running == 0) {
 
399
                /* start all */
 
400
                printf("<td><input type=submit name=\"all_start\" value=\"%s\"></td>\n", _("Start All"));
 
401
            }
 
402
            printf("</tr>\n");
 
403
        }
 
404
        printf("</table>\n");
 
405
        fflush(stdout);
 
406
 
 
407
        printf("<p><h3>%s</h3>\n", _("Active Connections"));
 
408
        printf("<table border=1>\n");
 
409
        printf("<tr><th>%s</th><th>%s</th><th>%s</th><th>%s</th>\n", _("PID"), _("Client"), _("IP address"), _("Date"));
 
410
        if (geteuid() == 0) {
 
411
                printf("<th>%s</th>\n", _("Kill"));
 
412
        }
 
413
        printf("</tr>\n");
 
414
 
 
415
        connections_forall(traverse_fn2, NULL);
 
416
 
 
417
        printf("</table><p>\n");
 
418
 
 
419
        printf("<p><h3>%s</h3>\n", _("Active Shares"));
 
420
        printf("<table border=1>\n");
 
421
        printf("<tr><th>%s</th><th>%s</th><th>%s</th><th>%s</th><th>%s</th><th>%s</th></tr>\n\n",
 
422
                _("Share"), _("User"), _("Group"), _("PID"), _("Client"), _("Date"));
 
423
 
 
424
        connections_forall(traverse_fn3, NULL);
 
425
 
 
426
        printf("</table><p>\n");
 
427
 
 
428
        printf("<h3>%s</h3>\n", _("Open Files"));
 
429
        printf("<table border=1>\n");
 
430
        printf("<tr><th>%s</th><th>%s</th><th>%s</th><th>%s</th><th>%s</th><th>%s</th><th>%s</th></tr>\n",
 
431
                _("PID"), _("UID"), _("Sharing"), _("R/W"), _("Oplock"), _("File"), _("Date"));
 
432
 
 
433
        locking_init_readonly();
 
434
        share_mode_forall(print_share_mode, NULL);
 
435
        locking_end();
 
436
        printf("</table>\n");
 
437
 
 
438
        printf("<br><input type=submit name=\"show_client_in_col_1\" value=\"%s\">\n", _("Show Client in col 1"));
 
439
        printf("<input type=submit name=\"show_pid_in_col_1\" value=\"%s\">\n", _("Show PID in col 1"));
 
440
 
 
441
        printf("</FORM>\n");
 
442
 
 
443
        if (autorefresh) {
 
444
                /* this little JavaScript allows for automatic refresh
 
445
                   of the page. There are other methods but this seems
 
446
                   to be the best alternative */
 
447
                printf("<script language=\"JavaScript\">\n");
 
448
                printf("<!--\nsetTimeout('window.location.replace(\"%s/status?refresh_interval=%d&refresh=1\")', %d)\n", 
 
449
                       cgi_baseurl(),
 
450
                       refresh_interval,
 
451
                       refresh_interval*1000);
 
452
                printf("//-->\n</script>\n");
 
453
        }
 
454
        TALLOC_FREE(ctx);
 
455
}