root/source3/lib/netapi/examples/netdomjoin-gui/netdomjoin-gui.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. debug
  2. callback_delete_event
  3. callback_do_close_data
  4. callback_do_close_widget
  5. callback_do_freeauth
  6. callback_do_freeauth_and_close
  7. free_join_state
  8. do_cleanup
  9. callback_apply_description_change
  10. callback_do_exit
  11. callback_do_reboot
  12. callback_return_username
  13. callback_return_username_and_enter
  14. callback_return_password
  15. callback_return_password_and_enter
  16. callback_do_storeauth
  17. callback_continue
  18. callback_do_storeauth_and_continue
  19. callback_do_storeauth_and_scan
  20. callback_do_hostname_change
  21. callback_creds_prompt
  22. callback_do_join
  23. callback_enter_hostname_and_unlock
  24. callback_enter_computer_description_and_unlock
  25. callback_enter_workgroup_and_unlock
  26. callback_enter_domain_and_unlock
  27. callback_apply_continue
  28. callback_do_join_workgroup
  29. callback_do_join_domain
  30. callback_do_getous
  31. callback_do_change
  32. callback_do_about
  33. draw_main_window
  34. init_join_state
  35. get_server_properties
  36. initialize_join_state
  37. main

   1 /*
   2  *  Unix SMB/CIFS implementation.
   3  *  Join Support (gtk + netapi)
   4  *  Copyright (C) Guenther Deschner 2007-2008
   5  *
   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.
  10  *
  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.
  15  *
  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/>.
  18  */
  19 
  20 #define _GNU_SOURCE
  21 #include <stdio.h>
  22 #include <sys/types.h>
  23 #include <inttypes.h>
  24 #include <stdlib.h>
  25 #include <unistd.h>
  26 #include <string.h>
  27 #include <netdb.h>
  28 
  29 #include <gtk/gtk.h>
  30 #include <glib/gprintf.h>
  31 
  32 #include <netapi.h>
  33 
  34 #define MAX_CRED_LEN 256
  35 #define MAX_NETBIOS_NAME_LEN 15
  36 
  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"
  40 
  41 #define SAFE_FREE(x) do { if ((x) != NULL) {free(x); x=NULL;} } while(0)
  42 
  43 static gboolean verbose = FALSE;
  44 
  45 typedef struct join_state {
  46         struct libnetapi_ctx *ctx;
  47         GtkWidget *window_main;
  48         GtkWidget *window_parent;
  49         GtkWidget *window_do_change;
  50         GtkWidget *window_creds_prompt;
  51         GtkWidget *entry_account;
  52         GtkWidget *entry_password;
  53         GtkWidget *entry_domain;
  54         GtkWidget *entry_ou_list;
  55         GtkWidget *entry_workgroup;
  56         GtkWidget *button_ok;
  57         GtkWidget *button_apply;
  58         GtkWidget *button_ok_creds;
  59         GtkWidget *button_get_ous;
  60         GtkWidget *label_reboot;
  61         GtkWidget *label_current_name_buffer;
  62         GtkWidget *label_current_name_type;
  63         GtkWidget *label_full_computer_name;
  64         GtkWidget *label_winbind;
  65         uint16_t name_type_initial;
  66         uint16_t name_type_new;
  67         char *name_buffer_initial;
  68         char *name_buffer_new;
  69         char *password;
  70         char *account;
  71         char *comment;
  72         char *comment_new;
  73         char *my_fqdn;
  74         char *my_dnsdomain;
  75         char *my_hostname;
  76         uint16_t server_role;
  77         gboolean settings_changed;
  78         gboolean hostname_changed;
  79         uint32_t stored_num_ous;
  80         char *target_hostname;
  81         uid_t uid;
  82 } join_state;
  83 
  84 static void callback_creds_prompt(GtkWidget *widget,
  85                                   gpointer data,
  86                                   const char *label_string,
  87                                   gpointer cont_fn);
  88 
  89 
  90 static void debug(const char *format, ...)
     /* [<][>][^][v][top][bottom][index][help] */
  91 {
  92         va_list args;
  93 
  94         if (!verbose) {
  95                 return;
  96         }
  97 
  98         va_start(args, format);
  99         g_vprintf(format, args);
 100         va_end(args);
 101 }
 102 
 103 static gboolean callback_delete_event(GtkWidget *widget,
     /* [<][>][^][v][top][bottom][index][help] */
 104                                       GdkEvent *event,
 105                                       gpointer data)
 106 {
 107         gtk_main_quit();
 108         return FALSE;
 109 }
 110 
 111 static void callback_do_close_data(GtkWidget *widget,
     /* [<][>][^][v][top][bottom][index][help] */
 112                                    gpointer data)
 113 {
 114         debug("callback_do_close_data called\n");
 115 
 116         if (data) {
 117                 gtk_widget_destroy(GTK_WIDGET(data));
 118         }
 119 }
 120 
 121 static void callback_do_close_widget(GtkWidget *widget,
     /* [<][>][^][v][top][bottom][index][help] */
 122                                      gpointer data)
 123 {
 124         debug("callback_do_close_widget called\n");
 125 
 126         if (widget) {
 127                 gtk_widget_destroy(widget);
 128         }
 129 }
 130 
 131 static void callback_do_freeauth(GtkWidget *widget,
     /* [<][>][^][v][top][bottom][index][help] */
 132                                  gpointer data)
 133 {
 134         struct join_state *state = (struct join_state *)data;
 135 
 136         debug("callback_do_freeauth called\n");
 137 
 138         SAFE_FREE(state->account);
 139         SAFE_FREE(state->password);
 140 
 141         if (state->window_creds_prompt) {
 142                 gtk_widget_destroy(GTK_WIDGET(state->window_creds_prompt));
 143                 state->window_creds_prompt = NULL;
 144         }
 145 }
 146 
 147 static void callback_do_freeauth_and_close(GtkWidget *widget,
     /* [<][>][^][v][top][bottom][index][help] */
 148                                            gpointer data)
 149 {
 150         struct join_state *state = (struct join_state *)data;
 151 
 152         debug("callback_do_freeauth_and_close called\n");
 153 
 154         SAFE_FREE(state->account);
 155         SAFE_FREE(state->password);
 156 
 157         if (state->window_creds_prompt) {
 158                 gtk_widget_destroy(GTK_WIDGET(state->window_creds_prompt));
 159                 state->window_creds_prompt = NULL;
 160         }
 161         if (state->window_do_change) {
 162                 gtk_widget_destroy(GTK_WIDGET(state->window_do_change));
 163                 state->window_do_change = NULL;
 164         }
 165 }
 166 
 167 static void free_join_state(struct join_state *s)
     /* [<][>][^][v][top][bottom][index][help] */
 168 {
 169         SAFE_FREE(s->name_buffer_initial);
 170         SAFE_FREE(s->name_buffer_new);
 171         SAFE_FREE(s->password);
 172         SAFE_FREE(s->account);
 173         SAFE_FREE(s->comment);
 174         SAFE_FREE(s->comment_new);
 175         SAFE_FREE(s->my_fqdn);
 176         SAFE_FREE(s->my_dnsdomain);
 177         SAFE_FREE(s->my_hostname);
 178 }
 179 
 180 static void do_cleanup(struct join_state *state)
     /* [<][>][^][v][top][bottom][index][help] */
 181 {
 182         libnetapi_free(state->ctx);
 183         free_join_state(state);
 184 }
 185 
 186 static void callback_apply_description_change(GtkWidget *widget,
     /* [<][>][^][v][top][bottom][index][help] */
 187                                               gpointer data)
 188 {
 189         struct join_state *state = (struct join_state *)data;
 190         NET_API_STATUS status = 0;
 191         uint32_t parm_err = 0;
 192         struct SERVER_INFO_1005 info1005;
 193         GtkWidget *dialog;
 194 
 195         info1005.sv1005_comment = state->comment_new;
 196 
 197         status = NetServerSetInfo(state->target_hostname,
 198                                   1005,
 199                                   (uint8_t *)&info1005,
 200                                   &parm_err);
 201         if (status) {
 202                 debug("NetServerSetInfo failed with: %s\n",
 203                         libnetapi_errstr(status));
 204                 dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_main),
 205                                                 GTK_DIALOG_DESTROY_WITH_PARENT,
 206                                                 GTK_MESSAGE_ERROR,
 207                                                 GTK_BUTTONS_OK,
 208                                                 "Failed to change computer description: %s.",
 209                                                 libnetapi_get_error_string(state->ctx, status));
 210                 gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
 211                 gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(state->window_main));
 212 
 213                 g_signal_connect_swapped(dialog, "response",
 214                                          G_CALLBACK(gtk_widget_destroy),
 215                                          dialog);
 216 
 217                 gtk_widget_show(dialog);
 218                 return;
 219         }
 220 
 221         gtk_widget_set_sensitive(GTK_WIDGET(state->button_apply), FALSE);
 222 }
 223 
 224 static void callback_do_exit(GtkWidget *widget,
     /* [<][>][^][v][top][bottom][index][help] */
 225                              gpointer data)
 226 {
 227 #if 0
 228         GtkWidget *dialog;
 229         gint result;
 230 #endif
 231         struct join_state *state = (struct join_state *)data;
 232 
 233         if (!state->settings_changed) {
 234                 callback_delete_event(NULL, NULL, NULL);
 235                 return;
 236         }
 237 
 238 #if 0
 239         dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_main),
 240                                         GTK_DIALOG_DESTROY_WITH_PARENT,
 241                                         GTK_MESSAGE_QUESTION,
 242                                         GTK_BUTTONS_YES_NO,
 243                                         "You must restart your computer before the new settings will take effect.");
 244         gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
 245         result = gtk_dialog_run(GTK_DIALOG(dialog));
 246         switch (result) {
 247                 case GTK_RESPONSE_YES:
 248                         g_print("would reboot here\n");
 249                         break;
 250                 case GTK_RESPONSE_NO:
 251                 default:
 252                         break;
 253         }
 254         if (dialog) {
 255                 gtk_widget_destroy(GTK_WIDGET(dialog));
 256         }
 257 #endif
 258         if (state->window_main) {
 259                 gtk_widget_destroy(GTK_WIDGET(state->window_main));
 260                 state->window_main = NULL;
 261         }
 262         do_cleanup(state);
 263         exit(0);
 264 }
 265 
 266 
 267 static void callback_do_reboot(GtkWidget *widget,
     /* [<][>][^][v][top][bottom][index][help] */
 268                                gpointer data,
 269                                gpointer data2)
 270 {
 271         GtkWidget *dialog;
 272         struct join_state *state = (struct join_state *)data2;
 273 
 274         debug("callback_do_reboot\n");
 275 
 276         state->settings_changed = TRUE;
 277         dialog = gtk_message_dialog_new(GTK_WINDOW(data),
 278                                         GTK_DIALOG_DESTROY_WITH_PARENT,
 279                                         GTK_MESSAGE_INFO,
 280                                         GTK_BUTTONS_OK,
 281                                         "You must restart this computer for the changes to take effect.");
 282         gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
 283         gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(state->window_do_change));
 284 #if 0
 285         g_signal_connect_swapped(dialog, "response",
 286                                  G_CALLBACK(gtk_widget_destroy),
 287                                  dialog);
 288 
 289         debug("showing dialog\n");
 290         gtk_widget_show(dialog);
 291 #else
 292         gtk_dialog_run(GTK_DIALOG(dialog));
 293         gtk_widget_destroy(GTK_WIDGET(dialog));
 294 #endif
 295 
 296         gtk_label_set_text(GTK_LABEL(state->label_reboot),
 297                            "Changes will take effect after you restart this computer");
 298 
 299         debug("destroying do_change window\n");
 300         gtk_widget_destroy(GTK_WIDGET(state->window_do_change));
 301 
 302         {
 303                 uint32_t status;
 304                 const char *buffer;
 305                 uint16_t type;
 306 
 307                 status = NetGetJoinInformation(state->target_hostname,
 308                                                &buffer,
 309                                                &type);
 310                 if (status != 0) {
 311                         g_print("failed to query status\n");
 312                         return;
 313                 }
 314 
 315                 debug("got new status: %s\n", buffer);
 316 
 317                 SAFE_FREE(state->name_buffer_new);
 318                 state->name_buffer_new = strdup(buffer);
 319                 state->name_type_new = type;
 320                 state->name_buffer_initial = strdup(buffer);
 321                 state->name_type_initial = type;
 322                 NetApiBufferFree((void *)buffer);
 323 
 324                 gtk_label_set_text(GTK_LABEL(state->label_current_name_buffer),
 325                                    state->name_buffer_new);
 326                 if (state->name_type_new == NetSetupDomainName) {
 327                         gtk_label_set_text(GTK_LABEL(state->label_current_name_type),
 328                                            "Domain:");
 329                 } else {
 330                         gtk_label_set_text(GTK_LABEL(state->label_current_name_type),
 331                                            "Workgroup:");
 332                 }
 333         }
 334 }
 335 
 336 static void callback_return_username(GtkWidget *widget,
     /* [<][>][^][v][top][bottom][index][help] */
 337                                      gpointer data)
 338 {
 339         const gchar *entry_text;
 340         struct join_state *state = (struct join_state *)data;
 341         debug("callback_return_username called\n");
 342         if (!widget) {
 343                 return;
 344         }
 345         entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
 346         if (!entry_text) {
 347                 return;
 348         }
 349         debug("callback_return_username: %s\n", entry_text);
 350         SAFE_FREE(state->account);
 351         state->account = strdup(entry_text);
 352 }
 353 
 354 static void callback_return_username_and_enter(GtkWidget *widget,
     /* [<][>][^][v][top][bottom][index][help] */
 355                                                gpointer data)
 356 {
 357         const gchar *entry_text;
 358         struct join_state *state = (struct join_state *)data;
 359         if (!widget) {
 360                 return;
 361         }
 362         entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
 363         if (!entry_text) {
 364                 return;
 365         }
 366         debug("callback_return_username_and_enter: %s\n", entry_text);
 367         SAFE_FREE(state->account);
 368         state->account = strdup(entry_text);
 369         g_signal_emit_by_name(state->button_ok_creds, "clicked");
 370 }
 371 
 372 static void callback_return_password(GtkWidget *widget,
     /* [<][>][^][v][top][bottom][index][help] */
 373                                      gpointer data)
 374 {
 375         const gchar *entry_text;
 376         struct join_state *state = (struct join_state *)data;
 377         debug("callback_return_password called\n");
 378         if (!widget) {
 379                 return;
 380         }
 381         entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
 382         if (!entry_text) {
 383                 return;
 384         }
 385 #ifdef DEBUG_PASSWORD
 386         debug("callback_return_password: %s\n", entry_text);
 387 #else
 388         debug("callback_return_password: (not printed)\n");
 389 #endif
 390         SAFE_FREE(state->password);
 391         state->password = strdup(entry_text);
 392 }
 393 
 394 static void callback_return_password_and_enter(GtkWidget *widget,
     /* [<][>][^][v][top][bottom][index][help] */
 395                                                gpointer data)
 396 {
 397         const gchar *entry_text;
 398         struct join_state *state = (struct join_state *)data;
 399         if (!widget) {
 400                 return;
 401         }
 402         entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
 403         if (!entry_text) {
 404                 return;
 405         }
 406 #ifdef DEBUG_PASSWORD
 407         debug("callback_return_password_and_enter: %s\n", entry_text);
 408 #else
 409         debug("callback_return_password_and_enter: (not printed)\n");
 410 #endif
 411         SAFE_FREE(state->password);
 412         state->password = strdup(entry_text);
 413         g_signal_emit_by_name(state->button_ok_creds, "clicked");
 414 }
 415 
 416 static void callback_do_storeauth(GtkWidget *widget,
     /* [<][>][^][v][top][bottom][index][help] */
 417                                   gpointer data)
 418 {
 419         struct join_state *state = (struct join_state *)data;
 420 
 421         debug("callback_do_storeauth called\n");
 422 
 423         SAFE_FREE(state->account);
 424         SAFE_FREE(state->password);
 425 
 426         callback_return_username(state->entry_account, (gpointer)state);
 427         callback_return_password(state->entry_password, (gpointer)state);
 428 
 429         if (state->window_creds_prompt) {
 430                 gtk_widget_destroy(GTK_WIDGET(state->window_creds_prompt));
 431                 state->window_creds_prompt = NULL;
 432         }
 433 }
 434 
 435 static void callback_continue(GtkWidget *widget,
     /* [<][>][^][v][top][bottom][index][help] */
 436                               gpointer data)
 437 {
 438         struct join_state *state = (struct join_state *)data;
 439 
 440         gtk_widget_grab_focus(GTK_WIDGET(state->button_ok));
 441         g_signal_emit_by_name(state->button_ok, "clicked");
 442 }
 443 
 444 static void callback_do_storeauth_and_continue(GtkWidget *widget,
     /* [<][>][^][v][top][bottom][index][help] */
 445                                                gpointer data)
 446 {
 447         callback_do_storeauth(widget, data);
 448         callback_continue(NULL, data);
 449 }
 450 
 451 static void callback_do_storeauth_and_scan(GtkWidget *widget,
     /* [<][>][^][v][top][bottom][index][help] */
 452                                            gpointer data)
 453 {
 454         struct join_state *state = (struct join_state *)data;
 455         callback_do_storeauth(widget, data);
 456         g_signal_emit_by_name(state->button_get_ous, "clicked");
 457 }
 458 
 459 static void callback_do_hostname_change(GtkWidget *widget,
     /* [<][>][^][v][top][bottom][index][help] */
 460                                         gpointer data)
 461 {
 462         GtkWidget *dialog;
 463         const char *str = NULL;
 464 
 465         struct join_state *state = (struct join_state *)data;
 466 
 467         switch (state->name_type_initial) {
 468                 case NetSetupDomainName: {
 469 #if 0
 470                         NET_API_STATUS status;
 471                         const char *newname;
 472                         char *p = NULL;
 473 
 474                         newname = strdup(gtk_label_get_text(GTK_LABEL(state->label_full_computer_name)));
 475                         if (!newname) {
 476                                 return;
 477                         }
 478 
 479                         p = strchr(newname, '.');
 480                         if (p) {
 481                                 *p = NULL;
 482                         }
 483 
 484                         if (!state->account || !state->password) {
 485                                 debug("callback_do_hostname_change: no creds yet\n");
 486                                 callback_creds_prompt(NULL, state,
 487                                                       "Enter the name and password of an account with permission to change a computer name in a the domain.",
 488                                                       callback_do_storeauth_and_continue);
 489                         }
 490 
 491                         if (!state->account || !state->password) {
 492                                 debug("callback_do_hostname_change: still no creds???\n");
 493                                 return;
 494                         }
 495 
 496                         status = NetRenameMachineInDomain(state->target_hostname,
 497                                                           newname,
 498                                                           state->account,
 499                                                           state->password,
 500                                                           NETSETUP_ACCT_CREATE);
 501                         SAFE_FREE(newname);
 502                         /* we renamed the machine in the domain */
 503                         if (status == 0) {
 504                                 return;
 505                         }
 506                         str = libnetapi_get_error_string(state->ctx, status);
 507 #else
 508                         str = "To be implemented: call NetRenameMachineInDomain\n";
 509 #endif
 510                         break;
 511                 }
 512                 case NetSetupWorkgroupName:
 513                         str = "To be implemented: call SetComputerNameEx\n";
 514                         break;
 515                 default:
 516                         break;
 517         }
 518 
 519         dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_parent),
 520                                         GTK_DIALOG_DESTROY_WITH_PARENT,
 521                                         GTK_MESSAGE_ERROR,
 522                                         GTK_BUTTONS_CLOSE,
 523                                         str);
 524 
 525         gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
 526         gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(state->window_main));
 527         g_signal_connect_swapped(dialog, "response",
 528                                  G_CALLBACK(gtk_widget_destroy),
 529                                  dialog);
 530         gtk_widget_show(dialog);
 531 }
 532 
 533 static void callback_creds_prompt(GtkWidget *widget,
     /* [<][>][^][v][top][bottom][index][help] */
 534                                   gpointer data,
 535                                   const char *label_string,
 536                                   gpointer cont_fn)
 537 {
 538         GtkWidget *window;
 539         GtkWidget *box1;
 540         GtkWidget *bbox;
 541         GtkWidget *button;
 542         GtkWidget *label;
 543 
 544         struct join_state *state = (struct join_state *)data;
 545 
 546         debug("callback_creds_prompt\n");
 547 
 548         window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
 549         gtk_window_set_modal(GTK_WINDOW(window), TRUE);
 550 
 551         gtk_window_set_title(GTK_WINDOW(window), "Computer Name Changes");
 552         gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
 553         gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
 554         gtk_widget_set_size_request(GTK_WIDGET(window), 380, 280);
 555         gtk_window_set_icon_from_file(GTK_WINDOW(window), SAMBA_ICON_PATH, NULL);
 556         gtk_window_set_transient_for(GTK_WINDOW(window), GTK_WINDOW(state->window_do_change));
 557         gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER_ALWAYS);
 558 
 559         g_signal_connect(G_OBJECT(window), "delete_event",
 560                          G_CALLBACK(callback_do_close_widget), NULL);
 561 
 562         state->window_creds_prompt = window;
 563         gtk_container_set_border_width(GTK_CONTAINER(window), 10);
 564 
 565         box1 = gtk_vbox_new(FALSE, 0);
 566 
 567         gtk_container_add(GTK_CONTAINER(window), box1);
 568 
 569         label = gtk_label_new(label_string);
 570         gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
 571         gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
 572 
 573         gtk_box_pack_start(GTK_BOX(box1), label, FALSE, FALSE, 0);
 574 
 575         gtk_widget_show(label);
 576 
 577         /* USER NAME */
 578         label = gtk_label_new("User name:");
 579         gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
 580         gtk_box_pack_start(GTK_BOX(box1), label, FALSE, FALSE, 0);
 581         gtk_widget_show(label);
 582 
 583         state->entry_account = gtk_entry_new();
 584         gtk_entry_set_max_length(GTK_ENTRY(state->entry_account), MAX_CRED_LEN);
 585         g_signal_connect(G_OBJECT(state->entry_account), "activate",
 586                          G_CALLBACK(callback_return_username_and_enter),
 587                          (gpointer)state);
 588         gtk_editable_select_region(GTK_EDITABLE(state->entry_account),
 589                                    0, GTK_ENTRY(state->entry_account)->text_length);
 590         gtk_box_pack_start(GTK_BOX(box1), state->entry_account, TRUE, TRUE, 0);
 591         gtk_widget_show(state->entry_account);
 592 
 593         /* PASSWORD */
 594         label = gtk_label_new("Password:");
 595         gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
 596         gtk_box_pack_start(GTK_BOX(box1), label, FALSE, FALSE, 0);
 597         gtk_widget_show(label);
 598 
 599         state->entry_password = gtk_entry_new();
 600         gtk_entry_set_max_length(GTK_ENTRY(state->entry_password), MAX_CRED_LEN);
 601         gtk_entry_set_visibility(GTK_ENTRY(state->entry_password), FALSE);
 602         g_signal_connect(G_OBJECT(state->entry_password), "activate",
 603                          G_CALLBACK(callback_return_password_and_enter),
 604                          (gpointer)state);
 605         gtk_editable_set_editable(GTK_EDITABLE(state->entry_password), TRUE);
 606         gtk_editable_select_region(GTK_EDITABLE(state->entry_password),
 607                                    0, GTK_ENTRY(state->entry_password)->text_length);
 608         gtk_box_pack_start(GTK_BOX(box1), state->entry_password, TRUE, TRUE, 0);
 609         gtk_widget_show(state->entry_password);
 610 
 611         /* BUTTONS */
 612         bbox = gtk_hbutton_box_new();
 613         gtk_container_set_border_width(GTK_CONTAINER(bbox), 5);
 614         gtk_container_add(GTK_CONTAINER(box1), bbox);
 615         gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);
 616         gtk_box_set_spacing(GTK_BOX(bbox), 10);
 617 
 618         state->button_ok_creds = gtk_button_new_from_stock(GTK_STOCK_OK);
 619         gtk_widget_grab_focus(GTK_WIDGET(state->button_ok_creds));
 620         gtk_container_add(GTK_CONTAINER(bbox), state->button_ok_creds);
 621         g_signal_connect(G_OBJECT(state->button_ok_creds), "clicked",
 622                          G_CALLBACK(cont_fn),
 623                          (gpointer)state);
 624         gtk_widget_show(state->button_ok_creds);
 625 
 626         button = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
 627         gtk_container_add(GTK_CONTAINER(bbox), button);
 628         g_signal_connect(G_OBJECT(button), "clicked",
 629                          G_CALLBACK(callback_do_freeauth),
 630                          (gpointer)state);
 631         gtk_widget_show_all(window);
 632 }
 633 
 634 static void callback_do_join(GtkWidget *widget,
     /* [<][>][^][v][top][bottom][index][help] */
 635                              gpointer data)
 636 {
 637         GtkWidget *dialog;
 638 
 639         NET_API_STATUS status;
 640         const char *err_str = NULL;
 641         uint32_t join_flags = 0;
 642         uint32_t unjoin_flags = 0;
 643         gboolean domain_join = FALSE;
 644         gboolean try_unjoin = FALSE;
 645         gboolean join_creds_required = TRUE;
 646         gboolean unjoin_creds_required = TRUE;
 647         const char *new_workgroup_type = NULL;
 648         const char *initial_workgroup_type = NULL;
 649         const char *account_ou = NULL;
 650 
 651         struct join_state *state = (struct join_state *)data;
 652 
 653         if (state->hostname_changed) {
 654                 callback_do_hostname_change(NULL, state);
 655                 return;
 656         }
 657 
 658         switch (state->name_type_initial) {
 659                 case NetSetupWorkgroupName:
 660                         initial_workgroup_type = "workgroup";
 661                         break;
 662                 case NetSetupDomainName:
 663                         initial_workgroup_type = "domain";
 664                         break;
 665                 default:
 666                         break;
 667         }
 668 
 669         switch (state->name_type_new) {
 670                 case NetSetupWorkgroupName:
 671                         new_workgroup_type = "workgroup";
 672                         break;
 673                 case NetSetupDomainName:
 674                         new_workgroup_type = "domain";
 675                         break;
 676                 default:
 677                         break;
 678         }
 679 
 680         account_ou = gtk_combo_box_get_active_text(GTK_COMBO_BOX(state->entry_ou_list));
 681         if (account_ou && strlen(account_ou) == 0) {
 682                 account_ou = NULL;
 683         }
 684 
 685         if ((state->name_type_initial != NetSetupDomainName) &&
 686             (state->name_type_new != NetSetupDomainName)) {
 687                 join_creds_required = FALSE;
 688                 unjoin_creds_required = FALSE;
 689         }
 690 
 691         if (state->name_type_new == NetSetupDomainName) {
 692                 domain_join = TRUE;
 693                 join_creds_required = TRUE;
 694                 join_flags = NETSETUP_JOIN_DOMAIN |
 695                              NETSETUP_ACCT_CREATE |
 696                              NETSETUP_DOMAIN_JOIN_IF_JOINED; /* for testing */
 697         }
 698 
 699         if ((state->name_type_initial == NetSetupDomainName) &&
 700             (state->name_type_new == NetSetupWorkgroupName)) {
 701                 try_unjoin = TRUE;
 702                 unjoin_creds_required = TRUE;
 703                 join_creds_required = FALSE;
 704                 unjoin_flags = NETSETUP_JOIN_DOMAIN |
 705                                NETSETUP_ACCT_DELETE |
 706                                NETSETUP_IGNORE_UNSUPPORTED_FLAGS;
 707         }
 708 
 709         if (try_unjoin) {
 710 
 711                 debug("callback_do_join: Unjoining\n");
 712 
 713                 if (unjoin_creds_required) {
 714                         if (!state->account || !state->password) {
 715                                 debug("callback_do_join: no creds yet\n");
 716                                 callback_creds_prompt(NULL, state,
 717                                                       "Enter the name and password of an account with permission to leave the domain.",
 718                                                       callback_do_storeauth_and_continue);
 719                         }
 720 
 721                         if (!state->account || !state->password) {
 722                                 debug("callback_do_join: still no creds???\n");
 723                                 return;
 724                         }
 725                 }
 726 
 727                 status = NetUnjoinDomain(state->target_hostname,
 728                                          state->account,
 729                                          state->password,
 730                                          unjoin_flags);
 731                 if (status != 0) {
 732                         callback_do_freeauth(NULL, state);
 733                         err_str = libnetapi_get_error_string(state->ctx, status);
 734                         g_print("callback_do_join: failed to unjoin (%s)\n",
 735                                 err_str);
 736 #if 0
 737 
 738         /* in fact we shouldn't annoy the user with an error message here */
 739 
 740                         dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_parent),
 741                                                         GTK_DIALOG_DESTROY_WITH_PARENT,
 742                                                         GTK_MESSAGE_ERROR,
 743                                                         GTK_BUTTONS_CLOSE,
 744                                                         "The following error occured attempting to unjoin the %s: \"%s\": %s",
 745                                                         initial_workgroup_type,
 746                                                         state->name_buffer_initial,
 747                                                         err_str);
 748                         gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
 749                         gtk_dialog_run(GTK_DIALOG(dialog));
 750                         gtk_widget_destroy(dialog);
 751 #endif
 752                 }
 753 
 754         }
 755 
 756         /* before prompting for creds, make sure we can find a dc */
 757 
 758         if (domain_join) {
 759 
 760                 struct DOMAIN_CONTROLLER_INFO *dc_info = NULL;
 761 
 762                 status = DsGetDcName(NULL,
 763                                      state->name_buffer_new,
 764                                      NULL,
 765                                      NULL,
 766                                      0,
 767                                      &dc_info);
 768                 if (status != 0) {
 769                         err_str = libnetapi_get_error_string(state->ctx, status);
 770                         g_print("callback_do_join: failed find dc (%s)\n", err_str);
 771 
 772                         dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_parent),
 773                                                         GTK_DIALOG_DESTROY_WITH_PARENT,
 774                                                         GTK_MESSAGE_ERROR,
 775                                                         GTK_BUTTONS_CLOSE,
 776                                                         "Failed to find a domain controller for domain: \"%s\": %s",
 777                                                         state->name_buffer_new,
 778                                                         err_str);
 779 
 780                         gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
 781                         gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(state->window_do_change));
 782                         g_signal_connect_swapped(dialog, "response",
 783                                                  G_CALLBACK(gtk_widget_destroy),
 784                                                  dialog);
 785 
 786                         gtk_widget_show(dialog);
 787 
 788                         return;
 789                 }
 790         }
 791 
 792         if (join_creds_required) {
 793                 if (!state->account || !state->password) {
 794                         debug("callback_do_join: no creds yet\n");
 795                         callback_creds_prompt(NULL, state,
 796                                               "Enter the name and password of an account with permission to join the domain.",
 797                                               callback_do_storeauth_and_continue);
 798                 }
 799 
 800                 if (!state->account || !state->password) {
 801                         debug("callback_do_join: still no creds???\n");
 802                         return;
 803                 }
 804         }
 805 
 806         debug("callback_do_join: Joining a %s named %s using join_flags 0x%08x ",
 807                 new_workgroup_type,
 808                 state->name_buffer_new,
 809                 join_flags);
 810         if (domain_join) {
 811                 debug("as %s ", state->account);
 812 #ifdef DEBUG_PASSWORD
 813                 debug("with %s ", state->password);
 814 #endif
 815         }
 816         debug("\n");
 817 
 818         status = NetJoinDomain(state->target_hostname,
 819                                state->name_buffer_new,
 820                                account_ou,
 821                                state->account,
 822                                state->password,
 823                                join_flags);
 824         if (status != 0) {
 825                 callback_do_freeauth(NULL, state);
 826                 err_str = libnetapi_get_error_string(state->ctx, status);
 827                 g_print("callback_do_join: failed to join (%s)\n", err_str);
 828 
 829                 dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_parent),
 830                                                 GTK_DIALOG_DESTROY_WITH_PARENT,
 831                                                 GTK_MESSAGE_ERROR,
 832                                                 GTK_BUTTONS_CLOSE,
 833                                                 "The following error occured attempting to join the %s: \"%s\": %s",
 834                                                 new_workgroup_type,
 835                                                 state->name_buffer_new,
 836                                                 err_str);
 837 
 838                 gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
 839                 gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(state->window_do_change));
 840                 g_signal_connect_swapped(dialog, "response",
 841                                          G_CALLBACK(gtk_widget_destroy),
 842                                          dialog);
 843 
 844                 gtk_widget_show(dialog);
 845 
 846                 return;
 847         }
 848 
 849         debug("callback_do_join: Successfully joined %s\n",
 850                 new_workgroup_type);
 851 
 852         callback_do_freeauth(NULL, state);
 853         dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_parent),
 854                                         GTK_DIALOG_DESTROY_WITH_PARENT,
 855                                         GTK_MESSAGE_INFO,
 856                                         GTK_BUTTONS_OK,
 857                                         "Welcome to the %s %s.",
 858                                         state->name_buffer_new,
 859                                         new_workgroup_type);
 860 
 861         gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
 862         gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(state->window_do_change));
 863         gtk_dialog_run(GTK_DIALOG(dialog));
 864         gtk_widget_destroy(dialog);
 865 
 866         callback_do_reboot(NULL, state->window_parent, state);
 867 }
 868 
 869 static void callback_enter_hostname_and_unlock(GtkWidget *widget,
     /* [<][>][^][v][top][bottom][index][help] */
 870                                                gpointer data)
 871 {
 872         const gchar *entry_text = NULL;
 873         char *str = NULL;
 874         struct join_state *state = (struct join_state *)data;
 875 
 876         entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
 877         debug("callback_enter_hostname_and_unlock: %s\n", entry_text);
 878         if (!entry_text || entry_text[0] == 0) {
 879                 state->hostname_changed = FALSE;
 880                 gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), FALSE);
 881                 gtk_label_set_text(GTK_LABEL(state->label_full_computer_name), "");
 882                 return;
 883         }
 884         if (strcasecmp(state->my_hostname, entry_text) == 0) {
 885                 state->hostname_changed = FALSE;
 886                 gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), FALSE);
 887                 /* return; */
 888         } else {
 889                 state->hostname_changed = TRUE;
 890         }
 891 
 892         if (state->name_type_initial == NetSetupDomainName) {
 893                 if (asprintf(&str, "%s.%s", entry_text, state->my_dnsdomain) == -1) {
 894                         return;
 895                 }
 896         } else {
 897                 if (asprintf(&str, "%s.", entry_text) == -1) {
 898                         return;
 899                 }
 900         }
 901         gtk_label_set_text(GTK_LABEL(state->label_full_computer_name), str);
 902         free(str);
 903 
 904         if (state->hostname_changed && entry_text && entry_text[0] != 0 && entry_text[0] != '.') {
 905                 gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), TRUE);
 906         }
 907 }
 908 
 909 static void callback_enter_computer_description_and_unlock(GtkWidget *widget,
     /* [<][>][^][v][top][bottom][index][help] */
 910                                                            gpointer data)
 911 {
 912         const gchar *entry_text = NULL;
 913         struct join_state *state = (struct join_state *)data;
 914         int string_unchanged = FALSE;
 915 
 916         entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
 917         debug("callback_enter_computer_description_and_unlock: %s\n",
 918                 entry_text);
 919 #if 0
 920         if (!entry_text || entry_text[0] == 0) {
 921                 string_unchanged = 1;
 922                 gtk_widget_set_sensitive(GTK_WIDGET(state->button_apply),
 923                                          FALSE);
 924                 return;
 925         }
 926 #endif
 927         if (entry_text && state->comment && strcasecmp(state->comment, entry_text) == 0) {
 928                 string_unchanged = TRUE;
 929                 gtk_widget_set_sensitive(GTK_WIDGET(state->button_apply),
 930                                          FALSE);
 931                 return;
 932         }
 933 
 934         gtk_widget_set_sensitive(GTK_WIDGET(state->button_apply), TRUE);
 935         SAFE_FREE(state->comment_new);
 936         state->comment_new = strdup(entry_text);
 937 
 938 }
 939 
 940 
 941 static void callback_enter_workgroup_and_unlock(GtkWidget *widget,
     /* [<][>][^][v][top][bottom][index][help] */
 942                                                 gpointer data)
 943 {
 944         const gchar *entry_text = NULL;
 945         struct join_state *state = (struct join_state *)data;
 946 
 947         entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
 948         debug("callback_enter_workgroup_and_unlock: %s\n", entry_text);
 949         if (!entry_text || entry_text[0] == 0) {
 950                 gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), FALSE);
 951                 return;
 952         }
 953         if ((strcasecmp(state->name_buffer_initial, entry_text) == 0) &&
 954             (state->name_type_initial == NetSetupWorkgroupName)) {
 955                 gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), FALSE);
 956                 return;
 957         }
 958         gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), TRUE);
 959         SAFE_FREE(state->name_buffer_new);
 960         state->name_buffer_new = strdup(entry_text);
 961         state->name_type_new = NetSetupWorkgroupName;
 962 }
 963 
 964 static void callback_enter_domain_and_unlock(GtkWidget *widget,
     /* [<][>][^][v][top][bottom][index][help] */
 965                                              gpointer data)
 966 {
 967         const gchar *entry_text = NULL;
 968         struct join_state *state = (struct join_state *)data;
 969 
 970         entry_text = gtk_entry_get_text(GTK_ENTRY(widget));
 971         debug("callback_enter_domain_and_unlock: %s\n", entry_text);
 972         if (!entry_text || entry_text[0] == 0) {
 973                 gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), FALSE);
 974                 return;
 975         }
 976         if ((strcasecmp(state->name_buffer_initial, entry_text) == 0) &&
 977             (state->name_type_initial == NetSetupDomainName)) {
 978                 gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), FALSE);
 979                 return;
 980         }
 981         gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), TRUE);
 982         gtk_widget_set_sensitive(GTK_WIDGET(state->entry_ou_list), TRUE);
 983         gtk_widget_set_sensitive(GTK_WIDGET(state->button_get_ous), TRUE);
 984         SAFE_FREE(state->name_buffer_new);
 985         state->name_buffer_new = strdup(entry_text);
 986         state->name_type_new = NetSetupDomainName;
 987 }
 988 
 989 static void callback_apply_continue(GtkWidget *widget,
     /* [<][>][^][v][top][bottom][index][help] */
 990                                     gpointer data)
 991 {
 992         struct join_state *state = (struct join_state *)data;
 993 
 994         gtk_widget_grab_focus(GTK_WIDGET(state->button_apply));
 995         g_signal_emit_by_name(state->button_apply, "clicked");
 996 }
 997 
 998 static void callback_do_join_workgroup(GtkWidget *widget,
     /* [<][>][^][v][top][bottom][index][help] */
 999                                        gpointer data)
