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/>.
22 #include <sys/types.h>
30 #include <glib/gprintf.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 NetSetupWorkgroupName ( 2 )
42 #define NetSetupDomainName ( 3 )
44 #define SAFE_FREE(x) do { if ((x) != NULL) {free(x); x=NULL;} } while(0)
46 static gboolean verbose = FALSE;
48 typedef struct join_state {
49 struct libnetapi_ctx *ctx;
50 GtkWidget *window_main;
51 GtkWidget *window_parent;
52 GtkWidget *window_do_change;
53 GtkWidget *window_creds_prompt;
54 GtkWidget *entry_account;
55 GtkWidget *entry_password;
56 GtkWidget *entry_domain;
57 GtkWidget *entry_ou_list;
58 GtkWidget *entry_workgroup;
60 GtkWidget *button_apply;
61 GtkWidget *button_ok_creds;
62 GtkWidget *button_get_ous;
63 GtkWidget *label_reboot;
64 GtkWidget *label_current_name_buffer;
65 GtkWidget *label_current_name_type;
66 GtkWidget *label_full_computer_name;
67 GtkWidget *label_winbind;
68 uint16_t name_type_initial;
69 uint16_t name_type_new;
70 char *name_buffer_initial;
71 char *name_buffer_new;
80 gboolean settings_changed;
81 gboolean hostname_changed;
82 uint32_t stored_num_ous;
85 static void debug(const char *format, ...)
93 va_start(args, format);
94 g_vprintf(format, args);
98 static gboolean callback_delete_event(GtkWidget *widget,
106 static void callback_do_close(GtkWidget *widget,
109 debug("callback_do_close called\n");
112 gtk_widget_destroy(GTK_WIDGET(data));
117 static void callback_do_freeauth(GtkWidget *widget,
120 struct join_state *state = (struct join_state *)data;
122 debug("callback_do_freeauth called\n");
124 SAFE_FREE(state->account);
125 SAFE_FREE(state->password);
127 if (state->window_creds_prompt) {
128 gtk_widget_destroy(GTK_WIDGET(state->window_creds_prompt));
129 state->window_creds_prompt = NULL;
133 static void callback_do_freeauth_and_close(GtkWidget *widget,
136 struct join_state *state = (struct join_state *)data;
138 debug("callback_do_freeauth_and_close called\n");
140 SAFE_FREE(state->account);
141 SAFE_FREE(state->password);
143 if (state->window_creds_prompt) {
144 gtk_widget_destroy(GTK_WIDGET(state->window_creds_prompt));
145 state->window_creds_prompt = NULL;
147 if (state->window_do_change) {
148 gtk_widget_destroy(GTK_WIDGET(state->window_do_change));
149 state->window_do_change = NULL;
153 static void free_join_state(struct join_state *s)
155 SAFE_FREE(s->name_buffer_initial);
156 SAFE_FREE(s->name_buffer_new);
157 SAFE_FREE(s->password);
158 SAFE_FREE(s->account);
159 SAFE_FREE(s->comment);
160 SAFE_FREE(s->comment_new);
161 SAFE_FREE(s->my_fqdn);
162 SAFE_FREE(s->my_dnsdomain);
163 SAFE_FREE(s->my_hostname);
166 static void do_cleanup(struct join_state *state)
168 libnetapi_free(state->ctx);
169 free_join_state(state);
172 static void callback_apply_description_change(GtkWidget *widget,
175 struct join_state *state = (struct join_state *)data;
176 NET_API_STATUS status = 0;
177 uint32_t parm_err = 0;
178 struct SERVER_INFO_1005 info1005;
181 info1005.sv1005_comment = state->comment_new;
183 status = NetServerSetInfo(NULL, 1005, (uint8_t *)&info1005, &parm_err);
185 debug("NetServerSetInfo failed with: %s\n",
186 libnetapi_errstr(status));
187 dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_main),
188 GTK_DIALOG_DESTROY_WITH_PARENT,
191 "Failed to change computer description: %s.",
192 libnetapi_get_error_string(state->ctx, status));
193 gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
195 g_signal_connect_swapped(dialog, "response",
196 G_CALLBACK(gtk_widget_destroy),
199 gtk_widget_show(dialog);
203 gtk_widget_set_sensitive(GTK_WIDGET(state->button_apply), FALSE);
206 static void callback_do_exit(GtkWidget *widget,
213 struct join_state *state = (struct join_state *)data;
215 if (!state->settings_changed) {
216 callback_delete_event(NULL, NULL, NULL);
221 dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_main),
222 GTK_DIALOG_DESTROY_WITH_PARENT,
223 GTK_MESSAGE_QUESTION,
225 "You must restart your computer before the new settings will take effect.");
226 gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
227 result = gtk_dialog_run(GTK_DIALOG(dialog));
229 case GTK_RESPONSE_YES:
230 g_print("would reboot here\n");
232 case GTK_RESPONSE_NO:
237 gtk_widget_destroy(GTK_WIDGET(dialog));
240 if (state->window_main) {
241 gtk_widget_destroy(GTK_WIDGET(state->window_main));
242 state->window_main = NULL;
249 static void callback_do_reboot(GtkWidget *widget,
254 struct join_state *state = (struct join_state *)data2;
256 debug("callback_do_reboot\n");
258 state->settings_changed = TRUE;
259 dialog = gtk_message_dialog_new(GTK_WINDOW(data),
260 GTK_DIALOG_DESTROY_WITH_PARENT,
263 "You must restart this computer for the changes to take effect.");
264 gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
266 g_signal_connect_swapped(dialog, "response",
267 G_CALLBACK(gtk_widget_destroy),
270 debug("showing dialog\n");
271 gtk_widget_show(dialog);
273 gtk_dialog_run(GTK_DIALOG(dialog));
274 gtk_widget_destroy(GTK_WIDGET(dialog));
277 gtk_label_set_text(GTK_LABEL(state->label_reboot),
278 "Changes will take effect after you restart this computer");
280 debug("destroying do_change window\n");
281 gtk_widget_destroy(GTK_WIDGET(state->window_do_change));
288 status = NetGetJoinInformation(NULL, &buffer, &type);
290 g_print("failed to query status\n");
294 debug("got new status: %s\n", buffer);
296 SAFE_FREE(state->name_buffer_new);
297 state->name_buffer_new = strdup(buffer);
298 state->name_type_new = type;
299 state->name_buffer_initial = strdup(buffer);
300 state->name_type_initial = type;
301 NetApiBufferFree((void *)buffer);
303 gtk_label_set_text(GTK_LABEL(state->label_current_name_buffer),
304 state->name_buffer_new);
305 if (state->name_type_new == NetSetupDomainName) {
306 gtk_label_set_text(GTK_LABEL(state->label_current_name_type),
309 gtk_label_set_text(GTK_LABEL(state->label_current_name_type),
315 static void callback_return_username(GtkWidget *widget,
318 const gchar *entry_text;
319 struct join_state *state = (struct join_state *)data;
320 debug("callback_return_username called\n");
324 entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
328 debug("callback_return_username: %s\n", entry_text);
329 SAFE_FREE(state->account);
330 state->account = strdup(entry_text);
333 static void callback_return_username_and_enter(GtkWidget *widget,
336 const gchar *entry_text;
337 struct join_state *state = (struct join_state *)data;
341 entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
345 debug("callback_return_username_and_enter: %s\n", entry_text);
346 SAFE_FREE(state->account);
347 state->account = strdup(entry_text);
348 g_signal_emit_by_name(state->button_ok_creds, "clicked");
351 static void callback_return_password(GtkWidget *widget,
354 const gchar *entry_text;
355 struct join_state *state = (struct join_state *)data;
356 debug("callback_return_password called\n");
360 entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
364 #ifdef DEBUG_PASSWORD
365 debug("callback_return_password: %s\n", entry_text);
367 debug("callback_return_password: (not printed)\n");
369 SAFE_FREE(state->password);
370 state->password = strdup(entry_text);
373 static void callback_return_password_and_enter(GtkWidget *widget,
376 const gchar *entry_text;
377 struct join_state *state = (struct join_state *)data;
381 entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
385 #ifdef DEBUG_PASSWORD
386 debug("callback_return_password_and_enter: %s\n", entry_text);
388 debug("callback_return_password_and_enter: (not printed)\n");
390 SAFE_FREE(state->password);
391 state->password = strdup(entry_text);
392 g_signal_emit_by_name(state->button_ok_creds, "clicked");
395 static void callback_do_storeauth(GtkWidget *widget,
398 struct join_state *state = (struct join_state *)data;
400 debug("callback_do_storeauth called\n");
402 SAFE_FREE(state->account);
403 SAFE_FREE(state->password);
405 callback_return_username(state->entry_account, (gpointer)state);
406 callback_return_password(state->entry_password, (gpointer)state);
408 if (state->window_creds_prompt) {
409 gtk_widget_destroy(GTK_WIDGET(state->window_creds_prompt));
410 state->window_creds_prompt = NULL;
414 static void callback_continue(GtkWidget *widget,
417 struct join_state *state = (struct join_state *)data;
419 gtk_widget_grab_focus(GTK_WIDGET(state->button_ok));
420 g_signal_emit_by_name(state->button_ok, "clicked");
423 static void callback_do_storeauth_and_continue(GtkWidget *widget,
426 callback_do_storeauth(widget, data);
427 callback_continue(NULL, data);
430 static void callback_do_storeauth_and_scan(GtkWidget *widget,
433 struct join_state *state = (struct join_state *)data;
434 callback_do_storeauth(widget, data);
435 g_signal_emit_by_name(state->button_get_ous, "clicked");
438 static void callback_do_hostname_change(GtkWidget *widget,
442 const char *str = NULL;
444 struct join_state *state = (struct join_state *)data;
446 switch (state->name_type_initial) {
447 case NetSetupDomainName:
448 str = "To be implemented: call NetRenameMachineInDomain\n";
450 case NetSetupWorkgroupName:
451 str = "To be implemented: call SetComputerNameEx\n";
457 dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_parent),
458 GTK_DIALOG_DESTROY_WITH_PARENT,
463 gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
464 g_signal_connect_swapped(dialog, "response",
465 G_CALLBACK(gtk_widget_destroy),
467 gtk_widget_show(dialog);
470 static void callback_creds_prompt(GtkWidget *widget,
472 const char *label_string,
481 struct join_state *state = (struct join_state *)data;
483 debug("callback_creds_prompt\n");
485 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
486 gtk_window_set_modal(GTK_WINDOW(window), TRUE);
488 gtk_window_set_title(GTK_WINDOW(window), "Computer Name Changes");
489 gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
490 gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
491 gtk_widget_set_size_request(GTK_WIDGET(window), 380, 280);
492 gtk_window_set_icon_from_file(GTK_WINDOW(window), SAMBA_ICON_PATH, NULL);
494 g_signal_connect(G_OBJECT(window), "delete_event",
495 G_CALLBACK(callback_do_close), window);
497 state->window_creds_prompt = window;
498 gtk_container_set_border_width(GTK_CONTAINER(window), 10);
500 box1 = gtk_vbox_new(FALSE, 0);
502 gtk_container_add(GTK_CONTAINER(window), box1);
504 label = gtk_label_new(label_string);
505 gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
506 gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
508 gtk_box_pack_start(GTK_BOX(box1), label, FALSE, FALSE, 0);
510 gtk_widget_show(label);
513 label = gtk_label_new("User name:");
514 gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
515 gtk_box_pack_start(GTK_BOX(box1), label, FALSE, FALSE, 0);
516 gtk_widget_show(label);
518 state->entry_account = gtk_entry_new();
519 gtk_entry_set_max_length(GTK_ENTRY(state->entry_account), MAX_CRED_LEN);
520 g_signal_connect(G_OBJECT(state->entry_account), "activate",
521 G_CALLBACK(callback_return_username_and_enter),
523 gtk_editable_select_region(GTK_EDITABLE(state->entry_account),
524 0, GTK_ENTRY(state->entry_account)->text_length);
525 gtk_box_pack_start(GTK_BOX(box1), state->entry_account, TRUE, TRUE, 0);
526 gtk_widget_show(state->entry_account);
529 label = gtk_label_new("Password:");
530 gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
531 gtk_box_pack_start(GTK_BOX(box1), label, FALSE, FALSE, 0);
532 gtk_widget_show(label);
534 state->entry_password = gtk_entry_new();
535 gtk_entry_set_max_length(GTK_ENTRY(state->entry_password), MAX_CRED_LEN);
536 gtk_entry_set_visibility(GTK_ENTRY(state->entry_password), FALSE);
537 g_signal_connect(G_OBJECT(state->entry_password), "activate",
538 G_CALLBACK(callback_return_password_and_enter),
540 gtk_editable_set_editable(GTK_EDITABLE(state->entry_password), TRUE);
541 gtk_editable_select_region(GTK_EDITABLE(state->entry_password),
542 0, GTK_ENTRY(state->entry_password)->text_length);
543 gtk_box_pack_start(GTK_BOX(box1), state->entry_password, TRUE, TRUE, 0);
544 gtk_widget_show(state->entry_password);
547 bbox = gtk_hbutton_box_new();
548 gtk_container_set_border_width(GTK_CONTAINER(bbox), 5);
549 gtk_container_add(GTK_CONTAINER(box1), bbox);
550 gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);
551 gtk_box_set_spacing(GTK_BOX(bbox), 10);
553 state->button_ok_creds = gtk_button_new_from_stock(GTK_STOCK_OK);
554 gtk_widget_grab_focus(GTK_WIDGET(state->button_ok_creds));
555 gtk_container_add(GTK_CONTAINER(bbox), state->button_ok_creds);
556 g_signal_connect(G_OBJECT(state->button_ok_creds), "clicked",
559 gtk_widget_show(state->button_ok_creds);
561 button = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
562 gtk_container_add(GTK_CONTAINER(bbox), button);
563 g_signal_connect(G_OBJECT(button), "clicked",
564 G_CALLBACK(callback_do_freeauth),
566 gtk_widget_show_all(window);
569 static void callback_do_join(GtkWidget *widget,
574 NET_API_STATUS status;
575 const char *err_str = NULL;
576 uint32_t join_flags = 0;
577 uint32_t unjoin_flags = 0;
578 gboolean domain_join = FALSE;
579 gboolean try_unjoin = FALSE;
580 gboolean join_creds_required = TRUE;
581 gboolean unjoin_creds_required = TRUE;
582 const char *new_workgroup_type = NULL;
583 const char *initial_workgroup_type = NULL;
584 const char *account_ou = NULL;
586 struct join_state *state = (struct join_state *)data;
588 if (state->hostname_changed) {
589 callback_do_hostname_change(NULL, state);
593 switch (state->name_type_initial) {
594 case NetSetupWorkgroupName:
595 initial_workgroup_type = "workgroup";
597 case NetSetupDomainName:
598 initial_workgroup_type = "domain";
604 switch (state->name_type_new) {
605 case NetSetupWorkgroupName:
606 new_workgroup_type = "workgroup";
608 case NetSetupDomainName:
609 new_workgroup_type = "domain";
615 account_ou = gtk_combo_box_get_active_text(GTK_COMBO_BOX(state->entry_ou_list));
616 if (account_ou && strlen(account_ou) == 0) {
620 if ((state->name_type_initial != NetSetupDomainName) &&
621 (state->name_type_new != NetSetupDomainName)) {
622 join_creds_required = FALSE;
623 unjoin_creds_required = FALSE;
626 if (state->name_type_new == NetSetupDomainName) {
628 join_creds_required = TRUE;
629 join_flags = NETSETUP_JOIN_DOMAIN |
630 NETSETUP_ACCT_CREATE |
631 NETSETUP_DOMAIN_JOIN_IF_JOINED; /* for testing */
634 if ((state->name_type_initial == NetSetupDomainName) &&
635 (state->name_type_new == NetSetupWorkgroupName)) {
637 unjoin_creds_required = TRUE;
638 join_creds_required = FALSE;
639 unjoin_flags = NETSETUP_JOIN_DOMAIN |
640 NETSETUP_ACCT_DELETE;
645 debug("callback_do_join: Unjoining\n");
647 if (unjoin_creds_required) {
648 if (!state->account || !state->password) {
649 debug("callback_do_join: no creds yet\n");
650 callback_creds_prompt(NULL, state,
651 "Enter the name and password of an account with permission to leave the domain.",
652 callback_do_storeauth_and_continue);
655 if (!state->account || !state->password) {
656 debug("callback_do_join: still no creds???\n");
661 status = NetUnjoinDomain(NULL,
666 callback_do_freeauth(NULL, state);
667 err_str = libnetapi_get_error_string(state->ctx, status);
668 g_print("callback_do_join: failed to unjoin (%s)\n",
672 /* in fact we shouldn't annoy the user with an error message here */
674 dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_parent),
675 GTK_DIALOG_DESTROY_WITH_PARENT,
678 "The following error occured attempting to unjoin the %s: \"%s\": %s",
679 initial_workgroup_type,
680 state->name_buffer_initial,
682 gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
683 gtk_dialog_run(GTK_DIALOG(dialog));
684 gtk_widget_destroy(dialog);
690 /* before prompting for creds, make sure we can find a dc */
694 struct DOMAIN_CONTROLLER_INFO *dc_info = NULL;
696 status = DsGetDcName(NULL,
697 state->name_buffer_new,
703 err_str = libnetapi_get_error_string(state->ctx, status);
704 g_print("callback_do_join: failed find dc (%s)\n", err_str);
706 dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_parent),
707 GTK_DIALOG_DESTROY_WITH_PARENT,
710 "Failed to find a domain controller for domain: \"%s\": %s",
711 state->name_buffer_new,
714 gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
715 g_signal_connect_swapped(dialog, "response",
716 G_CALLBACK(gtk_widget_destroy),
719 gtk_widget_show(dialog);
725 if (join_creds_required) {
726 if (!state->account || !state->password) {
727 debug("callback_do_join: no creds yet\n");
728 callback_creds_prompt(NULL, state,
729 "Enter the name and password of an account with permission to leave the domain.",
730 callback_do_storeauth_and_continue);
733 if (!state->account || !state->password) {
734 debug("callback_do_join: still no creds???\n");
739 debug("callback_do_join: Joining a %s named %s using join_flags 0x%08x ",
741 state->name_buffer_new,
744 debug("as %s ", state->account);
745 #ifdef DEBUG_PASSWORD
746 debug("with %s ", state->password);
751 status = NetJoinDomain(NULL,
752 state->name_buffer_new,
758 callback_do_freeauth(NULL, state);
759 err_str = libnetapi_get_error_string(state->ctx, status);
760 g_print("callback_do_join: failed to join (%s)\n", err_str);
762 dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_parent),
763 GTK_DIALOG_DESTROY_WITH_PARENT,
766 "The following error occured attempting to join the %s: \"%s\": %s",
768 state->name_buffer_new,
771 gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
772 g_signal_connect_swapped(dialog, "response",
773 G_CALLBACK(gtk_widget_destroy),
776 gtk_widget_show(dialog);
781 debug("callback_do_join: Successfully joined %s\n",
784 callback_do_freeauth(NULL, state);
785 dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_parent),
786 GTK_DIALOG_DESTROY_WITH_PARENT,
789 "Welcome to the %s %s.",
790 state->name_buffer_new,
793 gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
794 gtk_dialog_run(GTK_DIALOG(dialog));
795 gtk_widget_destroy(dialog);
797 callback_do_reboot(NULL, state->window_parent, state);
800 static void callback_enter_hostname_and_unlock(GtkWidget *widget,
803 const gchar *entry_text = NULL;
805 struct join_state *state = (struct join_state *)data;
807 entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
808 debug("callback_enter_hostname_and_unlock: %s\n", entry_text);
809 if (!entry_text || entry_text[0] == 0) {
810 state->hostname_changed = FALSE;
811 gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), FALSE);
814 if (strcasecmp(state->my_hostname, entry_text) == 0) {
815 state->hostname_changed = FALSE;
816 gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), FALSE);
819 state->hostname_changed = TRUE;
820 if (state->name_type_initial == NetSetupDomainName) {
821 if (asprintf(&str, "%s.%s", entry_text, state->my_dnsdomain) == -1) {
825 if (asprintf(&str, "%s.", entry_text) == -1) {
829 gtk_label_set_text(GTK_LABEL(state->label_full_computer_name), str);
832 if (state->hostname_changed && str && str[0] != 0 && str[0] != '.') {
833 gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), TRUE);
837 static void callback_enter_computer_description_and_unlock(GtkWidget *widget,
840 const gchar *entry_text = NULL;
841 struct join_state *state = (struct join_state *)data;
842 int string_unchanged = 0;
844 entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
845 debug("callback_enter_computer_description_and_unlock: %s\n",
848 if (!entry_text || entry_text[0] == 0) {
849 string_unchanged = 1;
850 gtk_widget_set_sensitive(GTK_WIDGET(state->button_apply),
855 if (entry_text && strcasecmp(state->comment, entry_text) == 0) {
856 string_unchanged = 1;
857 gtk_widget_set_sensitive(GTK_WIDGET(state->button_apply),
862 gtk_widget_set_sensitive(GTK_WIDGET(state->button_apply), TRUE);
863 SAFE_FREE(state->comment_new);
864 state->comment_new = strdup(entry_text);
869 static void callback_enter_workgroup_and_unlock(GtkWidget *widget,
872 const gchar *entry_text = NULL;
873 struct join_state *state = (struct join_state *)data;
875 entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
876 debug("callback_enter_workgroup_and_unlock: %s\n", entry_text);
877 if (!entry_text || entry_text[0] == 0) {
878 gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), FALSE);
881 if (strcasecmp(state->name_buffer_initial, entry_text) == 0) {
882 gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), FALSE);
885 gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), TRUE);
886 SAFE_FREE(state->name_buffer_new);
887 state->name_buffer_new = strdup(entry_text);
888 state->name_type_new = NetSetupWorkgroupName;
891 static void callback_enter_domain_and_unlock(GtkWidget *widget,
894 const gchar *entry_text = NULL;
895 struct join_state *state = (struct join_state *)data;
897 entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
898 debug("callback_enter_domain_and_unlock: %s\n", entry_text);
899 if (!entry_text || entry_text[0] == 0) {
900 gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), FALSE);
903 if (strcasecmp(state->name_buffer_initial, entry_text) == 0) {
904 gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), FALSE);
907 gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), TRUE);
908 gtk_widget_set_sensitive(GTK_WIDGET(state->entry_ou_list), TRUE);
909 gtk_widget_set_sensitive(GTK_WIDGET(state->button_get_ous), TRUE);
910 SAFE_FREE(state->name_buffer_new);
911 state->name_buffer_new = strdup(entry_text);
912 state->name_type_new = NetSetupDomainName;
915 static void callback_apply_continue(GtkWidget *widget,
918 struct join_state *state = (struct join_state *)data;
920 gtk_widget_grab_focus(GTK_WIDGET(state->button_apply));
921 g_signal_emit_by_name(state->button_apply, "clicked");
924 static void callback_do_join_workgroup(GtkWidget *widget,
927 struct join_state *state = (struct join_state *)data;
928 debug("callback_do_join_workgroup choosen\n");
929 gtk_widget_set_sensitive(GTK_WIDGET(state->entry_workgroup), TRUE);
930 gtk_widget_grab_focus(GTK_WIDGET(state->entry_workgroup));
931 gtk_widget_set_sensitive(GTK_WIDGET(state->entry_domain), FALSE);
932 gtk_widget_set_sensitive(GTK_WIDGET(state->entry_ou_list), FALSE);
933 gtk_widget_set_sensitive(GTK_WIDGET(state->button_get_ous), FALSE);
934 callback_enter_workgroup_and_unlock(state->entry_workgroup, state); /* TEST */
937 static void callback_do_join_domain(GtkWidget *widget,
940 struct join_state *state = (struct join_state *)data;
941 debug("callback_do_join_domain choosen\n");
942 gtk_widget_set_sensitive(GTK_WIDGET(state->entry_domain), TRUE);
943 gtk_widget_grab_focus(GTK_WIDGET(state->entry_domain));
944 gtk_widget_set_sensitive(GTK_WIDGET(state->entry_workgroup), FALSE);
945 callback_enter_domain_and_unlock(state->entry_domain, state); /* TEST */
948 static void callback_do_getous(GtkWidget *widget,
951 NET_API_STATUS status;
952 uint32_t num_ous = 0;
953 const char **ous = NULL;
955 const char *domain = NULL;
956 struct DOMAIN_CONTROLLER_INFO *dc_info = NULL;
957 const char *err_str = NULL;
960 struct join_state *state = (struct join_state *)data;
962 debug("callback_do_getous called\n");
964 domain = state->name_buffer_new ? state->name_buffer_new : state->name_buffer_initial;
966 status = DsGetDcName(NULL,
973 err_str = libnetapi_get_error_string(state->ctx, status);
974 g_print("callback_do_getous: failed find dc (%s)\n", err_str);
976 dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_parent),
977 GTK_DIALOG_DESTROY_WITH_PARENT,
980 "Failed to find a domain controller for domain: \"%s\": %s",
984 gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
985 g_signal_connect_swapped(dialog, "response",
986 G_CALLBACK(gtk_widget_destroy),
989 gtk_widget_show(dialog);
994 if (!state->account || !state->password) {
995 debug("callback_do_getous: no creds yet\n");
996 callback_creds_prompt(NULL, state,
997 "Enter the name and password of an account with permission to join the domain.",
998 callback_do_storeauth_and_scan);
1001 if (!state->account || !state->password) {
1002 debug("callback_do_getous: still no creds ???\n");
1006 status = NetGetJoinableOUs(NULL, domain,
1010 if (status != NET_API_STATUS_SUCCESS) {
1011 callback_do_freeauth(NULL, state);
1012 debug("failed to call NetGetJoinableOUs: %s\n",
1013 libnetapi_get_error_string(state->ctx, status));
1014 dialog = gtk_message_dialog_new(NULL,
1015 GTK_DIALOG_DESTROY_WITH_PARENT,
1018 "Failed to query joinable OUs: %s",
1019 libnetapi_get_error_string(state->ctx, status));
1020 gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
1021 gtk_dialog_run(GTK_DIALOG(dialog));
1022 gtk_widget_destroy(dialog);
1026 for (i=0; i<state->stored_num_ous; i++) {
1027 gtk_combo_box_remove_text(GTK_COMBO_BOX(state->entry_ou_list), 0);
1029 for (i=0; i<num_ous && ous[i] != NULL; i++) {
1030 gtk_combo_box_append_text(GTK_COMBO_BOX(state->entry_ou_list),
1033 NetApiBufferFree(ous);
1034 state->stored_num_ous = num_ous;
1035 gtk_combo_box_set_active(GTK_COMBO_BOX(state->entry_ou_list), num_ous-1);
1038 static void callback_do_change(GtkWidget *widget,
1044 GtkWidget *button_workgroup;
1045 GtkWidget *button_domain;
1048 GtkWidget *frame_horz;
1053 struct join_state *state = (struct join_state *)data;
1055 debug("callback_do_change called\n");
1058 /* FIXME: add proper warnings for Samba as a DC */
1059 if (state->server_role == 3) {
1061 callback_do_freeauth(NULL, state);
1062 dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_main),
1063 GTK_DIALOG_DESTROY_WITH_PARENT,
1066 "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.");
1067 gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
1068 g_signal_connect_swapped(dialog, "response",
1069 G_CALLBACK(gtk_widget_destroy),
1072 gtk_widget_show(dialog);
1077 state->button_ok = gtk_button_new_from_stock(GTK_STOCK_OK);
1078 state->button_get_ous = gtk_button_new_with_label("Scan for joinable OUs");
1079 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
1080 gtk_window_set_modal(GTK_WINDOW(window), TRUE);
1082 gtk_window_set_title(GTK_WINDOW(window), "Computer Name Changes");
1083 gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
1084 gtk_widget_set_size_request(GTK_WIDGET(window), 480, 650);
1085 gtk_window_set_icon_from_file(GTK_WINDOW(window), SAMBA_ICON_PATH, NULL);
1087 g_signal_connect(G_OBJECT(window), "delete_event",
1088 G_CALLBACK(callback_do_close), window);
1090 gtk_container_set_border_width(GTK_CONTAINER(window), 10);
1092 box1 = gtk_vbox_new(FALSE, 0);
1093 gtk_container_add(GTK_CONTAINER(window), box1);
1095 label = gtk_label_new("You can change the name and membership of this computer. Changes may affect access to network ressources.");
1096 gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
1097 gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
1098 gtk_box_pack_start(GTK_BOX(box1), label, TRUE, TRUE, 0);
1099 gtk_widget_show(label);
1102 label = gtk_label_new("Computer name:");
1103 gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
1104 gtk_box_pack_start(GTK_BOX(box1), label, TRUE, TRUE, 0);
1105 gtk_widget_show(label);
1107 state->label_full_computer_name = gtk_label_new(NULL);
1109 entry = gtk_entry_new();
1110 gtk_entry_set_max_length(GTK_ENTRY(entry), MAX_NETBIOS_NAME_LEN);
1111 g_signal_connect(G_OBJECT(entry), "changed",
1112 G_CALLBACK(callback_enter_hostname_and_unlock),
1114 gtk_entry_set_text(GTK_ENTRY(entry), state->my_hostname);
1115 gtk_editable_select_region(GTK_EDITABLE(entry),
1116 0, GTK_ENTRY(entry)->text_length);
1118 gtk_editable_set_editable(GTK_EDITABLE(entry), TRUE); /* ! */
1119 gtk_box_pack_start(GTK_BOX(box1), entry, TRUE, TRUE, 0);
1120 gtk_widget_show(entry);
1123 /* FULL COMPUTER NAME */
1124 label = gtk_label_new("Full computer name:");
1125 gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
1126 gtk_box_pack_start(GTK_BOX(box1), label, TRUE, TRUE, 0);
1127 gtk_widget_show(label);
1130 const gchar *entry_text;
1132 entry_text = gtk_entry_get_text(GTK_ENTRY(entry));
1133 if (state->name_type_initial == NetSetupDomainName) {
1134 if (asprintf(&str, "%s.%s", entry_text,
1135 state->my_dnsdomain) == -1) {
1139 if (asprintf(&str, "%s.", entry_text) == -1) {
1143 gtk_label_set_text(GTK_LABEL(state->label_full_computer_name),
1146 gtk_misc_set_alignment(GTK_MISC(state->label_full_computer_name), 0, 0);
1147 gtk_box_pack_start(GTK_BOX(box1),
1148 state->label_full_computer_name, TRUE, TRUE, 0);
1149 gtk_widget_show(state->label_full_computer_name);
1153 frame_horz = gtk_frame_new ("Member Of");
1154 gtk_box_pack_start(GTK_BOX(box1), frame_horz, TRUE, TRUE, 10);
1156 vbox = gtk_vbox_new(FALSE, 0);
1157 gtk_container_set_border_width(GTK_CONTAINER(vbox), 10);
1158 gtk_container_add(GTK_CONTAINER(frame_horz), vbox);
1161 state->entry_workgroup = gtk_entry_new();
1162 state->entry_domain = gtk_entry_new();
1165 button_domain = gtk_radio_button_new_with_label(NULL, "Domain");
1166 if (state->name_type_initial == NetSetupDomainName) {
1167 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button_domain), TRUE);
1169 gtk_box_pack_start(GTK_BOX(vbox), button_domain, TRUE, TRUE, 0);
1170 g_signal_connect(G_OBJECT(button_domain), "clicked",
1171 G_CALLBACK(callback_do_join_domain),
1175 gtk_entry_set_max_length(GTK_ENTRY(state->entry_domain), 50);
1176 g_signal_connect(G_OBJECT(state->entry_domain), "changed",
1177 G_CALLBACK(callback_enter_domain_and_unlock),
1179 g_signal_connect(G_OBJECT(state->entry_domain), "activate",
1180 G_CALLBACK(callback_continue),
1182 if (state->name_type_initial == NetSetupDomainName) {
1183 gtk_entry_set_text(GTK_ENTRY(state->entry_domain),
1184 state->name_buffer_initial);
1185 gtk_widget_set_sensitive(state->entry_workgroup, FALSE);
1186 gtk_widget_set_sensitive(state->entry_domain, TRUE);
1188 gtk_editable_set_editable(GTK_EDITABLE(state->entry_domain), TRUE);
1189 gtk_box_pack_start(GTK_BOX(vbox), state->entry_domain, TRUE, TRUE, 0);
1190 gtk_widget_show(state->entry_domain);
1192 gtk_widget_show(button_domain);
1195 group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button_domain));
1196 button_workgroup = gtk_radio_button_new_with_label(group, "Workgroup");
1197 if (state->name_type_initial == NetSetupWorkgroupName) {
1198 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button_workgroup), TRUE);
1200 gtk_box_pack_start(GTK_BOX(vbox), button_workgroup, TRUE, TRUE, 0);
1201 g_signal_connect(G_OBJECT(button_workgroup), "clicked",
1202 G_CALLBACK(callback_do_join_workgroup),
1205 gtk_entry_set_max_length(GTK_ENTRY(state->entry_workgroup),
1206 MAX_NETBIOS_NAME_LEN);
1207 g_signal_connect(G_OBJECT(state->entry_workgroup), "changed",
1208 G_CALLBACK(callback_enter_workgroup_and_unlock),
1210 g_signal_connect(G_OBJECT(state->entry_workgroup), "activate",
1211 G_CALLBACK(callback_continue),
1214 if (state->name_type_initial == NetSetupWorkgroupName) {
1215 gtk_entry_set_text(GTK_ENTRY(state->entry_workgroup),
1216 state->name_buffer_initial);
1217 gtk_widget_set_sensitive(GTK_WIDGET(state->entry_domain), FALSE);
1218 gtk_widget_set_sensitive(GTK_WIDGET(state->entry_workgroup), TRUE);
1220 gtk_box_pack_start(GTK_BOX(vbox), state->entry_workgroup, TRUE, TRUE, 0);
1221 gtk_widget_show(state->entry_workgroup);
1223 gtk_widget_show(button_workgroup);
1225 /* Advanced Options */
1226 frame_horz = gtk_frame_new("Advanced Options");
1227 gtk_box_pack_start(GTK_BOX(box1), frame_horz, TRUE, TRUE, 10);
1229 vbox = gtk_vbox_new(FALSE, 0);
1230 gtk_container_set_border_width(GTK_CONTAINER(vbox), 10);
1231 gtk_container_add(GTK_CONTAINER(frame_horz), vbox);
1234 gtk_container_add(GTK_CONTAINER(vbox), state->button_get_ous);
1235 gtk_widget_set_sensitive(GTK_WIDGET(state->button_get_ous), FALSE);
1236 g_signal_connect(G_OBJECT(state->button_get_ous), "clicked",
1237 G_CALLBACK(callback_do_getous),
1240 state->entry_ou_list = gtk_combo_box_entry_new_text();
1241 gtk_widget_set_sensitive(state->entry_ou_list, FALSE);
1242 if (state->name_type_initial == NetSetupWorkgroupName) {
1243 gtk_widget_set_sensitive(state->entry_ou_list, FALSE);
1244 gtk_widget_set_sensitive(state->button_get_ous, FALSE);
1246 gtk_box_pack_start(GTK_BOX(vbox), state->entry_ou_list, TRUE, TRUE, 0);
1247 gtk_widget_show(state->entry_ou_list);
1250 state->label_winbind = gtk_check_button_new_with_label("Modify winbind configuration");
1251 gtk_box_pack_start(GTK_BOX(vbox), state->label_winbind, TRUE, TRUE, 0);
1252 gtk_widget_set_sensitive(state->label_winbind, FALSE);
1257 bbox = gtk_hbutton_box_new();
1258 gtk_container_set_border_width(GTK_CONTAINER(bbox), 5);
1259 gtk_container_add(GTK_CONTAINER(box1), bbox);
1260 gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);
1261 gtk_box_set_spacing(GTK_BOX(bbox), 10);
1263 state->window_do_change = window;
1264 gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), FALSE);
1265 gtk_container_add(GTK_CONTAINER(bbox), state->button_ok);
1266 g_signal_connect(G_OBJECT(state->button_ok), "clicked",
1267 G_CALLBACK(callback_do_join),
1270 button = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
1271 gtk_container_add(GTK_CONTAINER(bbox), button);
1272 g_signal_connect(G_OBJECT(button), "clicked",
1273 G_CALLBACK(callback_do_freeauth_and_close),
1276 gtk_widget_show_all(window);
1279 static void callback_do_about(GtkWidget *widget,
1283 GError *error = NULL;
1286 debug("callback_do_about called\n");
1288 logo = gdk_pixbuf_new_from_file(SAMBA_IMAGE_PATH,
1291 g_print("failed to load logo from %s: %s\n",
1292 SAMBA_IMAGE_PATH, error->message);
1295 about = gtk_about_dialog_new();
1296 gtk_about_dialog_set_name(GTK_ABOUT_DIALOG(about), "Samba");
1297 gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(about), "3.2.0pre3");
1298 gtk_about_dialog_set_copyright(GTK_ABOUT_DIALOG(about),
1299 "Copyright Andrew Tridgell and the Samba Team 1992-2008\n"
1300 "Copyright Günther Deschner 2007-2008");
1301 gtk_about_dialog_set_license(GTK_ABOUT_DIALOG(about), "GPLv3");
1302 gtk_about_dialog_set_website(GTK_ABOUT_DIALOG(about), "http://www.samba.org");
1303 gtk_about_dialog_set_website_label(GTK_ABOUT_DIALOG(about), "http://www.samba.org");
1305 gtk_about_dialog_set_logo(GTK_ABOUT_DIALOG(about), logo);
1307 gtk_about_dialog_set_comments(GTK_ABOUT_DIALOG(about), "Samba gtk domain join utility");
1308 gtk_window_set_modal(GTK_WINDOW(about), TRUE);
1309 g_signal_connect_swapped(about, "response",
1310 G_CALLBACK(gtk_widget_destroy),
1313 gtk_widget_show(about);
1316 static int draw_main_window(struct join_state *state)
1321 GtkWidget *main_vbox;
1329 GError *error = NULL;
1331 icon = gdk_pixbuf_new_from_file(SAMBA_ICON_PATH,
1334 g_print("failed to load icon from %s : %s\n",
1335 SAMBA_ICON_PATH, error->message);
1339 image = gtk_image_new_from_file(SAMBA_IMAGE_PATH_SMALL);
1341 image = gtk_image_new_from_file("/usr/share/pixmaps/redhat-system_settings.png");
1343 if (image == NULL) {
1344 g_print("failed to load logo from %s : %s\n",
1345 SAMBA_IMAGE_PATH_SMALL, error->message);
1348 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
1349 state->window_main = window;
1351 gtk_window_set_title(GTK_WINDOW(window), "Samba - Join Domain dialogue");
1352 gtk_widget_set_size_request(GTK_WIDGET(window), 600, 600);
1353 gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
1354 gtk_window_set_icon_from_file(GTK_WINDOW(window), SAMBA_ICON_PATH, NULL);
1356 g_signal_connect(G_OBJECT(window), "delete_event",
1357 G_CALLBACK(callback_delete_event), NULL);
1359 gtk_container_set_border_width(GTK_CONTAINER(window), 10);
1361 main_vbox = gtk_vbox_new(FALSE, 10);
1362 gtk_container_add(GTK_CONTAINER(window), main_vbox);
1365 gtk_box_pack_start(GTK_BOX(main_vbox), image, TRUE, TRUE, 10);
1366 gtk_widget_show(image);
1369 hbox = gtk_hbox_new(FALSE, 10);
1370 gtk_container_add(GTK_CONTAINER(main_vbox), hbox);
1373 /* gtk_box_pack_start(GTK_BOX(main_vbox), image, TRUE, TRUE, 10); */
1374 /* gtk_misc_set_alignment(GTK_MISC(image), 0, 0); */
1375 gtk_widget_set_size_request(GTK_WIDGET(image), 150, 40);
1376 gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 10);
1377 gtk_widget_show(image);
1380 label = gtk_label_new("Samba uses the following information to identify your computer on the network.");
1381 /* gtk_misc_set_alignment(GTK_MISC(label), 0, 0); */
1382 gtk_widget_set_size_request(GTK_WIDGET(label), 400, 40);
1383 gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
1384 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
1385 gtk_widget_show(label);
1388 gtk_widget_show(hbox);
1390 vbox = gtk_vbox_new(FALSE, 0);
1391 gtk_container_set_border_width(GTK_CONTAINER(vbox), 10);
1392 gtk_container_add(GTK_CONTAINER(main_vbox), vbox);
1395 table = gtk_table_new(6, 3, TRUE);
1396 gtk_table_set_row_spacings(GTK_TABLE(table), 5);
1397 gtk_table_set_col_spacings(GTK_TABLE(table), 5);
1398 gtk_container_add(GTK_CONTAINER(vbox), table);
1402 label = gtk_label_new("Computer description:");
1403 gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
1404 gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 0, 1);
1405 gtk_widget_show(label);
1407 state->button_apply = gtk_button_new_from_stock(GTK_STOCK_APPLY);
1410 entry = gtk_entry_new();
1411 gtk_entry_set_max_length(GTK_ENTRY(entry), 256);
1412 g_signal_connect(G_OBJECT(entry), "changed",
1413 G_CALLBACK(callback_enter_computer_description_and_unlock),
1415 g_signal_connect(G_OBJECT(entry), "activate",
1416 G_CALLBACK(callback_apply_continue),
1419 gtk_entry_set_text(GTK_ENTRY(entry), (char *)state->comment);
1420 gtk_editable_set_editable(GTK_EDITABLE(entry), TRUE); /* ! */
1421 gtk_table_attach_defaults(GTK_TABLE(table), entry, 1, 3, 0, 1);
1422 gtk_widget_show(entry);
1426 label = gtk_label_new("For example: \"Samba \%v\".");
1427 gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
1428 gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
1429 gtk_table_attach_defaults(GTK_TABLE(table), label, 1, 3, 1, 2);
1430 gtk_widget_show(label);
1433 label = gtk_label_new("Full computer name:");
1434 gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
1435 gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 2, 3);
1436 gtk_widget_show(label);
1441 if (state->name_type_initial == NetSetupDomainName) {
1442 if (asprintf(&str, "%s.%s", state->my_hostname,
1443 state->my_dnsdomain) == -1) {
1447 if (asprintf(&str, "%s.", state->my_hostname) == -1) {
1452 label = gtk_label_new(str);
1454 gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
1455 gtk_table_attach_defaults(GTK_TABLE(table), label, 1, 3, 2, 3);
1456 gtk_widget_show(label);
1460 if (state->name_type_initial == NetSetupDomainName) {
1461 label = gtk_label_new("Domain:");
1463 label = gtk_label_new("Workgroup:");
1465 gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
1466 gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 3, 4);
1467 gtk_widget_show(label);
1468 state->label_current_name_type = label;
1471 label = gtk_label_new(state->name_buffer_initial);
1472 gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
1473 gtk_table_attach_defaults(GTK_TABLE(table), label, 1, 3, 3, 4);
1474 gtk_widget_show(label);
1475 state->label_current_name_buffer = label;
1478 hbox = gtk_hbox_new(FALSE, 0);
1479 gtk_container_add(GTK_CONTAINER(vbox), hbox);
1480 label = gtk_label_new("To rename this computer or join a domain, click Change.");
1481 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
1487 bbox = gtk_hbutton_box_new();
1488 gtk_container_set_border_width(GTK_CONTAINER(bbox), 5);
1489 gtk_container_add(GTK_CONTAINER(hbox), bbox);
1490 gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);
1491 gtk_box_set_spacing(GTK_BOX(bbox), 10);
1493 button = gtk_button_new_with_mnemonic("Ch_ange");
1494 g_signal_connect(G_OBJECT(button), "clicked",
1495 G_CALLBACK(callback_do_change),
1497 gtk_box_pack_start(GTK_BOX(bbox), button, TRUE, TRUE, 0);
1498 gtk_widget_show(button);
1500 /* Label (hidden) */
1501 state->label_reboot = gtk_label_new(NULL);
1502 gtk_label_set_line_wrap(GTK_LABEL(state->label_reboot), TRUE);
1503 gtk_misc_set_alignment(GTK_MISC(state->label_reboot), 0, 0);
1504 gtk_box_pack_start(GTK_BOX(vbox), state->label_reboot, TRUE, TRUE, 0);
1505 gtk_widget_show(state->label_reboot);
1508 gtk_box_pack_start(GTK_BOX(vbox),
1509 create_bbox(window, TRUE, NULL, 10, 85, 20, GTK_BUTTONBOX_END),
1518 frame = gtk_frame_new(NULL);
1519 bbox2 = gtk_hbutton_box_new();
1521 gtk_container_set_border_width(GTK_CONTAINER(bbox2), 5);
1522 gtk_container_add(GTK_CONTAINER(frame), bbox2);
1524 /* Set the appearance of the Button Box */
1525 gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox2), GTK_BUTTONBOX_END);
1526 gtk_box_set_spacing(GTK_BOX(bbox2), 10);
1527 /*gtk_button_box_set_child_size(GTK_BUTTON_BOX(bbox2), child_w, child_h);*/
1529 button2 = gtk_button_new_from_stock(GTK_STOCK_OK);
1530 gtk_container_add(GTK_CONTAINER(bbox2), button2);
1531 g_signal_connect(G_OBJECT(button2), "clicked", G_CALLBACK(callback_do_exit), state);
1533 button2 = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
1534 gtk_container_add(GTK_CONTAINER(bbox2), button2);
1535 g_signal_connect(G_OBJECT(button2), "clicked",
1536 G_CALLBACK(callback_delete_event),
1539 gtk_container_add(GTK_CONTAINER(bbox2), state->button_apply);
1540 g_signal_connect(G_OBJECT(state->button_apply), "clicked",
1541 G_CALLBACK(callback_apply_description_change),
1543 gtk_widget_set_sensitive(GTK_WIDGET(state->button_apply), FALSE);
1545 button2 = gtk_button_new_from_stock(GTK_STOCK_ABOUT);
1546 gtk_container_add(GTK_CONTAINER(bbox2), button2);
1547 g_signal_connect(G_OBJECT(button2), "clicked",
1548 G_CALLBACK(callback_do_about),
1551 button2 = gtk_button_new_from_stock(GTK_STOCK_HELP);
1552 gtk_container_add(GTK_CONTAINER(bbox2), button2);
1553 g_signal_connect(G_OBJECT(button2), "clicked",
1554 G_CALLBACK(callback_do_about),
1557 gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 5);
1560 gtk_widget_show_all(window);
1565 static int init_join_state(struct join_state **state)
1567 struct join_state *s;
1569 s = (struct join_state *)malloc(sizeof(struct join_state));
1574 memset(s, '\0', sizeof(struct join_state));
1581 static int initialize_join_state(struct join_state *state,
1582 const char *debug_level)
1584 struct libnetapi_ctx *ctx = NULL;
1585 NET_API_STATUS status = 0;
1587 status = libnetapi_init(&ctx);
1593 libnetapi_set_debuglevel(ctx, debug_level);
1597 char my_hostname[HOST_NAME_MAX];
1598 const char *p = NULL;
1599 struct hostent *hp = NULL;
1601 if (gethostname(my_hostname, sizeof(my_hostname)) == -1) {
1605 p = strchr(my_hostname, '.');
1607 my_hostname[strlen(my_hostname)-strlen(p)] = '\0';
1609 state->my_hostname = strdup(my_hostname);
1610 if (!state->my_hostname) {
1613 debug("state->my_hostname: %s\n", state->my_hostname);
1615 hp = gethostbyname(my_hostname);
1616 if (!hp || !hp->h_name || !*hp->h_name) {
1620 state->my_fqdn = strdup(hp->h_name);
1621 if (!state->my_fqdn) {
1624 debug("state->my_fqdn: %s\n", state->my_fqdn);
1626 p = strchr(state->my_fqdn, '.');
1629 state->my_dnsdomain = strdup(p);
1631 state->my_dnsdomain = strdup("");
1633 if (!state->my_dnsdomain) {
1636 debug("state->my_dnsdomain: %s\n", state->my_dnsdomain);
1640 const char *buffer = NULL;
1642 status = NetGetJoinInformation(NULL, &buffer, &type);
1644 printf("NetGetJoinInformation failed with: %s\n",
1645 libnetapi_get_error_string(state->ctx, status));
1648 debug("NetGetJoinInformation gave: %s and %d\n", buffer, type);
1649 state->name_buffer_initial = strdup(buffer);
1650 if (!state->name_buffer_initial) {
1653 state->name_type_initial = type;
1654 NetApiBufferFree((void *)buffer);
1658 struct SERVER_INFO_1005 *info1005 = NULL;
1659 uint8_t *buffer = NULL;
1661 status = NetServerGetInfo(NULL, 1005, &buffer);
1663 printf("NetServerGetInfo failed with: %s\n",
1664 libnetapi_get_error_string(state->ctx, status));
1668 info1005 = (struct SERVER_INFO_1005 *)buffer;
1670 state->comment = strdup(info1005->sv1005_comment);
1671 if (!state->comment) {
1674 NetApiBufferFree(buffer);
1678 struct srvsvc_NetSrvInfo100 *info100 = NULL;
1679 uint8_t *buffer = NULL;
1681 status = NetServerGetInfo(NULL, 100, &buffer);
1686 info100 = (struct srvsvc_NetSrvInfo100 *)buffer;
1688 state->comment = strdup(info100->comment);
1689 if (!state->comment) {
1700 int main(int argc, char **argv)
1702 GOptionContext *context = NULL;
1703 static const char *debug_level = NULL;
1704 struct join_state *state = NULL;
1705 GError *error = NULL;
1708 static GOptionEntry entries[] = {
1709 { "debug", 'd', 0, G_OPTION_ARG_STRING, &debug_level, "Debug level (for samba)", "N" },
1710 { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "Verbose output", 0 },
1714 context = g_option_context_new("- Samba domain join utility");
1715 g_option_context_add_main_entries(context, entries, NULL);
1716 /* g_option_context_add_main_entries(context, entries, GETTEXT_PACKAGE); */
1717 g_option_context_add_group(context, gtk_get_option_group(TRUE));
1718 g_option_context_parse(context, &argc, &argv, &error);
1720 gtk_init(&argc, &argv);
1721 g_set_application_name("Samba");
1723 ret = init_join_state(&state);
1728 ret = initialize_join_state(state, debug_level);
1733 draw_main_window(state);