Give a better error message why NetServerSetInfo() may fail in the gui.
[Samba/gebeck_regimport.git] / source3 / lib / netapi / examples / netdomjoin-gui / netdomjoin-gui.c
bloba3719c7442c60da8ac5216d07c6b49358880a73b
1 /*
2 * Unix SMB/CIFS implementation.
3 * Join Support (gtk + netapi)
4 * Copyright (C) Guenther Deschner 2007-2008
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.
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.
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/>.
20 #define _GNU_SOURCE
21 #include <stdio.h>
22 #include <sys/types.h>
23 #include <inttypes.h>
24 #include <stdlib.h>
25 #include <unistd.h>
26 #include <string.h>
27 #include <netdb.h>
29 #include <gtk/gtk.h>
30 #include <glib/gprintf.h>
32 #include <netapi.h>
34 #define MAX_CRED_LEN 256
35 #define MAX_NETBIOS_NAME_LEN 15
37 #define SAMBA_ICON_PATH "/usr/share/pixmaps/samba/samba.ico"
38 #define SAMBA_IMAGE_PATH "/usr/share/pixmaps/samba/logo.png"
39 #define SAMBA_IMAGE_PATH_SMALL "/usr/share/pixmaps/samba/logo-small.png"
41 #define WKSSVC_JOIN_FLAGS_DOMAIN_JOIN_IF_JOINED ( 0x00000020 )
42 #define WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE ( 0x00000004 )
43 #define WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE ( 0x00000002 )
44 #define WKSSVC_JOIN_FLAGS_JOIN_TYPE ( 0x00000001 )
46 #define NetSetupWorkgroupName ( 2 )
47 #define NetSetupDomainName ( 3 )
49 #define SAFE_FREE(x) do { if ((x) != NULL) {free(x); x=NULL;} } while(0)
51 struct srvsvc_NetSrvInfo1005 {
52 const char *comment;/* [unique,charset(UTF16)] */
55 static gboolean verbose = FALSE;
57 typedef struct join_state {
58 struct libnetapi_ctx *ctx;
59 GtkWidget *window_main;
60 GtkWidget *window_parent;
61 GtkWidget *window_do_change;
62 GtkWidget *window_creds_prompt;
63 GtkWidget *entry_account;
64 GtkWidget *entry_password;
65 GtkWidget *entry_domain;
66 GtkWidget *entry_workgroup;
67 GtkWidget *button_ok;
68 GtkWidget *button_apply;
69 GtkWidget *button_ok_creds;
70 GtkWidget *label_reboot;
71 GtkWidget *label_current_name_buffer;
72 GtkWidget *label_current_name_type;
73 GtkWidget *label_full_computer_name;
74 uint16_t name_type_initial;
75 uint16_t name_type_new;
76 char *name_buffer_initial;
77 char *name_buffer_new;
78 char *password;
79 char *account;
80 char *comment;
81 char *comment_new;
82 char *my_fqdn;
83 char *my_dnsdomain;
84 char *my_hostname;
85 uint16_t server_role;
86 gboolean settings_changed;
87 gboolean hostname_changed;
88 } join_state;
90 static void debug(const char *format, ...)
92 va_list args;
94 if (!verbose) {
95 return;
98 va_start(args, format);
99 g_vprintf(format, args);
100 va_end(args);
103 static gboolean callback_delete_event(GtkWidget *widget,
104 GdkEvent *event,
105 gpointer data)
107 gtk_main_quit();
108 return FALSE;
111 static void callback_do_close(GtkWidget *widget,
112 gpointer data)
114 debug("Closing now...\n");
115 gtk_widget_destroy(data);
118 static void free_join_state(struct join_state *s)
120 SAFE_FREE(s->name_buffer_initial);
121 SAFE_FREE(s->name_buffer_new);
122 SAFE_FREE(s->password);
123 SAFE_FREE(s->account);
124 SAFE_FREE(s->comment);
125 SAFE_FREE(s->comment_new);
126 SAFE_FREE(s->my_fqdn);
127 SAFE_FREE(s->my_dnsdomain);
128 SAFE_FREE(s->my_hostname);
131 static void do_cleanup(struct join_state *state)
133 libnetapi_free(state->ctx);
134 free_join_state(state);
137 static void callback_apply_description_change(GtkWidget *widget,
138 gpointer data)
140 struct join_state *state = (struct join_state *)data;
141 NET_API_STATUS status = 0;
142 uint32_t parm_err = 0;
143 struct srvsvc_NetSrvInfo1005 info1005;
144 GtkWidget *dialog;
146 info1005.comment = state->comment_new;
148 status = NetServerSetInfo(NULL, 1005, (uint8_t *)&info1005, &parm_err);
149 if (status) {
150 debug("NetServerSetInfo failed with: %s\n",
151 libnetapi_errstr(status));
152 dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_main),
153 GTK_DIALOG_DESTROY_WITH_PARENT,
154 GTK_MESSAGE_ERROR,
155 GTK_BUTTONS_OK,
156 "Failed to change computer description: %s.",
157 libnetapi_get_error_string(state->ctx, status));
158 g_signal_connect_swapped(dialog, "response",
159 G_CALLBACK(gtk_widget_destroy),
160 dialog);
162 gtk_widget_show(dialog);
163 return;
166 gtk_widget_set_sensitive(GTK_WIDGET(state->button_apply), FALSE);
169 static void callback_do_exit(GtkWidget *widget,
170 gpointer data)
172 GtkWidget *dialog;
173 gint result;
174 struct join_state *state = (struct join_state *)data;
176 if (!state->settings_changed) {
177 callback_delete_event(NULL, NULL, NULL);
178 return;
181 dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_main),
182 GTK_DIALOG_DESTROY_WITH_PARENT,
183 GTK_MESSAGE_QUESTION,
184 GTK_BUTTONS_YES_NO,
185 "You must restart your computer before the new settings will take effect.");
186 result = gtk_dialog_run(GTK_DIALOG(dialog));
187 switch (result) {
188 case GTK_RESPONSE_YES:
189 g_print("would reboot here\n");
190 break;
191 case GTK_RESPONSE_NO:
192 default:
193 break;
195 gtk_widget_destroy(dialog);
196 gtk_widget_destroy(state->window_main);
197 do_cleanup(state);
198 exit(0);
202 static void callback_do_reboot(GtkWidget *widget,
203 gpointer data,
204 gpointer data2)
206 GtkWidget *dialog;
207 struct join_state *state = (struct join_state *)data2;
209 debug("callback_do_reboot\n");
211 state->settings_changed = TRUE;
212 dialog = gtk_message_dialog_new(GTK_WINDOW(data),
213 GTK_DIALOG_DESTROY_WITH_PARENT,
214 GTK_MESSAGE_INFO,
215 GTK_BUTTONS_OK,
216 "You must restart this computer for the changes to take effect.");
217 #if 0
218 g_signal_connect_swapped(dialog, "response",
219 G_CALLBACK(gtk_widget_destroy),
220 dialog);
222 debug("showing dialog\n");
223 gtk_widget_show(dialog);
224 #else
225 gtk_dialog_run(GTK_DIALOG(dialog));
226 gtk_widget_destroy(dialog);
227 #endif
229 gtk_label_set_text(GTK_LABEL(state->label_reboot),
230 "Changes will take effect after you restart this computer");
232 debug("destroying do_change window\n");
233 gtk_widget_destroy(GTK_WIDGET(state->window_do_change));
236 uint32_t status;
237 const char *buffer;
238 uint16_t type;
240 status = NetGetJoinInformation(NULL, &buffer, &type);
241 if (status != 0) {
242 g_print("failed to query status\n");
243 return;
246 debug("got new status: %s\n", buffer);
247 #if 0
248 SAFE_FREE(state->name_buffer_new);
249 state->name_buffer_new = strdup(buffer);
250 SAFE_FREE(buffer);
251 state->name_type_new = type;
252 #endif
253 NetApiBufferFree((void *)buffer);
255 gtk_label_set_text(GTK_LABEL(state->label_current_name_buffer),
256 state->name_buffer_new);
257 if (state->name_type_new == NetSetupDomainName) {
258 gtk_label_set_text(GTK_LABEL(state->label_current_name_type),
259 "Domain:");
260 } else {
261 gtk_label_set_text(GTK_LABEL(state->label_current_name_type),
262 "Workgroup:");
267 static void callback_return_username(GtkWidget *widget,
268 gpointer data)
270 const gchar *entry_text;
271 struct join_state *state = (struct join_state *)data;
272 if (!widget) {
273 return;
275 entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
276 debug("callback_return_username: %s\n", entry_text);
277 SAFE_FREE(state->account);
278 state->account = strdup(entry_text);
281 static void callback_return_username_and_enter(GtkWidget *widget,
282 gpointer data)
284 const gchar *entry_text;
285 struct join_state *state = (struct join_state *)data;
286 if (!widget) {
287 return;
289 entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
290 debug("callback_return_username: %s\n", entry_text);
291 SAFE_FREE(state->account);
292 state->account = strdup(entry_text);
293 g_signal_emit_by_name(state->button_ok_creds, "clicked");
296 static void callback_return_password(GtkWidget *widget,
297 gpointer data)
299 const gchar *entry_text;
300 struct join_state *state = (struct join_state *)data;
301 if (!widget) {
302 return;
304 entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
305 #ifdef DEBUG_PASSWORD
306 debug("callback_return_password: %s\n", entry_text);
307 #else
308 debug("callback_return_password: (not printed)\n");
309 #endif
310 SAFE_FREE(state->password);
311 state->password = strdup(entry_text);
314 static void callback_return_password_and_enter(GtkWidget *widget,
315 gpointer data)
317 const gchar *entry_text;
318 struct join_state *state = (struct join_state *)data;
319 if (!widget) {
320 return;
322 entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
323 #ifdef DEBUG_PASSWORD
324 debug("callback_return_password: %s\n", entry_text);
325 #else
326 debug("callback_return_password: (not printed)\n");
327 #endif
328 SAFE_FREE(state->password);
329 state->password = strdup(entry_text);
330 g_signal_emit_by_name(state->button_ok_creds, "clicked");
333 static void callback_do_hostname_change(GtkWidget *widget,
334 gpointer data)
336 GtkWidget *dialog;
337 const char *str = NULL;
339 struct join_state *state = (struct join_state *)data;
341 switch (state->name_type_initial) {
342 case NetSetupDomainName:
343 str = "To be implemented: call NetRenameMachineInDomain\n";
344 break;
345 case NetSetupWorkgroupName:
346 str = "To be implemented: call SetComputerNameEx\n";
347 break;
348 default:
349 break;
352 dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_parent),
353 GTK_DIALOG_DESTROY_WITH_PARENT,
354 GTK_MESSAGE_ERROR,
355 GTK_BUTTONS_CLOSE,
356 str);
358 g_signal_connect_swapped(dialog, "response",
359 G_CALLBACK(gtk_widget_destroy),
360 dialog);
361 gtk_widget_show(dialog);
364 static void callback_do_join(GtkWidget *widget,
365 gpointer data)
367 GtkWidget *dialog;
369 NET_API_STATUS status;
370 const char *err_str = NULL;
371 uint32_t join_flags = 0;
372 uint32_t unjoin_flags = 0;
373 gboolean domain_join = FALSE;
374 gboolean try_unjoin = FALSE;
375 const char *new_workgroup_type = NULL;
376 const char *initial_workgroup_type = NULL;
378 struct join_state *state = (struct join_state *)data;
380 callback_return_username(state->entry_account, state);
381 callback_return_password(state->entry_password, state);
383 if (state->window_creds_prompt) {
384 gtk_widget_destroy(GTK_WIDGET(state->window_creds_prompt));
387 switch (state->name_type_initial) {
388 case NetSetupWorkgroupName:
389 initial_workgroup_type = "workgroup";
390 break;
391 case NetSetupDomainName:
392 initial_workgroup_type = "domain";
393 break;
394 default:
395 break;
398 switch (state->name_type_new) {
399 case NetSetupWorkgroupName:
400 new_workgroup_type = "workgroup";
401 break;
402 case NetSetupDomainName:
403 new_workgroup_type = "domain";
404 break;
405 default:
406 break;
409 if (state->name_type_new == NetSetupDomainName) {
410 domain_join = TRUE;
411 join_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
412 WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE |
413 WKSSVC_JOIN_FLAGS_DOMAIN_JOIN_IF_JOINED; /* for testing */
416 if ((state->name_type_initial == NetSetupDomainName) &&
417 (state->name_type_new == NetSetupWorkgroupName)) {
418 try_unjoin = TRUE;
419 unjoin_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
420 WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE;
423 debug("callback_do_join: Joining a %s named %s using join_flags 0x%08x ",
424 new_workgroup_type,
425 state->name_buffer_new,
426 join_flags);
427 if (domain_join) {
428 debug("as %s ", state->account);
429 #ifdef DEBUG_PASSWORD
430 debug("with %s ", state->password);
431 #endif
433 debug("\n");
434 if (try_unjoin) {
436 debug("callback_do_join: Unjoining\n");
438 status = NetUnjoinDomain(NULL,
439 state->account,
440 state->password,
441 unjoin_flags);
442 if (status != 0) {
443 err_str = libnetapi_get_error_string(state->ctx, status);
444 g_print("callback_do_join: failed to unjoin (%s)\n",
445 err_str);
447 dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_parent),
448 GTK_DIALOG_DESTROY_WITH_PARENT,
449 GTK_MESSAGE_ERROR,
450 GTK_BUTTONS_CLOSE,
451 "The following error occured attempting to unjoin the %s: \"%s\": %s",
452 initial_workgroup_type,
453 state->name_buffer_initial,
454 err_str);
455 gtk_dialog_run(GTK_DIALOG(dialog));
456 gtk_widget_destroy(dialog);
460 status = NetJoinDomain(NULL,
461 state->name_buffer_new,
462 NULL,
463 state->account,
464 state->password,
465 join_flags);
466 if (status != 0) {
467 err_str = libnetapi_get_error_string(state->ctx, status);
468 g_print("callback_do_join: failed to join (%s)\n", err_str);
470 dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_parent),
471 GTK_DIALOG_DESTROY_WITH_PARENT,
472 GTK_MESSAGE_ERROR,
473 GTK_BUTTONS_CLOSE,
474 "The following error occured attempting to join the %s: \"%s\": %s",
475 new_workgroup_type,
476 state->name_buffer_new,
477 err_str);
479 g_signal_connect_swapped(dialog, "response",
480 G_CALLBACK(gtk_widget_destroy),
481 dialog);
483 gtk_widget_show(dialog);
485 return;
488 debug("callback_do_join: Successfully joined %s\n",
489 new_workgroup_type);
491 dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_parent),
492 GTK_DIALOG_DESTROY_WITH_PARENT,
493 GTK_MESSAGE_INFO,
494 GTK_BUTTONS_OK,
495 "Welcome to the %s %s.",
496 state->name_buffer_new,
497 new_workgroup_type);
499 gtk_dialog_run(GTK_DIALOG(dialog));
500 gtk_widget_destroy(dialog);
502 callback_do_reboot(NULL, state->window_parent, state);
505 static void callback_creds_prompt(GtkWidget *widget,
506 gpointer data)
508 GtkWidget *window;
509 GtkWidget *box1;
510 GtkWidget *bbox;
511 GtkWidget *button;
512 GtkWidget *label;
514 struct join_state *state = (struct join_state *)data;
516 debug("callback_creds_prompt:\n");
518 state->window_parent = state->window_do_change;
520 if (state->hostname_changed) {
521 return callback_do_hostname_change(NULL, state);
524 if ((state->name_type_initial != NetSetupDomainName) &&
525 (state->name_type_new != NetSetupDomainName)) {
526 return callback_do_join(NULL, state);
529 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
531 gtk_window_set_title(GTK_WINDOW(window), "Computer Name Changes");
532 gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
533 gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
534 gtk_widget_set_size_request(GTK_WIDGET(window), 380, 280);
535 gtk_window_set_icon_from_file(GTK_WINDOW(window), SAMBA_ICON_PATH, NULL);
536 /* gtk_window_set_icon_name(GTK_WIDGET(window), GTK_STOCK_DIALOG_AUTHENTICATION); */
537 state->window_creds_prompt = window;
539 g_signal_connect(G_OBJECT(window), "delete_event",
540 G_CALLBACK(callback_do_close), window);
542 gtk_container_set_border_width(GTK_CONTAINER(window), 10);
544 box1 = gtk_vbox_new(FALSE, 0);
546 gtk_container_add(GTK_CONTAINER(window), box1);
548 if ((state->name_type_initial == NetSetupDomainName) &&
549 (state->name_type_new == NetSetupWorkgroupName)) {
550 label = gtk_label_new("Enter the name and password of an account with permission to leave the domain.\n");
551 } else {
552 label = gtk_label_new("Enter the name and password of an account with permission to join the domain.\n");
554 gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
555 gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
557 gtk_box_pack_start(GTK_BOX(box1), label, FALSE, FALSE, 0);
559 gtk_widget_show(label);
561 /* USER NAME */
562 label = gtk_label_new("User name:");
563 gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
564 gtk_box_pack_start(GTK_BOX(box1), label, FALSE, FALSE, 0);
565 gtk_widget_show(label);
567 state->entry_account = gtk_entry_new();
568 gtk_entry_set_max_length(GTK_ENTRY(state->entry_account), MAX_CRED_LEN);
569 g_signal_connect(G_OBJECT(state->entry_account), "activate",
570 G_CALLBACK(callback_return_username_and_enter),
571 (gpointer)state);
572 gtk_editable_select_region(GTK_EDITABLE(state->entry_account),
573 0, GTK_ENTRY(state->entry_account)->text_length);
574 gtk_box_pack_start(GTK_BOX(box1), state->entry_account, TRUE, TRUE, 0);
575 gtk_widget_show(state->entry_account);
577 /* PASSWORD */
578 label = gtk_label_new("Password:");
579 gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
580 gtk_box_pack_start(GTK_BOX(box1), label, FALSE, FALSE, 0);
581 gtk_widget_show(label);
583 state->entry_password = gtk_entry_new();
584 gtk_entry_set_max_length(GTK_ENTRY(state->entry_password), MAX_CRED_LEN);
585 gtk_entry_set_visibility(GTK_ENTRY(state->entry_password), FALSE);
586 g_signal_connect(G_OBJECT(state->entry_password), "activate",
587 G_CALLBACK(callback_return_password_and_enter),
588 (gpointer)state);
589 gtk_editable_set_editable(GTK_EDITABLE(state->entry_password), TRUE);
590 gtk_editable_select_region(GTK_EDITABLE(state->entry_password),
591 0, GTK_ENTRY(state->entry_password)->text_length);
592 gtk_box_pack_start(GTK_BOX(box1), state->entry_password, TRUE, TRUE, 0);
593 gtk_widget_show(state->entry_password);
595 bbox = gtk_hbutton_box_new();
596 gtk_container_set_border_width(GTK_CONTAINER(bbox), 5);
597 gtk_container_add(GTK_CONTAINER(box1), bbox);
598 gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);
599 gtk_box_set_spacing(GTK_BOX(bbox), 10);
601 state->button_ok_creds = gtk_button_new_from_stock(GTK_STOCK_OK);
602 gtk_widget_grab_focus(GTK_WIDGET(state->button_ok_creds));
603 gtk_container_add(GTK_CONTAINER(bbox), state->button_ok_creds);
604 g_signal_connect(G_OBJECT(state->button_ok_creds), "clicked",
605 G_CALLBACK(callback_do_join),
606 (gpointer)state);
607 gtk_widget_show(state->button_ok_creds);
609 button = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
610 gtk_container_add(GTK_CONTAINER(bbox), button);
611 g_signal_connect(G_OBJECT(button), "clicked",
612 G_CALLBACK(callback_do_close), (gpointer) window);
613 gtk_widget_show_all(window);
616 static void callback_enter_hostname_and_unlock(GtkWidget *widget,
617 gpointer data)
619 const gchar *entry_text = NULL;
620 char *str = NULL;
621 struct join_state *state = (struct join_state *)data;
623 entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
624 debug("callback_enter_hostname_and_unlock: %s\n", entry_text);
625 if (!entry_text || entry_text[0] == 0) {
626 state->hostname_changed = FALSE;
627 gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), FALSE);
628 return;
630 if (strcasecmp(state->my_hostname, entry_text) == 0) {
631 state->hostname_changed = FALSE;
632 gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), FALSE);
633 return;
635 state->hostname_changed = TRUE;
636 if (state->name_type_initial == NetSetupDomainName) {
637 asprintf(&str, "%s.%s", entry_text, state->my_dnsdomain);
638 } else {
639 asprintf(&str, "%s.", entry_text);
641 gtk_label_set_text(GTK_LABEL(state->label_full_computer_name), str);
642 free(str);
644 if (state->hostname_changed && str && str[0] != 0 && str[0] != '.') {
645 gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), TRUE);
649 static void callback_enter_computer_description_and_unlock(GtkWidget *widget,
650 gpointer data)
652 const gchar *entry_text = NULL;
653 struct join_state *state = (struct join_state *)data;
654 int string_unchanged = 0;
656 entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
657 debug("callback_enter_computer_description_and_unlock: %s\n",
658 entry_text);
659 #if 0
660 if (!entry_text || entry_text[0] == 0) {
661 string_unchanged = 1;
662 gtk_widget_set_sensitive(GTK_WIDGET(state->button_apply),
663 FALSE);
664 return;
666 #endif
667 if (entry_text && strcasecmp(state->comment, entry_text) == 0) {
668 string_unchanged = 1;
669 gtk_widget_set_sensitive(GTK_WIDGET(state->button_apply),
670 FALSE);
671 return;
674 gtk_widget_set_sensitive(GTK_WIDGET(state->button_apply), TRUE);
675 SAFE_FREE(state->comment_new);
676 state->comment_new = strdup(entry_text);
681 static void callback_enter_workgroup_and_unlock(GtkWidget *widget,
682 gpointer data)
684 const gchar *entry_text = NULL;
685 struct join_state *state = (struct join_state *)data;
687 entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
688 debug("callback_enter_workgroup_and_unlock: %s\n", entry_text);
689 if (!entry_text || entry_text[0] == 0) {
690 gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), FALSE);
691 return;
693 if (strcasecmp(state->name_buffer_initial, entry_text) == 0) {
694 gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), FALSE);
695 return;
697 gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), TRUE);
698 SAFE_FREE(state->name_buffer_new);
699 state->name_buffer_new = strdup(entry_text);
700 state->name_type_new = NetSetupWorkgroupName;
703 static void callback_enter_domain_and_unlock(GtkWidget *widget,
704 gpointer data)
706 const gchar *entry_text = NULL;
707 struct join_state *state = (struct join_state *)data;
709 entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
710 debug("callback_enter_domain_and_unlock: %s\n", entry_text);
711 if (!entry_text || entry_text[0] == 0) {
712 gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), FALSE);
713 return;
715 if (strcasecmp(state->name_buffer_initial, entry_text) == 0) {
716 gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), FALSE);
717 return;
719 gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), TRUE);
720 SAFE_FREE(state->name_buffer_new);
721 state->name_buffer_new = strdup(entry_text);
722 state->name_type_new = NetSetupDomainName;
725 static void callback_continue(GtkWidget *widget,
726 gpointer data)
728 struct join_state *state = (struct join_state *)data;
730 gtk_widget_grab_focus(GTK_WIDGET(state->button_ok));
731 g_signal_emit_by_name(state->button_ok, "clicked");
734 static void callback_apply_continue(GtkWidget *widget,
735 gpointer data)
737 struct join_state *state = (struct join_state *)data;
739 gtk_widget_grab_focus(GTK_WIDGET(state->button_apply));
740 g_signal_emit_by_name(state->button_apply, "clicked");
743 static void callback_do_join_workgroup(GtkWidget *widget,
744 gpointer data)
746 struct join_state *state = (struct join_state *)data;
747 debug("callback_do_join_workgroup choosen\n");
748 gtk_widget_set_sensitive(GTK_WIDGET(state->entry_workgroup), TRUE);
749 gtk_widget_grab_focus(GTK_WIDGET(state->entry_workgroup));
750 gtk_widget_set_sensitive(GTK_WIDGET(state->entry_domain), FALSE);
751 callback_enter_workgroup_and_unlock(state->entry_workgroup, state); /* TEST */
754 static void callback_do_join_domain(GtkWidget *widget,
755 gpointer data)
757 struct join_state *state = (struct join_state *)data;
758 debug("callback_do_join_domain choosen\n");
759 gtk_widget_set_sensitive(GTK_WIDGET(state->entry_domain), TRUE);
760 gtk_widget_grab_focus(GTK_WIDGET(state->entry_domain));
761 gtk_widget_set_sensitive(GTK_WIDGET(state->entry_workgroup), FALSE);
762 callback_enter_domain_and_unlock(state->entry_domain, state); /* TEST */
765 static void callback_do_change(GtkWidget *widget,
766 gpointer data)
768 GtkWidget *window;
769 GtkWidget *box1;
770 GtkWidget *bbox;
771 GtkWidget *button_workgroup;
772 GtkWidget *button_domain;
773 GtkWidget *button;
774 GtkWidget *label;
775 GtkWidget *frame_horz;
776 GtkWidget *vbox;
777 GtkWidget *entry;
778 GSList *group;
780 struct join_state *state = (struct join_state *)data;
782 debug("callback_do_change called\n");
784 #if 0
785 /* FIXME: add proper warnings for Samba as a DC */
786 if (state->server_role == 3) {
787 GtkWidget *dialog;
788 dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_main),
789 GTK_DIALOG_DESTROY_WITH_PARENT,
790 GTK_MESSAGE_ERROR,
791 GTK_BUTTONS_OK,
792 "Domain controller cannot be moved from one domain to another, they must first be demoted. Renaming this domain controller may cause it to become temporarily unavailable to users and computers. For information on renaming domain controllers, including alternate renaming methods, see Help and Support. To continue renaming this domain controller, click OK.");
793 g_signal_connect_swapped(dialog, "response",
794 G_CALLBACK(gtk_widget_destroy),
795 dialog);
797 gtk_widget_show(dialog);
798 return;
800 #endif
802 state->button_ok = gtk_button_new_from_stock(GTK_STOCK_OK);
803 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
805 gtk_window_set_title(GTK_WINDOW(window), "Computer Name Changes");
806 gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
807 gtk_widget_set_size_request(GTK_WIDGET(window), 480, 500);
808 gtk_window_set_icon_from_file(GTK_WINDOW(window), SAMBA_ICON_PATH, NULL);
810 g_signal_connect(G_OBJECT(window), "delete_event",
811 G_CALLBACK(callback_do_close), window);
813 gtk_container_set_border_width(GTK_CONTAINER(window), 10);
815 box1 = gtk_vbox_new(FALSE, 0);
816 gtk_container_add(GTK_CONTAINER(window), box1);
818 label = gtk_label_new("You can change the name and membership of this computer. Changes may affect access to network ressources.");
819 gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
820 gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
821 gtk_box_pack_start(GTK_BOX(box1), label, TRUE, TRUE, 0);
822 gtk_widget_show(label);
824 /* COMPUTER NAME */
825 label = gtk_label_new("Computer name:");
826 gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
827 gtk_box_pack_start(GTK_BOX(box1), label, TRUE, TRUE, 0);
828 gtk_widget_show(label);
830 state->label_full_computer_name = gtk_label_new(NULL);
832 entry = gtk_entry_new();
833 gtk_entry_set_max_length(GTK_ENTRY(entry), MAX_NETBIOS_NAME_LEN);
834 g_signal_connect(G_OBJECT(entry), "changed",
835 G_CALLBACK(callback_enter_hostname_and_unlock),
836 (gpointer)state);
837 gtk_entry_set_text(GTK_ENTRY(entry), state->my_hostname);
838 gtk_editable_select_region(GTK_EDITABLE(entry),
839 0, GTK_ENTRY(entry)->text_length);
841 gtk_editable_set_editable(GTK_EDITABLE(entry), TRUE); /* ! */
842 gtk_box_pack_start(GTK_BOX(box1), entry, TRUE, TRUE, 0);
843 gtk_widget_show(entry);
846 /* FULL COMPUTER NAME */
847 label = gtk_label_new("Full computer name:");
848 gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
849 gtk_box_pack_start(GTK_BOX(box1), label, TRUE, TRUE, 0);
850 gtk_widget_show(label);
853 const gchar *entry_text;
854 char *str = NULL;
855 entry_text = gtk_entry_get_text(GTK_ENTRY(entry));
856 if (state->name_type_initial == NetSetupDomainName) {
857 asprintf(&str, "%s.%s", entry_text,
858 state->my_dnsdomain);
859 } else {
860 asprintf(&str, "%s.", entry_text);
862 gtk_label_set_text(GTK_LABEL(state->label_full_computer_name),
863 str);
864 free(str);
865 gtk_misc_set_alignment(GTK_MISC(state->label_full_computer_name), 0, 0);
866 gtk_box_pack_start(GTK_BOX(box1),
867 state->label_full_computer_name, TRUE, TRUE, 0);
868 gtk_widget_show(state->label_full_computer_name);
871 /* BOX */
872 frame_horz = gtk_frame_new ("Member Of");
873 gtk_box_pack_start(GTK_BOX(box1), frame_horz, TRUE, TRUE, 10);
875 vbox = gtk_vbox_new(FALSE, 0);
876 gtk_container_set_border_width(GTK_CONTAINER(vbox), 10);
877 gtk_container_add(GTK_CONTAINER(frame_horz), vbox);
879 /* TWO ENTRIES */
880 state->entry_workgroup = gtk_entry_new();
881 state->entry_domain = gtk_entry_new();
883 /* DOMAIN */
884 button_domain = gtk_radio_button_new_with_label(NULL, "Domain");
885 if (state->name_type_initial == NetSetupDomainName) {
886 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button_domain), TRUE);
888 gtk_box_pack_start(GTK_BOX(vbox), button_domain, TRUE, TRUE, 0);
889 g_signal_connect(G_OBJECT(button_domain), "clicked",
890 G_CALLBACK(callback_do_join_domain),
891 (gpointer)state);
894 gtk_entry_set_max_length(GTK_ENTRY(state->entry_domain), 50);
895 g_signal_connect(G_OBJECT(state->entry_domain), "changed",
896 G_CALLBACK(callback_enter_domain_and_unlock),
897 (gpointer)state);
898 g_signal_connect(G_OBJECT(state->entry_domain), "activate",
899 G_CALLBACK(callback_continue),
900 (gpointer)state);
901 if (state->name_type_initial == NetSetupDomainName) {
902 gtk_entry_set_text(GTK_ENTRY(state->entry_domain),
903 state->name_buffer_initial);
904 gtk_widget_set_sensitive(state->entry_workgroup, FALSE);
905 gtk_widget_set_sensitive(state->entry_domain, TRUE);
907 gtk_editable_set_editable(GTK_EDITABLE(state->entry_domain), TRUE);
908 gtk_box_pack_start(GTK_BOX(vbox), state->entry_domain, TRUE, TRUE, 0);
909 gtk_widget_show(state->entry_domain);
911 gtk_widget_show(button_domain);
913 /* WORKGROUP */
914 group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button_domain));
915 button_workgroup = gtk_radio_button_new_with_label(group, "Workgroup");
916 if (state->name_type_initial == NetSetupWorkgroupName) {
917 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button_workgroup), TRUE);
919 gtk_box_pack_start(GTK_BOX(vbox), button_workgroup, TRUE, TRUE, 0);
920 g_signal_connect(G_OBJECT(button_workgroup), "clicked",
921 G_CALLBACK(callback_do_join_workgroup),
922 (gpointer)state);
924 gtk_entry_set_max_length(GTK_ENTRY(state->entry_workgroup),
925 MAX_NETBIOS_NAME_LEN);
926 g_signal_connect(G_OBJECT(state->entry_workgroup), "changed",
927 G_CALLBACK(callback_enter_workgroup_and_unlock),
928 (gpointer)state);
929 g_signal_connect(G_OBJECT(state->entry_workgroup), "activate",
930 G_CALLBACK(callback_continue),
931 (gpointer)state);
933 if (state->name_type_initial == NetSetupWorkgroupName) {
934 gtk_entry_set_text(GTK_ENTRY(state->entry_workgroup),
935 state->name_buffer_initial);
936 gtk_widget_set_sensitive(GTK_WIDGET(state->entry_domain), FALSE);
937 gtk_widget_set_sensitive(GTK_WIDGET(state->entry_workgroup), TRUE);
939 gtk_box_pack_start(GTK_BOX(vbox), state->entry_workgroup, TRUE, TRUE, 0);
940 gtk_widget_show(state->entry_workgroup);
942 gtk_widget_show(button_workgroup);
944 /* BUTTONS */
945 bbox = gtk_hbutton_box_new();
946 gtk_container_set_border_width(GTK_CONTAINER(bbox), 5);
947 gtk_container_add(GTK_CONTAINER(box1), bbox);
948 gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);
949 gtk_box_set_spacing(GTK_BOX(bbox), 10);
951 state->window_do_change = window;
952 gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), FALSE); /* !!! */
953 gtk_container_add(GTK_CONTAINER(bbox), state->button_ok);
954 g_signal_connect(G_OBJECT(state->button_ok), "clicked",
955 G_CALLBACK(callback_creds_prompt),
956 (gpointer)state);
958 button = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
959 gtk_container_add(GTK_CONTAINER(bbox), button);
960 g_signal_connect(G_OBJECT(button), "clicked",
961 G_CALLBACK(callback_do_close),
962 (gpointer)window);
964 gtk_widget_show_all(window);
968 static void callback_do_about(GtkWidget *widget,
969 gpointer data)
971 GdkPixbuf *logo;
972 GError *error = NULL;
974 debug("callback_do_about called\n");
976 logo = gdk_pixbuf_new_from_file(SAMBA_IMAGE_PATH,
977 &error);
978 if (logo == NULL) {
979 g_print("failed to load logo from %s: %s\n",
980 SAMBA_IMAGE_PATH, error->message);
983 gtk_show_about_dialog(data,
984 "name", "Samba",
985 "version", "3.2.0pre2-GIT-904a90-test",
986 "copyright", "Copyright Andrew Tridgell and the Samba Team 1992-2007",
987 "website", "http://www.samba.org",
988 "license", "GPLv3",
989 "logo", logo,
990 "comments", "Samba gtk domain join utility",
991 NULL);
994 static int draw_main_window(struct join_state *state)
996 GtkWidget *window;
997 GtkWidget *button;
998 GtkWidget *label;
999 GtkWidget *main_vbox;
1000 GtkWidget *vbox;
1001 GtkWidget *hbox;
1002 GtkWidget *bbox;
1003 GtkWidget *image;
1004 GtkWidget *table;
1005 GtkWidget *entry;
1006 GdkPixbuf *icon;
1007 GError *error = NULL;
1009 icon = gdk_pixbuf_new_from_file(SAMBA_ICON_PATH,
1010 &error);
1011 if (icon == NULL) {
1012 g_print("failed to load icon from %s : %s\n",
1013 SAMBA_ICON_PATH, error->message);
1016 #if 1
1017 image = gtk_image_new_from_file(SAMBA_IMAGE_PATH_SMALL);
1018 #else
1019 image = gtk_image_new_from_file("/usr/share/pixmaps/redhat-system_settings.png");
1020 #endif
1021 if (image == NULL) {
1022 g_print("failed to load logo from %s : %s\n",
1023 SAMBA_IMAGE_PATH_SMALL, error->message);
1026 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
1027 state->window_main = window;
1029 gtk_window_set_title(GTK_WINDOW(window), "Samba - Join Domain dialogue");
1030 gtk_widget_set_size_request(GTK_WIDGET(window), 600, 600);
1031 gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
1032 gtk_window_set_icon_from_file(GTK_WINDOW(window), SAMBA_ICON_PATH, NULL);
1034 g_signal_connect(G_OBJECT(window), "delete_event",
1035 G_CALLBACK(callback_delete_event), NULL);
1037 gtk_container_set_border_width(GTK_CONTAINER(window), 10);
1039 main_vbox = gtk_vbox_new(FALSE, 10);
1040 gtk_container_add(GTK_CONTAINER(window), main_vbox);
1042 #if 0
1043 gtk_box_pack_start(GTK_BOX(main_vbox), image, TRUE, TRUE, 10);
1044 gtk_widget_show(image);
1045 #endif
1046 /* Hbox */
1047 hbox = gtk_hbox_new(FALSE, 10);
1048 gtk_container_add(GTK_CONTAINER(main_vbox), hbox);
1051 /* gtk_box_pack_start(GTK_BOX(main_vbox), image, TRUE, TRUE, 10); */
1052 /* gtk_misc_set_alignment(GTK_MISC(image), 0, 0); */
1053 gtk_widget_set_size_request(GTK_WIDGET(image), 150, 40);
1054 gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 10);
1055 gtk_widget_show(image);
1057 /* Label */
1058 label = gtk_label_new("Samba uses the following information to identify your computer on the network.");
1059 /* gtk_misc_set_alignment(GTK_MISC(label), 0, 0); */
1060 gtk_widget_set_size_request(GTK_WIDGET(label), 400, 40);
1061 gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
1062 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
1063 gtk_widget_show(label);
1066 gtk_widget_show(hbox);
1068 vbox = gtk_vbox_new(FALSE, 0);
1069 gtk_container_set_border_width(GTK_CONTAINER(vbox), 10);
1070 gtk_container_add(GTK_CONTAINER(main_vbox), vbox);
1072 /* Table */
1073 table = gtk_table_new(6, 3, TRUE);
1074 gtk_table_set_row_spacings(GTK_TABLE(table), 5);
1075 gtk_table_set_col_spacings(GTK_TABLE(table), 5);
1076 gtk_container_add(GTK_CONTAINER(vbox), table);
1079 /* Label */
1080 label = gtk_label_new("Computer description:");
1081 /* gtk_misc_set_alignment(GTK_MISC(label), 0, 0); */
1082 gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 0, 1);
1083 gtk_widget_show(label);
1085 state->button_apply = gtk_button_new_from_stock(GTK_STOCK_APPLY);
1087 /* Entry */
1088 entry = gtk_entry_new();
1089 gtk_entry_set_max_length(GTK_ENTRY(entry), 256);
1090 g_signal_connect(G_OBJECT(entry), "changed",
1091 G_CALLBACK(callback_enter_computer_description_and_unlock),
1092 state);
1093 g_signal_connect(G_OBJECT(entry), "activate",
1094 G_CALLBACK(callback_apply_continue),
1095 (gpointer)state);
1097 gtk_entry_set_text(GTK_ENTRY(entry), (char *)state->comment);
1098 gtk_editable_set_editable(GTK_EDITABLE(entry), TRUE); /* ! */
1099 gtk_table_attach_defaults(GTK_TABLE(table), entry, 1, 3, 0, 1);
1100 gtk_widget_show(entry);
1103 /* Label */
1104 label = gtk_label_new("For example: \"Samba \%v\".");
1105 gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
1106 gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
1107 gtk_table_attach_defaults(GTK_TABLE(table), label, 1, 3, 1, 2);
1108 gtk_widget_show(label);
1110 /* Label */
1111 label = gtk_label_new("Full computer name:");
1112 gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
1113 gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 2, 3);
1114 gtk_widget_show(label);
1117 /* Label */
1118 char *str = NULL;
1119 if (state->name_type_initial == NetSetupDomainName) {
1120 asprintf(&str, "%s.%s", state->my_hostname,
1121 state->my_dnsdomain);
1122 } else {
1123 asprintf(&str, "%s.", state->my_hostname);
1126 label = gtk_label_new(str);
1127 SAFE_FREE(str);
1128 gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
1129 gtk_table_attach_defaults(GTK_TABLE(table), label, 1, 3, 2, 3);
1130 gtk_widget_show(label);
1133 /* Label */
1134 if (state->name_type_initial == NetSetupDomainName) {
1135 label = gtk_label_new("Domain:");
1136 } else {
1137 label = gtk_label_new("Workgroup:");
1139 gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
1140 gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 3, 4);
1141 gtk_widget_show(label);
1142 state->label_current_name_type = label;
1144 /* Label */
1145 label = gtk_label_new(state->name_buffer_initial);
1146 gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
1147 gtk_table_attach_defaults(GTK_TABLE(table), label, 1, 3, 3, 4);
1148 gtk_widget_show(label);
1149 state->label_current_name_buffer = label;
1152 hbox = gtk_hbox_new(FALSE, 0);
1153 gtk_container_add(GTK_CONTAINER(vbox), hbox);
1154 label = gtk_label_new("To rename this computer or join a domain, click Change.");
1155 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
1160 /* bbox */
1161 bbox = gtk_hbutton_box_new();
1162 gtk_container_set_border_width(GTK_CONTAINER(bbox), 5);
1163 gtk_container_add(GTK_CONTAINER(hbox), bbox);
1164 gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);
1165 gtk_box_set_spacing(GTK_BOX(bbox), 10);
1167 button = gtk_button_new_with_mnemonic("Ch_ange");
1168 g_signal_connect(G_OBJECT(button), "clicked",
1169 G_CALLBACK(callback_do_change),
1170 (gpointer)state);
1171 gtk_box_pack_start(GTK_BOX(bbox), button, TRUE, TRUE, 0);
1172 gtk_widget_show(button);
1174 /* Label (hidden) */
1175 state->label_reboot = gtk_label_new(NULL);
1176 gtk_label_set_line_wrap(GTK_LABEL(state->label_reboot), TRUE);
1177 gtk_misc_set_alignment(GTK_MISC(state->label_reboot), 0, 0);
1178 gtk_box_pack_start(GTK_BOX(vbox), state->label_reboot, TRUE, TRUE, 0);
1179 gtk_widget_show(state->label_reboot);
1181 #if 0
1182 gtk_box_pack_start(GTK_BOX(vbox),
1183 create_bbox(window, TRUE, NULL, 10, 85, 20, GTK_BUTTONBOX_END),
1184 TRUE, TRUE, 5);
1185 #endif
1188 GtkWidget *frame;
1189 GtkWidget *bbox2;
1190 GtkWidget *button2;
1192 frame = gtk_frame_new(NULL);
1193 bbox2 = gtk_hbutton_box_new();
1195 gtk_container_set_border_width(GTK_CONTAINER(bbox2), 5);
1196 gtk_container_add(GTK_CONTAINER(frame), bbox2);
1198 /* Set the appearance of the Button Box */
1199 gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox2), GTK_BUTTONBOX_END);
1200 gtk_box_set_spacing(GTK_BOX(bbox2), 10);
1201 /*gtk_button_box_set_child_size(GTK_BUTTON_BOX(bbox2), child_w, child_h);*/
1203 button2 = gtk_button_new_from_stock(GTK_STOCK_OK);
1204 gtk_container_add(GTK_CONTAINER(bbox2), button2);
1205 g_signal_connect(G_OBJECT(button2), "clicked", G_CALLBACK(callback_do_exit), state);
1207 button2 = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
1208 gtk_container_add(GTK_CONTAINER(bbox2), button2);
1209 g_signal_connect(G_OBJECT(button2), "clicked",
1210 G_CALLBACK(callback_delete_event),
1211 window);
1213 gtk_container_add(GTK_CONTAINER(bbox2), state->button_apply);
1214 g_signal_connect(G_OBJECT(state->button_apply), "clicked",
1215 G_CALLBACK(callback_apply_description_change),
1216 state);
1217 gtk_widget_set_sensitive(GTK_WIDGET(state->button_apply), FALSE);
1219 button2 = gtk_button_new_from_stock(GTK_STOCK_ABOUT);
1220 gtk_container_add(GTK_CONTAINER(bbox2), button2);
1221 g_signal_connect(G_OBJECT(button2), "clicked",
1222 G_CALLBACK(callback_do_about),
1223 window);
1225 gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 5);
1228 gtk_widget_show_all(window);
1230 return 0;
1233 static int init_join_state(struct join_state **state)
1235 struct join_state *s;
1237 s = malloc(sizeof(struct join_state));
1238 if (!s) {
1239 return -1;
1242 memset(s, '\0', sizeof(struct join_state));
1244 *state = s;
1246 return 0;
1249 static int initialize_join_state(struct join_state *state,
1250 const char *debug_level)
1252 struct libnetapi_ctx *ctx = NULL;
1253 NET_API_STATUS status = 0;
1255 status = libnetapi_init(&ctx);
1256 if (status) {
1257 return status;
1260 if (debug_level) {
1261 libnetapi_set_debuglevel(ctx, debug_level);
1265 char my_hostname[HOST_NAME_MAX];
1266 const char *p = NULL;
1267 struct hostent *hp = NULL;
1269 if (gethostname(my_hostname, sizeof(my_hostname)) == -1) {
1270 return -1;
1273 p = strchr(my_hostname, '.');
1274 if (p) {
1275 my_hostname[strlen(my_hostname)-strlen(p)] = '\0';
1277 state->my_hostname = strdup(my_hostname);
1278 if (!state->my_hostname) {
1279 return -1;
1281 debug("state->my_hostname: %s\n", state->my_hostname);
1283 hp = gethostbyname(my_hostname);
1284 if (!hp || !hp->h_name || !*hp->h_name) {
1285 return -1;
1288 state->my_fqdn = strdup(hp->h_name);
1289 if (!state->my_fqdn) {
1290 return -1;
1292 debug("state->my_fqdn: %s\n", state->my_fqdn);
1294 p = strchr(state->my_fqdn, '.');
1295 if (p) {
1296 p++;
1297 state->my_dnsdomain = strdup(p);
1298 } else {
1299 state->my_dnsdomain = strdup("");
1301 if (!state->my_dnsdomain) {
1302 return -1;
1304 debug("state->my_dnsdomain: %s\n", state->my_dnsdomain);
1308 const char *buffer = NULL;
1309 uint16_t type = 0;
1310 status = NetGetJoinInformation(NULL, &buffer, &type);
1311 if (status != 0) {
1312 printf("NetGetJoinInformation failed with: %s\n",
1313 libnetapi_get_error_string(state->ctx, status));
1314 return status;
1316 debug("NetGetJoinInformation gave: %s and %d\n", buffer, type);
1317 state->name_buffer_initial = strdup(buffer);
1318 if (!state->name_buffer_initial) {
1319 return -1;
1321 state->name_type_initial = type;
1322 NetApiBufferFree((void *)buffer);
1326 struct srvsvc_NetSrvInfo1005 *info1005 = NULL;
1327 uint8_t *buffer = NULL;
1329 status = NetServerGetInfo(NULL, 1005, &buffer);
1330 if (status != 0) {
1331 printf("NetServerGetInfo failed with: %s\n",
1332 libnetapi_get_error_string(state->ctx, status));
1333 return status;
1336 info1005 = (struct srvsvc_NetSrvInfo1005 *)buffer;
1338 state->comment = strdup(info1005->comment);
1339 if (!state->comment) {
1340 return -1;
1342 NetApiBufferFree(buffer);
1344 #if 0
1346 struct srvsvc_NetSrvInfo100 *info100 = NULL;
1347 uint8_t *buffer = NULL;
1349 status = NetServerGetInfo(NULL, 100, &buffer);
1350 if (status) {
1351 return status;
1354 info100 = (struct srvsvc_NetSrvInfo100 *)buffer;
1356 state->comment = strdup(info100->comment);
1357 if (!state->comment) {
1358 return -1;
1361 #endif
1363 state->ctx = ctx;
1365 return 0;
1368 int main(int argc, char **argv)
1370 GOptionContext *context = NULL;
1371 static const char *debug_level = NULL;
1372 struct join_state *state = NULL;
1373 GError *error = NULL;
1374 int ret = 0;
1376 static GOptionEntry entries[] = {
1377 { "debug", 'd', 0, G_OPTION_ARG_STRING, &debug_level, "Debug level (for samba)", "N" },
1378 { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "Verbose output", 0 },
1379 { NULL }
1382 context = g_option_context_new("- Samba domain join utility");
1383 g_option_context_add_main_entries(context, entries, NULL);
1384 /* g_option_context_add_main_entries(context, entries, GETTEXT_PACKAGE); */
1385 g_option_context_add_group(context, gtk_get_option_group(TRUE));
1386 g_option_context_parse(context, &argc, &argv, &error);
1388 gtk_init(&argc, &argv);
1389 g_set_application_name("Samba");
1391 ret = init_join_state(&state);
1392 if (ret) {
1393 return ret;
1396 ret = initialize_join_state(state, debug_level);
1397 if (ret) {
1398 return ret;
1401 draw_main_window(state);
1403 gtk_main();
1405 do_cleanup(state);
1407 return 0;