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
;
87 uint32_t stored_num_ous
;
90 static void debug(const char *format
, ...)
98 va_start(args
, format
);
99 g_vprintf(format
, args
);
103 static gboolean
callback_delete_event(GtkWidget
*widget
,
111 static void callback_do_close(GtkWidget
*widget
,
114 debug("callback_do_close called\n");
117 gtk_widget_destroy(GTK_WIDGET(data
));
122 static void callback_do_freeauth(GtkWidget
*widget
,
125 struct join_state
*state
= (struct join_state
*)data
;
127 debug("callback_do_freeauth called\n");
129 SAFE_FREE(state
->account
);
130 SAFE_FREE(state
->password
);
132 if (state
->window_creds_prompt
) {
133 gtk_widget_destroy(GTK_WIDGET(state
->window_creds_prompt
));
134 state
->window_creds_prompt
= NULL
;
138 static void callback_do_freeauth_and_close(GtkWidget
*widget
,
141 struct join_state
*state
= (struct join_state
*)data
;
143 debug("callback_do_freeauth_and_close called\n");
145 SAFE_FREE(state
->account
);
146 SAFE_FREE(state
->password
);
148 if (state
->window_creds_prompt
) {
149 gtk_widget_destroy(GTK_WIDGET(state
->window_creds_prompt
));
150 state
->window_creds_prompt
= NULL
;
152 if (state
->window_do_change
) {
153 gtk_widget_destroy(GTK_WIDGET(state
->window_do_change
));
154 state
->window_do_change
= NULL
;
158 static void free_join_state(struct join_state
*s
)
160 SAFE_FREE(s
->name_buffer_initial
);
161 SAFE_FREE(s
->name_buffer_new
);
162 SAFE_FREE(s
->password
);
163 SAFE_FREE(s
->account
);
164 SAFE_FREE(s
->comment
);
165 SAFE_FREE(s
->comment_new
);
166 SAFE_FREE(s
->my_fqdn
);
167 SAFE_FREE(s
->my_dnsdomain
);
168 SAFE_FREE(s
->my_hostname
);
171 static void do_cleanup(struct join_state
*state
)
173 libnetapi_free(state
->ctx
);
174 free_join_state(state
);
177 static void callback_apply_description_change(GtkWidget
*widget
,
180 struct join_state
*state
= (struct join_state
*)data
;
181 NET_API_STATUS status
= 0;
182 uint32_t parm_err
= 0;
183 struct SERVER_INFO_1005 info1005
;
186 info1005
.sv1005_comment
= state
->comment_new
;
188 status
= NetServerSetInfo(NULL
, 1005, (uint8_t *)&info1005
, &parm_err
);
190 debug("NetServerSetInfo failed with: %s\n",
191 libnetapi_errstr(status
));
192 dialog
= gtk_message_dialog_new(GTK_WINDOW(state
->window_main
),
193 GTK_DIALOG_DESTROY_WITH_PARENT
,
196 "Failed to change computer description: %s.",
197 libnetapi_get_error_string(state
->ctx
, status
));
198 gtk_window_set_modal(GTK_WINDOW(dialog
), TRUE
);
200 g_signal_connect_swapped(dialog
, "response",
201 G_CALLBACK(gtk_widget_destroy
),
204 gtk_widget_show(dialog
);
208 gtk_widget_set_sensitive(GTK_WIDGET(state
->button_apply
), FALSE
);
211 static void callback_do_exit(GtkWidget
*widget
,
218 struct join_state
*state
= (struct join_state
*)data
;
220 if (!state
->settings_changed
) {
221 callback_delete_event(NULL
, NULL
, NULL
);
226 dialog
= gtk_message_dialog_new(GTK_WINDOW(state
->window_main
),
227 GTK_DIALOG_DESTROY_WITH_PARENT
,
228 GTK_MESSAGE_QUESTION
,
230 "You must restart your computer before the new settings will take effect.");
231 gtk_window_set_modal(GTK_WINDOW(dialog
), TRUE
);
232 result
= gtk_dialog_run(GTK_DIALOG(dialog
));
234 case GTK_RESPONSE_YES
:
235 g_print("would reboot here\n");
237 case GTK_RESPONSE_NO
:
242 gtk_widget_destroy(GTK_WIDGET(dialog
));
245 if (state
->window_main
) {
246 gtk_widget_destroy(GTK_WIDGET(state
->window_main
));
247 state
->window_main
= NULL
;
254 static void callback_do_reboot(GtkWidget
*widget
,
259 struct join_state
*state
= (struct join_state
*)data2
;
261 debug("callback_do_reboot\n");
263 state
->settings_changed
= TRUE
;
264 dialog
= gtk_message_dialog_new(GTK_WINDOW(data
),
265 GTK_DIALOG_DESTROY_WITH_PARENT
,
268 "You must restart this computer for the changes to take effect.");
269 gtk_window_set_modal(GTK_WINDOW(dialog
), TRUE
);
271 g_signal_connect_swapped(dialog
, "response",
272 G_CALLBACK(gtk_widget_destroy
),
275 debug("showing dialog\n");
276 gtk_widget_show(dialog
);
278 gtk_dialog_run(GTK_DIALOG(dialog
));
279 gtk_widget_destroy(GTK_WIDGET(dialog
));
282 gtk_label_set_text(GTK_LABEL(state
->label_reboot
),
283 "Changes will take effect after you restart this computer");
285 debug("destroying do_change window\n");
286 gtk_widget_destroy(GTK_WIDGET(state
->window_do_change
));
293 status
= NetGetJoinInformation(NULL
, &buffer
, &type
);
295 g_print("failed to query status\n");
299 debug("got new status: %s\n", buffer
);
301 SAFE_FREE(state
->name_buffer_new
);
302 state
->name_buffer_new
= strdup(buffer
);
303 state
->name_type_new
= type
;
304 state
->name_buffer_initial
= strdup(buffer
);
305 state
->name_type_initial
= type
;
306 NetApiBufferFree((void *)buffer
);
308 gtk_label_set_text(GTK_LABEL(state
->label_current_name_buffer
),
309 state
->name_buffer_new
);
310 if (state
->name_type_new
== NetSetupDomainName
) {
311 gtk_label_set_text(GTK_LABEL(state
->label_current_name_type
),
314 gtk_label_set_text(GTK_LABEL(state
->label_current_name_type
),
320 static void callback_return_username(GtkWidget
*widget
,
323 const gchar
*entry_text
;
324 struct join_state
*state
= (struct join_state
*)data
;
325 debug("callback_return_username called\n");
329 entry_text
= gtk_entry_get_text(GTK_ENTRY(widget
));
333 debug("callback_return_username: %s\n", entry_text
);
334 SAFE_FREE(state
->account
);
335 state
->account
= strdup(entry_text
);
338 static void callback_return_username_and_enter(GtkWidget
*widget
,
341 const gchar
*entry_text
;
342 struct join_state
*state
= (struct join_state
*)data
;
346 entry_text
= gtk_entry_get_text(GTK_ENTRY(widget
));
350 debug("callback_return_username_and_enter: %s\n", entry_text
);
351 SAFE_FREE(state
->account
);
352 state
->account
= strdup(entry_text
);
353 g_signal_emit_by_name(state
->button_ok_creds
, "clicked");
356 static void callback_return_password(GtkWidget
*widget
,
359 const gchar
*entry_text
;
360 struct join_state
*state
= (struct join_state
*)data
;
361 debug("callback_return_password called\n");
365 entry_text
= gtk_entry_get_text(GTK_ENTRY(widget
));
369 #ifdef DEBUG_PASSWORD
370 debug("callback_return_password: %s\n", entry_text
);
372 debug("callback_return_password: (not printed)\n");
374 SAFE_FREE(state
->password
);
375 state
->password
= strdup(entry_text
);
378 static void callback_return_password_and_enter(GtkWidget
*widget
,
381 const gchar
*entry_text
;
382 struct join_state
*state
= (struct join_state
*)data
;
386 entry_text
= gtk_entry_get_text(GTK_ENTRY(widget
));
390 #ifdef DEBUG_PASSWORD
391 debug("callback_return_password_and_enter: %s\n", entry_text
);
393 debug("callback_return_password_and_enter: (not printed)\n");
395 SAFE_FREE(state
->password
);
396 state
->password
= strdup(entry_text
);
397 g_signal_emit_by_name(state
->button_ok_creds
, "clicked");
400 static void callback_do_storeauth(GtkWidget
*widget
,
403 struct join_state
*state
= (struct join_state
*)data
;
405 debug("callback_do_storeauth called\n");
407 SAFE_FREE(state
->account
);
408 SAFE_FREE(state
->password
);
410 callback_return_username(state
->entry_account
, (gpointer
)state
);
411 callback_return_password(state
->entry_password
, (gpointer
)state
);
413 if (state
->window_creds_prompt
) {
414 gtk_widget_destroy(GTK_WIDGET(state
->window_creds_prompt
));
415 state
->window_creds_prompt
= NULL
;
419 static void callback_continue(GtkWidget
*widget
,
422 struct join_state
*state
= (struct join_state
*)data
;
424 gtk_widget_grab_focus(GTK_WIDGET(state
->button_ok
));
425 g_signal_emit_by_name(state
->button_ok
, "clicked");
428 static void callback_do_storeauth_and_continue(GtkWidget
*widget
,
431 callback_do_storeauth(widget
, data
);
432 callback_continue(NULL
, data
);
435 static void callback_do_storeauth_and_scan(GtkWidget
*widget
,
438 struct join_state
*state
= (struct join_state
*)data
;
439 callback_do_storeauth(widget
, data
);
440 g_signal_emit_by_name(state
->button_get_ous
, "clicked");
443 static void callback_do_hostname_change(GtkWidget
*widget
,
447 const char *str
= NULL
;
449 struct join_state
*state
= (struct join_state
*)data
;
451 switch (state
->name_type_initial
) {
452 case NetSetupDomainName
:
453 str
= "To be implemented: call NetRenameMachineInDomain\n";
455 case NetSetupWorkgroupName
:
456 str
= "To be implemented: call SetComputerNameEx\n";
462 dialog
= gtk_message_dialog_new(GTK_WINDOW(state
->window_parent
),
463 GTK_DIALOG_DESTROY_WITH_PARENT
,
468 gtk_window_set_modal(GTK_WINDOW(dialog
), TRUE
);
469 g_signal_connect_swapped(dialog
, "response",
470 G_CALLBACK(gtk_widget_destroy
),
472 gtk_widget_show(dialog
);
475 static void callback_creds_prompt(GtkWidget
*widget
,
477 const char *label_string
,
486 struct join_state
*state
= (struct join_state
*)data
;
488 debug("callback_creds_prompt\n");
490 window
= gtk_window_new(GTK_WINDOW_TOPLEVEL
);
491 gtk_window_set_modal(GTK_WINDOW(window
), TRUE
);
493 gtk_window_set_title(GTK_WINDOW(window
), "Computer Name Changes");
494 gtk_window_set_resizable(GTK_WINDOW(window
), FALSE
);
495 gtk_window_set_position(GTK_WINDOW(window
), GTK_WIN_POS_CENTER
);
496 gtk_widget_set_size_request(GTK_WIDGET(window
), 380, 280);
497 gtk_window_set_icon_from_file(GTK_WINDOW(window
), SAMBA_ICON_PATH
, NULL
);
499 g_signal_connect(G_OBJECT(window
), "delete_event",
500 G_CALLBACK(callback_do_close
), window
);
502 state
->window_creds_prompt
= window
;
503 gtk_container_set_border_width(GTK_CONTAINER(window
), 10);
505 box1
= gtk_vbox_new(FALSE
, 0);
507 gtk_container_add(GTK_CONTAINER(window
), box1
);
509 label
= gtk_label_new(label_string
);
510 gtk_misc_set_alignment(GTK_MISC(label
), 0, 0);
511 gtk_label_set_line_wrap(GTK_LABEL(label
), TRUE
);
513 gtk_box_pack_start(GTK_BOX(box1
), label
, FALSE
, FALSE
, 0);
515 gtk_widget_show(label
);
518 label
= gtk_label_new("User name:");
519 gtk_misc_set_alignment(GTK_MISC(label
), 0, 0);
520 gtk_box_pack_start(GTK_BOX(box1
), label
, FALSE
, FALSE
, 0);
521 gtk_widget_show(label
);
523 state
->entry_account
= gtk_entry_new();
524 gtk_entry_set_max_length(GTK_ENTRY(state
->entry_account
), MAX_CRED_LEN
);
525 g_signal_connect(G_OBJECT(state
->entry_account
), "activate",
526 G_CALLBACK(callback_return_username_and_enter
),
528 gtk_editable_select_region(GTK_EDITABLE(state
->entry_account
),
529 0, GTK_ENTRY(state
->entry_account
)->text_length
);
530 gtk_box_pack_start(GTK_BOX(box1
), state
->entry_account
, TRUE
, TRUE
, 0);
531 gtk_widget_show(state
->entry_account
);
534 label
= gtk_label_new("Password:");
535 gtk_misc_set_alignment(GTK_MISC(label
), 0, 0);
536 gtk_box_pack_start(GTK_BOX(box1
), label
, FALSE
, FALSE
, 0);
537 gtk_widget_show(label
);
539 state
->entry_password
= gtk_entry_new();
540 gtk_entry_set_max_length(GTK_ENTRY(state
->entry_password
), MAX_CRED_LEN
);
541 gtk_entry_set_visibility(GTK_ENTRY(state
->entry_password
), FALSE
);
542 g_signal_connect(G_OBJECT(state
->entry_password
), "activate",
543 G_CALLBACK(callback_return_password_and_enter
),
545 gtk_editable_set_editable(GTK_EDITABLE(state
->entry_password
), TRUE
);
546 gtk_editable_select_region(GTK_EDITABLE(state
->entry_password
),
547 0, GTK_ENTRY(state
->entry_password
)->text_length
);
548 gtk_box_pack_start(GTK_BOX(box1
), state
->entry_password
, TRUE
, TRUE
, 0);
549 gtk_widget_show(state
->entry_password
);
552 bbox
= gtk_hbutton_box_new();
553 gtk_container_set_border_width(GTK_CONTAINER(bbox
), 5);
554 gtk_container_add(GTK_CONTAINER(box1
), bbox
);
555 gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox
), GTK_BUTTONBOX_END
);
556 gtk_box_set_spacing(GTK_BOX(bbox
), 10);
558 state
->button_ok_creds
= gtk_button_new_from_stock(GTK_STOCK_OK
);
559 gtk_widget_grab_focus(GTK_WIDGET(state
->button_ok_creds
));
560 gtk_container_add(GTK_CONTAINER(bbox
), state
->button_ok_creds
);
561 g_signal_connect(G_OBJECT(state
->button_ok_creds
), "clicked",
564 gtk_widget_show(state
->button_ok_creds
);
566 button
= gtk_button_new_from_stock(GTK_STOCK_CANCEL
);
567 gtk_container_add(GTK_CONTAINER(bbox
), button
);
568 g_signal_connect(G_OBJECT(button
), "clicked",
569 G_CALLBACK(callback_do_freeauth
),
571 gtk_widget_show_all(window
);
574 static void callback_do_join(GtkWidget
*widget
,
579 NET_API_STATUS status
;
580 const char *err_str
= NULL
;
581 uint32_t join_flags
= 0;
582 uint32_t unjoin_flags
= 0;
583 gboolean domain_join
= FALSE
;
584 gboolean try_unjoin
= FALSE
;
585 gboolean join_creds_required
= TRUE
;
586 gboolean unjoin_creds_required
= TRUE
;
587 const char *new_workgroup_type
= NULL
;
588 const char *initial_workgroup_type
= NULL
;
589 const char *account_ou
= NULL
;
591 struct join_state
*state
= (struct join_state
*)data
;
593 if (state
->hostname_changed
) {
594 callback_do_hostname_change(NULL
, state
);
598 switch (state
->name_type_initial
) {
599 case NetSetupWorkgroupName
:
600 initial_workgroup_type
= "workgroup";
602 case NetSetupDomainName
:
603 initial_workgroup_type
= "domain";
609 switch (state
->name_type_new
) {
610 case NetSetupWorkgroupName
:
611 new_workgroup_type
= "workgroup";
613 case NetSetupDomainName
:
614 new_workgroup_type
= "domain";
620 account_ou
= gtk_combo_box_get_active_text(GTK_COMBO_BOX(state
->entry_ou_list
));
621 if (account_ou
&& strlen(account_ou
) == 0) {
625 if ((state
->name_type_initial
!= NetSetupDomainName
) &&
626 (state
->name_type_new
!= NetSetupDomainName
)) {
627 join_creds_required
= FALSE
;
628 unjoin_creds_required
= FALSE
;
631 if (state
->name_type_new
== NetSetupDomainName
) {
633 join_creds_required
= TRUE
;
634 join_flags
= WKSSVC_JOIN_FLAGS_JOIN_TYPE
|
635 WKSSVC_JOIN_FLAGS_ACCOUNT_CREATE
|
636 WKSSVC_JOIN_FLAGS_DOMAIN_JOIN_IF_JOINED
; /* for testing */
639 if ((state
->name_type_initial
== NetSetupDomainName
) &&
640 (state
->name_type_new
== NetSetupWorkgroupName
)) {
642 unjoin_creds_required
= TRUE
;
643 join_creds_required
= FALSE
;
644 unjoin_flags
= WKSSVC_JOIN_FLAGS_JOIN_TYPE
|
645 WKSSVC_JOIN_FLAGS_ACCOUNT_DELETE
;
650 debug("callback_do_join: Unjoining\n");
652 if (unjoin_creds_required
) {
653 if (!state
->account
|| !state
->password
) {
654 debug("callback_do_join: no creds yet\n");
655 callback_creds_prompt(NULL
, state
,
656 "Enter the name and password of an account with permission to leave the domain.",
657 callback_do_storeauth_and_continue
);
660 if (!state
->account
|| !state
->password
) {
661 debug("callback_do_join: still no creds???\n");
666 status
= NetUnjoinDomain(NULL
,
671 callback_do_freeauth(NULL
, state
);
672 err_str
= libnetapi_get_error_string(state
->ctx
, status
);
673 g_print("callback_do_join: failed to unjoin (%s)\n",
677 /* in fact we shouldn't annoy the user with an error message here */
679 dialog
= gtk_message_dialog_new(GTK_WINDOW(state
->window_parent
),
680 GTK_DIALOG_DESTROY_WITH_PARENT
,
683 "The following error occured attempting to unjoin the %s: \"%s\": %s",
684 initial_workgroup_type
,
685 state
->name_buffer_initial
,
687 gtk_window_set_modal(GTK_WINDOW(dialog
), TRUE
);
688 gtk_dialog_run(GTK_DIALOG(dialog
));
689 gtk_widget_destroy(dialog
);
695 /* before prompting for creds, make sure we can find a dc */
699 struct DOMAIN_CONTROLLER_INFO
*dc_info
= NULL
;
701 status
= DsGetDcName(NULL
,
702 state
->name_buffer_new
,
708 err_str
= libnetapi_get_error_string(state
->ctx
, status
);
709 g_print("callback_do_join: failed find dc (%s)\n", err_str
);
711 dialog
= gtk_message_dialog_new(GTK_WINDOW(state
->window_parent
),
712 GTK_DIALOG_DESTROY_WITH_PARENT
,
715 "Failed to find a domain controller for domain: \"%s\": %s",
716 state
->name_buffer_new
,
719 gtk_window_set_modal(GTK_WINDOW(dialog
), TRUE
);
720 g_signal_connect_swapped(dialog
, "response",
721 G_CALLBACK(gtk_widget_destroy
),
724 gtk_widget_show(dialog
);
730 if (join_creds_required
) {
731 if (!state
->account
|| !state
->password
) {
732 debug("callback_do_join: no creds yet\n");
733 callback_creds_prompt(NULL
, state
,
734 "Enter the name and password of an account with permission to leave the domain.",
735 callback_do_storeauth_and_continue
);
738 if (!state
->account
|| !state
->password
) {
739 debug("callback_do_join: still no creds???\n");
744 debug("callback_do_join: Joining a %s named %s using join_flags 0x%08x ",
746 state
->name_buffer_new
,
749 debug("as %s ", state
->account
);
750 #ifdef DEBUG_PASSWORD
751 debug("with %s ", state
->password
);
756 status
= NetJoinDomain(NULL
,
757 state
->name_buffer_new
,
763 callback_do_freeauth(NULL
, state
);
764 err_str
= libnetapi_get_error_string(state
->ctx
, status
);
765 g_print("callback_do_join: failed to join (%s)\n", err_str
);
767 dialog
= gtk_message_dialog_new(GTK_WINDOW(state
->window_parent
),
768 GTK_DIALOG_DESTROY_WITH_PARENT
,
771 "The following error occured attempting to join the %s: \"%s\": %s",
773 state
->name_buffer_new
,
776 gtk_window_set_modal(GTK_WINDOW(dialog
), TRUE
);
777 g_signal_connect_swapped(dialog
, "response",
778 G_CALLBACK(gtk_widget_destroy
),
781 gtk_widget_show(dialog
);
786 debug("callback_do_join: Successfully joined %s\n",
789 callback_do_freeauth(NULL
, state
);
790 dialog
= gtk_message_dialog_new(GTK_WINDOW(state
->window_parent
),
791 GTK_DIALOG_DESTROY_WITH_PARENT
,
794 "Welcome to the %s %s.",
795 state
->name_buffer_new
,
798 gtk_window_set_modal(GTK_WINDOW(dialog
), TRUE
);
799 gtk_dialog_run(GTK_DIALOG(dialog
));
800 gtk_widget_destroy(dialog
);
802 callback_do_reboot(NULL
, state
->window_parent
, state
);
805 static void callback_enter_hostname_and_unlock(GtkWidget
*widget
,
808 const gchar
*entry_text
= NULL
;
810 struct join_state
*state
= (struct join_state
*)data
;
812 entry_text
= gtk_entry_get_text(GTK_ENTRY(widget
));
813 debug("callback_enter_hostname_and_unlock: %s\n", entry_text
);
814 if (!entry_text
|| entry_text
[0] == 0) {
815 state
->hostname_changed
= FALSE
;
816 gtk_widget_set_sensitive(GTK_WIDGET(state
->button_ok
), FALSE
);
819 if (strcasecmp(state
->my_hostname
, entry_text
) == 0) {
820 state
->hostname_changed
= FALSE
;
821 gtk_widget_set_sensitive(GTK_WIDGET(state
->button_ok
), FALSE
);
824 state
->hostname_changed
= TRUE
;
825 if (state
->name_type_initial
== NetSetupDomainName
) {
826 asprintf(&str
, "%s.%s", entry_text
, state
->my_dnsdomain
);
828 asprintf(&str
, "%s.", entry_text
);
830 gtk_label_set_text(GTK_LABEL(state
->label_full_computer_name
), str
);
833 if (state
->hostname_changed
&& str
&& str
[0] != 0 && str
[0] != '.') {
834 gtk_widget_set_sensitive(GTK_WIDGET(state
->button_ok
), TRUE
);
838 static void callback_enter_computer_description_and_unlock(GtkWidget
*widget
,
841 const gchar
*entry_text
= NULL
;
842 struct join_state
*state
= (struct join_state
*)data
;
843 int string_unchanged
= 0;
845 entry_text
= gtk_entry_get_text(GTK_ENTRY(widget
));
846 debug("callback_enter_computer_description_and_unlock: %s\n",
849 if (!entry_text
|| entry_text
[0] == 0) {
850 string_unchanged
= 1;
851 gtk_widget_set_sensitive(GTK_WIDGET(state
->button_apply
),
856 if (entry_text
&& strcasecmp(state
->comment
, entry_text
) == 0) {
857 string_unchanged
= 1;
858 gtk_widget_set_sensitive(GTK_WIDGET(state
->button_apply
),
863 gtk_widget_set_sensitive(GTK_WIDGET(state
->button_apply
), TRUE
);
864 SAFE_FREE(state
->comment_new
);
865 state
->comment_new
= strdup(entry_text
);
870 static void callback_enter_workgroup_and_unlock(GtkWidget
*widget
,
873 const gchar
*entry_text
= NULL
;
874 struct join_state
*state
= (struct join_state
*)data
;
876 entry_text
= gtk_entry_get_text(GTK_ENTRY(widget
));
877 debug("callback_enter_workgroup_and_unlock: %s\n", entry_text
);
878 if (!entry_text
|| entry_text
[0] == 0) {
879 gtk_widget_set_sensitive(GTK_WIDGET(state
->button_ok
), FALSE
);
882 if (strcasecmp(state
->name_buffer_initial
, entry_text
) == 0) {
883 gtk_widget_set_sensitive(GTK_WIDGET(state
->button_ok
), FALSE
);
886 gtk_widget_set_sensitive(GTK_WIDGET(state
->button_ok
), TRUE
);
887 SAFE_FREE(state
->name_buffer_new
);
888 state
->name_buffer_new
= strdup(entry_text
);
889 state
->name_type_new
= NetSetupWorkgroupName
;
892 static void callback_enter_domain_and_unlock(GtkWidget
*widget
,
895 const gchar
*entry_text
= NULL
;
896 struct join_state
*state
= (struct join_state
*)data
;
898 entry_text
= gtk_entry_get_text(GTK_ENTRY(widget
));
899 debug("callback_enter_domain_and_unlock: %s\n", entry_text
);
900 if (!entry_text
|| entry_text
[0] == 0) {
901 gtk_widget_set_sensitive(GTK_WIDGET(state
->button_ok
), FALSE
);
904 if (strcasecmp(state
->name_buffer_initial
, entry_text
) == 0) {
905 gtk_widget_set_sensitive(GTK_WIDGET(state
->button_ok
), FALSE
);
908 gtk_widget_set_sensitive(GTK_WIDGET(state
->button_ok
), TRUE
);
909 gtk_widget_set_sensitive(GTK_WIDGET(state
->entry_ou_list
), TRUE
);
910 gtk_widget_set_sensitive(GTK_WIDGET(state
->button_get_ous
), TRUE
);
911 SAFE_FREE(state
->name_buffer_new
);
912 state
->name_buffer_new
= strdup(entry_text
);
913 state
->name_type_new
= NetSetupDomainName
;
916 static void callback_apply_continue(GtkWidget
*widget
,
919 struct join_state
*state
= (struct join_state
*)data
;
921 gtk_widget_grab_focus(GTK_WIDGET(state
->button_apply
));
922 g_signal_emit_by_name(state
->button_apply
, "clicked");
925 static void callback_do_join_workgroup(GtkWidget
*widget
,
928 struct join_state
*state
= (struct join_state
*)data
;
929 debug("callback_do_join_workgroup choosen\n");
930 gtk_widget_set_sensitive(GTK_WIDGET(state
->entry_workgroup
), TRUE
);
931 gtk_widget_grab_focus(GTK_WIDGET(state
->entry_workgroup
));
932 gtk_widget_set_sensitive(GTK_WIDGET(state
->entry_domain
), FALSE
);
933 gtk_widget_set_sensitive(GTK_WIDGET(state
->entry_ou_list
), FALSE
);
934 gtk_widget_set_sensitive(GTK_WIDGET(state
->button_get_ous
), FALSE
);
935 callback_enter_workgroup_and_unlock(state
->entry_workgroup
, state
); /* TEST */
938 static void callback_do_join_domain(GtkWidget
*widget
,
941 struct join_state
*state
= (struct join_state
*)data
;
942 debug("callback_do_join_domain choosen\n");
943 gtk_widget_set_sensitive(GTK_WIDGET(state
->entry_domain
), TRUE
);
944 gtk_widget_grab_focus(GTK_WIDGET(state
->entry_domain
));
945 gtk_widget_set_sensitive(GTK_WIDGET(state
->entry_workgroup
), FALSE
);
946 callback_enter_domain_and_unlock(state
->entry_domain
, state
); /* TEST */
949 static void callback_do_getous(GtkWidget
*widget
,
952 NET_API_STATUS status
;
953 uint32_t num_ous
= 0;
954 const char **ous
= NULL
;
956 const char *domain
= NULL
;
957 struct DOMAIN_CONTROLLER_INFO
*dc_info
= NULL
;
958 const char *err_str
= NULL
;
961 struct join_state
*state
= (struct join_state
*)data
;
963 debug("callback_do_getous called\n");
965 domain
= state
->name_buffer_new
? state
->name_buffer_new
: state
->name_buffer_initial
;
967 status
= DsGetDcName(NULL
,
974 err_str
= libnetapi_get_error_string(state
->ctx
, status
);
975 g_print("callback_do_getous: failed find dc (%s)\n", err_str
);
977 dialog
= gtk_message_dialog_new(GTK_WINDOW(state
->window_parent
),
978 GTK_DIALOG_DESTROY_WITH_PARENT
,
981 "Failed to find a domain controller for domain: \"%s\": %s",
985 gtk_window_set_modal(GTK_WINDOW(dialog
), TRUE
);
986 g_signal_connect_swapped(dialog
, "response",
987 G_CALLBACK(gtk_widget_destroy
),
990 gtk_widget_show(dialog
);
995 if (!state
->account
|| !state
->password
) {
996 debug("callback_do_getous: no creds yet\n");
997 callback_creds_prompt(NULL
, state
,
998 "Enter the name and password of an account with permission to join the domain.",
999 callback_do_storeauth_and_scan
);
1002 if (!state
->account
|| !state
->password
) {
1003 debug("callback_do_getous: still no creds ???\n");
1007 status
= NetGetJoinableOUs(NULL
, domain
,
1011 if (status
!= NET_API_STATUS_SUCCESS
) {
1012 callback_do_freeauth(NULL
, state
);
1013 debug("failed to call NetGetJoinableOUs: %s\n",
1014 libnetapi_get_error_string(state
->ctx
, status
));
1015 dialog
= gtk_message_dialog_new(NULL
,
1016 GTK_DIALOG_DESTROY_WITH_PARENT
,
1019 "Failed to query joinable OUs: %s",
1020 libnetapi_get_error_string(state
->ctx
, status
));
1021 gtk_window_set_modal(GTK_WINDOW(dialog
), TRUE
);
1022 gtk_dialog_run(GTK_DIALOG(dialog
));
1023 gtk_widget_destroy(dialog
);
1027 for (i
=0; i
<state
->stored_num_ous
; i
++) {
1028 gtk_combo_box_remove_text(GTK_COMBO_BOX(state
->entry_ou_list
), 0);
1030 for (i
=0; i
<num_ous
&& ous
[i
] != NULL
; i
++) {
1031 gtk_combo_box_append_text(GTK_COMBO_BOX(state
->entry_ou_list
),
1034 NetApiBufferFree(ous
);
1035 state
->stored_num_ous
= num_ous
;
1036 gtk_combo_box_set_active(GTK_COMBO_BOX(state
->entry_ou_list
), num_ous
-1);
1039 static void callback_do_change(GtkWidget
*widget
,
1045 GtkWidget
*button_workgroup
;
1046 GtkWidget
*button_domain
;
1049 GtkWidget
*frame_horz
;
1054 struct join_state
*state
= (struct join_state
*)data
;
1056 debug("callback_do_change called\n");
1059 /* FIXME: add proper warnings for Samba as a DC */
1060 if (state
->server_role
== 3) {
1062 callback_do_freeauth(NULL
, state
);
1063 dialog
= gtk_message_dialog_new(GTK_WINDOW(state
->window_main
),
1064 GTK_DIALOG_DESTROY_WITH_PARENT
,
1067 "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.");
1068 gtk_window_set_modal(GTK_WINDOW(dialog
), TRUE
);
1069 g_signal_connect_swapped(dialog
, "response",
1070 G_CALLBACK(gtk_widget_destroy
),
1073 gtk_widget_show(dialog
);
1078 state
->button_ok
= gtk_button_new_from_stock(GTK_STOCK_OK
);
1079 state
->button_get_ous
= gtk_button_new_with_label("Scan for joinable OUs");
1080 window
= gtk_window_new(GTK_WINDOW_TOPLEVEL
);
1081 gtk_window_set_modal(GTK_WINDOW(window
), TRUE
);
1083 gtk_window_set_title(GTK_WINDOW(window
), "Computer Name Changes");
1084 gtk_window_set_resizable(GTK_WINDOW(window
), FALSE
);
1085 gtk_widget_set_size_request(GTK_WIDGET(window
), 480, 650);
1086 gtk_window_set_icon_from_file(GTK_WINDOW(window
), SAMBA_ICON_PATH
, NULL
);
1088 g_signal_connect(G_OBJECT(window
), "delete_event",
1089 G_CALLBACK(callback_do_close
), window
);
1091 gtk_container_set_border_width(GTK_CONTAINER(window
), 10);
1093 box1
= gtk_vbox_new(FALSE
, 0);
1094 gtk_container_add(GTK_CONTAINER(window
), box1
);
1096 label
= gtk_label_new("You can change the name and membership of this computer. Changes may affect access to network ressources.");
1097 gtk_label_set_line_wrap(GTK_LABEL(label
), TRUE
);
1098 gtk_misc_set_alignment(GTK_MISC(label
), 0, 0);
1099 gtk_box_pack_start(GTK_BOX(box1
), label
, TRUE
, TRUE
, 0);
1100 gtk_widget_show(label
);
1103 label
= gtk_label_new("Computer name:");
1104 gtk_misc_set_alignment(GTK_MISC(label
), 0, 0);
1105 gtk_box_pack_start(GTK_BOX(box1
), label
, TRUE
, TRUE
, 0);
1106 gtk_widget_show(label
);
1108 state
->label_full_computer_name
= gtk_label_new(NULL
);
1110 entry
= gtk_entry_new();
1111 gtk_entry_set_max_length(GTK_ENTRY(entry
), MAX_NETBIOS_NAME_LEN
);
1112 g_signal_connect(G_OBJECT(entry
), "changed",
1113 G_CALLBACK(callback_enter_hostname_and_unlock
),
1115 gtk_entry_set_text(GTK_ENTRY(entry
), state
->my_hostname
);
1116 gtk_editable_select_region(GTK_EDITABLE(entry
),
1117 0, GTK_ENTRY(entry
)->text_length
);
1119 gtk_editable_set_editable(GTK_EDITABLE(entry
), TRUE
); /* ! */
1120 gtk_box_pack_start(GTK_BOX(box1
), entry
, TRUE
, TRUE
, 0);
1121 gtk_widget_show(entry
);
1124 /* FULL COMPUTER NAME */
1125 label
= gtk_label_new("Full computer name:");
1126 gtk_misc_set_alignment(GTK_MISC(label
), 0, 0);
1127 gtk_box_pack_start(GTK_BOX(box1
), label
, TRUE
, TRUE
, 0);
1128 gtk_widget_show(label
);
1131 const gchar
*entry_text
;
1133 entry_text
= gtk_entry_get_text(GTK_ENTRY(entry
));
1134 if (state
->name_type_initial
== NetSetupDomainName
) {
1135 asprintf(&str
, "%s.%s", entry_text
,
1136 state
->my_dnsdomain
);
1138 asprintf(&str
, "%s.", entry_text
);
1140 gtk_label_set_text(GTK_LABEL(state
->label_full_computer_name
),
1143 gtk_misc_set_alignment(GTK_MISC(state
->label_full_computer_name
), 0, 0);
1144 gtk_box_pack_start(GTK_BOX(box1
),
1145 state
->label_full_computer_name
, TRUE
, TRUE
, 0);
1146 gtk_widget_show(state
->label_full_computer_name
);
1150 frame_horz
= gtk_frame_new ("Member Of");
1151 gtk_box_pack_start(GTK_BOX(box1
), frame_horz
, TRUE
, TRUE
, 10);
1153 vbox
= gtk_vbox_new(FALSE
, 0);
1154 gtk_container_set_border_width(GTK_CONTAINER(vbox
), 10);
1155 gtk_container_add(GTK_CONTAINER(frame_horz
), vbox
);
1158 state
->entry_workgroup
= gtk_entry_new();
1159 state
->entry_domain
= gtk_entry_new();
1162 button_domain
= gtk_radio_button_new_with_label(NULL
, "Domain");
1163 if (state
->name_type_initial
== NetSetupDomainName
) {
1164 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button_domain
), TRUE
);
1166 gtk_box_pack_start(GTK_BOX(vbox
), button_domain
, TRUE
, TRUE
, 0);
1167 g_signal_connect(G_OBJECT(button_domain
), "clicked",
1168 G_CALLBACK(callback_do_join_domain
),
1172 gtk_entry_set_max_length(GTK_ENTRY(state
->entry_domain
), 50);
1173 g_signal_connect(G_OBJECT(state
->entry_domain
), "changed",
1174 G_CALLBACK(callback_enter_domain_and_unlock
),
1176 g_signal_connect(G_OBJECT(state
->entry_domain
), "activate",
1177 G_CALLBACK(callback_continue
),
1179 if (state
->name_type_initial
== NetSetupDomainName
) {
1180 gtk_entry_set_text(GTK_ENTRY(state
->entry_domain
),
1181 state
->name_buffer_initial
);
1182 gtk_widget_set_sensitive(state
->entry_workgroup
, FALSE
);
1183 gtk_widget_set_sensitive(state
->entry_domain
, TRUE
);
1185 gtk_editable_set_editable(GTK_EDITABLE(state
->entry_domain
), TRUE
);
1186 gtk_box_pack_start(GTK_BOX(vbox
), state
->entry_domain
, TRUE
, TRUE
, 0);
1187 gtk_widget_show(state
->entry_domain
);
1189 gtk_widget_show(button_domain
);
1192 group
= gtk_radio_button_get_group(GTK_RADIO_BUTTON(button_domain
));
1193 button_workgroup
= gtk_radio_button_new_with_label(group
, "Workgroup");
1194 if (state
->name_type_initial
== NetSetupWorkgroupName
) {
1195 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button_workgroup
), TRUE
);
1197 gtk_box_pack_start(GTK_BOX(vbox
), button_workgroup
, TRUE
, TRUE
, 0);
1198 g_signal_connect(G_OBJECT(button_workgroup
), "clicked",
1199 G_CALLBACK(callback_do_join_workgroup
),
1202 gtk_entry_set_max_length(GTK_ENTRY(state
->entry_workgroup
),
1203 MAX_NETBIOS_NAME_LEN
);
1204 g_signal_connect(G_OBJECT(state
->entry_workgroup
), "changed",
1205 G_CALLBACK(callback_enter_workgroup_and_unlock
),
1207 g_signal_connect(G_OBJECT(state
->entry_workgroup
), "activate",
1208 G_CALLBACK(callback_continue
),
1211 if (state
->name_type_initial
== NetSetupWorkgroupName
) {
1212 gtk_entry_set_text(GTK_ENTRY(state
->entry_workgroup
),
1213 state
->name_buffer_initial
);
1214 gtk_widget_set_sensitive(GTK_WIDGET(state
->entry_domain
), FALSE
);
1215 gtk_widget_set_sensitive(GTK_WIDGET(state
->entry_workgroup
), TRUE
);
1217 gtk_box_pack_start(GTK_BOX(vbox
), state
->entry_workgroup
, TRUE
, TRUE
, 0);
1218 gtk_widget_show(state
->entry_workgroup
);
1220 gtk_widget_show(button_workgroup
);
1222 /* Advanced Options */
1223 frame_horz
= gtk_frame_new("Advanced Options");
1224 gtk_box_pack_start(GTK_BOX(box1
), frame_horz
, TRUE
, TRUE
, 10);
1226 vbox
= gtk_vbox_new(FALSE
, 0);
1227 gtk_container_set_border_width(GTK_CONTAINER(vbox
), 10);
1228 gtk_container_add(GTK_CONTAINER(frame_horz
), vbox
);
1231 gtk_container_add(GTK_CONTAINER(vbox
), state
->button_get_ous
);
1232 gtk_widget_set_sensitive(GTK_WIDGET(state
->button_get_ous
), FALSE
);
1233 g_signal_connect(G_OBJECT(state
->button_get_ous
), "clicked",
1234 G_CALLBACK(callback_do_getous
),
1237 state
->entry_ou_list
= gtk_combo_box_entry_new_text();
1238 gtk_widget_set_sensitive(state
->entry_ou_list
, FALSE
);
1239 if (state
->name_type_initial
== NetSetupWorkgroupName
) {
1240 gtk_widget_set_sensitive(state
->entry_ou_list
, FALSE
);
1241 gtk_widget_set_sensitive(state
->button_get_ous
, FALSE
);
1243 gtk_box_pack_start(GTK_BOX(vbox
), state
->entry_ou_list
, TRUE
, TRUE
, 0);
1244 gtk_widget_show(state
->entry_ou_list
);
1247 state
->label_winbind
= gtk_check_button_new_with_label("Modify winbind configuration");
1248 gtk_box_pack_start(GTK_BOX(vbox
), state
->label_winbind
, TRUE
, TRUE
, 0);
1249 gtk_widget_set_sensitive(state
->label_winbind
, FALSE
);
1254 bbox
= gtk_hbutton_box_new();
1255 gtk_container_set_border_width(GTK_CONTAINER(bbox
), 5);
1256 gtk_container_add(GTK_CONTAINER(box1
), bbox
);
1257 gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox
), GTK_BUTTONBOX_END
);
1258 gtk_box_set_spacing(GTK_BOX(bbox
), 10);
1260 state
->window_do_change
= window
;
1261 gtk_widget_set_sensitive(GTK_WIDGET(state
->button_ok
), FALSE
);
1262 gtk_container_add(GTK_CONTAINER(bbox
), state
->button_ok
);
1263 g_signal_connect(G_OBJECT(state
->button_ok
), "clicked",
1264 G_CALLBACK(callback_do_join
),
1267 button
= gtk_button_new_from_stock(GTK_STOCK_CANCEL
);
1268 gtk_container_add(GTK_CONTAINER(bbox
), button
);
1269 g_signal_connect(G_OBJECT(button
), "clicked",
1270 G_CALLBACK(callback_do_freeauth_and_close
),
1273 gtk_widget_show_all(window
);
1276 static void callback_do_about(GtkWidget
*widget
,
1280 GError
*error
= NULL
;
1283 debug("callback_do_about called\n");
1285 logo
= gdk_pixbuf_new_from_file(SAMBA_IMAGE_PATH
,
1288 g_print("failed to load logo from %s: %s\n",
1289 SAMBA_IMAGE_PATH
, error
->message
);
1292 about
= gtk_about_dialog_new();
1293 gtk_about_dialog_set_name(GTK_ABOUT_DIALOG(about
), "Samba");
1294 gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(about
), "3.2.0pre3");
1295 gtk_about_dialog_set_copyright(GTK_ABOUT_DIALOG(about
),
1296 "Copyright Andrew Tridgell and the Samba Team 1992-2008\n"
1297 "Copyright Günther Deschner 2007-2008");
1298 gtk_about_dialog_set_license(GTK_ABOUT_DIALOG(about
), "GPLv3");
1299 gtk_about_dialog_set_website(GTK_ABOUT_DIALOG(about
), "http://www.samba.org");
1300 gtk_about_dialog_set_website_label(GTK_ABOUT_DIALOG(about
), "http://www.samba.org");
1302 gtk_about_dialog_set_logo(GTK_ABOUT_DIALOG(about
), logo
);
1304 gtk_about_dialog_set_comments(GTK_ABOUT_DIALOG(about
), "Samba gtk domain join utility");
1305 gtk_window_set_modal(GTK_WINDOW(about
), TRUE
);
1306 g_signal_connect_swapped(about
, "response",
1307 G_CALLBACK(gtk_widget_destroy
),
1310 gtk_widget_show(about
);
1313 static int draw_main_window(struct join_state
*state
)
1318 GtkWidget
*main_vbox
;
1326 GError
*error
= NULL
;
1328 icon
= gdk_pixbuf_new_from_file(SAMBA_ICON_PATH
,
1331 g_print("failed to load icon from %s : %s\n",
1332 SAMBA_ICON_PATH
, error
->message
);
1336 image
= gtk_image_new_from_file(SAMBA_IMAGE_PATH_SMALL
);
1338 image
= gtk_image_new_from_file("/usr/share/pixmaps/redhat-system_settings.png");
1340 if (image
== NULL
) {
1341 g_print("failed to load logo from %s : %s\n",
1342 SAMBA_IMAGE_PATH_SMALL
, error
->message
);
1345 window
= gtk_window_new(GTK_WINDOW_TOPLEVEL
);
1346 state
->window_main
= window
;
1348 gtk_window_set_title(GTK_WINDOW(window
), "Samba - Join Domain dialogue");
1349 gtk_widget_set_size_request(GTK_WIDGET(window
), 600, 600);
1350 gtk_window_set_resizable(GTK_WINDOW(window
), FALSE
);
1351 gtk_window_set_icon_from_file(GTK_WINDOW(window
), SAMBA_ICON_PATH
, NULL
);
1353 g_signal_connect(G_OBJECT(window
), "delete_event",
1354 G_CALLBACK(callback_delete_event
), NULL
);
1356 gtk_container_set_border_width(GTK_CONTAINER(window
), 10);
1358 main_vbox
= gtk_vbox_new(FALSE
, 10);
1359 gtk_container_add(GTK_CONTAINER(window
), main_vbox
);
1362 gtk_box_pack_start(GTK_BOX(main_vbox
), image
, TRUE
, TRUE
, 10);
1363 gtk_widget_show(image
);
1366 hbox
= gtk_hbox_new(FALSE
, 10);
1367 gtk_container_add(GTK_CONTAINER(main_vbox
), hbox
);
1370 /* gtk_box_pack_start(GTK_BOX(main_vbox), image, TRUE, TRUE, 10); */
1371 /* gtk_misc_set_alignment(GTK_MISC(image), 0, 0); */
1372 gtk_widget_set_size_request(GTK_WIDGET(image
), 150, 40);
1373 gtk_box_pack_start(GTK_BOX(hbox
), image
, FALSE
, FALSE
, 10);
1374 gtk_widget_show(image
);
1377 label
= gtk_label_new("Samba uses the following information to identify your computer on the network.");
1378 /* gtk_misc_set_alignment(GTK_MISC(label), 0, 0); */
1379 gtk_widget_set_size_request(GTK_WIDGET(label
), 400, 40);
1380 gtk_label_set_line_wrap(GTK_LABEL(label
), TRUE
);
1381 gtk_box_pack_start(GTK_BOX(hbox
), label
, FALSE
, FALSE
, 0);
1382 gtk_widget_show(label
);
1385 gtk_widget_show(hbox
);
1387 vbox
= gtk_vbox_new(FALSE
, 0);
1388 gtk_container_set_border_width(GTK_CONTAINER(vbox
), 10);
1389 gtk_container_add(GTK_CONTAINER(main_vbox
), vbox
);
1392 table
= gtk_table_new(6, 3, TRUE
);
1393 gtk_table_set_row_spacings(GTK_TABLE(table
), 5);
1394 gtk_table_set_col_spacings(GTK_TABLE(table
), 5);
1395 gtk_container_add(GTK_CONTAINER(vbox
), table
);
1399 label
= gtk_label_new("Computer description:");
1400 gtk_misc_set_alignment(GTK_MISC(label
), 0, 0);
1401 gtk_table_attach_defaults(GTK_TABLE(table
), label
, 0, 1, 0, 1);
1402 gtk_widget_show(label
);
1404 state
->button_apply
= gtk_button_new_from_stock(GTK_STOCK_APPLY
);
1407 entry
= gtk_entry_new();
1408 gtk_entry_set_max_length(GTK_ENTRY(entry
), 256);
1409 g_signal_connect(G_OBJECT(entry
), "changed",
1410 G_CALLBACK(callback_enter_computer_description_and_unlock
),
1412 g_signal_connect(G_OBJECT(entry
), "activate",
1413 G_CALLBACK(callback_apply_continue
),
1416 gtk_entry_set_text(GTK_ENTRY(entry
), (char *)state
->comment
);
1417 gtk_editable_set_editable(GTK_EDITABLE(entry
), TRUE
); /* ! */
1418 gtk_table_attach_defaults(GTK_TABLE(table
), entry
, 1, 3, 0, 1);
1419 gtk_widget_show(entry
);
1423 label
= gtk_label_new("For example: \"Samba \%v\".");
1424 gtk_label_set_line_wrap(GTK_LABEL(label
), TRUE
);
1425 gtk_misc_set_alignment(GTK_MISC(label
), 0, 0);
1426 gtk_table_attach_defaults(GTK_TABLE(table
), label
, 1, 3, 1, 2);
1427 gtk_widget_show(label
);
1430 label
= gtk_label_new("Full computer name:");
1431 gtk_misc_set_alignment(GTK_MISC(label
), 0, 0);
1432 gtk_table_attach_defaults(GTK_TABLE(table
), label
, 0, 1, 2, 3);
1433 gtk_widget_show(label
);
1438 if (state
->name_type_initial
== NetSetupDomainName
) {
1439 asprintf(&str
, "%s.%s", state
->my_hostname
,
1440 state
->my_dnsdomain
);
1442 asprintf(&str
, "%s.", state
->my_hostname
);
1445 label
= gtk_label_new(str
);
1447 gtk_misc_set_alignment(GTK_MISC(label
), 0, 0);
1448 gtk_table_attach_defaults(GTK_TABLE(table
), label
, 1, 3, 2, 3);
1449 gtk_widget_show(label
);
1453 if (state
->name_type_initial
== NetSetupDomainName
) {
1454 label
= gtk_label_new("Domain:");
1456 label
= gtk_label_new("Workgroup:");
1458 gtk_misc_set_alignment(GTK_MISC(label
), 0, 0);
1459 gtk_table_attach_defaults(GTK_TABLE(table
), label
, 0, 1, 3, 4);
1460 gtk_widget_show(label
);
1461 state
->label_current_name_type
= label
;
1464 label
= gtk_label_new(state
->name_buffer_initial
);
1465 gtk_misc_set_alignment(GTK_MISC(label
), 0, 0);
1466 gtk_table_attach_defaults(GTK_TABLE(table
), label
, 1, 3, 3, 4);
1467 gtk_widget_show(label
);
1468 state
->label_current_name_buffer
= label
;
1471 hbox
= gtk_hbox_new(FALSE
, 0);
1472 gtk_container_add(GTK_CONTAINER(vbox
), hbox
);
1473 label
= gtk_label_new("To rename this computer or join a domain, click Change.");
1474 gtk_box_pack_start(GTK_BOX(hbox
), label
, FALSE
, FALSE
, 0);
1480 bbox
= gtk_hbutton_box_new();
1481 gtk_container_set_border_width(GTK_CONTAINER(bbox
), 5);
1482 gtk_container_add(GTK_CONTAINER(hbox
), bbox
);
1483 gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox
), GTK_BUTTONBOX_END
);
1484 gtk_box_set_spacing(GTK_BOX(bbox
), 10);
1486 button
= gtk_button_new_with_mnemonic("Ch_ange");
1487 g_signal_connect(G_OBJECT(button
), "clicked",
1488 G_CALLBACK(callback_do_change
),
1490 gtk_box_pack_start(GTK_BOX(bbox
), button
, TRUE
, TRUE
, 0);
1491 gtk_widget_show(button
);
1493 /* Label (hidden) */
1494 state
->label_reboot
= gtk_label_new(NULL
);
1495 gtk_label_set_line_wrap(GTK_LABEL(state
->label_reboot
), TRUE
);
1496 gtk_misc_set_alignment(GTK_MISC(state
->label_reboot
), 0, 0);
1497 gtk_box_pack_start(GTK_BOX(vbox
), state
->label_reboot
, TRUE
, TRUE
, 0);
1498 gtk_widget_show(state
->label_reboot
);
1501 gtk_box_pack_start(GTK_BOX(vbox
),
1502 create_bbox(window
, TRUE
, NULL
, 10, 85, 20, GTK_BUTTONBOX_END
),
1511 frame
= gtk_frame_new(NULL
);
1512 bbox2
= gtk_hbutton_box_new();
1514 gtk_container_set_border_width(GTK_CONTAINER(bbox2
), 5);
1515 gtk_container_add(GTK_CONTAINER(frame
), bbox2
);
1517 /* Set the appearance of the Button Box */
1518 gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox2
), GTK_BUTTONBOX_END
);
1519 gtk_box_set_spacing(GTK_BOX(bbox2
), 10);
1520 /*gtk_button_box_set_child_size(GTK_BUTTON_BOX(bbox2), child_w, child_h);*/
1522 button2
= gtk_button_new_from_stock(GTK_STOCK_OK
);
1523 gtk_container_add(GTK_CONTAINER(bbox2
), button2
);
1524 g_signal_connect(G_OBJECT(button2
), "clicked", G_CALLBACK(callback_do_exit
), state
);
1526 button2
= gtk_button_new_from_stock(GTK_STOCK_CANCEL
);
1527 gtk_container_add(GTK_CONTAINER(bbox2
), button2
);
1528 g_signal_connect(G_OBJECT(button2
), "clicked",
1529 G_CALLBACK(callback_delete_event
),
1532 gtk_container_add(GTK_CONTAINER(bbox2
), state
->button_apply
);
1533 g_signal_connect(G_OBJECT(state
->button_apply
), "clicked",
1534 G_CALLBACK(callback_apply_description_change
),
1536 gtk_widget_set_sensitive(GTK_WIDGET(state
->button_apply
), FALSE
);
1538 button2
= gtk_button_new_from_stock(GTK_STOCK_ABOUT
);
1539 gtk_container_add(GTK_CONTAINER(bbox2
), button2
);
1540 g_signal_connect(G_OBJECT(button2
), "clicked",
1541 G_CALLBACK(callback_do_about
),
1544 button2
= gtk_button_new_from_stock(GTK_STOCK_HELP
);
1545 gtk_container_add(GTK_CONTAINER(bbox2
), button2
);
1546 g_signal_connect(G_OBJECT(button2
), "clicked",
1547 G_CALLBACK(callback_do_about
),
1550 gtk_box_pack_start(GTK_BOX(vbox
), frame
, TRUE
, TRUE
, 5);
1553 gtk_widget_show_all(window
);
1558 static int init_join_state(struct join_state
**state
)
1560 struct join_state
*s
;
1562 s
= (struct join_state
*)malloc(sizeof(struct join_state
));
1567 memset(s
, '\0', sizeof(struct join_state
));
1574 static int initialize_join_state(struct join_state
*state
,
1575 const char *debug_level
)
1577 struct libnetapi_ctx
*ctx
= NULL
;
1578 NET_API_STATUS status
= 0;
1580 status
= libnetapi_init(&ctx
);
1586 libnetapi_set_debuglevel(ctx
, debug_level
);
1590 char my_hostname
[HOST_NAME_MAX
];
1591 const char *p
= NULL
;
1592 struct hostent
*hp
= NULL
;
1594 if (gethostname(my_hostname
, sizeof(my_hostname
)) == -1) {
1598 p
= strchr(my_hostname
, '.');
1600 my_hostname
[strlen(my_hostname
)-strlen(p
)] = '\0';
1602 state
->my_hostname
= strdup(my_hostname
);
1603 if (!state
->my_hostname
) {
1606 debug("state->my_hostname: %s\n", state
->my_hostname
);
1608 hp
= gethostbyname(my_hostname
);
1609 if (!hp
|| !hp
->h_name
|| !*hp
->h_name
) {
1613 state
->my_fqdn
= strdup(hp
->h_name
);
1614 if (!state
->my_fqdn
) {
1617 debug("state->my_fqdn: %s\n", state
->my_fqdn
);
1619 p
= strchr(state
->my_fqdn
, '.');
1622 state
->my_dnsdomain
= strdup(p
);
1624 state
->my_dnsdomain
= strdup("");
1626 if (!state
->my_dnsdomain
) {
1629 debug("state->my_dnsdomain: %s\n", state
->my_dnsdomain
);
1633 const char *buffer
= NULL
;
1635 status
= NetGetJoinInformation(NULL
, &buffer
, &type
);
1637 printf("NetGetJoinInformation failed with: %s\n",
1638 libnetapi_get_error_string(state
->ctx
, status
));
1641 debug("NetGetJoinInformation gave: %s and %d\n", buffer
, type
);
1642 state
->name_buffer_initial
= strdup(buffer
);
1643 if (!state
->name_buffer_initial
) {
1646 state
->name_type_initial
= type
;
1647 NetApiBufferFree((void *)buffer
);
1651 struct SERVER_INFO_1005
*info1005
= NULL
;
1652 uint8_t *buffer
= NULL
;
1654 status
= NetServerGetInfo(NULL
, 1005, &buffer
);
1656 printf("NetServerGetInfo failed with: %s\n",
1657 libnetapi_get_error_string(state
->ctx
, status
));
1661 info1005
= (struct SERVER_INFO_1005
*)buffer
;
1663 state
->comment
= strdup(info1005
->sv1005_comment
);
1664 if (!state
->comment
) {
1667 NetApiBufferFree(buffer
);
1671 struct srvsvc_NetSrvInfo100
*info100
= NULL
;
1672 uint8_t *buffer
= NULL
;
1674 status
= NetServerGetInfo(NULL
, 100, &buffer
);
1679 info100
= (struct srvsvc_NetSrvInfo100
*)buffer
;
1681 state
->comment
= strdup(info100
->comment
);
1682 if (!state
->comment
) {
1693 int main(int argc
, char **argv
)
1695 GOptionContext
*context
= NULL
;
1696 static const char *debug_level
= NULL
;
1697 struct join_state
*state
= NULL
;
1698 GError
*error
= NULL
;
1701 static GOptionEntry entries
[] = {
1702 { "debug", 'd', 0, G_OPTION_ARG_STRING
, &debug_level
, "Debug level (for samba)", "N" },
1703 { "verbose", 'v', 0, G_OPTION_ARG_NONE
, &verbose
, "Verbose output", 0 },
1707 context
= g_option_context_new("- Samba domain join utility");
1708 g_option_context_add_main_entries(context
, entries
, NULL
);
1709 /* g_option_context_add_main_entries(context, entries, GETTEXT_PACKAGE); */
1710 g_option_context_add_group(context
, gtk_get_option_group(TRUE
));
1711 g_option_context_parse(context
, &argc
, &argv
, &error
);
1713 gtk_init(&argc
, &argv
);
1714 g_set_application_name("Samba");
1716 ret
= init_join_state(&state
);
1721 ret
= initialize_join_state(state
, debug_level
);
1726 draw_main_window(state
);