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