Added Herb's fixes to HEAD.
[ira/wip.git] / source3 / utils / smbcontrol.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 3.0
4    program to send control messages to Samba processes
5    Copyright (C) Andrew Tridgell 1994-1998
6    
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.
11    
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 General Public License for more details.
16    
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., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #define NO_SYSLOG
23
24 #include "includes.h"
25
26 static struct {
27         char *name;
28         int value;
29 } msg_types[] = {
30         {"debug", MSG_DEBUG},
31         {"force-election", MSG_FORCE_ELECTION},
32         {"ping", MSG_PING},
33         {"profile", MSG_PROFILE},
34         {"debuglevel", MSG_REQ_DEBUGLEVEL},
35         {NULL, -1}
36 };
37
38 static void usage(BOOL doexit)
39 {
40         int i;
41         if (doexit) {
42                 printf("Usage: smbcontrol -i\n");
43                 printf("       smbcontrol <destination> <message-type> <parameters>\n\n");
44         } else {
45                 printf("<destination> <message-type> <parameters>\n\n");
46         }
47         printf("\t<destination> is one of \"nmbd\", \"smbd\" or a process ID\n");
48         printf("\t<message-type> is one of: ");
49         for (i=0; msg_types[i].name; i++) 
50             printf("%s%s", i?", ":"",msg_types[i].name);
51         printf("\n");
52         if (doexit) exit(1);
53 }
54
55 static int pong_count;
56 static BOOL got_level;
57 static BOOL pong_registered = False;
58 static BOOL debuglevel_registered = False;
59
60
61 /****************************************************************************
62 a useful function for testing the message system
63 ****************************************************************************/
64 void pong_function(int msg_type, pid_t src, void *buf, size_t len)
65 {
66         pong_count++;
67         printf("PONG\n");
68 }
69
70 /****************************************************************************
71 Prints out the current Debug level returned by MSG_DEBUGLEVEL
72 ****************************************************************************/
73 void debuglevel_function(int msg_type, pid_t src, void *buf, size_t len)
74 {
75         int level;
76         memcpy(&level, buf, sizeof(int));
77
78         printf("Current debug level is %d\n",level);
79         got_level = True;
80 }
81
82 /****************************************************************************
83 send a message to a named destination
84 ****************************************************************************/
85 static BOOL send_message(char *dest, int msg_type, void *buf, int len)
86 {
87         pid_t pid;
88
89         /* "smbd" is the only broadcast operation */
90         if (strequal(dest,"smbd")) {
91                 return message_send_all(msg_type, buf, len);
92         } else if (strequal(dest,"nmbd")) {
93                 pid = pidfile_pid(dest);
94                 if (pid == 0) {
95                         fprintf(stderr,"Can't find pid for nmbd\n");
96                         return False;
97                 }
98         } else {
99                 pid = atoi(dest);
100                 if (pid == 0) {
101                         fprintf(stderr,"Not a valid pid\n");
102                         return False;
103                 }               
104         } 
105
106         return message_send_pid(pid, msg_type, buf, len);
107 }
108
109 /****************************************************************************
110 evaluate a message type string
111 ****************************************************************************/
112 static int parse_type(char *mtype)
113 {
114         int i;
115         for (i=0;msg_types[i].name;i++) {
116                 if (strequal(mtype, msg_types[i].name)) return msg_types[i].value;
117         }
118         return -1;
119 }
120
121
122 /****************************************************************************
123 do command
124 ****************************************************************************/
125 static BOOL do_command(char *dest, char *msg_name, char *params)
126 {
127         int i, n, v;
128         int mtype;
129
130         mtype = parse_type(msg_name);
131         if (mtype == -1) {
132                 fprintf(stderr,"Couldn't resolve message type: %s\n", msg_name);
133                 return(False);
134         }
135
136         switch (mtype) {
137         case MSG_DEBUG:
138                 if (!params) {
139                         fprintf(stderr,"MSG_DEBUG needs a parameter\n");
140                         return(False);
141                 }
142                 v = atoi(params);
143                 send_message(dest, MSG_DEBUG, &v, sizeof(int));
144                 break;
145
146         case MSG_PROFILE:
147                 if (!params) {
148                         fprintf(stderr,"MSG_PROFILE needs a parameter\n");
149                         return(False);
150                 }
151                 if (strequal(params, "on")) {
152                         v = 2;
153                 } else if (strequal(params, "off")) {
154                         v = 0;
155                 } else if (strequal(params, "count")) {
156                         v = 1;
157                 } else {
158                     fprintf(stderr,
159                         "MSG_PROFILE parameter must be on, off, or count\n");
160                     return(False);
161                 }
162                 send_message(dest, MSG_PROFILE, &v, sizeof(int));
163                 break;
164
165         case MSG_FORCE_ELECTION:
166                 if (!strequal(dest, "nmbd")) {
167                         fprintf(stderr,"force-election can only be sent to nmbd\n");
168                         return(False);
169                 }
170                 send_message(dest, MSG_FORCE_ELECTION, NULL, 0);
171                 break;
172
173         case MSG_REQ_DEBUGLEVEL:
174                 if (!debuglevel_registered) {
175                     message_register(MSG_DEBUGLEVEL, debuglevel_function);
176                     debuglevel_registered = True;
177                 }
178                 if (strequal(dest, "nmbd") || strequal(dest, "smbd")) {
179                     fprintf(stderr,"debuglevel can only be sent to a PID\n");
180                     return(False);
181                 }
182                 got_level = False;
183                 send_message(dest, MSG_REQ_DEBUGLEVEL, NULL, 0);
184                 while (!got_level) message_dispatch();
185                 break;
186
187         case MSG_PING:
188                 if (!pong_registered) {
189                     message_register(MSG_PONG, pong_function);
190                     pong_registered = True;
191                 }
192                 if (!params) {
193                         fprintf(stderr,"MSG_PING needs a parameter\n");
194                         return(False);
195                 }
196                 n = atoi(params);
197                 pong_count = 0;
198                 for (i=0;i<n;i++) {
199                         send_message(dest, MSG_PING, NULL, 0);
200                 }
201                 while (pong_count < n) message_dispatch();
202                 break;
203
204         }
205         
206         return (True);
207 }
208
209  int main(int argc, char *argv[])
210 {
211         int opt;
212         char temp[255];
213         extern int optind;
214         pstring servicesf = CONFIGFILE;
215         BOOL interactive = False;
216
217         TimeInit();
218         setup_logging(argv[0],True);
219         
220         charset_initialise();
221         lp_load(servicesf,False,False,False);
222
223         message_init();
224
225         if (argc < 2) usage(True);
226
227         while ((opt = getopt(argc, argv,"i")) != EOF) {
228                 switch (opt) {
229                 case 'i':
230                         interactive = True;
231                         break;
232                 default:
233                         printf("Unknown option %c (%d)\n", (char)opt, opt);
234                         usage(True);
235                 }
236         }
237
238         argc -= optind;
239         argv = &argv[optind];
240
241         if (!interactive) {
242                 if (argc < 2) usage(True);
243                 return (do_command(argv[0],argv[1],argc > 2 ? argv[2] : 0));
244         }
245
246         while (True) {
247                 char *myargv[3];
248                 int myargc;
249
250                 printf("smbcontrol> ");
251                 if (!gets(temp)) break;
252                 myargc = 0;
253                 while ((myargc < 3) && 
254                        (myargv[myargc] = strtok(myargc?NULL:temp," \t"))) {
255                         myargc++;
256                 }
257                 if (!myargc) break;
258                 if (myargc < 2)
259                         usage(False);
260                 else if (!do_command(myargv[0],myargv[1],myargc > 2 ? myargv[2] : 0))
261                         usage(False);
262         }
263         return(0);
264 }
265