This source file includes following definitions.
- shell_set_blksize
- shell_default_stat
- shell_load_script_from_file
- shell_decode_reply
- shell_get_reply
- shell_command
- G_GNUC_PRINTF
- G_GNUC_PRINTF
- G_GNUC_PRINTF
- shell_new_archive
- shell_free_archive
- shell_pipeopen
- shell_set_env
- shell_info
- shell_open_archive_pipeopen
- shell_open_archive_talk
- shell_open_archive_int
- shell_open_archive
- shell_archive_same
- shell_parse_ls
- shell_dir_load
- shell_file_store
- shell_linear_start
- shell_linear_abort
- shell_linear_read
- shell_linear_close
- shell_ctl
- shell_rename
- shell_link
- shell_symlink
- shell_stat
- shell_lstat
- shell_fstat
- shell_chmod
- shell_chown
- shell_utime
- shell_unlink
- shell_exists
- shell_mkdir
- shell_rmdir
- shell_fh_new
- shell_fh_open
- shell_fill_names
- shell_open
- vfs_init_shell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53 #include <config.h>
54 #include <errno.h>
55 #include <pwd.h>
56 #include <grp.h>
57 #include <stdlib.h>
58 #include <string.h>
59 #include <inttypes.h>
60
61 #include "lib/global.h"
62 #include "lib/tty/tty.h"
63 #include "lib/strutil.h"
64 #include "lib/unixcompat.h"
65 #include "lib/fileloc.h"
66 #include "lib/util.h"
67 #include "lib/mcconfig.h"
68
69 #include "src/execute.h"
70
71 #include "lib/vfs/vfs.h"
72 #include "lib/vfs/utilvfs.h"
73 #include "lib/vfs/netutil.h"
74 #include "lib/vfs/xdirentry.h"
75 #include "lib/vfs/gc.h"
76
77 #include "shell.h"
78 #include "shelldef.h"
79
80
81
82 int shell_directory_timeout = 900;
83
84
85
86 #define DO_RESOLVE_SYMLINK 1
87 #define DO_OPEN 2
88 #define DO_FREE_RESOURCE 4
89
90 #define SHELL_FLAG_COMPRESSED 1
91 #define SHELL_FLAG_RSH 2
92
93 #define OPT_FLUSH 1
94 #define OPT_IGNORE_ERROR 2
95
96
97
98
99 #define PRELIM 1
100 #define COMPLETE 2
101 #define CONTINUE 3
102 #define TRANSIENT 4
103 #define ERROR 5
104
105
106 #define NONE 0x00
107 #define WAIT_REPLY 0x01
108 #define WANT_STRING 0x02
109
110
111 #define SHELL_HAVE_HEAD 1
112 #define SHELL_HAVE_SED 2
113 #define SHELL_HAVE_AWK 4
114 #define SHELL_HAVE_PERL 8
115 #define SHELL_HAVE_LSQ 16
116 #define SHELL_HAVE_DATE_MDYT 32
117 #define SHELL_HAVE_TAIL 64
118
119 #define SHELL_SUPER(super) ((shell_super_t *) (super))
120 #define SHELL_FILE_HANDLER(fh) ((shell_file_handler_t *) fh)
121
122
123
124 typedef struct
125 {
126 struct vfs_s_super base;
127
128 int sockr;
129 int sockw;
130 char *scr_ls;
131 char *scr_chmod;
132 char *scr_utime;
133 char *scr_exists;
134 char *scr_mkdir;
135 char *scr_unlink;
136 char *scr_chown;
137 char *scr_rmdir;
138 char *scr_ln;
139 char *scr_mv;
140 char *scr_hardlink;
141 char *scr_get;
142 char *scr_send;
143 char *scr_append;
144 char *scr_info;
145 int host_flags;
146 GString *scr_env;
147 } shell_super_t;
148
149 typedef struct
150 {
151 vfs_file_handler_t base;
152
153 off_t got;
154 off_t total;
155 gboolean append;
156 } shell_file_handler_t;
157
158
159
160
161
162 static char reply_str[80];
163
164 static struct vfs_s_subclass shell_subclass;
165 static struct vfs_class *vfs_shell_ops = VFS_CLASS (&shell_subclass);
166
167
168
169
170
171 static void
172 shell_set_blksize (struct stat *s)
173 {
174 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
175
176 s->st_blksize = 64 * 1024;
177 #endif
178 }
179
180
181
182 static struct stat *
183 shell_default_stat (struct vfs_class *me)
184 {
185 struct stat *s;
186
187 s = vfs_s_default_stat (me, S_IFDIR | 0755);
188 shell_set_blksize (s);
189 vfs_adjust_stat (s);
190
191 return s;
192 }
193
194
195
196 static char *
197 shell_load_script_from_file (const char *hostname, const char *script_name, const char *def_content)
198 {
199 char *scr_filename = NULL;
200 char *scr_content;
201 gsize scr_len = 0;
202
203
204 scr_filename = g_build_path (PATH_SEP_STR, mc_config_get_data_path (), VFS_SHELL_PREFIX,
205 hostname, script_name, (char *) NULL);
206
207 g_file_get_contents (scr_filename, &scr_content, &scr_len, NULL);
208 g_free (scr_filename);
209
210 if (scr_content == NULL)
211 {
212 scr_filename =
213 g_build_path (PATH_SEP_STR, LIBEXECDIR, VFS_SHELL_PREFIX, script_name, (char *) NULL);
214 g_file_get_contents (scr_filename, &scr_content, &scr_len, NULL);
215 g_free (scr_filename);
216 }
217
218 if (scr_content != NULL)
219 return scr_content;
220
221 return g_strdup (def_content);
222 }
223
224
225
226 static int
227 shell_decode_reply (char *s, gboolean was_garbage)
228 {
229 int code;
230
231
232 if (sscanf (s, "%d", &code) == 0)
233 {
234 code = 500;
235 return 5;
236 }
237 if (code < 100)
238 return was_garbage ? ERROR : (code == 0 ? COMPLETE : PRELIM);
239 return code / 100;
240 }
241
242
243
244
245 static int
246 shell_get_reply (struct vfs_class *me, int sock, char *string_buf, int string_len)
247 {
248 char answer[BUF_1K];
249 gboolean was_garbage = FALSE;
250
251 while (TRUE)
252 {
253 if (!vfs_s_get_line (me, sock, answer, sizeof (answer), '\n'))
254 {
255 if (string_buf != NULL)
256 *string_buf = '\0';
257 return 4;
258 }
259
260 if (strncmp (answer, "### ", 4) == 0)
261 return shell_decode_reply (answer + 4, was_garbage ? 1 : 0);
262
263 was_garbage = TRUE;
264 if (string_buf != NULL)
265 g_strlcpy (string_buf, answer, string_len);
266 }
267 }
268
269
270
271 static int
272 shell_command (struct vfs_class *me, struct vfs_s_super *super, int wait_reply, const char *cmd,
273 size_t cmd_len)
274 {
275 ssize_t status;
276 FILE *logfile = me->logfile;
277
278 if (cmd_len == (size_t) (-1))
279 cmd_len = strlen (cmd);
280
281 if (logfile != NULL)
282 {
283 size_t ret;
284
285 ret = fwrite (cmd, cmd_len, 1, logfile);
286 ret = fflush (logfile);
287 (void) ret;
288 }
289
290 tty_enable_interrupt_key ();
291 status = write (SHELL_SUPER (super)->sockw, cmd, cmd_len);
292 tty_disable_interrupt_key ();
293
294 if (status < 0)
295 return TRANSIENT;
296
297 if (wait_reply)
298 return shell_get_reply (me, SHELL_SUPER (super)->sockr,
299 (wait_reply & WANT_STRING) != 0 ? reply_str : NULL,
300 sizeof (reply_str) - 1);
301 return COMPLETE;
302 }
303
304
305
306 static int G_GNUC_PRINTF (5, 0)
307 shell_command_va (struct vfs_class *me, struct vfs_s_super *super, int wait_reply, const char *scr,
308 const char *vars, va_list ap)
309 {
310 int r;
311 GString *command;
312
313 command = mc_g_string_dup (SHELL_SUPER (super)->scr_env);
314 g_string_append_vprintf (command, vars, ap);
315 g_string_append (command, scr);
316 r = shell_command (me, super, wait_reply, command->str, command->len);
317 g_string_free (command, TRUE);
318
319 return r;
320 }
321
322
323
324 static int G_GNUC_PRINTF (5, 6)
325 shell_command_v (struct vfs_class *me, struct vfs_s_super *super, int wait_reply, const char *scr,
326 const char *vars, ...)
327 {
328 int r;
329 va_list ap;
330
331 va_start (ap, vars);
332 r = shell_command_va (me, super, wait_reply, scr, vars, ap);
333 va_end (ap);
334
335 return r;
336 }
337
338
339
340 static int G_GNUC_PRINTF (5, 6)
341 shell_send_command (struct vfs_class *me, struct vfs_s_super *super, int flags, const char *scr,
342 const char *vars, ...)
343 {
344 int r;
345 va_list ap;
346
347 va_start (ap, vars);
348 r = shell_command_va (me, super, WAIT_REPLY, scr, vars, ap);
349 va_end (ap);
350 vfs_stamp_create (vfs_shell_ops, super);
351
352 if (r != COMPLETE)
353 ERRNOR (E_REMOTE, -1);
354 if ((flags & OPT_FLUSH) != 0)
355 vfs_s_invalidate (me, super);
356
357 return 0;
358 }
359
360
361
362 static struct vfs_s_super *
363 shell_new_archive (struct vfs_class *me)
364 {
365 shell_super_t *arch;
366
367 arch = g_new0 (shell_super_t, 1);
368 arch->base.me = me;
369
370 return VFS_SUPER (arch);
371 }
372
373
374
375 static void
376 shell_free_archive (struct vfs_class *me, struct vfs_s_super *super)
377 {
378 shell_super_t *shell_super = SHELL_SUPER (super);
379
380 if ((shell_super->sockw != -1) || (shell_super->sockr != -1))
381 vfs_print_message (_ ("shell: Disconnecting from %s"), super->name ? super->name : "???");
382
383 if (shell_super->sockw != -1)
384 {
385 shell_command (me, super, NONE, "exit\n", -1);
386 close (shell_super->sockw);
387 shell_super->sockw = -1;
388 }
389
390 if (shell_super->sockr != -1)
391 {
392 close (shell_super->sockr);
393 shell_super->sockr = -1;
394 }
395
396 g_free (shell_super->scr_ls);
397 g_free (shell_super->scr_exists);
398 g_free (shell_super->scr_mkdir);
399 g_free (shell_super->scr_unlink);
400 g_free (shell_super->scr_chown);
401 g_free (shell_super->scr_chmod);
402 g_free (shell_super->scr_utime);
403 g_free (shell_super->scr_rmdir);
404 g_free (shell_super->scr_ln);
405 g_free (shell_super->scr_mv);
406 g_free (shell_super->scr_hardlink);
407 g_free (shell_super->scr_get);
408 g_free (shell_super->scr_send);
409 g_free (shell_super->scr_append);
410 g_free (shell_super->scr_info);
411 if (shell_super->scr_env != NULL)
412 g_string_free (shell_super->scr_env, TRUE);
413 }
414
415
416
417 static void
418 shell_pipeopen (struct vfs_s_super *super, const char *path, const char *argv[])
419 {
420 int fileset1[2], fileset2[2];
421 int res;
422
423 if ((pipe (fileset1) < 0) || (pipe (fileset2) < 0))
424 vfs_die ("Cannot pipe(): %m.");
425
426 res = my_fork ();
427
428 if (res != 0)
429 {
430 if (res < 0)
431 vfs_die ("Cannot fork(): %m.");
432
433 close (fileset1[0]);
434 SHELL_SUPER (super)->sockw = fileset1[1];
435 close (fileset2[1]);
436 SHELL_SUPER (super)->sockr = fileset2[0];
437 }
438 else
439 {
440 res = dup2 (fileset1[0], STDIN_FILENO);
441 close (fileset1[0]);
442 close (fileset1[1]);
443 res = dup2 (fileset2[1], STDOUT_FILENO);
444 close (STDERR_FILENO);
445
446 res = open ("/dev/null", O_WRONLY);
447 close (fileset2[0]);
448 close (fileset2[1]);
449 my_execvp (path, (char **) argv);
450 my_exit (3);
451 }
452 }
453
454
455
456 static GString *
457 shell_set_env (int flags)
458 {
459 GString *ret;
460
461 ret = g_string_sized_new (256);
462
463 if ((flags & SHELL_HAVE_HEAD) != 0)
464 g_string_append (ret, "SHELL_HAVE_HEAD=1 export SHELL_HAVE_HEAD; ");
465
466 if ((flags & SHELL_HAVE_SED) != 0)
467 g_string_append (ret, "SHELL_HAVE_SED=1 export SHELL_HAVE_SED; ");
468
469 if ((flags & SHELL_HAVE_AWK) != 0)
470 g_string_append (ret, "SHELL_HAVE_AWK=1 export SHELL_HAVE_AWK; ");
471
472 if ((flags & SHELL_HAVE_PERL) != 0)
473 g_string_append (ret, "SHELL_HAVE_PERL=1 export SHELL_HAVE_PERL; ");
474
475 if ((flags & SHELL_HAVE_LSQ) != 0)
476 g_string_append (ret, "SHELL_HAVE_LSQ=1 export SHELL_HAVE_LSQ; ");
477
478 if ((flags & SHELL_HAVE_DATE_MDYT) != 0)
479 g_string_append (ret, "SHELL_HAVE_DATE_MDYT=1 export SHELL_HAVE_DATE_MDYT; ");
480
481 if ((flags & SHELL_HAVE_TAIL) != 0)
482 g_string_append (ret, "SHELL_HAVE_TAIL=1 export SHELL_HAVE_TAIL; ");
483
484 return ret;
485 }
486
487
488
489 static gboolean
490 shell_info (struct vfs_class *me, struct vfs_s_super *super)
491 {
492 shell_super_t *shell_super = SHELL_SUPER (super);
493
494 if (shell_command (me, super, NONE, shell_super->scr_info, -1) == COMPLETE)
495 {
496 while (TRUE)
497 {
498 int res;
499 char buffer[BUF_8K] = "";
500
501 res = vfs_s_get_line_interruptible (me, buffer, sizeof (buffer), shell_super->sockr);
502 if ((res == 0) || (res == EINTR))
503 ERRNOR (ECONNRESET, FALSE);
504 if (strncmp (buffer, "### ", 4) == 0)
505 break;
506 shell_super->host_flags = atol (buffer);
507 }
508 return TRUE;
509 }
510 ERRNOR (E_PROTO, FALSE);
511 }
512
513
514
515 static void
516 shell_open_archive_pipeopen (struct vfs_s_super *super)
517 {
518 char gbuf[10];
519 const char *argv[10];
520 const char *xsh = (super->path_element->port == SHELL_FLAG_RSH ? "rsh" : "ssh");
521 int i = 0;
522
523 argv[i++] = xsh;
524 if (super->path_element->port == SHELL_FLAG_COMPRESSED)
525 argv[i++] = "-C";
526
527 if (super->path_element->port > SHELL_FLAG_RSH)
528 {
529 argv[i++] = "-p";
530 g_snprintf (gbuf, sizeof (gbuf), "%d", super->path_element->port);
531 argv[i++] = gbuf;
532 }
533
534
535
536
537
538
539
540
541 if (super->path_element->user != NULL)
542 {
543 argv[i++] = "-l";
544 argv[i++] = super->path_element->user;
545 }
546 else
547 {
548
549 super->path_element->user = vfs_get_local_username ();
550 }
551
552 argv[i++] = super->path_element->host;
553 argv[i++] = "echo SHELL:; /bin/sh";
554 argv[i++] = NULL;
555
556 shell_pipeopen (super, xsh, argv);
557 }
558
559
560
561 static gboolean
562 shell_open_archive_talk (struct vfs_class *me, struct vfs_s_super *super)
563 {
564 shell_super_t *shell_super = SHELL_SUPER (super);
565 char answer[2048];
566
567 printf ("\n%s\n", _ ("shell: Waiting for initial line..."));
568
569 if (vfs_s_get_line (me, shell_super->sockr, answer, sizeof (answer), ':') == 0)
570 return FALSE;
571
572 if (strstr (answer, "assword") != NULL)
573 {
574
575
576
577 printf ("\n%s\n", _ ("Sorry, we cannot do password authenticated connections for now."));
578
579 return FALSE;
580 #if 0
581 if (super->path_element->password == NULL)
582 {
583 char *p, *op;
584
585 p = g_strdup_printf (_("shell: Password is required for %s"),
586 super->path_element->user);
587 op = vfs_get_password (p);
588 g_free (p);
589 if (op == NULL)
590 return FALSE;
591 super->path_element->password = op;
592 }
593
594 printf ("\n%s\n", _("shell: Sending password..."));
595
596 {
597 size_t str_len;
598
599 str_len = strlen (super->path_element->password);
600 if ((write (shell_super.sockw, super->path_element->password, str_len) !=
601 (ssize_t) str_len) || (write (shell_super->sockw, "\n", 1) != 1))
602 return FALSE;
603 }
604 #endif
605 }
606 return TRUE;
607 }
608
609
610
611 static int
612 shell_open_archive_int (struct vfs_class *me, struct vfs_s_super *super)
613 {
614 gboolean ftalk;
615
616
617 pre_exec ();
618
619
620 shell_open_archive_pipeopen (super);
621
622
623 ftalk = shell_open_archive_talk (me, super);
624
625
626 post_exec ();
627
628 if (!ftalk)
629 ERRNOR (E_PROTO, -1);
630
631 vfs_print_message ("%s", _ ("shell: Sending initial line..."));
632
633
634 if (shell_command (me, super, WAIT_REPLY,
635 "LANG=C LC_ALL=C LC_TIME=C; export LANG LC_ALL LC_TIME;\n"
636 "echo '### 200'\n",
637 -1)
638 != COMPLETE)
639 ERRNOR (E_PROTO, -1);
640
641 vfs_print_message ("%s", _ ("shell: Getting host info..."));
642 if (shell_info (me, super))
643 SHELL_SUPER (super)->scr_env = shell_set_env (SHELL_SUPER (super)->host_flags);
644
645 #if 0
646 super->name =
647 g_strconcat ("sh://", super->path_element->user, "@", super->path_element->host,
648 PATH_SEP_STR, (char *) NULL);
649 #else
650 super->name = g_strdup (PATH_SEP_STR);
651 #endif
652
653 super->root = vfs_s_new_inode (me, super, shell_default_stat (me));
654
655 return 0;
656 }
657
658
659
660 static int
661 shell_open_archive (struct vfs_s_super *super, const vfs_path_t *vpath,
662 const vfs_path_element_t *vpath_element)
663 {
664 shell_super_t *shell_super = SHELL_SUPER (super);
665
666 (void) vpath;
667
668 super->path_element = vfs_path_element_clone (vpath_element);
669
670 if (strncmp (vpath_element->vfs_prefix, "rsh", 3) == 0)
671 super->path_element->port = SHELL_FLAG_RSH;
672
673 shell_super->scr_ls = shell_load_script_from_file (super->path_element->host, VFS_SHELL_LS_FILE,
674 VFS_SHELL_LS_DEF_CONTENT);
675 shell_super->scr_exists = shell_load_script_from_file (
676 super->path_element->host, VFS_SHELL_EXISTS_FILE, VFS_SHELL_EXISTS_DEF_CONTENT);
677 shell_super->scr_mkdir = shell_load_script_from_file (
678 super->path_element->host, VFS_SHELL_MKDIR_FILE, VFS_SHELL_MKDIR_DEF_CONTENT);
679 shell_super->scr_unlink = shell_load_script_from_file (
680 super->path_element->host, VFS_SHELL_UNLINK_FILE, VFS_SHELL_UNLINK_DEF_CONTENT);
681 shell_super->scr_chown = shell_load_script_from_file (
682 super->path_element->host, VFS_SHELL_CHOWN_FILE, VFS_SHELL_CHOWN_DEF_CONTENT);
683 shell_super->scr_chmod = shell_load_script_from_file (
684 super->path_element->host, VFS_SHELL_CHMOD_FILE, VFS_SHELL_CHMOD_DEF_CONTENT);
685 shell_super->scr_utime = shell_load_script_from_file (
686 super->path_element->host, VFS_SHELL_UTIME_FILE, VFS_SHELL_UTIME_DEF_CONTENT);
687 shell_super->scr_rmdir = shell_load_script_from_file (
688 super->path_element->host, VFS_SHELL_RMDIR_FILE, VFS_SHELL_RMDIR_DEF_CONTENT);
689 shell_super->scr_ln = shell_load_script_from_file (super->path_element->host, VFS_SHELL_LN_FILE,
690 VFS_SHELL_LN_DEF_CONTENT);
691 shell_super->scr_mv = shell_load_script_from_file (super->path_element->host, VFS_SHELL_MV_FILE,
692 VFS_SHELL_MV_DEF_CONTENT);
693 shell_super->scr_hardlink = shell_load_script_from_file (
694 super->path_element->host, VFS_SHELL_HARDLINK_FILE, VFS_SHELL_HARDLINK_DEF_CONTENT);
695 shell_super->scr_get = shell_load_script_from_file (
696 super->path_element->host, VFS_SHELL_GET_FILE, VFS_SHELL_GET_DEF_CONTENT);
697 shell_super->scr_send = shell_load_script_from_file (
698 super->path_element->host, VFS_SHELL_SEND_FILE, VFS_SHELL_SEND_DEF_CONTENT);
699 shell_super->scr_append = shell_load_script_from_file (
700 super->path_element->host, VFS_SHELL_APPEND_FILE, VFS_SHELL_APPEND_DEF_CONTENT);
701 shell_super->scr_info = shell_load_script_from_file (
702 super->path_element->host, VFS_SHELL_INFO_FILE, VFS_SHELL_INFO_DEF_CONTENT);
703
704 return shell_open_archive_int (vpath_element->class, super);
705 }
706
707
708
709 static int
710 shell_archive_same (const vfs_path_element_t *vpath_element, struct vfs_s_super *super,
711 const vfs_path_t *vpath, void *cookie)
712 {
713 vfs_path_element_t *path_element;
714 int result;
715
716 (void) vpath;
717 (void) cookie;
718
719 path_element = vfs_path_element_clone (vpath_element);
720
721 if (path_element->user == NULL)
722 path_element->user = vfs_get_local_username ();
723
724 result = ((strcmp (path_element->host, super->path_element->host) == 0)
725 && (strcmp (path_element->user, super->path_element->user) == 0)
726 && (path_element->port == super->path_element->port))
727 ? 1
728 : 0;
729
730 vfs_path_element_free (path_element);
731
732 return result;
733 }
734
735
736
737 static void
738 shell_parse_ls (char *buffer, struct vfs_s_entry *ent)
739 {
740 #define ST ent->ino->st
741
742 buffer++;
743
744 switch (buffer[-1])
745 {
746 case ':':
747 {
748 char *filename;
749 char *filename_bound;
750 char *temp;
751
752 filename = buffer;
753
754 if (strcmp (filename, "\".\"") == 0 || strcmp (filename, "\"..\"") == 0)
755 break;
756
757 filename_bound = filename + strlen (filename);
758
759 if (S_ISLNK (ST.st_mode))
760 {
761 char *linkname;
762 char *linkname_bound;
763
764
765
766
767 linkname_bound = filename_bound;
768
769 if (*filename == '"')
770 ++filename;
771
772 linkname = strstr (filename, "\" -> \"");
773 if (linkname == NULL)
774 {
775
776 linkname = filename_bound;
777 if (filename_bound > filename && *(filename_bound - 1) == '"')
778 --filename_bound;
779 }
780 else
781 {
782 filename_bound = linkname;
783 linkname += 6;
784 if (*(linkname_bound - 1) == '"')
785 --linkname_bound;
786 }
787
788 ent->name = g_strndup (filename, filename_bound - filename);
789 temp = ent->name;
790 ent->name = str_shell_unescape (ent->name);
791 g_free (temp);
792
793 ent->ino->linkname = g_strndup (linkname, linkname_bound - linkname);
794 temp = ent->ino->linkname;
795 ent->ino->linkname = str_shell_unescape (ent->ino->linkname);
796 g_free (temp);
797 }
798 else
799 {
800
801 if (filename_bound - filename > 2)
802 {
803
804
805
806
807 if (*filename == '"')
808 ++filename;
809 if (*(filename_bound - 1) == '"')
810 --filename_bound;
811 }
812
813 ent->name = g_strndup (filename, filename_bound - filename);
814 temp = ent->name;
815 ent->name = str_shell_unescape (ent->name);
816 g_free (temp);
817 }
818 break;
819 }
820
821 case 'S':
822 ST.st_size = (off_t) g_ascii_strtoll (buffer, NULL, 10);
823 break;
824
825 case 'P':
826 {
827 size_t skipped;
828
829 vfs_parse_filemode (buffer, &skipped, &ST.st_mode);
830 break;
831 }
832
833 case 'R':
834 {
835
836
837
838
839 size_t skipped;
840
841 vfs_parse_raw_filemode (buffer, &skipped, &ST.st_mode);
842 break;
843 }
844
845 case 'd':
846 vfs_split_text (buffer);
847 vfs_zero_stat_times (&ST);
848 if (vfs_parse_filedate (0, &ST.st_ctime) == 0)
849 break;
850 ST.st_atime = ST.st_mtime = ST.st_ctime;
851 break;
852
853 case 'D':
854 {
855 struct tm tim;
856
857 memset (&tim, 0, sizeof (tim));
858
859 if (sscanf (buffer, "%d %d %d %d %d %d", &tim.tm_year, &tim.tm_mon, &tim.tm_mday,
860 &tim.tm_hour, &tim.tm_min, &tim.tm_sec)
861 != 6)
862 break;
863 vfs_zero_stat_times (&ST);
864 ST.st_atime = ST.st_mtime = ST.st_ctime = mktime (&tim);
865 }
866 break;
867
868 case 'E':
869 {
870 int maj, min;
871
872
873 if (sscanf (buffer, "%d,%d", &maj, &min) != 2)
874 break;
875 #ifdef HAVE_STRUCT_STAT_ST_RDEV
876 ST.st_rdev = makedev (maj, min);
877 #endif
878 }
879 break;
880
881 default:
882 break;
883 }
884
885 #undef ST
886 }
887
888
889
890 static int
891 shell_dir_load (struct vfs_class *me, struct vfs_s_inode *dir, const char *remote_path)
892 {
893 struct vfs_s_super *super = dir->super;
894 char buffer[BUF_8K] = "\0";
895 struct vfs_s_entry *ent = NULL;
896 char *quoted_path;
897 int reply_code;
898
899
900
901
902 #if 0
903 if (me->logfile == NULL)
904 me->logfile = fopen ("/tmp/mc-SHELL.sh", "w");
905 #endif
906
907 vfs_print_message (_ ("shell: Reading directory %s..."), remote_path);
908
909 dir->timestamp = g_get_monotonic_time () + shell_directory_timeout * G_USEC_PER_SEC;
910
911 quoted_path = str_shell_escape (remote_path);
912 (void) shell_command_v (me, super, NONE, SHELL_SUPER (super)->scr_ls, "SHELL_FILENAME=%s;\n",
913 quoted_path);
914 g_free (quoted_path);
915
916 ent = vfs_s_generate_entry (me, NULL, dir, 0);
917
918 while (TRUE)
919 {
920 int res;
921
922 res =
923 vfs_s_get_line_interruptible (me, buffer, sizeof (buffer), SHELL_SUPER (super)->sockr);
924
925 if ((res == 0) || (res == EINTR))
926 {
927 vfs_s_free_entry (me, ent);
928 me->verrno = ECONNRESET;
929 goto error;
930 }
931 if (me->logfile != NULL)
932 {
933 fputs (buffer, me->logfile);
934 fputs ("\n", me->logfile);
935 fflush (me->logfile);
936 }
937 if (strncmp (buffer, "### ", 4) == 0)
938 break;
939
940 if (buffer[0] != '\0')
941 shell_parse_ls (buffer, ent);
942 else if (ent->name != NULL)
943 {
944 vfs_s_insert_entry (me, dir, ent);
945 ent = vfs_s_generate_entry (me, NULL, dir, 0);
946 }
947 }
948
949 vfs_s_free_entry (me, ent);
950 reply_code = shell_decode_reply (buffer + 4, 0);
951 if (reply_code == COMPLETE)
952 {
953 vfs_print_message (_ ("%s: done."), me->name);
954 return 0;
955 }
956
957 me->verrno = reply_code == ERROR ? EACCES : E_REMOTE;
958
959 error:
960 vfs_print_message (_ ("%s: failure"), me->name);
961 return -1;
962 }
963
964
965
966 static int
967 shell_file_store (struct vfs_class *me, vfs_file_handler_t *fh, char *name, char *localname)
968 {
969 shell_file_handler_t *shell = SHELL_FILE_HANDLER (fh);
970 struct vfs_s_super *super = VFS_FILE_HANDLER_SUPER (fh);
971 shell_super_t *shell_super = SHELL_SUPER (super);
972 int code;
973 off_t total = 0;
974 char buffer[BUF_8K];
975 struct stat s;
976 int h;
977 char *quoted_name;
978
979 h = open (localname, O_RDONLY);
980 if (h == -1)
981 ERRNOR (EIO, -1);
982 if (fstat (h, &s) < 0)
983 {
984 close (h);
985 ERRNOR (EIO, -1);
986 }
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017 quoted_name = str_shell_escape (name);
1018 vfs_print_message (_ ("shell: store %s: sending command..."), quoted_name);
1019
1020
1021 code = shell_command_v (
1022 me, super, WAIT_REPLY, shell->append ? shell_super->scr_append : shell_super->scr_send,
1023 "SHELL_FILENAME=%s SHELL_FILESIZE=%" PRIuMAX ";\n", quoted_name, (uintmax_t) s.st_size);
1024 g_free (quoted_name);
1025
1026 if (code != PRELIM)
1027 {
1028 close (h);
1029 ERRNOR (E_REMOTE, -1);
1030 }
1031
1032 while (TRUE)
1033 {
1034 ssize_t n, t;
1035
1036 while ((n = read (h, buffer, sizeof (buffer))) < 0)
1037 {
1038 if ((errno == EINTR) && tty_got_interrupt ())
1039 continue;
1040 vfs_print_message ("%s", _ ("shell: Local read failed, sending zeros"));
1041 close (h);
1042 h = open ("/dev/zero", O_RDONLY);
1043 }
1044
1045 if (n == 0)
1046 break;
1047
1048 t = write (shell_super->sockw, buffer, n);
1049 if (t != n)
1050 {
1051 if (t == -1)
1052 me->verrno = errno;
1053 else
1054 me->verrno = EIO;
1055 goto error_return;
1056 }
1057 tty_disable_interrupt_key ();
1058 total += n;
1059 vfs_print_message ("%s: %" PRIuMAX "/%" PRIuMAX, _ ("shell: storing file"),
1060 (uintmax_t) total, (uintmax_t) s.st_size);
1061 }
1062 close (h);
1063
1064 if (shell_get_reply (me, shell_super->sockr, NULL, 0) != COMPLETE)
1065 ERRNOR (E_REMOTE, -1);
1066 return 0;
1067
1068 error_return:
1069 close (h);
1070 shell_get_reply (me, shell_super->sockr, NULL, 0);
1071 return -1;
1072 }
1073
1074
1075
1076 static int
1077 shell_linear_start (struct vfs_class *me, vfs_file_handler_t *fh, off_t offset)
1078 {
1079 shell_file_handler_t *shell = SHELL_FILE_HANDLER (fh);
1080 struct vfs_s_super *super = VFS_FILE_HANDLER_SUPER (fh);
1081 char *name;
1082 char *quoted_name;
1083
1084 name = vfs_s_fullpath (me, fh->ino);
1085 if (name == NULL)
1086 return 0;
1087 quoted_name = str_shell_escape (name);
1088 g_free (name);
1089 shell->append = FALSE;
1090
1091
1092
1093
1094
1095
1096
1097
1098 offset = shell_command_v (me, super, WANT_STRING, SHELL_SUPER (super)->scr_get,
1099 "SHELL_FILENAME=%s SHELL_START_OFFSET=%" PRIuMAX ";\n", quoted_name,
1100 (uintmax_t) offset);
1101 g_free (quoted_name);
1102
1103 if (offset != PRELIM)
1104 ERRNOR (E_REMOTE, 0);
1105 fh->linear = LS_LINEAR_OPEN;
1106 shell->got = 0;
1107 errno = 0;
1108 #if SIZEOF_OFF_T == SIZEOF_LONG
1109 shell->total = (off_t) strtol (reply_str, NULL, 10);
1110 #else
1111 shell->total = (off_t) g_ascii_strtoll (reply_str, NULL, 10);
1112 #endif
1113 if (errno != 0)
1114 ERRNOR (E_REMOTE, 0);
1115 return 1;
1116 }
1117
1118
1119
1120 static void
1121 shell_linear_abort (struct vfs_class *me, vfs_file_handler_t *fh)
1122 {
1123 shell_file_handler_t *shell = SHELL_FILE_HANDLER (fh);
1124 struct vfs_s_super *super = VFS_FILE_HANDLER_SUPER (fh);
1125 char buffer[BUF_8K];
1126 ssize_t n;
1127
1128 vfs_print_message ("%s", _ ("Aborting transfer..."));
1129
1130 do
1131 {
1132 n = MIN ((off_t) sizeof (buffer), (shell->total - shell->got));
1133 if (n != 0)
1134 {
1135 n = read (SHELL_SUPER (super)->sockr, buffer, n);
1136 if (n < 0)
1137 return;
1138 shell->got += n;
1139 }
1140 }
1141 while (n != 0);
1142
1143 if (shell_get_reply (me, SHELL_SUPER (super)->sockr, NULL, 0) != COMPLETE)
1144 vfs_print_message ("%s", _ ("Error reported after abort."));
1145 else
1146 vfs_print_message ("%s", _ ("Aborted transfer would be successful."));
1147 }
1148
1149
1150
1151 static ssize_t
1152 shell_linear_read (struct vfs_class *me, vfs_file_handler_t *fh, void *buf, size_t len)
1153 {
1154 shell_file_handler_t *shell = SHELL_FILE_HANDLER (fh);
1155 struct vfs_s_super *super = VFS_FILE_HANDLER_SUPER (fh);
1156 ssize_t n = 0;
1157
1158 len = MIN ((size_t) (shell->total - shell->got), len);
1159 tty_disable_interrupt_key ();
1160 while (len != 0 && ((n = read (SHELL_SUPER (super)->sockr, buf, len)) < 0))
1161 {
1162 if ((errno == EINTR) && !tty_got_interrupt ())
1163 continue;
1164 break;
1165 }
1166 tty_enable_interrupt_key ();
1167
1168 if (n > 0)
1169 shell->got += n;
1170 else if (n < 0)
1171 shell_linear_abort (me, fh);
1172 else if (shell_get_reply (me, SHELL_SUPER (super)->sockr, NULL, 0) != COMPLETE)
1173 ERRNOR (E_REMOTE, -1);
1174 ERRNOR (errno, n);
1175 }
1176
1177
1178
1179 static void
1180 shell_linear_close (struct vfs_class *me, vfs_file_handler_t *fh)
1181 {
1182 shell_file_handler_t *shell = SHELL_FILE_HANDLER (fh);
1183
1184 if (shell->total != shell->got)
1185 shell_linear_abort (me, fh);
1186 }
1187
1188
1189
1190 static int
1191 shell_ctl (void *fh, int ctlop, void *arg)
1192 {
1193 (void) arg;
1194 (void) fh;
1195 (void) ctlop;
1196
1197 return 0;
1198
1199 #if 0
1200 switch (ctlop)
1201 {
1202 case VFS_CTL_IS_NOTREADY:
1203 {
1204 vfs_file_handler_t *file = VFS_FILE_HANDLER (fh);
1205 int v;
1206
1207 if (file->linear == LS_NOT_LINEAR)
1208 vfs_die ("You may not do this");
1209 if (file->linear == LS_LINEAR_CLOSED || file->linear == LS_LINEAR_PREOPEN)
1210 return 0;
1211
1212 v = vfs_s_select_on_two (VFS_FILE_HANDLER_SUPER (fh)->u.shell.sockr, 0);
1213
1214 return (((v < 0) && (errno == EINTR)) || v == 0) ? 1 : 0;
1215 }
1216 default:
1217 return 0;
1218 }
1219 #endif
1220 }
1221
1222
1223
1224 static int
1225 shell_rename (const vfs_path_t *vpath1, const vfs_path_t *vpath2)
1226 {
1227 const char *crpath1, *crpath2;
1228 char *rpath1, *rpath2;
1229 struct vfs_s_super *super, *super2;
1230 struct vfs_class *me;
1231 int ret;
1232
1233 crpath1 = vfs_s_get_path (vpath1, &super, 0);
1234 if (crpath1 == NULL)
1235 return -1;
1236
1237 crpath2 = vfs_s_get_path (vpath2, &super2, 0);
1238 if (crpath2 == NULL)
1239 return -1;
1240
1241 rpath1 = str_shell_escape (crpath1);
1242 rpath2 = str_shell_escape (crpath2);
1243
1244 me = VFS_CLASS (vfs_path_get_last_path_vfs (vpath1));
1245
1246 ret = shell_send_command (me, super2, OPT_FLUSH, SHELL_SUPER (super)->scr_mv,
1247 "SHELL_FILEFROM=%s SHELL_FILETO=%s;\n", rpath1, rpath2);
1248
1249 g_free (rpath1);
1250 g_free (rpath2);
1251
1252 return ret;
1253 }
1254
1255
1256
1257 static int
1258 shell_link (const vfs_path_t *vpath1, const vfs_path_t *vpath2)
1259 {
1260 const char *crpath1, *crpath2;
1261 char *rpath1, *rpath2;
1262 struct vfs_s_super *super, *super2;
1263 struct vfs_class *me;
1264 int ret;
1265
1266 crpath1 = vfs_s_get_path (vpath1, &super, 0);
1267 if (crpath1 == NULL)
1268 return -1;
1269
1270 crpath2 = vfs_s_get_path (vpath2, &super2, 0);
1271 if (crpath2 == NULL)
1272 return -1;
1273
1274 rpath1 = str_shell_escape (crpath1);
1275 rpath2 = str_shell_escape (crpath2);
1276
1277 me = VFS_CLASS (vfs_path_get_last_path_vfs (vpath1));
1278
1279 ret = shell_send_command (me, super2, OPT_FLUSH, SHELL_SUPER (super)->scr_hardlink,
1280 "SHELL_FILEFROM=%s SHELL_FILETO=%s;\n", rpath1, rpath2);
1281
1282 g_free (rpath1);
1283 g_free (rpath2);
1284
1285 return ret;
1286 }
1287
1288
1289
1290 static int
1291 shell_symlink (const vfs_path_t *vpath1, const vfs_path_t *vpath2)
1292 {
1293 char *qsetto;
1294 const char *crpath;
1295 char *rpath;
1296 struct vfs_s_super *super;
1297 struct vfs_class *me;
1298 int ret;
1299
1300 crpath = vfs_s_get_path (vpath2, &super, 0);
1301 if (crpath == NULL)
1302 return -1;
1303
1304 rpath = str_shell_escape (crpath);
1305 qsetto = str_shell_escape (vfs_path_get_last_path_str (vpath1));
1306
1307 me = VFS_CLASS (vfs_path_get_last_path_vfs (vpath2));
1308
1309 ret = shell_send_command (me, super, OPT_FLUSH, SHELL_SUPER (super)->scr_ln,
1310 "SHELL_FILEFROM=%s SHELL_FILETO=%s;\n", qsetto, rpath);
1311
1312 g_free (qsetto);
1313 g_free (rpath);
1314
1315 return ret;
1316 }
1317
1318
1319
1320 static int
1321 shell_stat (const vfs_path_t *vpath, struct stat *buf)
1322 {
1323 int ret;
1324
1325 ret = vfs_s_stat (vpath, buf);
1326 shell_set_blksize (buf);
1327 return ret;
1328 }
1329
1330
1331
1332 static int
1333 shell_lstat (const vfs_path_t *vpath, struct stat *buf)
1334 {
1335 int ret;
1336
1337 ret = vfs_s_lstat (vpath, buf);
1338 shell_set_blksize (buf);
1339 return ret;
1340 }
1341
1342
1343
1344 static int
1345 shell_fstat (void *vfs_info, struct stat *buf)
1346 {
1347 int ret;
1348
1349 ret = vfs_s_fstat (vfs_info, buf);
1350 shell_set_blksize (buf);
1351 return ret;
1352 }
1353
1354
1355
1356 static int
1357 shell_chmod (const vfs_path_t *vpath, mode_t mode)
1358 {
1359 const char *crpath;
1360 char *rpath;
1361 struct vfs_s_super *super;
1362 struct vfs_class *me;
1363 int ret;
1364
1365 crpath = vfs_s_get_path (vpath, &super, 0);
1366 if (crpath == NULL)
1367 return -1;
1368
1369 rpath = str_shell_escape (crpath);
1370
1371 me = VFS_CLASS (vfs_path_get_last_path_vfs (vpath));
1372
1373 ret = shell_send_command (me, super, OPT_FLUSH, SHELL_SUPER (super)->scr_chmod,
1374 "SHELL_FILENAME=%s SHELL_FILEMODE=%4.4o;\n", rpath,
1375 (unsigned int) (mode & 07777));
1376
1377 g_free (rpath);
1378
1379 return ret;
1380 ;
1381 }
1382
1383
1384
1385 static int
1386 shell_chown (const vfs_path_t *vpath, uid_t owner, gid_t group)
1387 {
1388 char *sowner, *sgroup;
1389 struct passwd *pw;
1390 struct group *gr;
1391 const char *crpath;
1392 char *rpath;
1393 struct vfs_s_super *super;
1394 struct vfs_class *me;
1395 int ret;
1396
1397 pw = getpwuid (owner);
1398 if (pw == NULL)
1399 return 0;
1400
1401 gr = getgrgid (group);
1402 if (gr == NULL)
1403 return 0;
1404
1405 sowner = pw->pw_name;
1406 sgroup = gr->gr_name;
1407
1408 crpath = vfs_s_get_path (vpath, &super, 0);
1409 if (crpath == NULL)
1410 return -1;
1411
1412 rpath = str_shell_escape (crpath);
1413
1414 me = VFS_CLASS (vfs_path_get_last_path_vfs (vpath));
1415
1416
1417 ret = shell_send_command (me, super, OPT_FLUSH, SHELL_SUPER (super)->scr_chown,
1418 "SHELL_FILENAME=%s SHELL_FILEOWNER=%s SHELL_FILEGROUP=%s;\n", rpath,
1419 sowner, sgroup);
1420
1421 g_free (rpath);
1422
1423 return ret;
1424 }
1425
1426
1427
1428 static int
1429 shell_utime (const vfs_path_t *vpath, mc_timesbuf_t *times)
1430 {
1431 char utcatime[16], utcmtime[16];
1432 char utcatime_w_nsec[30], utcmtime_w_nsec[30];
1433 mc_timespec_t atime, mtime;
1434 struct tm *gmt;
1435 const char *crpath;
1436 char *rpath;
1437 struct vfs_s_super *super;
1438 struct vfs_class *me;
1439 int ret;
1440
1441 crpath = vfs_s_get_path (vpath, &super, 0);
1442 if (crpath == NULL)
1443 return -1;
1444
1445 rpath = str_shell_escape (crpath);
1446
1447 vfs_get_timespecs_from_timesbuf (times, &atime, &mtime);
1448
1449 gmt = gmtime (&atime.tv_sec);
1450 g_snprintf (utcatime, sizeof (utcatime), "%04d%02d%02d%02d%02d.%02d", gmt->tm_year + 1900,
1451 gmt->tm_mon + 1, gmt->tm_mday, gmt->tm_hour, gmt->tm_min, gmt->tm_sec);
1452 g_snprintf (utcatime_w_nsec, sizeof (utcatime_w_nsec), "%04d-%02d-%02d %02d:%02d:%02d.%09ld",
1453 gmt->tm_year + 1900, gmt->tm_mon + 1, gmt->tm_mday, gmt->tm_hour, gmt->tm_min,
1454 gmt->tm_sec, atime.tv_nsec);
1455
1456 gmt = gmtime (&mtime.tv_sec);
1457 g_snprintf (utcmtime, sizeof (utcmtime), "%04d%02d%02d%02d%02d.%02d", gmt->tm_year + 1900,
1458 gmt->tm_mon + 1, gmt->tm_mday, gmt->tm_hour, gmt->tm_min, gmt->tm_sec);
1459 g_snprintf (utcmtime_w_nsec, sizeof (utcmtime_w_nsec), "%04d-%02d-%02d %02d:%02d:%02d.%09ld",
1460 gmt->tm_year + 1900, gmt->tm_mon + 1, gmt->tm_mday, gmt->tm_hour, gmt->tm_min,
1461 gmt->tm_sec, mtime.tv_nsec);
1462
1463 me = VFS_CLASS (vfs_path_get_last_path_vfs (vpath));
1464
1465 ret = shell_send_command (
1466 me, super, OPT_FLUSH, SHELL_SUPER (super)->scr_utime,
1467 "SHELL_FILENAME=%s SHELL_FILEATIME=%ju SHELL_FILEMTIME=%ju "
1468 "SHELL_TOUCHATIME=%s SHELL_TOUCHMTIME=%s SHELL_TOUCHATIME_W_NSEC=\"%s\" "
1469 "SHELL_TOUCHMTIME_W_NSEC=\"%s\";\n",
1470 rpath, (uintmax_t) atime.tv_sec, (uintmax_t) mtime.tv_sec, utcatime, utcmtime,
1471 utcatime_w_nsec, utcmtime_w_nsec);
1472
1473 g_free (rpath);
1474
1475 return ret;
1476 }
1477
1478
1479
1480 static int
1481 shell_unlink (const vfs_path_t *vpath)
1482 {
1483 const char *crpath;
1484 char *rpath;
1485 struct vfs_s_super *super;
1486 struct vfs_class *me;
1487 int ret;
1488
1489 crpath = vfs_s_get_path (vpath, &super, 0);
1490 if (crpath == NULL)
1491 return -1;
1492
1493 rpath = str_shell_escape (crpath);
1494
1495 me = VFS_CLASS (vfs_path_get_last_path_vfs (vpath));
1496
1497 ret = shell_send_command (me, super, OPT_FLUSH, SHELL_SUPER (super)->scr_unlink,
1498 "SHELL_FILENAME=%s;\n", rpath);
1499
1500 g_free (rpath);
1501
1502 return ret;
1503 }
1504
1505
1506
1507 static int
1508 shell_exists (const vfs_path_t *vpath)
1509 {
1510 const char *crpath;
1511 char *rpath;
1512 struct vfs_s_super *super;
1513 struct vfs_class *me;
1514 int ret;
1515
1516 crpath = vfs_s_get_path (vpath, &super, 0);
1517 if (crpath == NULL)
1518 return -1;
1519
1520 rpath = str_shell_escape (crpath);
1521
1522 me = VFS_CLASS (vfs_path_get_last_path_vfs (vpath));
1523
1524 ret = shell_send_command (me, super, OPT_FLUSH, SHELL_SUPER (super)->scr_exists,
1525 "SHELL_FILENAME=%s;\n", rpath);
1526
1527 g_free (rpath);
1528
1529 return (ret == 0 ? 1 : 0);
1530 }
1531
1532
1533
1534 static int
1535 shell_mkdir (const vfs_path_t *vpath, mode_t mode)
1536 {
1537 const char *crpath;
1538 char *rpath;
1539 struct vfs_s_super *super;
1540 struct vfs_class *me;
1541 int ret;
1542
1543 (void) mode;
1544
1545 crpath = vfs_s_get_path (vpath, &super, 0);
1546 if (crpath == NULL)
1547 return -1;
1548
1549 rpath = str_shell_escape (crpath);
1550
1551 me = VFS_CLASS (vfs_path_get_last_path_vfs (vpath));
1552
1553 ret = shell_send_command (me, super, OPT_FLUSH, SHELL_SUPER (super)->scr_mkdir,
1554 "SHELL_FILENAME=%s;\n", rpath);
1555 g_free (rpath);
1556
1557 if (ret != 0)
1558 return ret;
1559
1560 if (shell_exists (vpath) == 0)
1561 {
1562 me->verrno = EACCES;
1563 return -1;
1564 }
1565 return 0;
1566 }
1567
1568
1569
1570 static int
1571 shell_rmdir (const vfs_path_t *vpath)
1572 {
1573 const char *crpath;
1574 char *rpath;
1575 struct vfs_s_super *super;
1576 struct vfs_class *me;
1577 int ret;
1578
1579 crpath = vfs_s_get_path (vpath, &super, 0);
1580 if (crpath == NULL)
1581 return -1;
1582
1583 rpath = str_shell_escape (crpath);
1584
1585 me = VFS_CLASS (vfs_path_get_last_path_vfs (vpath));
1586
1587 ret = shell_send_command (me, super, OPT_FLUSH, SHELL_SUPER (super)->scr_rmdir,
1588 "SHELL_FILENAME=%s;\n", rpath);
1589
1590 g_free (rpath);
1591
1592 return ret;
1593 }
1594
1595
1596
1597 static vfs_file_handler_t *
1598 shell_fh_new (struct vfs_s_inode *ino, gboolean changed)
1599 {
1600 shell_file_handler_t *fh;
1601
1602 fh = g_new0 (shell_file_handler_t, 1);
1603 vfs_s_init_fh (VFS_FILE_HANDLER (fh), ino, changed);
1604
1605 return VFS_FILE_HANDLER (fh);
1606 }
1607
1608
1609
1610 static int
1611 shell_fh_open (struct vfs_class *me, vfs_file_handler_t *fh, int flags, mode_t mode)
1612 {
1613 shell_file_handler_t *shell = SHELL_FILE_HANDLER (fh);
1614
1615 (void) mode;
1616
1617
1618 if (((flags & O_WRONLY) == O_WRONLY) && ((flags & (O_RDONLY | O_RDWR)) == 0))
1619 {
1620
1621 if ((flags & O_APPEND) != 0)
1622 shell->append = TRUE;
1623
1624 if (fh->ino->localname == NULL)
1625 {
1626 vfs_path_t *vpath = NULL;
1627 int tmp_handle;
1628
1629 tmp_handle = vfs_mkstemps (&vpath, me->name, fh->ino->ent->name);
1630 if (tmp_handle == -1)
1631 return (-1);
1632
1633 fh->ino->localname = vfs_path_free (vpath, FALSE);
1634 close (tmp_handle);
1635 }
1636 return 0;
1637 }
1638
1639 if (fh->ino->localname == NULL && vfs_s_retrieve_file (me, fh->ino) == -1)
1640 return (-1);
1641
1642 if (fh->ino->localname == NULL)
1643 vfs_die ("retrieve_file failed to fill in localname");
1644 return 0;
1645 }
1646
1647
1648
1649 static void
1650 shell_fill_names (struct vfs_class *me, fill_names_f func)
1651 {
1652 GList *iter;
1653
1654 for (iter = VFS_SUBCLASS (me)->supers; iter != NULL; iter = g_list_next (iter))
1655 {
1656 const struct vfs_s_super *super = (const struct vfs_s_super *) iter->data;
1657
1658 char *name;
1659 char gbuf[10];
1660 const char *flags = "";
1661
1662 switch (super->path_element->port)
1663 {
1664 case SHELL_FLAG_RSH:
1665 flags = ":r";
1666 break;
1667 case SHELL_FLAG_COMPRESSED:
1668 flags = ":C";
1669 break;
1670 default:
1671 if (super->path_element->port > SHELL_FLAG_RSH)
1672 {
1673 g_snprintf (gbuf, sizeof (gbuf), ":%d", super->path_element->port);
1674 flags = gbuf;
1675 }
1676 break;
1677 }
1678
1679 name = g_strconcat (vfs_shell_ops->prefix, VFS_PATH_URL_DELIMITER,
1680 super->path_element->user, "@", super->path_element->host, flags,
1681 PATH_SEP_STR, super->path_element->path, (char *) NULL);
1682 func (name);
1683 g_free (name);
1684 }
1685 }
1686
1687
1688
1689 static void *
1690 shell_open (const vfs_path_t *vpath, int flags, mode_t mode)
1691 {
1692
1693
1694
1695
1696 flags &= ~O_EXCL;
1697 return vfs_s_open (vpath, flags, mode);
1698 }
1699
1700
1701
1702
1703
1704 void
1705 vfs_init_shell (void)
1706 {
1707 tcp_init ();
1708
1709 vfs_init_subclass (&shell_subclass, "shell", VFSF_REMOTE | VFSF_USETMP, "sh");
1710 vfs_shell_ops->fill_names = shell_fill_names;
1711 vfs_shell_ops->stat = shell_stat;
1712 vfs_shell_ops->lstat = shell_lstat;
1713 vfs_shell_ops->fstat = shell_fstat;
1714 vfs_shell_ops->chmod = shell_chmod;
1715 vfs_shell_ops->chown = shell_chown;
1716 vfs_shell_ops->utime = shell_utime;
1717 vfs_shell_ops->open = shell_open;
1718 vfs_shell_ops->symlink = shell_symlink;
1719 vfs_shell_ops->link = shell_link;
1720 vfs_shell_ops->unlink = shell_unlink;
1721 vfs_shell_ops->rename = shell_rename;
1722 vfs_shell_ops->mkdir = shell_mkdir;
1723 vfs_shell_ops->rmdir = shell_rmdir;
1724 vfs_shell_ops->ctl = shell_ctl;
1725 shell_subclass.archive_same = shell_archive_same;
1726 shell_subclass.new_archive = shell_new_archive;
1727 shell_subclass.open_archive = shell_open_archive;
1728 shell_subclass.free_archive = shell_free_archive;
1729 shell_subclass.fh_new = shell_fh_new;
1730 shell_subclass.fh_open = shell_fh_open;
1731 shell_subclass.dir_load = shell_dir_load;
1732 shell_subclass.file_store = shell_file_store;
1733 shell_subclass.linear_start = shell_linear_start;
1734 shell_subclass.linear_read = shell_linear_read;
1735 shell_subclass.linear_close = shell_linear_close;
1736 vfs_register_class (vfs_shell_ops);
1737 }
1738
1739