1000 {
1001         struct join_state *state = (struct join_state *)data;
1002         debug("callback_do_join_workgroup choosen\n");
1003         gtk_widget_set_sensitive(GTK_WIDGET(state->entry_workgroup), TRUE);
1004         gtk_widget_grab_focus(GTK_WIDGET(state->entry_workgroup));
1005         gtk_widget_set_sensitive(GTK_WIDGET(state->entry_domain), FALSE);
1006         gtk_widget_set_sensitive(GTK_WIDGET(state->entry_ou_list), FALSE);
1007         gtk_widget_set_sensitive(GTK_WIDGET(state->button_get_ous), FALSE);
1008         callback_enter_workgroup_and_unlock(state->entry_workgroup, state); /* TEST */
1009 }
1010 
1011 static void callback_do_join_domain(GtkWidget *widget,
     /* [<][>][^][v][top][bottom][index][help] */
1012                                     gpointer data)
1013 {
1014         struct join_state *state = (struct join_state *)data;
1015         debug("callback_do_join_domain choosen\n");
1016         gtk_widget_set_sensitive(GTK_WIDGET(state->entry_domain), TRUE);
1017         gtk_widget_grab_focus(GTK_WIDGET(state->entry_domain));
1018         gtk_widget_set_sensitive(GTK_WIDGET(state->entry_workgroup), FALSE);
1019         callback_enter_domain_and_unlock(state->entry_domain, state); /* TEST */
1020 }
1021 
1022 static void callback_do_getous(GtkWidget *widget,
     /* [<][>][^][v][top][bottom][index][help] */
1023                                gpointer data)
1024 {
1025         NET_API_STATUS status;
1026         uint32_t num_ous = 0;
1027         const char **ous = NULL;
1028         int i;
1029         const char *domain = NULL;
1030         struct DOMAIN_CONTROLLER_INFO *dc_info = NULL;
1031         const char *err_str = NULL;
1032         GtkWidget *dialog;
1033 
1034         struct join_state *state = (struct join_state *)data;
1035 
1036         debug("callback_do_getous called\n");
1037 
1038         domain = state->name_buffer_new ? state->name_buffer_new : state->name_buffer_initial;
1039 
1040         status = DsGetDcName(NULL,
1041                              domain,
1042                              NULL,
1043                              NULL,
1044                              0,
1045                              &dc_info);
1046         if (status != 0) {
1047                 err_str = libnetapi_get_error_string(state->ctx, status);
1048                 g_print("callback_do_getous: failed find dc (%s)\n", err_str);
1049 
1050                 dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_parent),
1051                                                 GTK_DIALOG_DESTROY_WITH_PARENT,
1052                                                 GTK_MESSAGE_ERROR,
1053                                                 GTK_BUTTONS_CLOSE,
1054                                                 "Failed to find a domain controller for domain: \"%s\": %s",
1055                                                 domain,
1056                                                 err_str);
1057 
1058                 gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
1059                 gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(state->window_do_change));
1060                 g_signal_connect_swapped(dialog, "response",
1061                                          G_CALLBACK(gtk_widget_destroy),
1062                                          dialog);
1063 
1064                 gtk_widget_show(dialog);
1065 
1066                 return;
1067         }
1068 
1069         if (!state->account || !state->password) {
1070                 debug("callback_do_getous: no creds yet\n");
1071                 callback_creds_prompt(NULL, state,
1072                                       "Enter the name and password of an account with permission to join the domain.",
1073                                       callback_do_storeauth_and_scan);
1074         }
1075 
1076         if (!state->account || !state->password) {
1077                 debug("callback_do_getous: still no creds ???\n");
1078                 return;
1079         }
1080 
1081         status = NetGetJoinableOUs(state->target_hostname,
1082                                    domain,
1083                                    state->account,
1084                                    state->password,
1085                                    &num_ous, &ous);
1086         if (status != NET_API_STATUS_SUCCESS) {
1087                 callback_do_freeauth(NULL, state);
1088                 debug("failed to call NetGetJoinableOUs: %s\n",
1089                         libnetapi_get_error_string(state->ctx, status));
1090                 dialog = gtk_message_dialog_new(NULL,
1091                                                 GTK_DIALOG_DESTROY_WITH_PARENT,
1092                                                 GTK_MESSAGE_INFO,
1093                                                 GTK_BUTTONS_OK,
1094                                                 "Failed to query joinable OUs: %s",
1095                                                 libnetapi_get_error_string(state->ctx, status));
1096                 gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
1097                 gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(state->window_do_change));
1098                 gtk_dialog_run(GTK_DIALOG(dialog));
1099                 gtk_widget_destroy(dialog);
1100                 return;
1101         }
1102 
1103         for (i=0; i<state->stored_num_ous; i++) {
1104                 gtk_combo_box_remove_text(GTK_COMBO_BOX(state->entry_ou_list), 0);
1105         }
1106         for (i=0; i<num_ous && ous[i] != NULL; i++) {
1107                 gtk_combo_box_append_text(GTK_COMBO_BOX(state->entry_ou_list),
1108                                           ous[i]);
1109         }
1110         NetApiBufferFree(ous);
1111         state->stored_num_ous = num_ous;
1112         gtk_combo_box_set_active(GTK_COMBO_BOX(state->entry_ou_list), num_ous-1);
1113 }
1114 
1115 static void callback_do_change(GtkWidget *widget,
     /* [<][>][^][v][top][bottom][index][help] */
1116                                gpointer data)
1117 {
1118         GtkWidget *window;
1119         GtkWidget *box1;
1120         GtkWidget *bbox;
1121         GtkWidget *button_workgroup;
1122         GtkWidget *button_domain;
1123         GtkWidget *button;
1124         GtkWidget *label;
1125         GtkWidget *frame_horz;
1126         GtkWidget *vbox;
1127         GtkWidget *entry;
1128         GSList *group;
1129 
1130         struct join_state *state = (struct join_state *)data;
1131 
1132         debug("callback_do_change called\n");
1133 
1134 #if 0
1135         /* FIXME: add proper warnings for Samba as a DC */
1136         if (state->server_role == 3) {
1137                 GtkWidget *dialog;
1138                 callback_do_freeauth(NULL, state);
1139                 dialog = gtk_message_dialog_new(GTK_WINDOW(state->window_main),
1140                                                 GTK_DIALOG_DESTROY_WITH_PARENT,
1141                                                 GTK_MESSAGE_ERROR,
1142                                                 GTK_BUTTONS_OK,
1143                                                 "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.");
1144                 gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
1145                 g_signal_connect_swapped(dialog, "response",
1146                                          G_CALLBACK(gtk_widget_destroy),
1147                                          dialog);
1148 
1149                 gtk_widget_show(dialog);
1150                 return;
1151         }
1152 #endif
1153 
1154         state->button_ok = gtk_button_new_from_stock(GTK_STOCK_OK);
1155         state->button_get_ous = gtk_button_new_with_label("Scan for joinable OUs");
1156         window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
1157         gtk_window_set_modal(GTK_WINDOW(window), TRUE);
1158 
1159         gtk_window_set_title(GTK_WINDOW(window), "Computer Name Changes");
1160         gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
1161         gtk_widget_set_size_request(GTK_WIDGET(window), 480, 650);
1162         gtk_window_set_icon_from_file(GTK_WINDOW(window), SAMBA_ICON_PATH, NULL);
1163         gtk_window_set_transient_for(GTK_WINDOW(window), GTK_WINDOW(state->window_main));
1164         gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER_ALWAYS);
1165 
1166         g_signal_connect(G_OBJECT(window), "delete_event",
1167                          G_CALLBACK(callback_do_close_widget), NULL);
1168 
1169         gtk_container_set_border_width(GTK_CONTAINER(window), 10);
1170 
1171         box1 = gtk_vbox_new(FALSE, 0);
1172         gtk_container_add(GTK_CONTAINER(window), box1);
1173 
1174         label = gtk_label_new("You can change the name and membership of this computer. Changes may affect access to network ressources.");
1175         gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
1176         gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
1177         gtk_box_pack_start(GTK_BOX(box1), label, TRUE, TRUE, 0);
1178         gtk_widget_show(label);
1179 
1180         /* COMPUTER NAME */
1181         label = gtk_label_new("Computer name:");
1182         gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
1183         gtk_box_pack_start(GTK_BOX(box1), label, TRUE, TRUE, 0);
1184         gtk_widget_show(label);
1185 
1186         state->label_full_computer_name = gtk_label_new(NULL);
1187         {
1188                 entry = gtk_entry_new();
1189                 gtk_entry_set_max_length(GTK_ENTRY(entry), MAX_NETBIOS_NAME_LEN);
1190                 g_signal_connect(G_OBJECT(entry), "changed",
1191                                  G_CALLBACK(callback_enter_hostname_and_unlock),
1192                                  (gpointer)state);
1193                 gtk_entry_set_text(GTK_ENTRY(entry), state->my_hostname);
1194                 gtk_editable_select_region(GTK_EDITABLE(entry),
1195                                            0, GTK_ENTRY(entry)->text_length);
1196 
1197                 gtk_editable_set_editable(GTK_EDITABLE(entry), TRUE); /* ! */
1198                 gtk_box_pack_start(GTK_BOX(box1), entry, TRUE, TRUE, 0);
1199                 gtk_widget_show(entry);
1200         }
1201 
1202         /* FULL COMPUTER NAME */
1203         label = gtk_label_new("Full computer name:");
1204         gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
1205         gtk_box_pack_start(GTK_BOX(box1), label, TRUE, TRUE, 0);
1206         gtk_widget_show(label);
1207 
1208         {
1209                 const gchar *entry_text;
1210                 char *str = NULL;
1211                 entry_text = gtk_entry_get_text(GTK_ENTRY(entry));
1212                 if (state->name_type_initial == NetSetupDomainName) {
1213                         if (asprintf(&str, "%s.%s", entry_text,
1214                                  state->my_dnsdomain) == -1) {
1215                                 return;
1216                         }
1217                 } else {
1218                         if (asprintf(&str, "%s.", entry_text) == -1) {
1219                                 return;
1220                         }
1221                 }
1222                 gtk_label_set_text(GTK_LABEL(state->label_full_computer_name),
1223                                    str);
1224                 free(str);
1225                 gtk_misc_set_alignment(GTK_MISC(state->label_full_computer_name), 0, 0);
1226                 gtk_box_pack_start(GTK_BOX(box1),
1227                                    state->label_full_computer_name, TRUE, TRUE, 0);
1228                 gtk_widget_show(state->label_full_computer_name);
1229         }
1230 
1231         /* BOX */
1232         frame_horz = gtk_frame_new ("Member Of");
1233         gtk_box_pack_start(GTK_BOX(box1), frame_horz, TRUE, TRUE, 10);
1234 
1235         vbox = gtk_vbox_new(FALSE, 0);
1236         gtk_container_set_border_width(GTK_CONTAINER(vbox), 10);
1237         gtk_container_add(GTK_CONTAINER(frame_horz), vbox);
1238 
1239         /* TWO ENTRIES */
1240         state->entry_workgroup = gtk_entry_new();
1241         state->entry_domain = gtk_entry_new();
1242 
1243         /* DOMAIN */
1244         button_domain = gtk_radio_button_new_with_label(NULL, "Domain");
1245         if (state->name_type_initial == NetSetupDomainName) {
1246                 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button_domain), TRUE);
1247         }
1248         gtk_box_pack_start(GTK_BOX(vbox), button_domain, TRUE, TRUE, 0);
1249         g_signal_connect(G_OBJECT(button_domain), "clicked",
1250                          G_CALLBACK(callback_do_join_domain),
1251                          (gpointer)state);
1252 
1253         {
1254                 gtk_entry_set_max_length(GTK_ENTRY(state->entry_domain), 50);
1255                 g_signal_connect(G_OBJECT(state->entry_domain), "changed",
1256                                  G_CALLBACK(callback_enter_domain_and_unlock),
1257                                  (gpointer)state);
1258                 g_signal_connect(G_OBJECT(state->entry_domain), "activate",
1259                                  G_CALLBACK(callback_continue),
1260                                  (gpointer)state);
1261                 if (state->name_type_initial == NetSetupDomainName) {
1262                         gtk_entry_set_text(GTK_ENTRY(state->entry_domain),
1263                                            state->name_buffer_initial);
1264                         gtk_widget_set_sensitive(state->entry_workgroup, FALSE);
1265                         gtk_widget_set_sensitive(state->entry_domain, TRUE);
1266                 }
1267                 gtk_editable_set_editable(GTK_EDITABLE(state->entry_domain), TRUE);
1268                 gtk_box_pack_start(GTK_BOX(vbox), state->entry_domain, TRUE, TRUE, 0);
1269                 gtk_widget_show(state->entry_domain);
1270         }
1271         gtk_widget_show(button_domain);
1272 
1273         /* WORKGROUP */
1274         group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(button_domain));
1275         button_workgroup = gtk_radio_button_new_with_label(group, "Workgroup");
1276         if (state->name_type_initial == NetSetupWorkgroupName) {
1277                 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button_workgroup), TRUE);
1278         }
1279         gtk_box_pack_start(GTK_BOX(vbox), button_workgroup, TRUE, TRUE, 0);
1280         g_signal_connect(G_OBJECT(button_workgroup), "clicked",
1281                          G_CALLBACK(callback_do_join_workgroup),
1282                          (gpointer)state);
1283         {
1284                 gtk_entry_set_max_length(GTK_ENTRY(state->entry_workgroup),
1285                                          MAX_NETBIOS_NAME_LEN);
1286                 g_signal_connect(G_OBJECT(state->entry_workgroup), "changed",
1287                                  G_CALLBACK(callback_enter_workgroup_and_unlock),
1288                                  (gpointer)state);
1289                 g_signal_connect(G_OBJECT(state->entry_workgroup), "activate",
1290                                  G_CALLBACK(callback_continue),
1291                                  (gpointer)state);
1292 
1293                 if (state->name_type_initial == NetSetupWorkgroupName) {
1294                         gtk_entry_set_text(GTK_ENTRY(state->entry_workgroup),
1295                                            state->name_buffer_initial);
1296                         gtk_widget_set_sensitive(GTK_WIDGET(state->entry_domain), FALSE);
1297                         gtk_widget_set_sensitive(GTK_WIDGET(state->entry_workgroup), TRUE);
1298                 }
1299                 gtk_box_pack_start(GTK_BOX(vbox), state->entry_workgroup, TRUE, TRUE, 0);
1300                 gtk_widget_show(state->entry_workgroup);
1301         }
1302         gtk_widget_show(button_workgroup);
1303 
1304         /* Advanced Options */
1305         frame_horz = gtk_frame_new("Advanced Options");
1306         gtk_box_pack_start(GTK_BOX(box1), frame_horz, TRUE, TRUE, 10);
1307 
1308         vbox = gtk_vbox_new(FALSE, 0);
1309         gtk_container_set_border_width(GTK_CONTAINER(vbox), 10);
1310         gtk_container_add(GTK_CONTAINER(frame_horz), vbox);
1311 
1312         /* OUs */
1313         gtk_container_add(GTK_CONTAINER(vbox), state->button_get_ous);
1314         gtk_widget_set_sensitive(GTK_WIDGET(state->button_get_ous), FALSE);
1315         g_signal_connect(G_OBJECT(state->button_get_ous), "clicked",
1316                          G_CALLBACK(callback_do_getous),
1317                          (gpointer)state);
1318 
1319         state->entry_ou_list = gtk_combo_box_entry_new_text();
1320         gtk_widget_set_sensitive(state->entry_ou_list, FALSE);
1321         if (state->name_type_initial == NetSetupWorkgroupName) {
1322                 gtk_widget_set_sensitive(state->entry_ou_list, FALSE);
1323                 gtk_widget_set_sensitive(state->button_get_ous, FALSE);
1324         }
1325         gtk_box_pack_start(GTK_BOX(vbox), state->entry_ou_list, TRUE, TRUE, 0);
1326         gtk_widget_show(state->entry_ou_list);
1327 
1328         {
1329                 state->label_winbind = gtk_check_button_new_with_label("Modify winbind configuration");
1330                 gtk_box_pack_start(GTK_BOX(vbox), state->label_winbind, TRUE, TRUE, 0);
1331                 gtk_widget_set_sensitive(state->label_winbind, FALSE);
1332         }
1333 
1334 
1335         /* BUTTONS */
1336         bbox = gtk_hbutton_box_new();
1337         gtk_container_set_border_width(GTK_CONTAINER(bbox), 5);
1338         gtk_container_add(GTK_CONTAINER(box1), bbox);
1339         gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);
1340         gtk_box_set_spacing(GTK_BOX(bbox), 10);
1341 
1342         state->window_do_change = window;
1343         gtk_widget_set_sensitive(GTK_WIDGET(state->button_ok), FALSE);
1344         gtk_container_add(GTK_CONTAINER(bbox), state->button_ok);
1345         g_signal_connect(G_OBJECT(state->button_ok), "clicked",
1346                          G_CALLBACK(callback_do_join),
1347                          (gpointer)state);
1348 
1349         button = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
1350         gtk_container_add(GTK_CONTAINER(bbox), button);
1351         g_signal_connect(G_OBJECT(button), "clicked",
1352                          G_CALLBACK(callback_do_freeauth_and_close),
1353                          (gpointer)state);
1354 
1355         gtk_widget_show_all(window);
1356 }
1357 
1358 static void callback_do_about(GtkWidget *widget,
     /* [<][>][^][v][top][bottom][index][help] */
1359                              gpointer data)
1360 {
1361         GdkPixbuf *logo;
1362         GError    *error = NULL;
1363         GtkWidget *about;
1364 
1365         struct join_state *state = (struct join_state *)data;
1366 
1367         debug("callback_do_about called\n");
1368 
1369         logo = gdk_pixbuf_new_from_file(SAMBA_IMAGE_PATH,
1370                                         &error);
1371         if (logo == NULL) {
1372                 g_print("failed to load logo from %s: %s\n",
1373                         SAMBA_IMAGE_PATH, error->message);
1374         }
1375 
1376         about = gtk_about_dialog_new();
1377         gtk_about_dialog_set_name(GTK_ABOUT_DIALOG(about), "Samba");
1378         gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(about), "3.2.0pre3");
1379         gtk_about_dialog_set_copyright(GTK_ABOUT_DIALOG(about),
1380                 "Copyright Andrew Tridgell and the Samba Team 1992-2008\n"
1381                 "Copyright Günther Deschner 2007-2008");
1382         gtk_about_dialog_set_license(GTK_ABOUT_DIALOG(about), "GPLv3");
1383         gtk_about_dialog_set_website(GTK_ABOUT_DIALOG(about), "http://www.samba.org");
1384         gtk_about_dialog_set_website_label(GTK_ABOUT_DIALOG(about), "http://www.samba.org");
1385         if (logo) {
1386                 gtk_about_dialog_set_logo(GTK_ABOUT_DIALOG(about), logo);
1387         }
1388         gtk_about_dialog_set_comments(GTK_ABOUT_DIALOG(about), "Samba gtk domain join utility");
1389         gtk_window_set_modal(GTK_WINDOW(about), TRUE);
1390         gtk_window_set_transient_for(GTK_WINDOW(about), GTK_WINDOW(state->window_main));
1391         g_signal_connect_swapped(about, "response",
1392                                  G_CALLBACK(gtk_widget_destroy),
1393                                  about);
1394 
1395         gtk_widget_show(about);
1396 }
1397 
1398 static int draw_main_window(struct join_state *state)
     /* [<][>][^][v][top][bottom][index][help] */
