1/* 2 Unix SMB/Netbios implementation. 3 Version 2.0 4 SMB client GTK+ tree-based application 5 Copyright (C) Andrew Tridgell 1998 6 Copyright (C) Richard Sharpe 2001 7 Copyright (C) John Terpstra 2001 8 9 This program is free software; you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation; either version 2 of the License, or 12 (at your option) any later version. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program; if not, write to the Free Software 21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 22*/ 23 24/* example-gtk+ application, ripped off from the gtk+ tree.c sample */ 25 26#include <stdio.h> 27#include <errno.h> 28#include <gtk/gtk.h> 29#include "libsmbclient.h" 30 31static GtkWidget *clist; 32 33struct tree_data { 34 35 guint32 type; /* Type of tree item, an SMBC_TYPE */ 36 char name[256]; /* May need to change this later */ 37 38}; 39 40void error_message(gchar *message) { 41 42 GtkWidget *dialog, *label, *okay_button; 43 44 /* Create the widgets */ 45 46 dialog = gtk_dialog_new(); 47 gtk_window_set_modal(GTK_WINDOW(dialog), TRUE); 48 label = gtk_label_new (message); 49 okay_button = gtk_button_new_with_label("Okay"); 50 51 /* Ensure that the dialog box is destroyed when the user clicks ok. */ 52 53 gtk_signal_connect_object (GTK_OBJECT (okay_button), "clicked", 54 GTK_SIGNAL_FUNC (gtk_widget_destroy), 55 GTK_OBJECT(dialog)); 56 gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->action_area), 57 okay_button); 58 59 /* Add the label, and show everything we've added to the dialog. */ 60 61 gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox), 62 label); 63 gtk_widget_show_all (dialog); 64} 65 66/* 67 * We are given a widget, and we want to retrieve its URL so we 68 * can do a directory listing. 69 * 70 * We walk back up the tree, picking up pieces until we hit a server or 71 * workgroup type and return a path from there 72 */ 73 74static char path_string[1024]; 75 76char *get_path(GtkWidget *item) 77{ 78 GtkWidget *p = item; 79 struct tree_data *pd; 80 char *comps[1024]; /* We keep pointers to the components here */ 81 int i = 0, j, level,type; 82 83 /* Walk back up the tree, getting the private data */ 84 85 level = GTK_TREE(item->parent)->level; 86 87 /* Pick up this item's component info */ 88 89 pd = (struct tree_data *)gtk_object_get_user_data(GTK_OBJECT(item)); 90 91 comps[i++] = pd->name; 92 type = pd->type; 93 94 while (level > 0 && type != SMBC_SERVER && type != SMBC_WORKGROUP) { 95 96 /* Find the parent and extract the data etc ... */ 97 98 p = GTK_WIDGET(p->parent); 99 p = GTK_WIDGET(GTK_TREE(p)->tree_owner); 100 101 pd = (struct tree_data *)gtk_object_get_user_data(GTK_OBJECT(p)); 102 103 level = GTK_TREE(item->parent)->level; 104 105 comps[i++] = pd->name; 106 type = pd->type; 107 108 } 109 110 /* 111 * Got a list of comps now, should check that we did not hit a workgroup 112 * when we got other things as well ... Later 113 * 114 * Now, build the path 115 */ 116 117 snprintf(path_string, sizeof(path_string), "smb:/"); 118 119 for (j = i - 1; j >= 0; j--) { 120 121 strncat(path_string, "/", sizeof(path_string) - strlen(path_string)); 122 strncat(path_string, comps[j], sizeof(path_string) - strlen(path_string)); 123 124 } 125 126 fprintf(stdout, "Path string = %s\n", path_string); 127 128 return path_string; 129 130} 131 132struct tree_data *make_tree_data(guint32 type, const char *name) 133{ 134 struct tree_data *p = (struct tree_data *)malloc(sizeof(struct tree_data)); 135 136 if (p) { 137 138 p->type = type; 139 strncpy(p->name, name, sizeof(p->name)); 140 141 } 142 143 return p; 144 145} 146 147/* Note that this is called every time the user clicks on an item, 148 whether it is already selected or not. */ 149static void cb_select_child (GtkWidget *root_tree, GtkWidget *child, 150 GtkWidget *subtree) 151{ 152 gint dh, err, dirlen; 153 char dirbuf[512]; 154 struct smbc_dirent *dirp; 155 struct stat st1; 156 char path[1024], path1[1024]; 157 158 g_print ("select_child called for root tree %p, subtree %p, child %p\n", 159 root_tree, subtree, child); 160 161 /* Now, figure out what it is, and display it in the clist ... */ 162 163 gtk_clist_clear(GTK_CLIST(clist)); /* Clear the CLIST */ 164 165 /* Now, get the private data for the subtree */ 166 167 strncpy(path, get_path(child), 1024); 168 169 if ((dh = smbc_opendir(path)) < 0) { /* Handle error */ 170 171 g_print("cb_select_child: Could not open dir %s, %s\n", path, 172 strerror(errno)); 173 174 gtk_main_quit(); 175 176 return; 177 178 } 179 180 while ((err = smbc_getdents(dh, (struct smbc_dirent *)dirbuf, 181 sizeof(dirbuf))) != 0) { 182 183 if (err < 0) { 184 185 g_print("cb_select_child: Could not read dir %s, %s\n", path, 186 strerror(errno)); 187 188 gtk_main_quit(); 189 190 return; 191 192 } 193 194 dirp = (struct smbc_dirent *)dirbuf; 195 196 while (err > 0) { 197 gchar col1[128], col2[128], col3[128], col4[128]; 198 gchar *rowdata[4] = {col1, col2, col3, col4}; 199 200 dirlen = dirp->dirlen; 201 202 /* Format each of the items ... */ 203 204 strncpy(col1, dirp->name, 128); 205 206 col2[0] = col3[0] = col4[0] = (char)0; 207 208 switch (dirp->smbc_type) { 209 210 case SMBC_WORKGROUP: 211 212 break; 213 214 case SMBC_SERVER: 215 216 strncpy(col2, (dirp->comment?dirp->comment:""), 128); 217 218 break; 219 220 case SMBC_FILE_SHARE: 221 222 strncpy(col2, (dirp->comment?dirp->comment:""), 128); 223 224 break; 225 226 case SMBC_PRINTER_SHARE: 227 228 strncpy(col2, (dirp->comment?dirp->comment:""), 128); 229 break; 230 231 case SMBC_COMMS_SHARE: 232 233 break; 234 235 case SMBC_IPC_SHARE: 236 237 break; 238 239 case SMBC_DIR: 240 case SMBC_FILE: 241 242 /* Get stats on the file/dir and see what we have */ 243 244 if ((strcmp(dirp->name, ".") != 0) && 245 (strcmp(dirp->name, "..") != 0)) { 246 247 strncpy(path1, path, sizeof(path1)); 248 strncat(path1, "/", sizeof(path) - strlen(path)); 249 strncat(path1, dirp->name, sizeof(path) - strlen(path)); 250 251 if (smbc_stat(path1, &st1) < 0) { 252 253 if (errno != EBUSY) { 254 255 g_print("cb_select_child: Could not stat file %s, %s\n", path1, 256 strerror(errno)); 257 258 gtk_main_quit(); 259 260 return; 261 262 } 263 else { 264 265 strncpy(col2, "Device or resource busy", sizeof(col2)); 266 267 } 268 } 269 else { 270 /* Now format each of the relevant things ... */ 271 272 snprintf(col2, sizeof(col2), "%c%c%c%c%c%c%c%c%c(%0X)", 273 (st1.st_mode&S_IRUSR?'r':'-'), 274 (st1.st_mode&S_IWUSR?'w':'-'), 275 (st1.st_mode&S_IXUSR?'x':'-'), 276 (st1.st_mode&S_IRGRP?'r':'-'), 277 (st1.st_mode&S_IWGRP?'w':'-'), 278 (st1.st_mode&S_IXGRP?'x':'-'), 279 (st1.st_mode&S_IROTH?'r':'-'), 280 (st1.st_mode&S_IWOTH?'w':'-'), 281 (st1.st_mode&S_IXOTH?'x':'-'), 282 st1.st_mode); 283 snprintf(col3, sizeof(col3), "%u", st1.st_size); 284 snprintf(col4, sizeof(col4), "%s", ctime(&st1.st_mtime)); 285 } 286 } 287 288 break; 289 290 default: 291 292 break; 293 } 294 295 gtk_clist_append(GTK_CLIST(clist), rowdata); 296 297 (char *)dirp += dirlen; 298 err -= dirlen; 299 300 } 301 302 } 303 304} 305 306/* Note that this is never called */ 307static void cb_unselect_child( GtkWidget *root_tree, 308 GtkWidget *child, 309 GtkWidget *subtree ) 310{ 311 g_print ("unselect_child called for root tree %p, subtree %p, child %p\n", 312 root_tree, subtree, child); 313} 314 315/* for all the GtkItem:: and GtkTreeItem:: signals */ 316static void cb_itemsignal( GtkWidget *item, 317 gchar *signame ) 318{ 319 GtkWidget *real_tree, *aitem, *subtree; 320 gchar *name; 321 GtkLabel *label; 322 gint dh, err, dirlen, level; 323 char dirbuf[512]; 324 struct smbc_dirent *dirp; 325 326 label = GTK_LABEL (GTK_BIN (item)->child); 327 /* Get the text of the label */ 328 gtk_label_get (label, &name); 329 330 level = GTK_TREE(item->parent)->level; 331 332 /* Get the level of the tree which the item is in */ 333 g_print ("%s called for item %s->%p, level %d\n", signame, name, 334 item, GTK_TREE (item->parent)->level); 335 336 real_tree = GTK_TREE_ITEM_SUBTREE(item); /* Get the subtree */ 337 338 if (strncmp(signame, "expand", 6) == 0) { /* Expand called */ 339 char server[128]; 340 341 if ((dh = smbc_opendir(get_path(item))) < 0) { /* Handle error */ 342 gchar errmsg[256]; 343 344 g_print("cb_itemsignal: Could not open dir %s, %s\n", get_path(item), 345 strerror(errno)); 346 347 snprintf(errmsg, sizeof(errmsg), "cb_itemsignal: Could not open dir %s, %s\n", get_path(item), strerror(errno)); 348 349 error_message(errmsg); 350 351 /* gtk_main_quit();*/ 352 353 return; 354 355 } 356 357 while ((err = smbc_getdents(dh, (struct smbc_dirent *)dirbuf, 358 sizeof(dirbuf))) != 0) { 359 360 if (err < 0) { /* An error, report it */ 361 gchar errmsg[256]; 362 363 g_print("cb_itemsignal: Could not read dir smbc://, %s\n", 364 strerror(errno)); 365 366 snprintf(errmsg, sizeof(errmsg), "cb_itemsignal: Could not read dir smbc://, %s\n", strerror(errno)); 367 368 error_message(errmsg); 369 370 /* gtk_main_quit();*/ 371 372 return; 373 374 } 375 376 dirp = (struct smbc_dirent *)dirbuf; 377 378 while (err > 0) { 379 struct tree_data *my_data; 380 381 dirlen = dirp->dirlen; 382 383 my_data = make_tree_data(dirp->smbc_type, dirp->name); 384 385 if (!my_data) { 386 387 g_print("Could not allocate space for tree_data: %s\n", 388 dirp->name); 389 390 gtk_main_quit(); 391 return; 392 393 } 394 395 aitem = gtk_tree_item_new_with_label(dirp->name); 396 397 /* Connect all GtkItem:: and GtkTreeItem:: signals */ 398 gtk_signal_connect (GTK_OBJECT(aitem), "select", 399 GTK_SIGNAL_FUNC(cb_itemsignal), "select"); 400 gtk_signal_connect (GTK_OBJECT(aitem), "deselect", 401 GTK_SIGNAL_FUNC(cb_itemsignal), "deselect"); 402 gtk_signal_connect (GTK_OBJECT(aitem), "toggle", 403 GTK_SIGNAL_FUNC(cb_itemsignal), "toggle"); 404 gtk_signal_connect (GTK_OBJECT(aitem), "expand", 405 GTK_SIGNAL_FUNC(cb_itemsignal), "expand"); 406 gtk_signal_connect (GTK_OBJECT(aitem), "collapse", 407 GTK_SIGNAL_FUNC(cb_itemsignal), "collapse"); 408 /* Add it to the parent tree */ 409 gtk_tree_append (GTK_TREE(real_tree), aitem); 410 411 gtk_widget_show (aitem); 412 413 gtk_object_set_user_data(GTK_OBJECT(aitem), (gpointer)my_data); 414 415 fprintf(stdout, "Added: %s, len: %u\n", dirp->name, dirlen); 416 417 if (dirp->smbc_type != SMBC_FILE && 418 dirp->smbc_type != SMBC_IPC_SHARE && 419 (strcmp(dirp->name, ".") != 0) && 420 (strcmp(dirp->name, "..") !=0)){ 421 422 subtree = gtk_tree_new(); 423 gtk_tree_item_set_subtree(GTK_TREE_ITEM(aitem), subtree); 424 425 gtk_signal_connect(GTK_OBJECT(subtree), "select_child", 426 GTK_SIGNAL_FUNC(cb_select_child), real_tree); 427 gtk_signal_connect(GTK_OBJECT(subtree), "unselect_child", 428 GTK_SIGNAL_FUNC(cb_unselect_child), real_tree); 429 430 } 431 432 (char *)dirp += dirlen; 433 err -= dirlen; 434 435 } 436 437 } 438 439 smbc_closedir(dh); 440 441 } 442 else if (strncmp(signame, "collapse", 8) == 0) { 443 GtkWidget *subtree = gtk_tree_new(); 444 445 gtk_tree_remove_items(GTK_TREE(real_tree), GTK_TREE(real_tree)->children); 446 447 gtk_tree_item_set_subtree(GTK_TREE_ITEM(item), subtree); 448 449 gtk_signal_connect (GTK_OBJECT(subtree), "select_child", 450 GTK_SIGNAL_FUNC(cb_select_child), real_tree); 451 gtk_signal_connect (GTK_OBJECT(subtree), "unselect_child", 452 GTK_SIGNAL_FUNC(cb_unselect_child), real_tree); 453 454 } 455 456} 457 458static void cb_selection_changed( GtkWidget *tree ) 459{ 460 GList *i; 461 462 g_print ("selection_change called for tree %p\n", tree); 463 g_print ("selected objects are:\n"); 464 465 i = GTK_TREE_SELECTION(tree); 466 while (i){ 467 gchar *name; 468 GtkLabel *label; 469 GtkWidget *item; 470 471 /* Get a GtkWidget pointer from the list node */ 472 item = GTK_WIDGET (i->data); 473 label = GTK_LABEL (GTK_BIN (item)->child); 474 gtk_label_get (label, &name); 475 g_print ("\t%s on level %d\n", name, GTK_TREE 476 (item->parent)->level); 477 i = i->next; 478 } 479} 480 481/* 482 * Expand or collapse the whole network ... 483 */ 484static void cb_wholenet(GtkWidget *item, gchar *signame) 485{ 486 GtkWidget *real_tree, *aitem, *subtree; 487 gchar *name; 488 GtkLabel *label; 489 gint dh, err, dirlen; 490 char dirbuf[512]; 491 struct smbc_dirent *dirp; 492 493 label = GTK_LABEL (GTK_BIN (item)->child); 494 gtk_label_get (label, &name); 495 g_print ("%s called for item %s->%p, level %d\n", signame, name, 496 item, GTK_TREE (item->parent)->level); 497 498 real_tree = GTK_TREE_ITEM_SUBTREE(item); /* Get the subtree */ 499 500 if (strncmp(signame, "expand", 6) == 0) { /* Expand called */ 501 502 if ((dh = smbc_opendir("smb://")) < 0) { /* Handle error */ 503 504 g_print("cb_wholenet: Could not open dir smbc://, %s\n", 505 strerror(errno)); 506 507 gtk_main_quit(); 508 509 return; 510 511 } 512 513 while ((err = smbc_getdents(dh, (struct smbc_dirent *)dirbuf, 514 sizeof(dirbuf))) != 0) { 515 516 if (err < 0) { /* An error, report it */ 517 518 g_print("cb_wholenet: Could not read dir smbc://, %s\n", 519 strerror(errno)); 520 521 gtk_main_quit(); 522 523 return; 524 525 } 526 527 dirp = (struct smbc_dirent *)dirbuf; 528 529 while (err > 0) { 530 struct tree_data *my_data; 531 532 dirlen = dirp->dirlen; 533 534 my_data = make_tree_data(dirp->smbc_type, dirp->name); 535 536 aitem = gtk_tree_item_new_with_label(dirp->name); 537 538 /* Connect all GtkItem:: and GtkTreeItem:: signals */ 539 gtk_signal_connect (GTK_OBJECT(aitem), "select", 540 GTK_SIGNAL_FUNC(cb_itemsignal), "select"); 541 gtk_signal_connect (GTK_OBJECT(aitem), "deselect", 542 GTK_SIGNAL_FUNC(cb_itemsignal), "deselect"); 543 gtk_signal_connect (GTK_OBJECT(aitem), "toggle", 544 GTK_SIGNAL_FUNC(cb_itemsignal), "toggle"); 545 gtk_signal_connect (GTK_OBJECT(aitem), "expand", 546 GTK_SIGNAL_FUNC(cb_itemsignal), "expand"); 547 gtk_signal_connect (GTK_OBJECT(aitem), "collapse", 548 GTK_SIGNAL_FUNC(cb_itemsignal), "collapse"); 549 550 gtk_tree_append (GTK_TREE(real_tree), aitem); 551 /* Show it - this can be done at any time */ 552 gtk_widget_show (aitem); 553 554 gtk_object_set_user_data(GTK_OBJECT(aitem), (gpointer)my_data); 555 556 fprintf(stdout, "Added: %s, len: %u\n", dirp->name, dirlen); 557 558 subtree = gtk_tree_new(); 559 560 gtk_tree_item_set_subtree(GTK_TREE_ITEM(aitem), subtree); 561 562 gtk_signal_connect(GTK_OBJECT(subtree), "select_child", 563 GTK_SIGNAL_FUNC(cb_select_child), real_tree); 564 gtk_signal_connect(GTK_OBJECT(subtree), "unselect_child", 565 GTK_SIGNAL_FUNC(cb_unselect_child), real_tree); 566 567 (char *)dirp += dirlen; 568 err -= dirlen; 569 570 } 571 572 } 573 574 smbc_closedir(dh); 575 576 } 577 else { /* Must be collapse ... FIXME ... */ 578 GtkWidget *subtree = gtk_tree_new(); 579 580 gtk_tree_remove_items(GTK_TREE(real_tree), GTK_TREE(real_tree)->children); 581 582 gtk_tree_item_set_subtree(GTK_TREE_ITEM(item), subtree); 583 584 gtk_signal_connect (GTK_OBJECT(subtree), "select_child", 585 GTK_SIGNAL_FUNC(cb_select_child), real_tree); 586 gtk_signal_connect (GTK_OBJECT(subtree), "unselect_child", 587 GTK_SIGNAL_FUNC(cb_unselect_child), real_tree); 588 589 590 } 591 592} 593 594/* Should put up a dialog box to ask the user for username and password */ 595 596static void 597auth_fn(const char *server, const char *share, 598 char *workgroup, int wgmaxlen, char *username, int unmaxlen, 599 char *password, int pwmaxlen) 600{ 601 602 strncpy(username, "test", unmaxlen); 603 strncpy(password, "test", pwmaxlen); 604 605} 606 607static char *col_titles[] = { 608 "Name", "Attributes", "Size", "Modification Date", 609}; 610 611int main( int argc, 612 char *argv[] ) 613{ 614 GtkWidget *window, *scrolled_win, *scrolled_win2, *tree; 615 GtkWidget *subtree, *item, *main_hbox, *r_pane, *l_pane; 616 gint err, dh; 617 gint i; 618 char dirbuf[512]; 619 struct smbc_dirent *dirp; 620 621 gtk_init (&argc, &argv); 622 623 /* Init the smbclient library */ 624 625 err = smbc_init(auth_fn, 10); 626 627 /* Print an error response ... */ 628 629 if (err < 0) { 630 631 fprintf(stderr, "smbc_init returned %s (%i)\nDo you have a ~/.smb/smb.conf file?\n", strerror(errno), errno); 632 exit(1); 633 634 } 635 636 /* a generic toplevel window */ 637 window = gtk_window_new (GTK_WINDOW_TOPLEVEL); 638 gtk_widget_set_name(window, "main browser window"); 639 gtk_signal_connect (GTK_OBJECT(window), "delete_event", 640 GTK_SIGNAL_FUNC (gtk_main_quit), NULL); 641 gtk_window_set_title(GTK_WINDOW(window), "The Linux Windows Network Browser"); 642 gtk_widget_set_usize(GTK_WIDGET(window), 750, -1); 643 gtk_container_set_border_width (GTK_CONTAINER(window), 5); 644 645 gtk_widget_show (window); 646 647 /* A container for the two panes ... */ 648 649 main_hbox = gtk_hbox_new(FALSE, 1); 650 gtk_container_border_width(GTK_CONTAINER(main_hbox), 1); 651 gtk_container_add(GTK_CONTAINER(window), main_hbox); 652 653 gtk_widget_show(main_hbox); 654 655 l_pane = gtk_hpaned_new(); 656 gtk_paned_gutter_size(GTK_PANED(l_pane), (GTK_PANED(l_pane))->handle_size); 657 r_pane = gtk_hpaned_new(); 658 gtk_paned_gutter_size(GTK_PANED(r_pane), (GTK_PANED(r_pane))->handle_size); 659 gtk_container_add(GTK_CONTAINER(main_hbox), l_pane); 660 gtk_widget_show(l_pane); 661 662 /* A generic scrolled window */ 663 scrolled_win = gtk_scrolled_window_new (NULL, NULL); 664 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win), 665 GTK_POLICY_AUTOMATIC, 666 GTK_POLICY_AUTOMATIC); 667 gtk_widget_set_usize (scrolled_win, 150, 200); 668 gtk_container_add (GTK_CONTAINER(l_pane), scrolled_win); 669 gtk_widget_show (scrolled_win); 670 671 /* Another generic scrolled window */ 672 scrolled_win2 = gtk_scrolled_window_new (NULL, NULL); 673 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win2), 674 GTK_POLICY_AUTOMATIC, 675 GTK_POLICY_AUTOMATIC); 676 gtk_widget_set_usize (scrolled_win2, 150, 200); 677 gtk_paned_add2 (GTK_PANED(l_pane), scrolled_win2); 678 gtk_widget_show (scrolled_win2); 679 680 /* Create the root tree */ 681 tree = gtk_tree_new(); 682 g_print ("root tree is %p\n", tree); 683 /* connect all GtkTree:: signals */ 684 gtk_signal_connect (GTK_OBJECT(tree), "select_child", 685 GTK_SIGNAL_FUNC(cb_select_child), tree); 686 gtk_signal_connect (GTK_OBJECT(tree), "unselect_child", 687 GTK_SIGNAL_FUNC(cb_unselect_child), tree); 688 gtk_signal_connect (GTK_OBJECT(tree), "selection_changed", 689 GTK_SIGNAL_FUNC(cb_selection_changed), tree); 690 /* Add it to the scrolled window */ 691 gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW(scrolled_win), 692 tree); 693 /* Set the selection mode */ 694 gtk_tree_set_selection_mode (GTK_TREE(tree), 695 GTK_SELECTION_MULTIPLE); 696 /* Show it */ 697 gtk_widget_show (tree); 698 699 /* Now, create a clist and attach it to the second pane */ 700 701 clist = gtk_clist_new_with_titles(4, col_titles); 702 703 gtk_container_add (GTK_CONTAINER(scrolled_win2), clist); 704 705 gtk_widget_show(clist); 706 707 /* Now, build the top level display ... */ 708 709 if ((dh = smbc_opendir("smb://")) < 0) { 710 711 fprintf(stderr, "Could not list workgroups: smb://: %s\n", 712 strerror(errno)); 713 714 exit(1); 715 716 } 717 718 /* Create a tree item for Whole Network */ 719 720 item = gtk_tree_item_new_with_label ("Whole Network"); 721 /* Connect all GtkItem:: and GtkTreeItem:: signals */ 722 gtk_signal_connect (GTK_OBJECT(item), "select", 723 GTK_SIGNAL_FUNC(cb_itemsignal), "select"); 724 gtk_signal_connect (GTK_OBJECT(item), "deselect", 725 GTK_SIGNAL_FUNC(cb_itemsignal), "deselect"); 726 gtk_signal_connect (GTK_OBJECT(item), "toggle", 727 GTK_SIGNAL_FUNC(cb_itemsignal), "toggle"); 728 gtk_signal_connect (GTK_OBJECT(item), "expand", 729 GTK_SIGNAL_FUNC(cb_wholenet), "expand"); 730 gtk_signal_connect (GTK_OBJECT(item), "collapse", 731 GTK_SIGNAL_FUNC(cb_wholenet), "collapse"); 732 /* Add it to the parent tree */ 733 gtk_tree_append (GTK_TREE(tree), item); 734 /* Show it - this can be done at any time */ 735 gtk_widget_show (item); 736 737 subtree = gtk_tree_new(); /* A subtree for Whole Network */ 738 739 gtk_tree_item_set_subtree(GTK_TREE_ITEM(item), subtree); 740 741 gtk_signal_connect (GTK_OBJECT(subtree), "select_child", 742 GTK_SIGNAL_FUNC(cb_select_child), tree); 743 gtk_signal_connect (GTK_OBJECT(subtree), "unselect_child", 744 GTK_SIGNAL_FUNC(cb_unselect_child), tree); 745 746 /* Now, get the items in smb:/// and add them to the tree */ 747 748 while ((err = smbc_getdents(dh, (struct smbc_dirent *)dirbuf, 749 sizeof(dirbuf))) != 0) { 750 751 if (err < 0) { /* Handle the error */ 752 753 fprintf(stderr, "Could not read directory for smbc:///: %s\n", 754 strerror(errno)); 755 756 exit(1); 757 758 } 759 760 dirp = (struct smbc_dirent *)dirbuf; 761 762 fprintf(stdout, "Dir len: %u\n", err); 763 764 while (err > 0) { /* Extract each entry and make a sub-tree */ 765 struct tree_data *my_data; 766 int dirlen = dirp->dirlen; 767 768 my_data = make_tree_data(dirp->smbc_type, dirp->name); 769 770 item = gtk_tree_item_new_with_label(dirp->name); 771 /* Connect all GtkItem:: and GtkTreeItem:: signals */ 772 gtk_signal_connect (GTK_OBJECT(item), "select", 773 GTK_SIGNAL_FUNC(cb_itemsignal), "select"); 774 gtk_signal_connect (GTK_OBJECT(item), "deselect", 775 GTK_SIGNAL_FUNC(cb_itemsignal), "deselect"); 776 gtk_signal_connect (GTK_OBJECT(item), "toggle", 777 GTK_SIGNAL_FUNC(cb_itemsignal), "toggle"); 778 gtk_signal_connect (GTK_OBJECT(item), "expand", 779 GTK_SIGNAL_FUNC(cb_itemsignal), "expand"); 780 gtk_signal_connect (GTK_OBJECT(item), "collapse", 781 GTK_SIGNAL_FUNC(cb_itemsignal), "collapse"); 782 /* Add it to the parent tree */ 783 gtk_tree_append (GTK_TREE(tree), item); 784 /* Show it - this can be done at any time */ 785 gtk_widget_show (item); 786 787 gtk_object_set_user_data(GTK_OBJECT(item), (gpointer)my_data); 788 789 fprintf(stdout, "Added: %s, len: %u\n", dirp->name, dirlen); 790 791 subtree = gtk_tree_new(); 792 793 gtk_tree_item_set_subtree(GTK_TREE_ITEM(item), subtree); 794 795 gtk_signal_connect (GTK_OBJECT(subtree), "select_child", 796 GTK_SIGNAL_FUNC(cb_select_child), tree); 797 gtk_signal_connect (GTK_OBJECT(subtree), "unselect_child", 798 GTK_SIGNAL_FUNC(cb_unselect_child), tree); 799 800 (char *)dirp += dirlen; 801 err -= dirlen; 802 803 } 804 805 } 806 807 smbc_closedir(dh); /* FIXME, check for error :-) */ 808 809 /* Show the window and loop endlessly */ 810 gtk_main(); 811 return 0; 812} 813/* example-end */ 814