ftp://ftp.redhat.com/pub/redhat/linux/rawhide/SRPMS/SRPMS/gnome-vfs2-2.3.8-1.src.rpm
[gnome-vfs-httpcaptive.git] / test / test-shell.c
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2 /* test-shell.c - A small program to allow testing of a wide variety of
3    gnome-vfs functionality
4
5    Copyright (C) 2000 Free Software Foundation
6
7    The Gnome Library is free software; you can redistribute it and/or
8    modify it under the terms of the GNU Library General Public License as
9    published by the Free Software Foundation; either version 2 of the
10    License, or (at your option) any later version.
11
12    The Gnome Library is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15    Library General Public License for more details.
16
17    You should have received a copy of the GNU Library General Public
18    License along with the Gnome Library; see the file COPYING.LIB.  If not,
19    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20    Boston, MA 02111-1307, USA.
21
22    Author: Michael Meeks <mmeeks@gnu.org> 
23    
24    NB. This code leaks everywhere, don't loose hair.
25 */
26
27 #include <config.h>
28
29 #include <errno.h>
30 #include <glib/ghash.h>
31 #include <glib/gstrfuncs.h>
32 #include <glib/gstring.h>
33 #include <glib/gmessages.h>
34 #include <glib/gutils.h>
35 #include <libgnomevfs/gnome-vfs-init.h>
36 #include <libgnomevfs/gnome-vfs-directory.h>
37 #include <libgnomevfs/gnome-vfs-find-directory.h>
38 #include <libgnomevfs/gnome-vfs-ops.h>
39 #include <libgnomevfs/gnome-vfs-ssl.h>
40 #include <libgnomevfs/gnome-vfs-module-callback.h>
41 #include <libgnomevfs/gnome-vfs-standard-callbacks.h>
42 #include <popt.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <time.h>
47 #include <unistd.h>
48
49 #define TEST_DEBUG 0
50
51 static char delim[]=" ";
52 static char **arg_data = NULL;
53 static int    arg_cur  = 0;
54
55 static char *cur_dir = NULL;
56
57 static GHashTable *files = NULL;
58
59 FILE *vfserr = NULL;
60
61
62 static gboolean
63 show_if_error (GnomeVFSResult result, const char *what, const char *what2)
64 {
65         if (result != GNOME_VFS_OK) {
66                 fprintf (vfserr, "%s%s `%s'\n",
67                          what, what2, gnome_vfs_result_to_string (result));
68                 return TRUE;
69         } else
70                 return FALSE;
71 }
72
73 static void
74 register_file (const char *str, GnomeVFSHandle *handle)
75 {
76         if (!str)
77                 fprintf (vfserr, "Need a valid name");
78         else
79                 g_hash_table_insert (files, g_strdup (str), handle);
80 }
81
82 static GnomeVFSHandle *
83 lookup_file (const char *str)
84 {
85         GnomeVFSHandle *handle;
86
87         if (!str) {
88                 fprintf (vfserr, "Invalid handle '%s'\n", str);
89                 return NULL;
90         }
91
92         handle = g_hash_table_lookup (files, str);
93         if (!handle)
94                 fprintf (vfserr, "Can't find handle '%s'\n", str);
95
96         return handle;
97 }
98
99 static void
100 close_file (const char *str)
101 {
102         GnomeVFSResult result;
103         gpointer hash_key, value;
104
105         if (!str)
106                 fprintf (vfserr, "Can't close NULL handles\n");
107
108         else if (g_hash_table_lookup_extended (files, str, &hash_key, &value)) {
109                 g_hash_table_remove (files, str);
110
111                 result = gnome_vfs_close ((GnomeVFSHandle *)value);
112                 show_if_error (result, "closing ", (char *)hash_key);
113
114                 g_free (hash_key);
115         } else
116
117                 fprintf (vfserr, "Unknown file handle '%s'\n", str);
118 }
119
120 static gboolean
121 kill_file_cb (gpointer  key,
122               gpointer  value,
123               gpointer  user_data)
124 {
125         GnomeVFSResult result;
126
127         result = gnome_vfs_close (value);
128         show_if_error (result, "closing ", key);
129         g_free (key);
130
131         return TRUE;
132 }
133
134 static void
135 close_files (void)
136 {
137         g_hash_table_foreach_remove (files, kill_file_cb, NULL);
138         g_hash_table_destroy (files);
139 }
140
141 static void
142 do_ls (void)
143 {
144         GnomeVFSResult result;
145         GList *list, *node;
146         GnomeVFSFileInfo *info;
147         const char *path;
148
149         if (!arg_data [arg_cur])
150                 path = cur_dir;
151         else
152                 path = arg_data [arg_cur++];
153
154         result = gnome_vfs_directory_list_load
155                 (&list, path,
156                  GNOME_VFS_FILE_INFO_DEFAULT |
157                  GNOME_VFS_FILE_INFO_GET_MIME_TYPE);
158         if (show_if_error (result, "open directory ", cur_dir))
159                 return;
160
161         for (node = list; node != NULL; node = node->next) {
162                 char prechar = '\0', postchar = '\0';
163                 info = node->data;
164
165                 if (info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_TYPE) {
166                         switch (info->type) {
167                         case GNOME_VFS_FILE_TYPE_DIRECTORY:
168                                 prechar = '[';
169                                 postchar = ']';
170                                 break;
171                         case GNOME_VFS_FILE_TYPE_UNKNOWN:
172                                 prechar = '?';
173                                 break;
174                         case GNOME_VFS_FILE_TYPE_FIFO:
175                                 prechar = '|';
176                                 break;
177                         case GNOME_VFS_FILE_TYPE_SOCKET:
178                                 prechar = '-';
179                                 break;
180                         case GNOME_VFS_FILE_TYPE_CHARACTER_DEVICE:
181                         case GNOME_VFS_FILE_TYPE_BLOCK_DEVICE:
182                                 prechar = '@';
183                                 break;
184                         case GNOME_VFS_FILE_TYPE_SYMBOLIC_LINK:
185                                 prechar = '#';
186                                 break;
187                         default:
188                                 prechar = '\0';
189                                 break;
190                         }
191                         if (!postchar)
192                                 postchar = prechar;
193                 }
194                 printf ("%c%s%c", prechar, info->name, postchar);
195
196                 if (strlen (info->name) < 40) {
197                         int i, pad;
198
199                         pad = 40 - strlen (info->name) -
200                                 (prechar?1:0) - (postchar?1:0);
201
202                         for (i = 0; i < pad; i++)
203                                 printf (" ");
204                 }
205                 if (info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
206                         long i = info->size;
207                         printf (" : %ld bytes", i);
208                 }
209
210                 if (info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_MIME_TYPE) {
211                         printf (", type '%s'", info->mime_type);
212                 }
213
214                 printf ("\n");
215         }
216         
217         gnome_vfs_file_info_list_free (list);
218 }
219
220 static void
221 list_commands (void)
222 {
223         printf ("command can be one or all of:\n");
224         printf ("Main operations:\n");
225         printf (" * ls [opt_dir]            list files\n");
226         printf (" * cd [dir]                enter storage\n");
227         printf (" * mv <a> <b>              move object\n");
228         printf (" * rm <file>               remove stream\n");
229         printf (" * mkdir <dir>             make storage\n");
230         printf (" * rmdir <dir>             remove storage\n");
231         printf (" * info,stat <a>           get information on object\n");
232         printf (" * cat,type <a>            dump text file to console\n");
233         printf (" * dump <a>                dump binary file to console\n");
234         printf (" * sync:                   for sinkers\n");
235         printf (" * ssl:                    displays ssl enabled state\n");
236         printf (" * findtrash:              locates a trash directory for a URI\n");
237         printf (" * quit,exit,bye:          exit\n");
238         printf ("File operations:\n");
239         printf (" * open <handle> <name>:   open a file\n");
240         printf (" * create <handle> <name>: create a file\n");
241         printf (" * handleinfo <handle>:    information from handle\n");
242         printf (" * close <handle>:         close a file\n");
243         printf (" * read <handle> <bytes>:  read bytes from stream\n");
244         printf (" * seek <handle> <pos>:    seek set position\n");
245 }
246
247 static gboolean
248 simple_regexp (const char *regexp, const char *fname)
249 {
250         int      i, j;
251         gboolean ret = TRUE;
252
253         g_return_val_if_fail (fname != NULL, FALSE);
254         g_return_val_if_fail (regexp != NULL, FALSE);
255
256         for (i = j = 0; regexp [i] && fname [j]; j++, i++) {
257                 if (regexp [i] == '\\' &&
258                     !(i > 0 && regexp [i - 1] == '\\')) {
259                         j--;
260                         continue;
261                 }
262
263                 if (regexp [i] == '.' &&
264                     !(i > 0 && regexp [i - 1] == '\\'))
265                         continue;
266
267                 if (g_ascii_tolower (regexp [i]) != g_ascii_tolower (fname [j])) {
268                         ret = FALSE;
269                         break;
270                 }
271         }
272
273         if (regexp [i] && regexp [i] == '*')
274                 ret = TRUE;
275
276         else if (!regexp [i] && fname [j])
277                 ret = FALSE;
278         
279         else if (!fname [j] && regexp [i])
280                 ret = FALSE;
281
282 /*      if (ret)
283         printf ("'%s' matched '%s'\n", regexp, fname);*/
284
285         return ret;
286 }
287
288 static gboolean
289 validate_path (const char *path)
290 {
291         GnomeVFSResult result;
292         GList *list;
293
294         result = gnome_vfs_directory_list_load (
295                 &list, path, GNOME_VFS_FILE_INFO_DEFAULT);
296
297         if (show_if_error (result, "open directory ", path)) {
298                 return FALSE;
299         }
300
301         gnome_vfs_file_info_list_free (list);
302
303         return TRUE;
304 }
305
306 static char *
307 get_regexp_name (const char *regexp, const char *path, gboolean dir)
308 {
309         GnomeVFSResult result;
310         GList *list, *node;
311         GnomeVFSFileInfo *info;
312         char *res = NULL;
313
314         result = gnome_vfs_directory_list_load (
315                 &list, path, GNOME_VFS_FILE_INFO_DEFAULT);
316
317         if (show_if_error (result, "open directory ", path))
318                 return NULL;
319
320         for (node = list; node != NULL; node = node->next) {
321                 info = node->data;
322
323                 if (simple_regexp (regexp, info->name)) {
324                         if (info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_TYPE) {
325                                 if ((dir  && info->type == GNOME_VFS_FILE_TYPE_DIRECTORY) ||
326                                     (!dir && info->type != GNOME_VFS_FILE_TYPE_DIRECTORY)) {
327                                         res = g_strdup (info->name);
328                                         break;
329                                 }
330                         } else {
331                                 fprintf (vfserr, "Can't cope with no type data");
332                                 res = g_strdup (info->name);
333                                 break;
334                         }
335                 }
336         }
337         gnome_vfs_file_info_list_free (list);
338
339         return res;
340 }
341
342 static void
343 do_cd (void)
344 {
345         char *p;
346
347         p = arg_data [arg_cur++];
348
349         if (!p) {
350                 fprintf (vfserr, "Takes a directory argument\n");
351                 return;
352         }
353
354         if (!g_ascii_strcasecmp (p, "..")) {
355                 guint lp;
356                 char **tmp;
357                 GString *newp = g_string_new ("");
358
359                 tmp = g_strsplit (cur_dir, "/", -1);
360                 lp  = 0;
361                 if (!tmp [lp])
362                         return;
363
364                 while (tmp [lp + 1]) {
365                         g_string_append_printf (newp, "%s/", tmp [lp]);
366                         lp++;
367                 }
368                 g_free (cur_dir);
369                 cur_dir = newp->str;
370                 g_string_free (newp, FALSE);
371         } else if (!g_ascii_strcasecmp (p, ".")) {
372         } else {
373                 char *newpath;
374
375                 if (strchr (p, ':') ||
376                     p [0] == '/') {
377                         if (p [strlen (p) - 1] != '/')
378                                 newpath = g_strconcat (p, "/", NULL);
379                         else
380                                 newpath = g_strdup (p);
381                 } else {
382                         char *ptr;
383                         
384                         ptr = get_regexp_name (p, cur_dir, TRUE);
385                         if (!ptr) {
386                                 fprintf (vfserr, "Can't find '%s'\n", p);
387                                 return;
388                         }
389
390                         newpath = g_strconcat (cur_dir, ptr, "/", NULL);
391                 }
392
393                 if (validate_path (newpath)) {
394                         g_free (cur_dir);
395                         cur_dir = newpath;
396                 } else
397                         fprintf (vfserr, "Invalid path %s\n", newpath);
398         }
399 }
400
401 static char *
402 get_fname (void)
403 {
404         char *fname, *reg_name, *f;
405
406         if (!arg_data [arg_cur])
407                 return NULL;
408         
409         reg_name = arg_data [arg_cur++];
410         fname = get_regexp_name (reg_name, cur_dir, FALSE);
411
412         if (!fname)
413                 fname = reg_name;
414         
415         if (strchr (fname, ':') ||
416             fname [0] == '/')
417                 f = g_strdup (fname);
418         else if (cur_dir)
419                 f = g_strconcat (cur_dir, fname, NULL);
420         else
421                 f = g_strdup (fname);
422
423         return f;
424 }
425
426 static void
427 do_cat (void)
428 {
429         char *from;
430         GnomeVFSHandle *from_handle;
431         GnomeVFSResult  result;
432
433         from = get_fname ();
434
435         result = gnome_vfs_open (&from_handle, from, GNOME_VFS_OPEN_READ);
436         if (show_if_error (result, "open ", from))
437                 return;
438
439         while (1) {
440                 GnomeVFSFileSize bytes_read;
441                 guint8           data [1025];
442                 
443                 result = gnome_vfs_read (from_handle, data, 1024, &bytes_read);
444                 if (show_if_error (result, "read ", from))
445                         return;
446
447                 if (bytes_read == 0)
448                         break;
449                 
450                 if (bytes_read >  0 &&
451                     bytes_read <= 1024)
452                         data [bytes_read] = '\0';
453                 else {
454                         data [1024] = '\0';
455                         g_warning ("Wierd error from vfs_read");
456                 }
457                 fprintf (stdout, "%s", data);
458         }
459
460         result = gnome_vfs_close (from_handle);
461         if (show_if_error (result, "close ", from))
462                 return;
463         fprintf (stdout, "\n");
464 }
465
466 static void
467 do_rm (void)
468 {
469         char          *fname;
470         GnomeVFSResult result;
471
472         fname = get_fname ();
473
474         result = gnome_vfs_unlink (fname);
475         if (show_if_error (result, "unlink ", fname))
476                 return; 
477 }
478
479 static void
480 do_mkdir (void)
481 {
482         char          *fname;
483         GnomeVFSResult result;
484
485         fname = get_fname ();
486
487         result = gnome_vfs_make_directory (fname, GNOME_VFS_PERM_USER_ALL);
488         if (show_if_error (result, "mkdir ", fname))
489                 return; 
490 }
491
492 static void
493 do_rmdir (void)
494 {
495         char          *fname;
496         GnomeVFSResult result;
497
498         fname = get_fname ();
499
500         result = gnome_vfs_remove_directory (fname);
501         if (show_if_error (result, "rmdir ", fname))
502                 return; 
503 }
504
505 static void
506 do_mv (void)
507 {
508         char          *from, *to;
509         char          *msg;
510         GnomeVFSResult result;
511
512         from = get_fname ();
513         to = get_fname ();
514         if (!from || !to) {
515                 fprintf (vfserr, "mv <from> <to>\n");
516                 return;
517         }
518
519         result = gnome_vfs_move (from, to, FALSE);
520
521         msg = g_strdup_printf ("%s to %s", from, to);
522         show_if_error (result, "move ", msg);
523         g_free (msg);
524 }
525
526 static void
527 do_findtrash (void)
528 {
529         char *from;
530         char *uri_as_string;
531         GnomeVFSResult    result;
532         GnomeVFSURI *from_uri;
533         GnomeVFSURI *result_vfs_uri;
534
535         from = get_fname ();
536
537         from_uri = gnome_vfs_uri_new (from);
538         result = gnome_vfs_find_directory (from_uri, 
539                                            GNOME_VFS_DIRECTORY_KIND_TRASH, 
540                                            &result_vfs_uri, 
541                                            TRUE, TRUE, 0777);
542
543         if (result != GNOME_VFS_OK) {
544                 fprintf (stdout, "couldn't find or create trash there, error code %d", result);
545         } else {
546                 uri_as_string = gnome_vfs_uri_to_string (result_vfs_uri, GNOME_VFS_URI_HIDE_NONE);
547                 fprintf (stdout, "trash found or created here: %s", uri_as_string);
548                 g_free (uri_as_string);
549         }
550
551         gnome_vfs_uri_unref (from_uri);
552         gnome_vfs_uri_unref (result_vfs_uri);
553 }
554
555 static void
556 do_ssl (void)
557 {
558         if (gnome_vfs_ssl_enabled ())
559                 fprintf (stdout, "SSL enabled\n");
560         else
561                 fprintf (stdout, "SSL disabled\n");
562 }
563
564 static void
565 print_info (GnomeVFSFileInfo *info)
566 {
567         const char *mime_type;
568         struct tm *loctime;
569
570         fprintf (stdout, "Name: '%s'\n", info->name);
571         if (info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_TYPE) {
572                 fprintf (stdout, "Type: ");
573                 switch (info->type) {
574                 case GNOME_VFS_FILE_TYPE_UNKNOWN:
575                         fprintf (stdout, "unknown");
576                         break;
577                 case GNOME_VFS_FILE_TYPE_REGULAR:
578                         fprintf (stdout, "regular");
579                         break;
580                 case GNOME_VFS_FILE_TYPE_DIRECTORY:
581                         fprintf (stdout, "directory");
582                         break;
583                 case GNOME_VFS_FILE_TYPE_FIFO:
584                         fprintf (stdout, "fifo");
585                         break;
586                 case GNOME_VFS_FILE_TYPE_SOCKET:
587                         fprintf (stdout, "socket");
588                         break;
589                 case GNOME_VFS_FILE_TYPE_CHARACTER_DEVICE:
590                         fprintf (stdout, "char");
591                         break;
592                 case GNOME_VFS_FILE_TYPE_BLOCK_DEVICE:
593                         fprintf (stdout, "block");
594                         break;
595                 case GNOME_VFS_FILE_TYPE_SYMBOLIC_LINK:
596                         fprintf (stdout, "symlink\n");
597                         fprintf (stdout, "symlink points to: %s", 
598                                  info->symlink_name);
599                         break;
600                 default:
601                         fprintf (stdout, "Error; invalid value");
602                         break;
603                 }
604         } else
605                 fprintf (stdout, "Type invalid");
606         fprintf (stdout, "\n");
607
608         if (info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) {
609                 long i = info->size;
610                 fprintf (stdout, "Size: %ld bytes", i);
611         } else {
612                 fprintf (stdout, "Size invalid");
613         }
614         fprintf (stdout, "\n");
615
616         mime_type = gnome_vfs_file_info_get_mime_type (info);
617
618         fprintf (stdout, "Mime Type: %s \n", mime_type);
619         
620         loctime = localtime(&info->atime);
621         fprintf (stdout, "Last Accessed: %s", asctime(loctime));
622         loctime = localtime(&info->mtime);
623         fprintf (stdout, "Last Modified: %s", asctime(loctime));
624         loctime = localtime(&info->ctime);
625         fprintf (stdout, "Last Changed: %s", asctime(loctime));
626         
627         fprintf (stdout, "uid: %d\n", info->uid);
628
629         fprintf (stdout, "gid: %d\n", info->gid);
630         fprintf (stdout, "\n");
631         /* FIXME bugzilla.eazel.com 2800: hack here; should dump them all */
632 }
633
634 static void
635 do_info (void)
636 {
637         char             *from;
638         GnomeVFSResult    result;
639         GnomeVFSFileInfo *info;
640
641         from = get_fname ();
642
643
644         info = gnome_vfs_file_info_new ();
645         result = gnome_vfs_get_file_info (
646                 from, info, GNOME_VFS_FILE_INFO_GET_MIME_TYPE);
647
648         if (show_if_error (result, "getting info on: ", from))
649                 return;
650
651         print_info (info);
652         gnome_vfs_file_info_unref (info);
653 }
654
655 static void
656 do_cp (void)
657 {
658         char *from = NULL;
659         char *to = NULL;
660         GnomeVFSHandle *from_handle = NULL;
661         GnomeVFSHandle *to_handle = NULL;
662         GnomeVFSResult  result;
663
664         from = get_fname ();
665
666         if (from)
667                 to = get_fname ();
668         else {
669                 fprintf (vfserr, "cp <from> <to>\n");
670                 goto out;
671         }
672        
673         result = gnome_vfs_open (&from_handle, from, GNOME_VFS_OPEN_READ);
674         if (show_if_error (result, "open ", from))
675                 goto out;
676
677         result = gnome_vfs_open (&to_handle, to, GNOME_VFS_OPEN_WRITE);
678         if (result == GNOME_VFS_ERROR_NOT_FOUND)
679                 result = gnome_vfs_create (&to_handle, to, GNOME_VFS_OPEN_WRITE, FALSE,
680                                            GNOME_VFS_PERM_USER_ALL);
681         if (show_if_error (result, "open ", to))
682                 goto out;
683
684         while (1) {
685                 GnomeVFSFileSize bytes_read;
686                 GnomeVFSFileSize bytes_written;
687                 guint8           data [1024];
688                 
689                 result = gnome_vfs_read (from_handle, data, 1024, &bytes_read);
690                 if (show_if_error (result, "read ", from))
691                         goto out;
692
693                 if (bytes_read == 0)
694                         break;
695                 
696                 result = gnome_vfs_write (to_handle, data, bytes_read, &bytes_written);
697                 if (show_if_error (result, "write ", to))
698                         goto out;
699
700                 if (bytes_read != bytes_written)
701                         fprintf (vfserr, "Didn't write it all");
702         }
703
704  out:
705         g_free (from);
706         g_free (to);
707
708         if (to_handle) {
709                 result = gnome_vfs_close (to_handle);
710                 if (show_if_error (result, "close ", to))
711                         /* Nothing */;
712         }
713
714         if (from_handle) {
715                 result = gnome_vfs_close (from_handle);
716                 if (show_if_error (result, "close ", from))
717                         /* Nothing */;
718         }
719 }
720
721 static void
722 ms_ole_dump (guint8 const *ptr, guint32 len, guint32 offset)
723 {
724         guint32 lp,lp2;
725         guint32 off;
726
727         for (lp = 0;lp<(len+15)/16;lp++) {
728                 printf ("%8x | ", lp*16 + offset);
729                 for (lp2=0;lp2<16;lp2++) {
730                         off = lp2 + (lp<<4);
731                         off<len?printf("%2x ", ptr[off]):printf("XX ");
732                 }
733                 printf ("| ");
734                 for (lp2=0;lp2<16;lp2++) {
735                         off = lp2 + (lp<<4);
736                         printf ("%c", off<len?(ptr[off]>'!'&&ptr[off]<127?ptr[off]:'.'):'*');
737                 }
738                 printf ("\n");
739         }
740 }
741
742 static void
743 do_dump (void)
744 {
745         char *from;
746         GnomeVFSHandle *from_handle;
747         GnomeVFSResult  result;
748         guint32         offset;
749
750         from = get_fname ();
751
752         result = gnome_vfs_open (&from_handle, from, GNOME_VFS_OPEN_READ);
753         if (show_if_error (result, "open ", from))
754                 return;
755
756         for (offset = 0; 1; ) {
757                 GnomeVFSFileSize bytes_read;
758                 guint8           data [1024];
759                 
760                 result = gnome_vfs_read (from_handle, data, 1024, &bytes_read);
761                 if (show_if_error (result, "read ", from))
762                         return;
763
764                 if (bytes_read == 0)
765                         break;
766
767                 ms_ole_dump (data, bytes_read, offset);
768                 
769                 offset += bytes_read;
770         }
771
772         result = gnome_vfs_close (from_handle);
773         if (show_if_error (result, "close ", from))
774                 return;
775 }
776
777
778 /*
779  * ---------------------------------------------------------------------
780  */
781
782 static char *
783 get_handle (void)
784 {
785         if (!arg_data [arg_cur])
786                 return NULL;
787
788         return arg_data [arg_cur++];
789 }
790
791 static int
792 get_int (void)
793 {
794         if (!arg_data [arg_cur])
795                 return 0;
796
797         return atoi (arg_data [arg_cur++]);
798 }
799
800 static void
801 do_open (void)
802 {
803         char *from, *handle;
804         GnomeVFSHandle *from_handle;
805         GnomeVFSResult  result;
806
807         handle = get_handle ();
808         from = get_fname ();
809
810         if (!handle || !from) {
811                 fprintf (vfserr, "open <handle> <filename>\n");
812                 return;
813         }
814
815         result = gnome_vfs_open (&from_handle, from, GNOME_VFS_OPEN_READ);
816         if (show_if_error (result, "open ", from))
817                 return;
818
819         register_file (handle, from_handle);
820 }
821
822 static void
823 do_create (void)
824 {
825         char *from, *handle;
826         GnomeVFSHandle *from_handle;
827         GnomeVFSResult  result;
828
829         handle = get_handle ();
830         from = get_fname ();
831
832         if (!handle || !from) {
833                 fprintf (vfserr, "create <handle> <filename>\n");
834                 return;
835         }
836
837         result = gnome_vfs_create (&from_handle, from, GNOME_VFS_OPEN_READ,
838                                    FALSE, GNOME_VFS_PERM_USER_READ |
839                                    GNOME_VFS_PERM_USER_WRITE);
840         if (show_if_error (result, "create ", from))
841                 return;
842
843         register_file (handle, from_handle);
844 }
845
846 static void
847 do_read (void)
848 {
849         char            *handle;
850         int              length;
851         GnomeVFSHandle  *from_handle;
852         GnomeVFSResult   result;
853         GnomeVFSFileSize bytes_read;
854         guint8          *data;
855
856         handle = get_handle ();
857         length = get_int ();
858
859         if (length < 0) {
860                 fprintf (vfserr, "Can't read %d bytes\n", length);
861                 return;
862         }
863
864         from_handle = lookup_file (handle);
865         if (!from_handle)
866                 return;
867
868         data = g_malloc (length);
869         result = gnome_vfs_read (from_handle, data, length, &bytes_read);
870         if (show_if_error (result, "read ", handle))
871                 return;
872
873         ms_ole_dump (data, bytes_read, 0);
874 }
875
876 static void
877 do_seek (void)
878 {
879         char            *handle;
880         int              offset;
881         GnomeVFSHandle  *from_handle;
882         GnomeVFSResult   result;
883
884         handle = get_handle ();
885         offset = get_int ();
886
887         if (offset < 0) {
888                 fprintf (vfserr, "Can't seek to %d bytes offset\n", offset);
889                 return;
890         }
891
892         from_handle = lookup_file (handle);
893         if (!from_handle)
894                 return;
895
896         result = gnome_vfs_seek (from_handle, GNOME_VFS_SEEK_START, offset);
897         if (show_if_error (result, "seek ", handle))
898                 return;
899 }
900
901 static void
902 do_close (void)
903 {
904         close_file (get_handle ());
905 }
906
907 static void
908 do_handleinfo (void)
909 {
910         const char *handlename = get_handle ();
911         GnomeVFSResult    result;
912         GnomeVFSHandle *handle = lookup_file (handlename);
913         GnomeVFSFileInfo *info;
914
915         if (!handle)
916                 return;
917
918         info = gnome_vfs_file_info_new ();
919         result = gnome_vfs_get_file_info_from_handle (handle, info,
920                                                       GNOME_VFS_FILE_INFO_GET_MIME_TYPE);
921
922         if (show_if_error (result, "getting info from handle: ", handlename))
923                 return;
924
925         print_info (info);
926         gnome_vfs_file_info_unref (info);
927 }
928
929 /*
930  * ---------------------------------------------------------------------
931  */
932
933 GMainLoop *main_loop = NULL;
934
935 int interactive = 0;
936 const struct poptOption options [] = {
937         { "interactive", 'i', POPT_ARG_NONE, &interactive, 0,
938           "Allow interactive input", NULL  },
939         { NULL, '\0', 0, NULL, 0 }
940 };
941
942 static gboolean
943 callback (GIOChannel *source,
944           GIOCondition condition,
945           gpointer data)
946 {
947         char *buffer = data;
948         char buf[1024];
949         int len;
950
951         len = read (0, buf, sizeof (buf) - 1);
952
953         if (len + strlen (buffer) + 1 > 1024)
954                 len = 1024 - strlen (buffer) - 1;
955
956         buf[len] = '\0';
957         strcat (buffer, buf);
958
959         if (strchr (buf, '\n') != NULL &&
960             main_loop != NULL) {
961                 g_main_loop_quit (main_loop);
962         }
963
964         return TRUE;
965 }
966
967 static char *
968 get_input_string (const char *prompt)
969 {
970         char buffer[512];
971
972         printf (prompt);
973         fgets (buffer, 511, stdin);
974         if (strchr (buffer, '\n'))
975                 *strchr (buffer, '\n') = '\0';
976         
977         return g_strndup (buffer, 512);
978 }
979
980 static void
981 authentication_callback (gconstpointer in, size_t in_size,
982                          gpointer out, size_t out_size,
983                          gpointer user_data)
984 {
985         GnomeVFSModuleCallbackAuthenticationIn *in_real;
986         GnomeVFSModuleCallbackAuthenticationOut *out_real;
987
988         g_return_if_fail (sizeof (GnomeVFSModuleCallbackAuthenticationIn) == in_size
989                 && sizeof (GnomeVFSModuleCallbackAuthenticationOut) == out_size);
990
991         g_return_if_fail (in != NULL);
992         g_return_if_fail (out != NULL);
993
994         in_real = (GnomeVFSModuleCallbackAuthenticationIn *)in;
995         out_real = (GnomeVFSModuleCallbackAuthenticationOut *)out;
996         
997         printf ("Authenticate for uri: %s realm: %s\n", in_real->uri, in_real->realm);
998
999         out_real->username = get_input_string ("Username:\n");
1000         out_real->password = get_input_string ("Password:\n");
1001 }
1002
1003 int
1004 main (int argc, const char **argv)
1005 {
1006         poptContext popt_context;
1007         int exit = 0;
1008         char *buffer = g_new (char, 1024) ;
1009         const char **args;
1010         FILE *instream;
1011
1012         /* default to interactive on a terminal */
1013         interactive = isatty (0);
1014
1015         files = g_hash_table_new (g_str_hash, g_str_equal);
1016
1017         popt_context = poptGetContext ("test-vfs", argc, argv,
1018                                        options, 0);
1019
1020         if (interactive)
1021                 vfserr = stderr;
1022         else
1023                 vfserr = stdout;
1024
1025         if (!gnome_vfs_init ()) {
1026                 fprintf (vfserr, "Cannot initialize gnome-vfs.\n");
1027                 return 1;
1028         }
1029         gnome_vfs_module_callback_push
1030                 (GNOME_VFS_MODULE_CALLBACK_AUTHENTICATION,
1031                  authentication_callback, NULL, NULL);
1032
1033         instream = stdin;
1034         args = poptGetArgs (popt_context);
1035         if (!args)
1036                 cur_dir = g_get_current_dir ();
1037         else
1038                 cur_dir = g_strdup (args [0]);
1039
1040         if (cur_dir && cur_dir [strlen (cur_dir)] != '/') {
1041                 char *new_dir = g_strconcat (cur_dir, "/", NULL);
1042                 g_free (cur_dir);
1043                 cur_dir = new_dir;
1044         }
1045                 
1046         poptFreeContext (popt_context);
1047
1048         while (!exit) {
1049                 char *ptr;
1050
1051                 if (interactive) {
1052                         GIOChannel *ioc;
1053                         guint watch_id;
1054                         strcpy (buffer, "");
1055
1056                         main_loop = g_main_loop_new (NULL, TRUE);
1057
1058                         ioc = g_io_channel_unix_new (0 /* stdin */);
1059                         watch_id = g_io_add_watch (ioc,
1060                                                    G_IO_IN | G_IO_HUP | G_IO_ERR,
1061                                                    callback, buffer);
1062                         g_io_channel_unref (ioc);
1063
1064                         if (interactive) {
1065                                 fprintf (stdout,"\n%s > ", cur_dir);
1066                                 fflush (stdout);
1067                         }
1068
1069                         g_main_loop_run (main_loop);
1070
1071                         g_source_remove (watch_id);
1072
1073                         g_main_loop_unref (main_loop);
1074                         main_loop = NULL;
1075                 } else {
1076                         /* In non-interactive mode we just do this evil
1077                          * thingie */
1078                         buffer[0] = '\0';
1079                         fgets (buffer, 1023, instream);
1080                         if (!buffer [0]) {
1081                                 exit = 1;
1082                                 continue;
1083                         }
1084                 }
1085
1086                 if (!buffer || buffer [0] == '#')
1087                         continue;
1088
1089                 arg_data = g_strsplit (g_strchomp (buffer), delim, -1);
1090                 arg_cur  = 0;
1091                 if ((!arg_data || !arg_data[0]) && interactive) continue;
1092                 if (!interactive)
1093                         printf ("Command : '%s'\n", arg_data [0]);
1094                 ptr = arg_data[arg_cur++];
1095                 if (!ptr)
1096                         continue;
1097
1098                 if (g_ascii_strcasecmp (ptr, "ls") == 0)
1099                         do_ls ();
1100                 else if (g_ascii_strcasecmp (ptr, "cd") == 0)
1101                         do_cd ();
1102                 else if (g_ascii_strcasecmp (ptr, "dump") == 0)
1103                         do_dump ();
1104                 else if (g_ascii_strcasecmp (ptr, "type") == 0 ||
1105                          g_ascii_strcasecmp (ptr, "cat") == 0)
1106                         do_cat ();
1107                 else if (g_ascii_strcasecmp (ptr, "cp") == 0)
1108                         do_cp ();
1109                 else if (g_ascii_strcasecmp (ptr, "rm") == 0)
1110                         do_rm ();
1111                 else if (g_ascii_strcasecmp (ptr, "mkdir") == 0)
1112                         do_mkdir ();
1113                 else if (g_ascii_strcasecmp (ptr, "rmdir") == 0)
1114                         do_rmdir ();
1115                 else if (g_ascii_strcasecmp (ptr, "mv") == 0)
1116                         do_mv ();
1117                 else if (g_ascii_strcasecmp (ptr, "info") == 0 ||
1118                          g_ascii_strcasecmp (ptr, "stat") == 0)
1119                         do_info ();
1120                 else if (g_ascii_strcasecmp (ptr, "findtrash") == 0)
1121                         do_findtrash ();
1122                 else if (g_ascii_strcasecmp (ptr, "ssl") == 0)
1123                         do_ssl ();
1124                 else if (g_ascii_strcasecmp (ptr, "sync") == 0)
1125                         fprintf (vfserr, "a shell is like a boat, it lists or syncs (RMS)\n");
1126                 else if (g_ascii_strcasecmp (ptr,"help") == 0 ||
1127                          g_ascii_strcasecmp (ptr,"?")    == 0 ||
1128                          g_ascii_strcasecmp (ptr,"info") == 0 ||
1129                          g_ascii_strcasecmp (ptr,"man")  == 0)
1130                         list_commands ();
1131                 else if (g_ascii_strcasecmp (ptr,"exit") == 0 ||
1132                          g_ascii_strcasecmp (ptr,"quit") == 0 ||
1133                          g_ascii_strcasecmp (ptr,"q")    == 0 ||
1134                          g_ascii_strcasecmp (ptr,"bye") == 0)
1135                         exit = 1;
1136
1137                 /* File ops */
1138                 else if (g_ascii_strcasecmp (ptr, "open") == 0)
1139                         do_open ();
1140                 else if (g_ascii_strcasecmp (ptr, "create") == 0)
1141                         do_create ();
1142                 else if (g_ascii_strcasecmp (ptr, "close") == 0)
1143                         do_close ();
1144                 else if (g_ascii_strcasecmp (ptr, "handleinfo") == 0)
1145                         do_handleinfo ();
1146                 else if (g_ascii_strcasecmp (ptr, "read") == 0)
1147                         do_read ();
1148                 else if (g_ascii_strcasecmp (ptr, "seek") == 0)
1149                         do_seek ();
1150                 
1151                 else
1152                         fprintf (vfserr, "Unknown command '%s'", ptr);
1153
1154                 g_strfreev (arg_data);
1155                 arg_data = NULL;
1156         }
1157
1158         g_free (buffer);
1159         g_free (cur_dir);
1160
1161         close_files ();
1162
1163         return 0;
1164 }
1165