1399 {
1400         GtkWidget *window;
1401         GtkWidget *button;
1402         GtkWidget *label;
1403         GtkWidget *main_vbox;
1404         GtkWidget *vbox;
1405         GtkWidget *hbox;
1406         GtkWidget *bbox;
1407         GtkWidget *image;
1408         GtkWidget *table;
1409         GtkWidget *entry;
1410         GdkPixbuf *icon;
1411         GError    *error = NULL;
1412 
1413         icon = gdk_pixbuf_new_from_file(SAMBA_ICON_PATH,
1414                                         &error);
1415         if (icon == NULL) {
1416                 g_print("failed to load icon from %s : %s\n",
1417                         SAMBA_ICON_PATH, error->message);
1418         }
1419 
1420 #if 1
1421         image = gtk_image_new_from_file(SAMBA_IMAGE_PATH_SMALL);
1422 #else
1423         image = gtk_image_new_from_file("/usr/share/pixmaps/redhat-system_settings.png");
1424 #endif
1425         if (image == NULL) {
1426                 g_print("failed to load logo from %s : %s\n",
1427                         SAMBA_IMAGE_PATH_SMALL, error->message);
1428         }
1429 
1430         window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
1431         state->window_main = window;
1432 
1433         gtk_window_set_title(GTK_WINDOW(window), "Samba - Join Domain dialogue");
1434         gtk_widget_set_size_request(GTK_WIDGET(window), 600, 600);
1435         gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
1436         gtk_window_set_icon_from_file(GTK_WINDOW(window), SAMBA_ICON_PATH, NULL);
1437         gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER_ALWAYS);
1438 
1439         g_signal_connect(G_OBJECT(window), "delete_event",
1440                          G_CALLBACK(callback_delete_event), NULL);
1441 
1442         gtk_container_set_border_width(GTK_CONTAINER(window), 10);
1443 
1444         main_vbox = gtk_vbox_new(FALSE, 10);
1445         gtk_container_add(GTK_CONTAINER(window), main_vbox);
1446 
1447 #if 0
1448         gtk_box_pack_start(GTK_BOX(main_vbox), image, TRUE, TRUE, 10);
1449         gtk_widget_show(image);
1450 #endif
1451         /* Hbox */
1452         hbox = gtk_hbox_new(FALSE, 10);
1453         gtk_container_add(GTK_CONTAINER(main_vbox), hbox);
1454 
1455         {
1456 /*              gtk_box_pack_start(GTK_BOX(main_vbox), image, TRUE, TRUE, 10); */
1457 /*              gtk_misc_set_alignment(GTK_MISC(image), 0, 0); */
1458                 gtk_widget_set_size_request(GTK_WIDGET(image), 150, 40);
1459                 gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 10);
1460                 gtk_widget_show(image);
1461 
1462                 /* Label */
1463                 label = gtk_label_new("Samba uses the following information to identify your computer on the network.");
1464 /*              gtk_misc_set_alignment(GTK_MISC(label), 0, 0); */
1465                 gtk_widget_set_size_request(GTK_WIDGET(label), 400, 40);
1466                 gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
1467                 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
1468                 gtk_widget_show(label);
1469         }
1470 
1471         gtk_widget_show(hbox);
1472 
1473         vbox = gtk_vbox_new(FALSE, 0);
1474         gtk_container_set_border_width(GTK_CONTAINER(vbox), 10);
1475         gtk_container_add(GTK_CONTAINER(main_vbox), vbox);
1476 
1477         /* Table */
1478         table = gtk_table_new(6, 3, TRUE);
1479         gtk_table_set_row_spacings(GTK_TABLE(table), 5);
1480         gtk_table_set_col_spacings(GTK_TABLE(table), 5);
1481         gtk_container_add(GTK_CONTAINER(vbox), table);
1482 
1483         {
1484                 /* Label */
1485                 label = gtk_label_new("Computer description:");
1486                 gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
1487                 gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 0, 1);
1488                 gtk_widget_show(label);
1489 
1490                 state->button_apply = gtk_button_new_from_stock(GTK_STOCK_APPLY);
1491 
1492                 /* Entry */
1493                 entry = gtk_entry_new();
1494                 gtk_entry_set_max_length(GTK_ENTRY(entry), 256);
1495 
1496                 if (!state->target_hostname && state->uid != 0) {
1497                         gtk_widget_set_sensitive(GTK_WIDGET(entry), FALSE);
1498                 }
1499                 g_signal_connect(G_OBJECT(entry), "changed",
1500                                  G_CALLBACK(callback_enter_computer_description_and_unlock),
1501                                  state);
1502                 g_signal_connect(G_OBJECT(entry), "activate",
1503                                  G_CALLBACK(callback_apply_continue),
1504                                  (gpointer)state);
1505 
1506                 gtk_entry_set_text(GTK_ENTRY(entry), (char *)state->comment);
1507                 gtk_editable_set_editable(GTK_EDITABLE(entry), TRUE); /* ! */
1508                 gtk_table_attach_defaults(GTK_TABLE(table), entry, 1, 3, 0, 1);
1509                 gtk_widget_show(entry);
1510         }
1511 
1512         /* Label */
1513         label = gtk_label_new("For example: \"Samba \%v\".");
1514         gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
1515         gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
1516         gtk_table_attach_defaults(GTK_TABLE(table), label, 1, 3, 1, 2);
1517         gtk_widget_show(label);
1518 
1519         /* Label */
1520         label = gtk_label_new("Full computer name:");
1521         gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
1522         gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 2, 3);
1523         gtk_widget_show(label);
1524 
1525         {
1526                 /* Label */
1527                 char *str = NULL;
1528                 if (state->name_type_initial == NetSetupDomainName) {
1529                         if (asprintf(&str, "%s.%s", state->my_hostname,
1530                                  state->my_dnsdomain) == -1) {
1531                                 return -1;
1532                         }
1533                 } else {
1534                         if (asprintf(&str, "%s.", state->my_hostname) == -1) {
1535                                 return -1;
1536                         }
1537                 }
1538 
1539                 label = gtk_label_new(str);
1540                 SAFE_FREE(str);
1541                 gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
1542                 gtk_table_attach_defaults(GTK_TABLE(table), label, 1, 3, 2, 3);
1543                 gtk_widget_show(label);
1544         }
1545 
1546         /* Label */
1547         if (state->name_type_initial == NetSetupDomainName) {
1548                 label = gtk_label_new("Domain:");
1549         } else {
1550                 label = gtk_label_new("Workgroup:");
1551         }
1552         gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
1553         gtk_table_attach_defaults(GTK_TABLE(table), label, 0, 1, 3, 4);
1554         gtk_widget_show(label);
1555         state->label_current_name_type = label;
1556 
1557         /* Label */
1558         label = gtk_label_new(state->name_buffer_initial);
1559         gtk_misc_set_alignment(GTK_MISC(label), 0, 0);
1560         gtk_table_attach_defaults(GTK_TABLE(table), label, 1, 3, 3, 4);
1561         gtk_widget_show(label);
1562         state->label_current_name_buffer = label;
1563 
1564         {
1565                 hbox = gtk_hbox_new(FALSE, 0);
1566                 gtk_container_add(GTK_CONTAINER(vbox), hbox);
1567                 label = gtk_label_new("To rename this computer or join a domain, click Change.");
1568                 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
1569 
1570 
1571         }
1572 
1573         /* bbox */
1574         bbox = gtk_hbutton_box_new();
1575         gtk_container_set_border_width(GTK_CONTAINER(bbox), 5);
1576         gtk_container_add(GTK_CONTAINER(hbox), bbox);
1577         gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);
1578         gtk_box_set_spacing(GTK_BOX(bbox), 10);
1579 
1580         button = gtk_button_new_with_mnemonic("Ch_ange");
1581         g_signal_connect(G_OBJECT(button), "clicked",
1582                          G_CALLBACK(callback_do_change),
1583                          (gpointer)state);
1584         gtk_box_pack_start(GTK_BOX(bbox), button, TRUE, TRUE, 0);
1585         if (!state->target_hostname && state->uid != 0) {
1586                 gtk_widget_set_sensitive(GTK_WIDGET(button), FALSE);
1587         }
1588         gtk_widget_show(button);
1589 
1590         /* Label (hidden) */
1591         state->label_reboot = gtk_label_new(NULL);
1592         gtk_label_set_line_wrap(GTK_LABEL(state->label_reboot), TRUE);
1593         gtk_misc_set_alignment(GTK_MISC(state->label_reboot), 0, 0);
1594         gtk_box_pack_start(GTK_BOX(vbox), state->label_reboot, TRUE, TRUE, 0);
1595         if (!state->target_hostname && state->uid != 0) {
1596                 gtk_label_set_text(GTK_LABEL(state->label_reboot),
1597                            "You cannot change computer description as you're not running with root permissions");
1598         }
1599 
1600         gtk_widget_show(state->label_reboot);
1601 
1602 #if 0
1603         gtk_box_pack_start(GTK_BOX(vbox),
1604            create_bbox(window, TRUE, NULL, 10, 85, 20, GTK_BUTTONBOX_END),
1605                       TRUE, TRUE, 5);
1606 #endif
1607         {
1608 
1609                 GtkWidget *frame;
1610                 GtkWidget *bbox2;
1611                 GtkWidget *button2;
1612 
1613                 frame = gtk_frame_new(NULL);
1614                 bbox2 = gtk_hbutton_box_new();
1615 
1616                 gtk_container_set_border_width(GTK_CONTAINER(bbox2), 5);
1617                 gtk_container_add(GTK_CONTAINER(frame), bbox2);
1618 
1619                 /* Set the appearance of the Button Box */
1620                 gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox2), GTK_BUTTONBOX_END);
1621                 gtk_box_set_spacing(GTK_BOX(bbox2), 10);
1622                 /*gtk_button_box_set_child_size(GTK_BUTTON_BOX(bbox2), child_w, child_h);*/
1623 
1624                 button2 = gtk_button_new_from_stock(GTK_STOCK_OK);
1625                 gtk_container_add(GTK_CONTAINER(bbox2), button2);
1626                 g_signal_connect(G_OBJECT(button2), "clicked", G_CALLBACK(callback_do_exit), state);
1627 
1628                 button2 = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
1629                 gtk_container_add(GTK_CONTAINER(bbox2), button2);
1630                 g_signal_connect(G_OBJECT(button2), "clicked",
1631                                  G_CALLBACK(callback_delete_event),
1632                                  window);
1633 
1634                 gtk_container_add(GTK_CONTAINER(bbox2), state->button_apply);
1635                 g_signal_connect(G_OBJECT(state->button_apply), "clicked",
1636                                  G_CALLBACK(callback_apply_description_change),
1637                                  state);
1638                 gtk_widget_set_sensitive(GTK_WIDGET(state->button_apply), FALSE);
1639 
1640                 button2 = gtk_button_new_from_stock(GTK_STOCK_ABOUT);
1641                 gtk_container_add(GTK_CONTAINER(bbox2), button2);
1642                 g_signal_connect(G_OBJECT(button2), "clicked",
1643                                  G_CALLBACK(callback_do_about),
1644                                  state);
1645 #if 0
1646                 button2 = gtk_button_new_from_stock(GTK_STOCK_HELP);
1647                 gtk_container_add(GTK_CONTAINER(bbox2), button2);
1648                 g_signal_connect(G_OBJECT(button2), "clicked",
1649                                  G_CALLBACK(callback_do_about),
1650                                  window);
1651 #endif
1652                 gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 5);
1653         }
1654 
1655         gtk_widget_show_all(window);
1656 
1657         return 0;
1658 }
1659 
1660 static int init_join_state(struct join_state **state)
     /* [<][>][^][v][top][bottom][index][help] */
