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 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 static gboolean verbose = FALSE;
53 typedef struct join_state {
54 struct libnetapi_ctx *ctx;
55 GtkWidget *window_main;
56 GtkWidget *window_parent;
57 GtkWidget *window_do_change;
58 GtkWidget *window_creds_prompt;
59 GtkWidget *entry_account;
60 GtkWidget *entry_password;
61 GtkWidget *entry_domain;
62 GtkWidget *entry_ou_list;
63 GtkWidget *entry_workgroup;
65 GtkWidget *button_apply;
66 GtkWidget *button_ok_creds;
67 GtkWidget *button_get_ous;
68 GtkWidget *label_reboot;
69 GtkWidget *label_current_name_buffer;
70 GtkWidget *label_current_name_type;
71 GtkWidget *label_full_computer_name;
72 GtkWidget *label_winbind;
73 uint16_t name_type_initial;
74 uint16_t name_type_new;
75 char *name_buffer_initial;
76 char *name_buffer_new;
85 gboolean settings_changed;
86 gboolean hostname_changed;
89 static void debug(const char *format, ...)
97 va_start(args, format);
98 g_vprintf(format, args);
102 static gboolean callback_delete_event(GtkWidget *widget,
110 static void callback_do_close(GtkWidget *widget,
113 debug("callback_do_close called\n");
115 gtk_widget_destroy(data);
118 static void callback_do_freeauth(GtkWidget *widget,
121 struct join_state *state = (struct join_state *)data;
123 debug("callback_do_freeauth called\n");
125 SAFE_FREE(state->account);
126 SAFE_FREE(state->password);
128 if (state->window_creds_prompt) {
129 gtk_widget_destroy(state->window_creds_prompt);
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 gtk_widget_destroy(state->window_creds_prompt);
144 gtk_widget_destroy(state->window_do_change);
147 static void free_join_state(struct join_state *s)
149 SAFE_FREE(s->name_buffer_initial);
150 SAFE_FREE(s->name_buffer_new);
151 SAFE_FREE(s->password);
152 SAFE_FREE(s->account);
153 SAFE_FREE(s->comment);
154 SAFE_FREE(s->comment_new);
155 SAFE_FREE(s->my_fqdn);
156 SAFE_FREE(s->my_dnsdomain);
157 SAFE_FREE(s->my_hostname);
160 static void do_cleanup(struct join_state *state)
162 libnetapi_free(state->ctx);
163 free_join_state(state);
166 static void callback_apply_description_change(GtkWidget *widget,
169 struct join_state *state = (struct join_state *)data;
170 NET_API_STATUS status = 0;
171 uint32_t parm_err = 0;
172 struct SERVER_INFO_1005 info1005;
175 info1005.sv1005_comment = state->comment_new;
177 status = NetServerSetInfo(NULL, 1005, (uint8_t *)&info1005, &parm_err);
179 debug("NetServerSetInfo failed with: %s\n",
180 libnetapi_errstr(status));
181 dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_main),
182 GTK_DIALOG_DESTROY_WITH_PARENT,
185 "Failed to change computer description: %s.",
186 libnetapi_get_error_string(state->ctx, status));
187 gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
189 g_signal_connect_swapped(dialog, "response",
190 G_CALLBACK(gtk_widget_destroy),
193 gtk_widget_show(dialog);
197 gtk_widget_set_sensitive(GTK_WIDGET(state->button_apply), FALSE);
200 static void callback_do_exit(GtkWidget *widget,
205 struct join_state *state = (struct join_state *)data;
207 if (!state->settings_changed) {
208 callback_delete_event(NULL, NULL, NULL);
212 dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_main),
213 GTK_DIALOG_DESTROY_WITH_PARENT,
214 GTK_MESSAGE_QUESTION,
216 "You must restart your computer before the new settings will take effect.");
217 gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
218 result = gtk_dialog_run(GTK_DIALOG(dialog));
220 case GTK_RESPONSE_YES:
221 g_print("would reboot here\n");
223 case GTK_RESPONSE_NO:
227 gtk_widget_destroy(dialog);
228 gtk_widget_destroy(state->window_main);
234 static void callback_do_reboot(GtkWidget *widget,
239 struct join_state *state = (struct join_state *)data2;
241 debug("callback_do_reboot\n");
243 state->settings_changed = TRUE;
244 dialog = gtk_message_dialog_new(GTK_WINDOW(data),
245 GTK_DIALOG_DESTROY_WITH_PARENT,
248 "You must restart this computer for the changes to take effect.");
249 gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
251 g_signal_connect_swapped(dialog, "response",
252 G_CALLBACK(gtk_widget_destroy),
255 debug("showing dialog\n");
256 gtk_widget_show(dialog);
258 gtk_dialog_run(GTK_DIALOG(dialog));
259 gtk_widget_destroy(dialog);
262 gtk_label_set_text(GTK_LABEL(state->label_reboot),
263 "Changes will take effect after you restart this computer");
265 debug("destroying do_change window\n");
266 gtk_widget_destroy(GTK_WIDGET(state->window_do_change));
273 status = NetGetJoinInformation(NULL, &buffer, &type);
275 g_print("failed to query status\n");
279 debug("got new status: %s\n", buffer);
281 SAFE_FREE(state->name_buffer_new);
282 state->name_buffer_new = strdup(buffer);
284 state->name_type_new = type;
286 NetApiBufferFree((void *)buffer);
288 gtk_label_set_text(GTK_LABEL(state->label_current_name_buffer),
289 state->name_buffer_new);
290 if (state->name_type_new == NetSetupDomainName) {
291 gtk_label_set_text(GTK_LABEL(state->label_current_name_type),
294 gtk_label_set_text(GTK_LABEL(state->label_current_name_type),
300 static void callback_return_username(GtkWidget *widget,
303 const gchar *entry_text;
304 struct join_state *state = (struct join_state *)data;
305 debug("callback_return_username called\n");
309 entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
313 debug("callback_return_username: %s\n", entry_text);
314 SAFE_FREE(state->account);
315 state->account = strdup(entry_text);
318 static void callback_return_username_and_enter(GtkWidget *widget,
321 const gchar *entry_text;
322 struct join_state *state = (struct join_state *)data;
326 entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
330 debug("callback_return_username_and_enter: %s\n", entry_text);
331 SAFE_FREE(state->account);
332 state->account = strdup(entry_text);
333 g_signal_emit_by_name(state->button_ok_creds, "clicked");
336 static void callback_return_password(GtkWidget *widget,
339 const gchar *entry_text;
340 struct join_state *state = (struct join_state *)data;
341 debug("callback_return_password called\n");
345 entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
349 #ifdef DEBUG_PASSWORD
350 debug("callback_return_password: %s\n", entry_text);
352 debug("callback_return_password: (not printed)\n");
354 SAFE_FREE(state->password);
355 state->password = strdup(entry_text);
358 static void callback_return_password_and_enter(GtkWidget *widget,
361 const gchar *entry_text;
362 struct join_state *state = (struct join_state *)data;
366 entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
370 #ifdef DEBUG_PASSWORD
371 debug("callback_return_password_and_enter: %s\n", entry_text);
373 debug("callback_return_password_and_enter: (not printed)\n");
375 SAFE_FREE(state->password);
376 state->password = strdup(entry_text);
377 g_signal_emit_by_name(state->button_ok_creds, "clicked");
380 static void callback_do_storeauth(GtkWidget *widget,
383 struct join_state *state = (struct join_state *)data;
385 debug("callback_do_storeauth called\n");
387 SAFE_FREE(state->account);
388 SAFE_FREE(state->password);
390 callback_return_username(state->entry_account, state);
391 callback_return_password(state->entry_password, state);
393 gtk_widget_destroy(state->window_creds_prompt);
396 static void callback_continue(GtkWidget *widget,
399 struct join_state *state = (struct join_state *)data;
401 gtk_widget_grab_focus(GTK_WIDGET(state->button_ok));
402 g_signal_emit_by_name(state->button_ok, "clicked");
405 static void callback_do_storeauth_and_continue(GtkWidget *widget,
408 callback_do_storeauth(widget, data);
409 callback_continue(NULL, data);
412 static void callback_do_storeauth_and_scan(GtkWidget *widget,
415 struct join_state *state = (struct join_state *)data;
416 callback_do_storeauth(widget, data);
417 g_signal_emit_by_name(state->button_get_ous, "clicked");
420 static void callback_do_hostname_change(GtkWidget *widget,
424 const char *str = NULL;
426 struct join_state *state = (struct join_state *)data;
428 switch (state->name_type_initial) {
429 case NetSetupDomainName:
430 str = "To be implemented: call NetRenameMachineInDomain\n";
432 case NetSetupWorkgroupName:
433 str = "To be implemented: call SetComputerNameEx\n";
439 dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_parent),
440 GTK_DIALOG_DESTROY_WITH_PARENT,
445 gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
446 g_signal_connect_swapped(dialog, "response",
447 G_CALLBACK(gtk_widget_destroy),
449 gtk_widget_show(dialog);
452 static void callback_creds_prompt(GtkWidget *widget,
454 const char *label_string,
463 struct join_state *state = (struct join_state *)data;
465 debug("callback_creds_prompt\n");
467 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
468 gtk_window_set_modal(GTK_WINDOW(window), TRUE);
470 gtk_window_set_title(GTK_WINDOW(window), "Computer Name Changes");
471 gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
472 gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
473 gtk_widget_set_size_request(GTK_WIDGET(window), 380, 280);
474 gtk_window_set_icon_from_file(GTK_WINDOW(window), SAMBA_ICON_PATH, NULL);
476 g_signal_connect(G_OBJECT(window), "delete_event",
477 G_CALLBACK(callback_do_close), window);
479 state->window_creds_prompt = window;
480 gtk_container_set_border_width(GTK_CONTAINER(window), 10);
482 box1 = gtk_vbox_new(FALSE, 0);
484 gtk_container_add(GTK_CONTAINER(window), box1);
486 label = gtk_label_new(label_string);
487 gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
488 gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
490 gtk_box_pack_start(GTK_BOX(box1), label, FALSE, FALSE, 0);
492 gtk_widget_show(label);
495 label = gtk_label_new("User name:");
496 gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
497 gtk_box_pack_start(GTK_BOX(box1), label, FALSE, FALSE, 0);
498 gtk_widget_show(label);
500 state->entry_account = gtk_entry_new();
501 gtk_entry_set_max_length(GTK_ENTRY(state->entry_account), MAX_CRED_LEN);
502 g_signal_connect(G_OBJECT(state->entry_account), "activate",
503 G_CALLBACK(callback_return_username_and_enter),
505 gtk_editable_select_region(GTK_EDITABLE(state->entry_account),
506 0, GTK_ENTRY(state->entry_account)->text_length);
507 gtk_box_pack_start(GTK_BOX(box1), state->entry_account, TRUE, TRUE, 0);
508 gtk_widget_show(state->entry_account);
511 label = gtk_label_new("Password:");
512 gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
513 gtk_box_pack_start(GTK_BOX(box1), label, FALSE, FALSE, 0);
514 gtk_widget_show(label);
516 state->entry_password = gtk_entry_new();
517 gtk_entry_set_max_length(GTK_ENTRY(state->entry_password), MAX_CRED_LEN);
518 gtk_entry_set_visibility(GTK_ENTRY(state->entry_password), FALSE);
519 g_signal_connect(G_OBJECT(state->entry_password), "activate",
520 G_CALLBACK(callback_return_password_and_enter),
522 gtk_editable_set_editable(GTK_EDITABLE(state->entry_password), TRUE);
523 gtk_editable_select_region(GTK_EDITABLE(state->entry_password),
524 0, GTK_ENTRY(state->entry_password)->text_length);
525 gtk_box_pack_start(GTK_BOX(box1), state->entry_password, TRUE, TRUE, 0);
526 gtk_widget_show(state->entry_password);
529 bbox = gtk_hbutton_box_new();
530 gtk_container_set_border_width(GTK_CONTAINER(bbox), 5);
531 gtk_container_add(GTK_CONTAINER(box1), bbox);
532 gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);
533 gtk_box_set_spacing(GTK_BOX(bbox), 10);
535 state->button_ok_creds = gtk_button_new_from_stock(GTK_STOCK_OK);
536 gtk_widget_grab_focus(GTK_WIDGET(state->button_ok_creds));
537 gtk_container_add(GTK_CONTAINER(bbox), state->button_ok_creds);
538 g_signal_connect(G_OBJECT(state->button_ok_creds), "clicked",
541 gtk_widget_show(state->button_ok_creds);
543 button = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
544 gtk_container_add(GTK_CONTAINER(bbox), button);
545 g_signal_connect(G_OBJECT(button), "clicked",
546 G_CALLBACK(callback_do_freeauth),
548 gtk_widget_show_all(window);
551 static void callback_do_join(GtkWidget *widget,
556 NET_API_STATUS status;
557 const char *err_str = NULL;
558 uint32_t join_flags = 0;
559 uint32_t unjoin_flags = 0;
560 gboolean domain_join = FALSE;
561 gboolean try_unjoin = FALSE;
562 gboolean join_creds_required = TRUE;
563 gboolean unjoin_creds_required = TRUE;
564 const char *new_workgroup_type = NULL;
565 const char *initial_workgroup_type = NULL;
566 const char *account_ou = NULL;
568 struct join_state *state = (struct join_state *)data;
570 if (state->hostname_changed) {
571 callback_do_hostname_change(NULL, state);
575 switch (state->name_type_initial) {
576 case NetSetupWorkgroupName:
577 initial_workgroup_type = "workgroup";
579 case NetSetupDomainName:
580 initial_workgroup_type = "domain";
586 switch (state->name_type_new) {
587 case NetSetupWorkgroupName:
588 new_workgroup_type = "workgroup";
590 case NetSetupDomainName:
591 new_workgroup_type = "domain";
597 account_ou = gtk_combo_box_get_active_text(GTK_COMBO_BOX(state->entry_ou_list));
598 if (account_ou && strlen(account_ou) == 0) {
602 if ((state->name_type_initial != NetSetupDomainName) &&
603 (state->name_type_new != NetSetupDomainName)) {
604 join_creds_required = FALSE;
605 unjoin_creds_required = FALSE;
608 if (state->name_type_new == NetSetupDomainName) {
610 join_creds_required = TRUE;
611 join_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
612 WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE |
613 WKSSVC_JOIN_FLAGS_DOMAIN_JOIN_IF_JOINED; /* for testing */
616 if ((state->name_type_initial == NetSetupDomainName) &&
617 (state->name_type_new == NetSetupWorkgroupName)) {
619 unjoin_creds_required = TRUE;
620 join_creds_required = FALSE;
621 unjoin_flags = WKSSVC_JOIN_FLAGS_JOIN_TYPE |
622 WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE;
627 debug("callback_do_join: Unjoining\n");
629 if (unjoin_creds_required) {
630 if (!state->account || !state->password) {
631 debug("callback_do_join: no creds yet\n");
632 callback_creds_prompt(NULL, state,
633 "Enter the name and password of an account with permission to leave the domain.",
634 callback_do_storeauth_and_continue);
637 if (!state->account || !state->password) {
638 debug("callback_do_join: still no creds???\n");
643 status = NetUnjoinDomain(NULL,
648 callback_do_freeauth(NULL, state);
649 err_str = libnetapi_get_error_string(state->ctx, status);
650 g_print("callback_do_join: failed to unjoin (%s)\n",
653 dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_parent),
654 GTK_DIALOG_DESTROY_WITH_PARENT,
657 "The following error occured attempting to unjoin the %s: \"%s\": %s",
658 initial_workgroup_type,
659 state->name_buffer_initial,
661 gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
662 gtk_dialog_run(GTK_DIALOG(dialog));
663 gtk_widget_destroy(dialog);
668 if (join_creds_required) {
669 if (!state->account || !state->password) {
670 debug("callback_do_join: no creds yet\n");
671 callback_creds_prompt(NULL, state,
672 "Enter the name and password of an account with permission to leave the domain.",
673 callback_do_storeauth_and_continue);
676 if (!state->account || !state->password) {
677 debug("callback_do_join: still no creds???\n");
682 debug("callback_do_join: Joining a %s named %s using join_flags 0x%08x ",
684 state->name_buffer_new,
687 debug("as %s ", state->account);
688 #ifdef DEBUG_PASSWORD
689 debug("with %s ", state->password);
694 status = NetJoinDomain(NULL,
695 state->name_buffer_new,
701 callback_do_freeauth(NULL, state);
702 err_str = libnetapi_get_error_string(state->ctx, status);
703 g_print("callback_do_join: failed to join (%s)\n", err_str);
705 dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_parent),
706 GTK_DIALOG_DESTROY_WITH_PARENT,
709 "The following error occured attempting to join the %s: \"%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);
724 debug("callback_do_join: Successfully joined %s\n",
727 callback_do_freeauth(NULL, state);
728 dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_parent),
729 GTK_DIALOG_DESTROY_WITH_PARENT,
732 "Welcome to the %s %s.",
733 state->name_buffer_new,
736 gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
737 gtk_dialog_run(GTK_DIALOG(dialog));
738 gtk_widget_destroy(dialog);
740 callback_do_reboot(NULL, state->window_parent, state);
743 static void callback_enter_hostname_and_unlock(GtkWidget *widget,
746 const gchar *entry_text = NULL;
748 struct join_state *state = (struct join_state *)data;
750 entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
751 debug("callback_enter_hostname_and_unlock: %s\n", entry_text);
752 if (!entry_text || entry_text[0] == 0) {
753 state->hostname_changed = FALSE;
754 gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), FALSE);
757 if (strcasecmp(state->my_hostname, entry_text) == 0) {
758 state->hostname_changed = FALSE;
759 gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), FALSE);
762 state->hostname_changed = TRUE;
763 if (state->name_type_initial == NetSetupDomainName) {
764 asprintf(&str, "%s.%s", entry_text, state->my_dnsdomain);
766 asprintf(&str, "%s.", entry_text);
768 gtk_label_set_text(GTK_LABEL(state->label_full_computer_name), str);
771 if (state->hostname_changed && str && str[0] != 0 && str[0] != '.') {
772 gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), TRUE);
776 static void callback_enter_computer_description_and_unlock(GtkWidget *widget,
779 const gchar *entry_text = NULL;
780 struct join_state *state = (struct join_state *)data;
781 int string_unchanged = 0;
783 entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
784 debug("callback_enter_computer_description_and_unlock: %s\n",
787 if (!entry_text || entry_text[0] == 0) {
788 string_unchanged = 1;
789 gtk_widget_set_sensitive(GTK_WIDGET(state->button_apply),
794 if (entry_text && strcasecmp(state->comment, entry_text) == 0) {
795 string_unchanged = 1;
796 gtk_widget_set_sensitive(GTK_WIDGET(state->button_apply),
801 gtk_widget_set_sensitive(GTK_WIDGET(state->button_apply), TRUE);
802 SAFE_FREE(state->comment_new);
803 state->comment_new = strdup(entry_text);
808 static void callback_enter_workgroup_and_unlock(GtkWidget *widget,
811 const gchar *entry_text = NULL;
812 struct join_state *state = (struct join_state *)data;
814 entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
815 debug("callback_enter_workgroup_and_unlock: %s\n", entry_text);
816 if (!entry_text || entry_text[0] == 0) {
817 gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), FALSE);
820 if (strcasecmp(state->name_buffer_initial, entry_text) == 0) {
821 gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), FALSE);
824 gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), TRUE);
825 SAFE_FREE(state->name_buffer_new);
826 state->name_buffer_new = strdup(entry_text);
827 state->name_type_new = NetSetupWorkgroupName;
830 static void callback_enter_domain_and_unlock(GtkWidget *widget,
833 const gchar *entry_text = NULL;
834 struct join_state *state = (struct join_state *)data;
836 entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
837 debug("callback_enter_domain_and_unlock: %s\n", entry_text);
838 if (!entry_text || entry_text[0] == 0) {
839 gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), FALSE);
842 if (strcasecmp(state->name_buffer_initial, entry_text) == 0) {
843 gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), FALSE);
846 gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), TRUE);
847 gtk_widget_set_sensitive(GTK_WIDGET(state->entry_ou_list), TRUE);
848 gtk_widget_set_sensitive(GTK_WIDGET(state->button_get_ous), TRUE);
849 SAFE_FREE(state->name_buffer_new);
850 state->name_buffer_new = strdup(entry_text);
851 state->name_type_new = NetSetupDomainName;
854 static void callback_apply_continue(GtkWidget *widget,
857 struct join_state *state = (struct join_state *)data;
859 gtk_widget_grab_focus(GTK_WIDGET(state->button_apply));
860 g_signal_emit_by_name(state->button_apply, "clicked");
863 static void callback_do_join_workgroup(GtkWidget *widget,
866 struct join_state *state = (struct join_state *)data;
867 debug("callback_do_join_workgroup choosen\n");
868 gtk_widget_set_sensitive(GTK_WIDGET(state->entry_workgroup), TRUE);
869 gtk_widget_grab_focus(GTK_WIDGET(state->entry_workgroup));
870 gtk_widget_set_sensitive(GTK_WIDGET(state->entry_domain), FALSE);
871 gtk_widget_set_sensitive(GTK_WIDGET(state->entry_ou_list), FALSE);
872 gtk_widget_set_sensitive(GTK_WIDGET(state->button_get_ous), FALSE);
873 callback_enter_workgroup_and_unlock(state->entry_workgroup, state); /* TEST */
876 static void callback_do_join_domain(GtkWidget *widget,
879 struct join_state *state = (struct join_state *)data;
880 debug("callback_do_join_domain choosen\n");
881 gtk_widget_set_sensitive(GTK_WIDGET(state->entry_domain), TRUE);
882 gtk_widget_grab_focus(GTK_WIDGET(state->entry_domain));
883 gtk_widget_set_sensitive(GTK_WIDGET(state->entry_workgroup), FALSE);
884 callback_enter_domain_and_unlock(state->entry_domain, state); /* TEST */
887 static void callback_do_getous(GtkWidget *widget,
890 NET_API_STATUS status;
891 uint32_t num_ous = 0;
892 const char **ous = NULL;
894 const char *domain = NULL;
896 struct join_state *state = (struct join_state *)data;
898 debug("callback_do_getous called\n");
900 domain = state->name_buffer_new ? state->name_buffer_new : state->name_buffer_initial;
902 if (!state->account || !state->password) {
903 debug("callback_do_getous: no creds yet\n");
904 callback_creds_prompt(NULL, state,
905 "Enter the name and password of an account with permission to join the domain.",
906 callback_do_storeauth_and_scan);
909 if (!state->account || !state->password) {
910 debug("callback_do_getous: still no creds ???\n");
914 status = NetGetJoinableOUs(NULL, domain,
918 if (status != NET_API_STATUS_SUCCESS) {
920 callback_do_freeauth(NULL, state);
921 debug("failed to call NetGetJoinableOUs: %s\n",
922 libnetapi_get_error_string(state->ctx, status));
923 dialog = gtk_message_dialog_new(NULL,
924 GTK_DIALOG_DESTROY_WITH_PARENT,
927 "Failed to query joinable OUs: %s",
928 libnetapi_get_error_string(state->ctx, status));
929 gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
930 gtk_dialog_run(GTK_DIALOG(dialog));
931 gtk_widget_destroy(dialog);
935 for (i=0; i<num_ous && ous[i] != NULL; i++) {
936 gtk_combo_box_append_text(GTK_COMBO_BOX(state->entry_ou_list),
939 NetApiBufferFree(ous);
940 gtk_combo_box_set_active(GTK_COMBO_BOX(state->entry_ou_list), num_ous-1);
943 static void callback_do_change(GtkWidget *widget,
949 GtkWidget *button_workgroup;
950 GtkWidget *button_domain;
953 GtkWidget *frame_horz;
958 struct join_state *state = (struct join_state *)data;
960 debug("callback_do_change called\n");
963 /* FIXME: add proper warnings for Samba as a DC */
964 if (state->server_role == 3) {
966 callback_do_freeauth(NULL, state);
967 dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_main),
968 GTK_DIALOG_DESTROY_WITH_PARENT,
971 "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.");
972 gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
973 g_signal_connect_swapped(dialog, "response",
974 G_CALLBACK(gtk_widget_destroy),
977 gtk_widget_show(dialog);
982 state->button_ok = gtk_button_new_from_stock(GTK_STOCK_OK);
983 state->button_get_ous = gtk_button_new_with_label("Scan for joinable OUs");
984 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
985 gtk_window_set_modal(GTK_WINDOW(window), TRUE);
987 gtk_window_set_title(GTK_WINDOW(window), "Computer Name Changes");
988 gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
989 gtk_widget_set_size_request(GTK_WIDGET(window), 480, 650);
990 gtk_window_set_icon_from_file(GTK_WINDOW(window), SAMBA_ICON_PATH, NULL);
992 g_signal_connect(G_OBJECT(window), "delete_event",
993 G_CALLBACK(callback_do_close), window);
995 gtk_container_set_border_width(GTK_CONTAINER(window), 10);
997 box1 = gtk_vbox_new(FALSE, 0);
998 gtk_container_add(GTK_CONTAINER(window), box1);
1000 label = gtk_label_new("You can change the name and membership of this computer. Changes may affect access to network ressources.");
1001 gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
1002 gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
1003 gtk_box_pack_start(GTK_BOX(box1), label, TRUE, TRUE, 0);
1004 gtk_widget_show(label);
1007 label = gtk_label_new("Computer name:");
1008 gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
1009 gtk_box_pack_start(GTK_BOX(box1), label, TRUE, TRUE, 0);
1010 gtk_widget_show(label);
1012 state->label_full_computer_name = gtk_label_new(NULL);
1014 entry = gtk_entry_new();
1015 gtk_entry_set_max_length(GTK_ENTRY(entry), MAX_NETBIOS_NAME_LEN);
1016 g_signal_connect(G_OBJECT(entry), "changed",
1017 G_CALLBACK(callback_enter_hostname_and_unlock),
1019 gtk_entry_set_text(GTK_ENTRY(entry), state->my_hostname);
1020 gtk_editable_select_region(GTK_EDITABLE(entry),
1021 0, GTK_ENTRY(entry)->text_length);
1023 gtk_editable_set_editable(GTK_EDITABLE(entry), TRUE); /* ! */
1024 gtk_box_pack_start(GTK_BOX(box1), entry, TRUE, TRUE, 0);
1025 gtk_widget_show(entry);
1028 /* FULL COMPUTER NAME */
1029 label = gtk_label_new("Full computer name:");
1030 gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
1031 gtk_box_pack_start(GTK_BOX(box1), label, TRUE, TRUE, 0);
1032 gtk_widget_show(label);
1035 const gchar *entry_text;
1037 entry_text = gtk_entry_get_text(GTK_ENTRY(entry));
1038 if (state->name_type_initial == NetSetupDomainName) {
1039 asprintf(&str, "%s.%s", entry_text,
1040 state->my_dnsdomain);
1042 asprintf(&str, "%s.", entry_text);
1044 gtk_label_set_text(GTK_LABEL(state->label_full_computer_name),
1047 gtk_misc_set_alignment(GTK_MISC(state->label_full_computer_name), 0, 0);
1048 gtk_box_pack_start(GTK_BOX(box1),
1049 state->label_full_computer_name, TRUE, TRUE, 0);
1050 gtk_widget_show(state->label_full_computer_name);
1054 frame_horz = gtk_frame_new ("Member Of");
1055 gtk_box_pack_start(GTK_BOX(box1), frame_horz, TRUE, TRUE, 10);
1057 vbox = gtk_vbox_new(FALSE, 0);
1058 gtk_container_set_border_width(GTK_CONTAINER(vbox), 10);
1059 gtk_container_add(GTK_CONTAINER(frame_horz), vbox);
1062 state->entry_workgroup = gtk_entry_new();
1063 state->entry_domain = gtk_entry_new();
1066 button_domain = gtk_radio_button_new_with_label(NULL, "Domain");
1067 if (state->name_type_initial == NetSetupDomainName) {
1068 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button_domain), TRUE);
1070 gtk_box_pack_start(GTK_BOX(vbox), button_domain, TRUE, TRUE, 0);
1071 g_signal_connect(G_OBJECT(button_domain), "clicked",
1072 G_CALLBACK(callback_do_join_domain),
1076 gtk_entry_set_max_length(GTK_ENTRY(state->entry_domain), 50);
1077 g_signal_connect(G_OBJECT(state->entry_domain), "changed",
1078 G_CALLBACK(callback_enter_domain_and_unlock),
1080 g_signal_connect(G_OBJECT(state->entry_domain), "activate",
1081 G_CALLBACK(callback_continue),
1083 if (state->name_type_initial == NetSetupDomainName) {
1084 gtk_entry_set_text(GTK_ENTRY(state->entry_domain),
1085 state->name_buffer_initial);
1086 gtk_widget_set_sensitive(state->entry_workgroup, FALSE);
1087 gtk_widget_set_sensitive(state->entry_domain, TRUE);
1089 gtk_editable_set_editable(GTK_EDITABLE(state->entry_domain), TRUE);
1090 gtk_box_pack_start(GTK_BOX(vbox), state->entry_domain, TRUE, TRUE, 0);
1091 gtk_widget_show(state->entry_domain);
1093 gtk_widget_show(button_domain);
1096 group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button_domain));
1097 button_workgroup = gtk_radio_button_new_with_label(group, "Workgroup");
1098 if (state->name_type_initial == NetSetupWorkgroupName) {
1099 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button_workgroup), TRUE);
1101 gtk_box_pack_start(GTK_BOX(vbox), button_workgroup, TRUE, TRUE, 0);
1102 g_signal_connect(G_OBJECT(button_workgroup), "clicked",
1103 G_CALLBACK(callback_do_join_workgroup),
1106 gtk_entry_set_max_length(GTK_ENTRY(state->entry_workgroup),
1107 MAX_NETBIOS_NAME_LEN);
1108 g_signal_connect(G_OBJECT(state->entry_workgroup), "changed",
1109 G_CALLBACK(callback_enter_workgroup_and_unlock),
1111 g_signal_connect(G_OBJECT(state->entry_workgroup), "activate",
1112 G_CALLBACK(callback_continue),
1115 if (state->name_type_initial == NetSetupWorkgroupName) {
1116 gtk_entry_set_text(GTK_ENTRY(state->entry_workgroup),
1117 state->name_buffer_initial);
1118 gtk_widget_set_sensitive(GTK_WIDGET(state->entry_domain), FALSE);
1119 gtk_widget_set_sensitive(GTK_WIDGET(state->entry_workgroup), TRUE);
1121 gtk_box_pack_start(GTK_BOX(vbox), state->entry_workgroup, TRUE, TRUE, 0);
1122 gtk_widget_show(state->entry_workgroup);
1124 gtk_widget_show(button_workgroup);
1126 /* Advanced Options */
1127 frame_horz = gtk_frame_new("Advanced Options");
1128 gtk_box_pack_start(GTK_BOX(box1), frame_horz, TRUE, TRUE, 10);
1130 vbox = gtk_vbox_new(FALSE, 0);
1131 gtk_container_set_border_width(GTK_CONTAINER(vbox), 10);
1132 gtk_container_add(GTK_CONTAINER(frame_horz), vbox);
1135 gtk_container_add(GTK_CONTAINER(vbox), state->button_get_ous);
1136 gtk_widget_set_sensitive(GTK_WIDGET(state->button_get_ous), FALSE);
1137 g_signal_connect(G_OBJECT(state->button_get_ous), "clicked",
1138 G_CALLBACK(callback_do_getous),
1141 state->entry_ou_list = gtk_combo_box_entry_new_text();
1142 gtk_widget_set_sensitive(state->entry_ou_list, FALSE);
1143 if (state->name_type_initial == NetSetupWorkgroupName) {
1144 gtk_widget_set_sensitive(state->entry_ou_list, FALSE);
1145 gtk_widget_set_sensitive(state->button_get_ous, FALSE);
1147 gtk_box_pack_start(GTK_BOX(vbox), state->entry_ou_list, TRUE, TRUE, 0);
1148 gtk_widget_show(state->entry_ou_list);
1151 state->label_winbind = gtk_check_button_new_with_label("Modify winbind configuration");
1152 gtk_box_pack_start(GTK_BOX(vbox), state->label_winbind, TRUE, TRUE, 0);
1153 gtk_widget_set_sensitive(state->label_winbind, FALSE);
1158 bbox = gtk_hbutton_box_new();
1159 gtk_container_set_border_width(GTK_CONTAINER(bbox), 5);
1160 gtk_container_add(GTK_CONTAINER(box1), bbox);
1161 gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);
1162 gtk_box_set_spacing(GTK_BOX(bbox), 10);
1164 state->window_do_change = window;
1165 gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), FALSE);
1166 gtk_container_add(GTK_CONTAINER(bbox), state->button_ok);
1167 g_signal_connect(G_OBJECT(state->button_ok), "clicked",
1168 G_CALLBACK(callback_do_join),
1171 button = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
1172 gtk_container_add(GTK_CONTAINER(bbox), button);
1173 g_signal_connect(G_OBJECT(button), "clicked",
1174 G_CALLBACK(callback_do_freeauth_and_close),
1177 gtk_widget_show_all(window);
1180 static void callback_do_about(GtkWidget *widget,
1184 GError *error = NULL;
1187 debug("callback_do_about called\n");
1189 logo = gdk_pixbuf_new_from_file(SAMBA_IMAGE_PATH,
1192 g_print("failed to load logo from %s: %s\n",
1193 SAMBA_IMAGE_PATH, error->message);
1196 about = gtk_about_dialog_new();
1197 gtk_about_dialog_set_name(GTK_ABOUT_DIALOG(about), "Samba");
1198 gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(about), "3.2.0pre3");
1199 gtk_about_dialog_set_copyright(GTK_ABOUT_DIALOG(about),
1200 "Copyright Andrew Tridgell and the Samba Team 1992-2008\n"
1201 "Copyright Günther Deschner 2007-2008");
1202 gtk_about_dialog_set_license(GTK_ABOUT_DIALOG(about), "GPLv3");
1203 gtk_about_dialog_set_website(GTK_ABOUT_DIALOG(about), "http://www.samba.org");
1204 gtk_about_dialog_set_website_label(GTK_ABOUT_DIALOG(about), "http://www.samba.org");
1206 gtk_about_dialog_set_logo(GTK_ABOUT_DIALOG(about), logo);
1208 gtk_about_dialog_set_comments(GTK_ABOUT_DIALOG(about), "Samba gtk domain join utility");
1209 gtk_window_set_modal(GTK_WINDOW(about), TRUE);
1210 g_signal_connect_swapped(about, "response",
1211 G_CALLBACK(gtk_widget_destroy),
1214 gtk_widget_show(about);
1217 static int draw_main_window(struct join_state *state)
1222 GtkWidget *main_vbox;
1230 GError *error = NULL;
1232 icon = gdk_pixbuf_new_from_file(SAMBA_ICON_PATH,
1235 g_print("failed to load icon from %s : %s\n",
1236 SAMBA_ICON_PATH, error->message);
1240 image = gtk_image_new_from_file(SAMBA_IMAGE_PATH_SMALL);
1242 image = gtk_image_new_from_file("/usr/share/pixmaps/redhat-system_settings.png");
1244 if (image == NULL) {
1245 g_print("failed to load logo from %s : %s\n",
1246 SAMBA_IMAGE_PATH_SMALL, error->message);
1249 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
1250 state->window_main = window;
1252 gtk_window_set_title(GTK_WINDOW(window), "Samba - Join Domain dialogue");
1253 gtk_widget_set_size_request(GTK_WIDGET(window), 600, 600);
1254 gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
1255 gtk_window_set_icon_from_file(GTK_WINDOW(window), SAMBA_ICON_PATH, NULL);
1257 g_signal_connect(G_OBJECT(window), "delete_event",
1258 G_CALLBACK(callback_delete_event), NULL);
1260 gtk_container_set_border_width(GTK_CONTAINER(window), 10);
1262 main_vbox = gtk_vbox_new(FALSE, 10);
1263 gtk_container_add(GTK_CONTAINER(window), main_vbox);
1266 gtk_box_pack_start(GTK_BOX(main_vbox), image, TRUE, TRUE, 10);
1267 gtk_widget_show(image);
1270 hbox = gtk_hbox_new(FALSE, 10);
1271 gtk_container_add(GTK_CONTAINER(main_vbox), hbox);
1274 /* gtk_box_pack_start(GTK_BOX(main_vbox), image, TRUE, TRUE, 10); */
1275 /* gtk_misc_set_alignment(GTK_MISC(image), 0, 0); */
1276 gtk_widget_set_size_request(GTK_WIDGET(image), 150, 40);
1277 gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 10);
1278 gtk_widget_show(image);
1281 label = gtk_label_new("Samba uses the following information to identify your computer on the network.");
1282 /* gtk_misc_set_alignment(GTK_MISC(label), 0, 0); */
1283 gtk_widget_set_size_request(GTK_WIDGET(label), 400, 40);
1284 gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
1285 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
1286 gtk_widget_show(label);
1289 gtk_widget_show(hbox);
1291 vbox = gtk_vbox_new(FALSE, 0);
1292 gtk_container_set_border_width(GTK_CONTAINER(vbox), 10);
1293 gtk_container_add(GTK_CONTAINER(main_vbox), vbox);
1296 table = gtk_table_new(6, 3, TRUE);
1297 gtk_table_set_row_spacings(GTK_TABLE(table), 5);
1298 gtk_table_set_col_spacings(GTK_TABLE(table), 5);
1299 gtk_container_add(GTK_CONTAINER(vbox), table);
1303 label = gtk_label_new("Computer description:");
1304 /* gtk_misc_set_alignment(GTK_MISC(label), 0, 0); */
1305 gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 0, 1);
1306 gtk_widget_show(label);
1308 state->button_apply = gtk_button_new_from_stock(GTK_STOCK_APPLY);
1311 entry = gtk_entry_new();
1312 gtk_entry_set_max_length(GTK_ENTRY(entry), 256);
1313 g_signal_connect(G_OBJECT(entry), "changed",
1314 G_CALLBACK(callback_enter_computer_description_and_unlock),
1316 g_signal_connect(G_OBJECT(entry), "activate",
1317 G_CALLBACK(callback_apply_continue),
1320 gtk_entry_set_text(GTK_ENTRY(entry), (char *)state->comment);
1321 gtk_editable_set_editable(GTK_EDITABLE(entry), TRUE); /* ! */
1322 gtk_table_attach_defaults(GTK_TABLE(table), entry, 1, 3, 0, 1);
1323 gtk_widget_show(entry);
1327 label = gtk_label_new("For example: \"Samba \%v\".");
1328 gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
1329 gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
1330 gtk_table_attach_defaults(GTK_TABLE(table), label, 1, 3, 1, 2);
1331 gtk_widget_show(label);
1334 label = gtk_label_new("Full computer name:");
1335 gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
1336 gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 2, 3);
1337 gtk_widget_show(label);
1342 if (state->name_type_initial == NetSetupDomainName) {
1343 asprintf(&str, "%s.%s", state->my_hostname,
1344 state->my_dnsdomain);
1346 asprintf(&str, "%s.", state->my_hostname);
1349 label = gtk_label_new(str);
1351 gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
1352 gtk_table_attach_defaults(GTK_TABLE(table), label, 1, 3, 2, 3);
1353 gtk_widget_show(label);
1357 if (state->name_type_initial == NetSetupDomainName) {
1358 label = gtk_label_new("Domain:");
1360 label = gtk_label_new("Workgroup:");
1362 gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
1363 gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 3, 4);
1364 gtk_widget_show(label);
1365 state->label_current_name_type = label;
1368 label = gtk_label_new(state->name_buffer_initial);
1369 gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
1370 gtk_table_attach_defaults(GTK_TABLE(table), label, 1, 3, 3, 4);
1371 gtk_widget_show(label);
1372 state->label_current_name_buffer = label;
1375 hbox = gtk_hbox_new(FALSE, 0);
1376 gtk_container_add(GTK_CONTAINER(vbox), hbox);
1377 label = gtk_label_new("To rename this computer or join a domain, click Change.");
1378 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
1384 bbox = gtk_hbutton_box_new();
1385 gtk_container_set_border_width(GTK_CONTAINER(bbox), 5);
1386 gtk_container_add(GTK_CONTAINER(hbox), bbox);
1387 gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);
1388 gtk_box_set_spacing(GTK_BOX(bbox), 10);
1390 button = gtk_button_new_with_mnemonic("Ch_ange");
1391 g_signal_connect(G_OBJECT(button), "clicked",
1392 G_CALLBACK(callback_do_change),
1394 gtk_box_pack_start(GTK_BOX(bbox), button, TRUE, TRUE, 0);
1395 gtk_widget_show(button);
1397 /* Label (hidden) */
1398 state->label_reboot = gtk_label_new(NULL);
1399 gtk_label_set_line_wrap(GTK_LABEL(state->label_reboot), TRUE);
1400 gtk_misc_set_alignment(GTK_MISC(state->label_reboot), 0, 0);
1401 gtk_box_pack_start(GTK_BOX(vbox), state->label_reboot, TRUE, TRUE, 0);
1402 gtk_widget_show(state->label_reboot);
1405 gtk_box_pack_start(GTK_BOX(vbox),
1406 create_bbox(window, TRUE, NULL, 10, 85, 20, GTK_BUTTONBOX_END),
1415 frame = gtk_frame_new(NULL);
1416 bbox2 = gtk_hbutton_box_new();
1418 gtk_container_set_border_width(GTK_CONTAINER(bbox2), 5);
1419 gtk_container_add(GTK_CONTAINER(frame), bbox2);
1421 /* Set the appearance of the Button Box */
1422 gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox2), GTK_BUTTONBOX_END);
1423 gtk_box_set_spacing(GTK_BOX(bbox2), 10);
1424 /*gtk_button_box_set_child_size(GTK_BUTTON_BOX(bbox2), child_w, child_h);*/
1426 button2 = gtk_button_new_from_stock(GTK_STOCK_OK);
1427 gtk_container_add(GTK_CONTAINER(bbox2), button2);
1428 g_signal_connect(G_OBJECT(button2), "clicked", G_CALLBACK(callback_do_exit), state);
1430 button2 = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
1431 gtk_container_add(GTK_CONTAINER(bbox2), button2);
1432 g_signal_connect(G_OBJECT(button2), "clicked",
1433 G_CALLBACK(callback_delete_event),
1436 gtk_container_add(GTK_CONTAINER(bbox2), state->button_apply);
1437 g_signal_connect(G_OBJECT(state->button_apply), "clicked",
1438 G_CALLBACK(callback_apply_description_change),
1440 gtk_widget_set_sensitive(GTK_WIDGET(state->button_apply), FALSE);
1442 button2 = gtk_button_new_from_stock(GTK_STOCK_ABOUT);
1443 gtk_container_add(GTK_CONTAINER(bbox2), button2);
1444 g_signal_connect(G_OBJECT(button2), "clicked",
1445 G_CALLBACK(callback_do_about),
1448 button2 = gtk_button_new_from_stock(GTK_STOCK_HELP);
1449 gtk_container_add(GTK_CONTAINER(bbox2), button2);
1450 g_signal_connect(G_OBJECT(button2), "clicked",
1451 G_CALLBACK(callback_do_about),
1454 gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 5);
1457 gtk_widget_show_all(window);
1462 static int init_join_state(struct join_state **state)
1464 struct join_state *s;
1466 s = malloc(sizeof(struct join_state));
1471 memset(s, '\0', sizeof(struct join_state));
1478 static int initialize_join_state(struct join_state *state,
1479 const char *debug_level)
1481 struct libnetapi_ctx *ctx = NULL;
1482 NET_API_STATUS status = 0;
1484 status = libnetapi_init(&ctx);
1490 libnetapi_set_debuglevel(ctx, debug_level);
1494 char my_hostname[HOST_NAME_MAX];
1495 const char *p = NULL;
1496 struct hostent *hp = NULL;
1498 if (gethostname(my_hostname, sizeof(my_hostname)) == -1) {
1502 p = strchr(my_hostname, '.');
1504 my_hostname[strlen(my_hostname)-strlen(p)] = '\0';
1506 state->my_hostname = strdup(my_hostname);
1507 if (!state->my_hostname) {
1510 debug("state->my_hostname: %s\n", state->my_hostname);
1512 hp = gethostbyname(my_hostname);
1513 if (!hp || !hp->h_name || !*hp->h_name) {
1517 state->my_fqdn = strdup(hp->h_name);
1518 if (!state->my_fqdn) {
1521 debug("state->my_fqdn: %s\n", state->my_fqdn);
1523 p = strchr(state->my_fqdn, '.');
1526 state->my_dnsdomain = strdup(p);
1528 state->my_dnsdomain = strdup("");
1530 if (!state->my_dnsdomain) {
1533 debug("state->my_dnsdomain: %s\n", state->my_dnsdomain);
1537 const char *buffer = NULL;
1539 status = NetGetJoinInformation(NULL, &buffer, &type);
1541 printf("NetGetJoinInformation failed with: %s\n",
1542 libnetapi_get_error_string(state->ctx, status));
1545 debug("NetGetJoinInformation gave: %s and %d\n", buffer, type);
1546 state->name_buffer_initial = strdup(buffer);
1547 if (!state->name_buffer_initial) {
1550 state->name_type_initial = type;
1551 NetApiBufferFree((void *)buffer);
1555 struct SERVER_INFO_1005 *info1005 = NULL;
1556 uint8_t *buffer = NULL;
1558 status = NetServerGetInfo(NULL, 1005, &buffer);
1560 printf("NetServerGetInfo failed with: %s\n",
1561 libnetapi_get_error_string(state->ctx, status));
1565 info1005 = (struct SERVER_INFO_1005 *)buffer;
1567 state->comment = strdup(info1005->sv1005_comment);
1568 if (!state->comment) {
1571 NetApiBufferFree(buffer);
1575 struct srvsvc_NetSrvInfo100 *info100 = NULL;
1576 uint8_t *buffer = NULL;
1578 status = NetServerGetInfo(NULL, 100, &buffer);
1583 info100 = (struct srvsvc_NetSrvInfo100 *)buffer;
1585 state->comment = strdup(info100->comment);
1586 if (!state->comment) {
1597 int main(int argc, char **argv)
1599 GOptionContext *context = NULL;
1600 static const char *debug_level = NULL;
1601 struct join_state *state = NULL;
1602 GError *error = NULL;
1605 static GOptionEntry entries[] = {
1606 { "debug", 'd', 0, G_OPTION_ARG_STRING, &debug_level, "Debug level (for samba)", "N" },
1607 { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "Verbose output", 0 },
1611 context = g_option_context_new("- Samba domain join utility");
1612 g_option_context_add_main_entries(context, entries, NULL);
1613 /* g_option_context_add_main_entries(context, entries, GETTEXT_PACKAGE); */
1614 g_option_context_add_group(context, gtk_get_option_group(TRUE));
1615 g_option_context_parse(context, &argc, &argv, &error);
1617 gtk_init(&argc, &argv);
1618 g_set_application_name("Samba");
1620 ret = init_join_state(&state);
1625 ret = initialize_join_state(state, debug_level);
1630 draw_main_window(state);