2 Unix SMB/CIFS implementation.
3 program to send control messages to Samba processes
4 Copyright (C) Andrew Tridgell 1994-1998
5 Copyright (C) 2001, 2002 by Martin Pool
6 Copyright (C) Simo Sorce 2002
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 extern BOOL AllowDebugChange
;
32 {"force-election", MSG_FORCE_ELECTION
},
34 {"profile", MSG_PROFILE
},
35 {"profilelevel", MSG_REQ_PROFILELEVEL
},
36 {"debuglevel", MSG_REQ_DEBUGLEVEL
},
37 {"printer-notify", MSG_PRINTER_NOTIFY
},
38 {"close-share", MSG_SMB_FORCE_TDIS
},
39 {"samsync", MSG_SMB_SAM_SYNC
},
40 {"samrepl", MSG_SMB_SAM_REPL
},
41 {"pool-usage", MSG_REQ_POOL_USAGE
},
42 {"dmalloc-mark", MSG_REQ_DMALLOC_MARK
},
43 {"dmalloc-log-changed", MSG_REQ_DMALLOC_LOG_CHANGED
},
44 {"shutdown", MSG_SHUTDOWN
},
52 static void usage(BOOL doexit
)
56 printf("Usage: smbcontrol -i -s configfile\n");
57 printf(" smbcontrol <destination> <message-type> <parameters>\n\n");
59 printf("<destination> <message-type> <parameters>\n\n");
61 printf("\t<destination> is one of \"nmbd\", \"smbd\" or a process ID\n");
62 printf("\t<message-type> is one of: ");
63 for (i
=0; msg_types
[i
].name
; i
++)
64 printf("%s%s", i
?", ":"",msg_types
[i
].name
);
69 static int pong_count
;
70 static BOOL got_level
;
71 static BOOL pong_registered
= False
;
72 static BOOL debuglevel_registered
= False
;
73 static BOOL profilelevel_registered
= False
;
77 * Wait for replies for up to @p *max_secs seconds, or until @p
78 * max_replies are received. max_replies may be NULL in which case it
81 * @note This is a pretty lame timeout; all it means is that after
82 * max_secs we won't look for any more messages.
84 static void wait_for_replies(int max_secs
, int *max_replies
)
86 time_t timeout_end
= time(NULL
) + max_secs
;
88 while ((!max_replies
|| (*max_replies
)-- > 0)
89 && (time(NULL
) < timeout_end
)) {
95 /****************************************************************************
96 a useful function for testing the message system
97 ****************************************************************************/
98 void pong_function(int msg_type
, pid_t src
, void *buf
, size_t len
)
101 printf("PONG from PID %u\n",(unsigned int)src
);
104 /****************************************************************************
105 Prints out the current Debug level returned by MSG_DEBUGLEVEL
106 ****************************************************************************/
107 void debuglevel_function(int msg_type
, pid_t src
, void *buf
, size_t len
)
109 char *levels
= (char *)buf
;
112 printf("Current debug levels of PID %u are:\n",(unsigned int)src
);
114 while(next_token(&levels
, dbgcl
, " ", sizeof(pstring
)))
115 printf("%s\n", dbgcl
);
120 /****************************************************************************
121 Prints out the current Profile level returned by MSG_PROFILELEVEL
122 ****************************************************************************/
123 void profilelevel_function(int msg_type
, pid_t src
, void *buf
, size_t len
)
127 memcpy(&level
, buf
, sizeof(int));
138 s
= "count and time";
144 printf("Profiling %s on PID %u\n",s
,(unsigned int)src
);
146 printf("Profiling not available on PID %u\n",(unsigned int)src
);
152 * Handle reply from POOL_USAGE.
154 static void pool_usage_cb(int msg_type
, pid_t src_pid
, void *buf
, size_t len
)
156 printf("Got POOL_USAGE reply from pid%u:\n%.*s",
157 (unsigned int) src_pid
, (int) len
, (const char *) buf
);
162 * Send a message to a named destination
164 * @return False if an error occurred.
166 static BOOL
send_message(char *dest
, int msg_type
, void *buf
, int len
, BOOL duplicates
)
169 /* "smbd" is the only broadcast operation */
170 if (strequal(dest
,"smbd")) {
175 tdb
= tdb_open_log(lock_path("connections.tdb"), 0, TDB_DEFAULT
, O_RDWR
, 0);
177 fprintf(stderr
,"Failed to open connections database in send_message.\n");
181 ret
= message_send_all(tdb
,msg_type
, buf
, len
, duplicates
,
183 DEBUG(10,("smbcontrol/send_message: broadcast message to "
184 "%d processes\n", n_sent
));
188 } else if (strequal(dest
,"nmbd")) {
189 pid
= pidfile_pid(dest
);
191 fprintf(stderr
,"Can't find pid for nmbd\n");
194 } else if (strequal(dest
,"self")) {
199 fprintf(stderr
,"Not a valid pid\n");
204 DEBUG(10,("smbcontrol/send_message: send message to pid%d\n", pid
));
205 return message_send_pid(pid
, msg_type
, buf
, len
, duplicates
);
208 /****************************************************************************
209 evaluate a message type string
210 ****************************************************************************/
211 static int parse_type(char *mtype
)
214 for (i
=0;msg_types
[i
].name
;i
++) {
215 if (strequal(mtype
, msg_types
[i
].name
)) return msg_types
[i
].value
;
221 static void register_all(void)
223 message_register(MSG_POOL_USAGE
, pool_usage_cb
);
227 /****************************************************************************
229 ****************************************************************************/
230 static BOOL
do_command(char *dest
, char *msg_name
, int iparams
, char **params
)
236 mtype
= parse_type(msg_name
);
238 fprintf(stderr
,"Couldn't resolve message type: %s\n", msg_name
);
248 if (!params
|| !params
[0]) {
249 fprintf(stderr
,"MSG_DEBUG needs a parameter\n");
253 /* first pass retrieve total lenght */
254 for (p
= params
; p
&& *p
; p
++)
255 dim
+= (strnlen(*p
, 1024) +1); /* lenght + space */
256 b
= buf
= malloc(dim
);
258 fprintf(stderr
, "Out of memory!");
261 /* now build a single string with all parameters */
262 for(p
= params
; p
&& *p
; p
++) {
263 int l
= strnlen(*p
, 1024);
270 send_message(dest
, MSG_DEBUG
, buf
, dim
, False
);
278 if (!params
|| !params
[0]) {
279 fprintf(stderr
,"MSG_PROFILE needs a parameter\n");
282 if (strequal(params
[0], "off")) {
284 } else if (strequal(params
[0], "count")) {
286 } else if (strequal(params
[0], "on")) {
288 } else if (strequal(params
[0], "flush")) {
292 "MSG_PROFILE parameter must be off, count, on, or flush\n");
295 send_message(dest
, MSG_PROFILE
, &v
, sizeof(int), False
);
298 case MSG_FORCE_ELECTION
:
299 if (!strequal(dest
, "nmbd")) {
300 fprintf(stderr
,"force-election can only be sent to nmbd\n");
303 send_message(dest
, MSG_FORCE_ELECTION
, NULL
, 0, False
);
306 case MSG_REQ_PROFILELEVEL
:
307 if (!profilelevel_registered
) {
308 message_register(MSG_PROFILELEVEL
, profilelevel_function
);
309 profilelevel_registered
= True
;
312 retval
= send_message(dest
, MSG_REQ_PROFILELEVEL
, NULL
, 0, True
);
314 timeout_start
= time(NULL
);
317 if ((time(NULL
) - timeout_start
) > MAX_WAIT
) {
318 fprintf(stderr
,"profilelevel timeout\n");
325 case MSG_REQ_DEBUGLEVEL
:
326 if (!debuglevel_registered
) {
327 message_register(MSG_DEBUGLEVEL
, debuglevel_function
);
328 debuglevel_registered
= True
;
331 retval
= send_message(dest
, MSG_REQ_DEBUGLEVEL
, NULL
, 0, True
);
333 timeout_start
= time(NULL
);
336 if ((time(NULL
) - timeout_start
) > MAX_WAIT
) {
337 fprintf(stderr
,"debuglevel timeout\n");
344 case MSG_PRINTER_NOTIFY
:
345 if (!strequal(dest
, "smbd")) {
346 fprintf(stderr
,"printer-notify can only be sent to smbd\n");
349 if (!params
|| !params
[0]) {
350 fprintf(stderr
, "printer-notify needs a printer name\n");
354 char msg
[8 + sizeof(fstring
)];
355 SIVAL(msg
,0,PRINTER_CHANGE_ALL
);
357 fstrcpy(&msg
[8], params
[0]);
359 retval
= send_message(dest
, MSG_PRINTER_NOTIFY
, msg
, 8 + strlen(params
[0]) + 1, False
);
363 case MSG_SMB_FORCE_TDIS
:
364 if (!strequal(dest
, "smbd")) {
365 fprintf(stderr
,"close-share can only be sent to smbd\n");
368 if (!params
|| !params
[0]) {
369 fprintf(stderr
, "close-share needs a share name or '*'\n");
372 retval
= send_message(dest
, MSG_SMB_FORCE_TDIS
, params
[0],
373 strlen(params
[0]) + 1, False
);
376 case MSG_SMB_SAM_SYNC
:
377 if (!strequal(dest
, "smbd")) {
378 fprintf(stderr
, "samsync can only be sent to smbd\n");
383 fprintf(stderr
, "samsync does not take any parameters\n");
387 retval
= send_message(dest
, MSG_SMB_SAM_SYNC
, NULL
, 0, False
);
391 case MSG_SMB_SAM_REPL
: {
394 if (!strequal(dest
, "smbd")) {
395 fprintf(stderr
, "sam repl can only be sent to smbd\n");
399 if (!params
|| !params
[0]) {
400 fprintf(stderr
, "SAM_REPL needs a parameter\n");
404 seqnum
= atoi(params
[0]);
406 retval
= send_message(dest
, MSG_SMB_SAM_SYNC
,
407 (char *)&seqnum
, sizeof(uint32
), False
);
413 if (!pong_registered
) {
414 message_register(MSG_PONG
, pong_function
);
415 pong_registered
= True
;
417 if (!params
|| !params
[0]) {
418 fprintf(stderr
,"MSG_PING needs a parameter\n");
425 retval
= send_message(dest
, MSG_PING
, params
[1], strlen(params
[1]) + 1, True
);
427 retval
= send_message(dest
, MSG_PING
, NULL
, 0, True
);
431 wait_for_replies(MAX_WAIT
, &n
);
433 fprintf(stderr
,"PING timeout\n");
437 case MSG_REQ_POOL_USAGE
:
438 if (!send_message(dest
, MSG_REQ_POOL_USAGE
, NULL
, 0, True
))
440 wait_for_replies(MAX_WAIT
, NULL
);
444 case MSG_REQ_DMALLOC_LOG_CHANGED
:
445 case MSG_REQ_DMALLOC_MARK
:
446 if (!send_message(dest
, mtype
, NULL
, 0, False
))
451 if (!send_message(dest
, MSG_SHUTDOWN
, NULL
, 0, False
))
459 int main(int argc
, char *argv
[])
464 BOOL interactive
= False
;
466 AllowDebugChange
= False
;
469 setup_logging(argv
[0],True
);
471 if (argc
< 2) usage(True
);
473 while ((opt
= getopt(argc
, argv
,"is:")) != EOF
) {
479 pstrcpy(dyn_CONFIGFILE
, optarg
);
482 printf("Unknown option %c (%d)\n", (char)opt
, opt
);
487 lp_load(dyn_CONFIGFILE
,False
,False
,False
);
489 if (!message_init()) exit(1);
492 argv
= &argv
[optind
];
497 if (argc
< 2) usage(True
);
498 /* Need to invert sense of return code -- samba
499 * routines mostly return True==1 for success, but
501 return ! do_command(argv
[0],argv
[1], argc
-2, argc
> 2 ? &argv
[2] : 0);
508 printf("smbcontrol> ");
509 if (!fgets(temp
, sizeof(temp
)-1, stdin
)) break;
511 while ((myargc
< 4) &&
512 (myargv
[myargc
] = strtok(myargc
?NULL
:temp
," \t\n"))) {
516 if (strequal(myargv
[0],"q")) break;
519 else if (!do_command(myargv
[0],myargv
[1],myargc
-2,myargc
> 2 ? &myargv
[2] : 0))