1661 {
1662         struct join_state *s;
1663 
1664         s = (struct join_state *)malloc(sizeof(struct join_state));
1665         if (!s) {
1666                 return -1;
1667         }
1668 
1669         memset(s, '\0', sizeof(struct join_state));
1670 
1671         *state = s;
1672 
1673         return 0;
1674 }
1675 
1676 static NET_API_STATUS get_server_properties(struct join_state *state)
     /* [<][>][^][v][top][bottom][index][help] */
1677 {
1678         struct SERVER_INFO_101 *info101 = NULL;
1679         struct SERVER_INFO_1005 *info1005 = NULL;
1680         NET_API_STATUS status;
1681 
1682         status = NetServerGetInfo(state->target_hostname,
1683                                   101,
1684                                   (uint8_t **)&info101);
1685         if (status == 0) {
1686                 state->comment = strdup(info101->sv101_comment);
1687                 if (!state->comment) {
1688                         return -1;
1689                 }
1690                 SAFE_FREE(state->my_hostname);
1691                 state->my_hostname = strdup(info101->sv101_name);
1692                 if (!state->my_hostname) {
1693                         return -1;
1694                 }
1695                 NetApiBufferFree(info101);
1696                 return NET_API_STATUS_SUCCESS;
1697         }
1698 
1699         switch (status) {
1700                 case 124: /* WERR_UNKNOWN_LEVEL */
1701                 case 50: /* WERR_NOT_SUPPORTED */
1702                         break;
1703                 default:
1704                         goto failed;
1705         }
1706 
1707         status = NetServerGetInfo(state->target_hostname,
1708                                   1005,
1709                                   (uint8_t **)&info1005);
1710         if (status == 0) {
1711                 state->comment = strdup(info1005->sv1005_comment);
1712                 if (!state->comment) {
1713                         return -1;
1714                 }
1715                 NetApiBufferFree(info1005);
1716                 return NET_API_STATUS_SUCCESS;
1717         }
1718 
1719  failed:
1720         printf("NetServerGetInfo failed with: %s\n",
1721                 libnetapi_get_error_string(state->ctx, status));
1722 
1723         return status;
1724 }
1725 
1726 static int initialize_join_state(struct join_state *state,
     /* [<][>][^][v][top][bottom][index][help] */
1727                                  const char *debug_level,
1728                                  const char *target_hostname,
1729                                  const char *target_username)
1730 {
1731         struct libnetapi_ctx *ctx = NULL;
1732         NET_API_STATUS status = 0;
1733 
1734         status = libnetapi_init(&ctx);
1735         if (status) {
1736                 return status;
1737         }
1738 
1739         if (debug_level) {
1740                 libnetapi_set_debuglevel(ctx, debug_level);
1741         }
1742 
1743         if (target_hostname) {
1744                 state->target_hostname = strdup(target_hostname);
1745                 if (!state->target_hostname) {
1746                         return -1;
1747                 }
1748         }
1749 
1750         if (target_username) {
1751                 char *puser = strdup(target_username);
1752                 char *p = NULL;
1753 
1754                 if ((p = strchr(puser,'%'))) {
1755                         size_t len;
1756                         *p = 0;
1757                         libnetapi_set_username(ctx, puser);
1758                         libnetapi_set_password(ctx, p+1);
1759                         len = strlen(p+1);
1760                         memset(strchr(target_username,'%')+1,'X',len);
1761                 } else {
1762                         libnetapi_set_username(ctx, puser);
1763                 }
1764                 free(puser);
1765         }
1766 
1767         {
1768                 char my_hostname[HOST_NAME_MAX];
1769                 const char *p = NULL;
1770                 struct hostent *hp = NULL;
1771 
1772                 if (gethostname(my_hostname, sizeof(my_hostname)) == -1) {
1773                         return -1;
1774                 }
1775 
1776                 p = strchr(my_hostname, '.');
1777                 if (p) {
1778                         my_hostname[strlen(my_hostname)-strlen(p)] = '\0';
1779                 }
1780                 state->my_hostname = strdup(my_hostname);
1781                 if (!state->my_hostname) {
1782                         return -1;
1783                 }
1784                 debug("state->my_hostname: %s\n", state->my_hostname);
1785 
1786                 hp = gethostbyname(my_hostname);
1787                 if (!hp || !hp->h_name || !*hp->h_name) {
1788                         return -1;
1789                 }
1790 
1791                 state->my_fqdn = strdup(hp->h_name);
1792                 if (!state->my_fqdn) {
1793                         return -1;
1794                 }
1795                 debug("state->my_fqdn: %s\n", state->my_fqdn);
1796 
1797                 p = strchr(state->my_fqdn, '.');
1798                 if (p) {
1799                         p++;
1800                         state->my_dnsdomain = strdup(p);
1801                 } else {
1802                         state->my_dnsdomain = strdup("");
1803                 }
1804                 if (!state->my_dnsdomain) {
1805                         return -1;
1806                 }
1807                 debug("state->my_dnsdomain: %s\n", state->my_dnsdomain);
1808         }
1809 
1810         {
1811                 const char *buffer = NULL;
1812                 uint16_t type = 0;
1813                 status = NetGetJoinInformation(state->target_hostname,
1814                                                &buffer,
1815                                                &type);
1816                 if (status != 0) {
1817                         printf("NetGetJoinInformation failed with: %s\n",
1818                                 libnetapi_get_error_string(state->ctx, status));
1819                         return status;
1820                 }
1821                 debug("NetGetJoinInformation gave: %s and %d\n", buffer, type);
1822                 state->name_buffer_initial = strdup(buffer);
1823                 if (!state->name_buffer_initial) {
1824                         return -1;
1825                 }
1826                 state->name_type_initial = type;
1827                 NetApiBufferFree((void *)buffer);
1828         }
1829 
1830         status = get_server_properties(state);
1831         if (status != 0) {
1832                 return -1;
1833         }
1834 
1835         state->uid = geteuid();
1836 
1837         state->ctx = ctx;
1838 
1839         return 0;
1840 }
1841 
1842 int main(int argc, char **argv)
     /* [<][>][^][v][top][bottom][index][help] */
1843 {
1844         GOptionContext *context = NULL;
1845         static const char *debug_level = NULL;
1846         static const char *target_hostname = NULL;
1847         static const char *target_username = NULL;
1848         struct join_state *state = NULL;
1849         GError *error = NULL;
1850         int ret = 0;
1851 
1852         static GOptionEntry entries[] = {
1853                 { "debug", 'd', 0, G_OPTION_ARG_STRING, &debug_level, "Debug level (for samba)", "N" },
1854                 { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "Verbose output", 0 },
1855                 { "target", 'S', 0, G_OPTION_ARG_STRING, &target_hostname, "Target hostname", 0 },
1856                 { "username", 'U', 0, G_OPTION_ARG_STRING, &target_username, "Target hostname", 0 },
1857                 { NULL }
1858         };
1859 
1860         context = g_option_context_new("- Samba domain join utility");
1861         g_option_context_add_main_entries(context, entries, NULL);
1862 /*      g_option_context_add_main_entries(context, entries, GETTEXT_PACKAGE); */
1863         g_option_context_add_group(context, gtk_get_option_group(TRUE));
1864         g_option_context_parse(context, &argc, &argv, &error);
1865 
1866         gtk_init(&argc, &argv);
1867         g_set_application_name("Samba");
1868 
1869         ret = init_join_state(&state);
1870         if (ret) {
1871                 return ret;
1872         }
1873 
1874         ret = initialize_join_state(state, debug_level,
1875                                     target_hostname,
1876                                     target_username);
1877         if (ret) {
1878                 return ret;
1879         }
1880 
1881         draw_main_window(state);
1882 
1883         gtk_main();
1884 
1885         do_cleanup(state);
1886 
1887         return 0;
1888 }

/* [<][>][^][v][top][bottom][index][help] */