1
|
1 /*****************************************************************************/
|
|
2 /* gftp-text.c - text port of gftp */
|
122
|
3 /* Copyright (C) 1998-2003 Brian Masney <masneyb@gftp.org> */
|
1
|
4 /* */
|
|
5 /* This program is free software; you can redistribute it and/or modify */
|
|
6 /* it under the terms of the GNU General Public License as published by */
|
|
7 /* the Free Software Foundation; either version 2 of the License, or */
|
|
8 /* (at your option) any later version. */
|
|
9 /* */
|
|
10 /* This program is distributed in the hope that it will be useful, */
|
|
11 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
|
|
12 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
|
|
13 /* GNU General Public License for more details. */
|
|
14 /* */
|
|
15 /* You should have received a copy of the GNU General Public License */
|
|
16 /* along with this program; if not, write to the Free Software */
|
|
17 /* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA */
|
|
18 /*****************************************************************************/
|
|
19
|
|
20 #include "gftp-text.h"
|
33
|
21 static const char cvsid[] = "$Id$";
|
1
|
22
|
|
23 static gftp_request * gftp_text_locreq = NULL;
|
|
24 static gftp_request * gftp_text_remreq = NULL;
|
|
25
|
|
26 int
|
341
|
27 gftp_text_get_win_size (void)
|
1
|
28 {
|
341
|
29 struct winsize size;
|
|
30 int ret;
|
1
|
31
|
341
|
32 if (ioctl (0, TIOCGWINSZ, (char *) &size) < 0)
|
|
33 ret = 80;
|
|
34 else
|
|
35 ret = size.ws_col;
|
1
|
36
|
341
|
37 return (ret);
|
|
38 }
|
1
|
39
|
|
40
|
341
|
41 void
|
|
42 sig_child (int signo)
|
|
43 {
|
1
|
44 }
|
|
45
|
|
46
|
|
47 void
|
186
|
48 gftp_text_log (gftp_logging_level level, gftp_request * request,
|
|
49 const char *string, ...)
|
1
|
50 {
|
186
|
51 char tempstr[512], *stpos, *endpos, *utf8_str = NULL, *outstr;
|
1
|
52 va_list argp;
|
|
53 int sw;
|
|
54
|
|
55 g_return_if_fail (string != NULL);
|
|
56
|
|
57 switch (level)
|
|
58 {
|
|
59 case gftp_logging_send:
|
341
|
60 printf ("%s", GFTPUI_COMMON_COLOR_GREEN);
|
1
|
61 break;
|
|
62 case gftp_logging_recv:
|
341
|
63 printf ("%s", GFTPUI_COMMON_COLOR_YELLOW);
|
1
|
64 break;
|
|
65 case gftp_logging_error:
|
341
|
66 printf ("%s", GFTPUI_COMMON_COLOR_RED);
|
1
|
67 break;
|
|
68 default:
|
341
|
69 printf ("%s", GFTPUI_COMMON_COLOR_DEFAULT);
|
1
|
70 break;
|
|
71 }
|
|
72
|
|
73 va_start (argp, string);
|
|
74 g_vsnprintf (tempstr, sizeof (tempstr), string, argp);
|
|
75 va_end (argp);
|
|
76
|
186
|
77 #if GLIB_MAJOR_VERSION > 1
|
|
78 if (!g_utf8_validate (tempstr, -1, NULL))
|
|
79 utf8_str = gftp_string_to_utf8 (request, tempstr);
|
|
80 #endif
|
|
81
|
|
82 if (utf8_str != NULL)
|
|
83 outstr = utf8_str;
|
|
84 else
|
|
85 outstr = tempstr;
|
|
86
|
354
|
87 if (gftp_logfd != NULL && level != gftp_logging_misc_nolog)
|
1
|
88 {
|
186
|
89 fwrite (outstr, 1, strlen (outstr), gftp_logfd);
|
122
|
90 if (ferror (gftp_logfd))
|
1
|
91 {
|
122
|
92 fclose (gftp_logfd);
|
|
93 gftp_logfd = NULL;
|
1
|
94 }
|
|
95 else
|
122
|
96 fflush (gftp_logfd);
|
1
|
97 }
|
|
98
|
|
99 sw = gftp_text_get_win_size ();
|
186
|
100 stpos = outstr;
|
|
101 endpos = outstr + 1;
|
1
|
102 do
|
|
103 {
|
|
104 if (strlen (stpos) <= sw)
|
|
105 {
|
|
106 printf ("%s", stpos);
|
|
107 break;
|
|
108 }
|
|
109 for (endpos = stpos + sw - 1; *endpos != ' ' && endpos > stpos; endpos--);
|
|
110 if (endpos != stpos)
|
|
111 {
|
|
112 *endpos = '\0';
|
|
113 }
|
|
114 printf ("%s\n", stpos);
|
|
115 stpos = endpos + 1;
|
|
116 }
|
|
117 while (stpos != endpos);
|
|
118
|
341
|
119 printf ("%s", GFTPUI_COMMON_COLOR_DEFAULT);
|
186
|
120
|
|
121 if (utf8_str != NULL)
|
|
122 g_free (utf8_str);
|
1
|
123 }
|
|
124
|
|
125
|
341
|
126 char *
|
|
127 gftp_text_ask_question (const char *question, int echo, char *buf, size_t size)
|
|
128 {
|
|
129 struct termios term, oldterm;
|
|
130 sigset_t sig, sigsave;
|
|
131 char *pos, *termname;
|
|
132 FILE *infd;
|
|
133
|
|
134 if (!echo)
|
|
135 {
|
|
136 sigemptyset (&sig);
|
|
137 sigaddset (&sig, SIGINT);
|
|
138 sigaddset (&sig, SIGTSTP);
|
|
139 sigprocmask (SIG_BLOCK, &sig, &sigsave);
|
|
140
|
|
141 termname = ctermid (NULL);
|
|
142 if ((infd = fopen (termname, "r+")) == NULL)
|
|
143 {
|
|
144
|
|
145 gftp_text_log (gftp_logging_error, NULL,
|
|
146 _("Cannot open controlling terminal %s\n"), termname);
|
|
147 return (NULL);
|
|
148 }
|
|
149
|
|
150 tcgetattr (0, &term);
|
|
151 oldterm = term;
|
|
152 term.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
|
|
153 tcsetattr (fileno (infd), TCSAFLUSH, &term);
|
|
154 }
|
|
155 else
|
|
156 infd = stdin;
|
|
157
|
356
|
158 printf ("%s%s%s ", GFTPUI_COMMON_COLOR_BLUE, question, GFTPUI_COMMON_COLOR_DEFAULT);
|
341
|
159
|
|
160 if (fgets (buf, size, infd) == NULL)
|
|
161 return (NULL);
|
|
162 buf[size - 1] = '\0';
|
|
163
|
|
164 if (!echo)
|
|
165 {
|
|
166 printf ("\n");
|
|
167 tcsetattr (fileno (infd), TCSAFLUSH, &oldterm);
|
|
168 fclose (infd);
|
|
169 sigprocmask (SIG_SETMASK, &sigsave, NULL);
|
|
170 }
|
|
171
|
|
172 for (pos = buf + strlen (buf) - 1; *pos == ' ' || *pos == '\r' ||
|
|
173 *pos == '\n'; pos--);
|
|
174 *(pos+1) = '\0';
|
|
175
|
|
176 for (pos = buf; *pos == ' '; pos++);
|
|
177 if (*pos == '\0')
|
|
178 return (NULL);
|
|
179
|
|
180 return (pos);
|
|
181 }
|
|
182
|
|
183
|
|
184 int
|
|
185 main (int argc, char **argv)
|
|
186 {
|
|
187 char *startup_directory;
|
|
188 #if HAVE_LIBREADLINE
|
|
189 char *tempstr, prompt[20];
|
|
190 #else
|
|
191 char tempstr[512];
|
|
192 #endif
|
|
193
|
|
194 gftp_locale_init ();
|
|
195
|
|
196 signal (SIGCHLD, sig_child);
|
|
197 signal (SIGPIPE, SIG_IGN);
|
|
198
|
|
199 gftp_read_config_file (SHARE_DIR);
|
|
200
|
|
201 if (gftp_parse_command_line (&argc, &argv) != 0)
|
|
202 exit (0);
|
|
203
|
|
204 /* SSH doesn't support reading the password with askpass via the command
|
|
205 line */
|
|
206
|
|
207 gftp_text_remreq = gftp_request_new ();
|
|
208 gftp_set_request_option (gftp_text_remreq, "ssh_use_askpass",
|
|
209 GINT_TO_POINTER(0));
|
|
210 gftp_set_request_option (gftp_text_remreq, "sshv2_use_sftp_subsys",
|
|
211 GINT_TO_POINTER(0));
|
|
212 gftp_text_remreq->logging_function = gftp_text_log;
|
|
213
|
|
214 gftp_text_locreq = gftp_request_new ();
|
|
215 gftp_set_request_option (gftp_text_locreq, "ssh_use_askpass",
|
|
216 GINT_TO_POINTER(0));
|
|
217 gftp_set_request_option (gftp_text_locreq, "sshv2_use_sftp_subsys",
|
|
218 GINT_TO_POINTER(0));
|
|
219
|
|
220 gftp_text_locreq->logging_function = gftp_text_log;
|
|
221 if (gftp_protocols[GFTP_LOCAL_NUM].init (gftp_text_locreq) == 0)
|
|
222 {
|
|
223 gftp_lookup_request_option (gftp_text_locreq, "startup_directory",
|
|
224 &startup_directory);
|
|
225 if (*startup_directory != '\0')
|
|
226 gftp_set_directory (gftp_text_locreq, startup_directory);
|
|
227
|
|
228 gftp_connect (gftp_text_locreq);
|
|
229 }
|
|
230
|
|
231 gftpui_common_about (gftp_text_log, NULL);
|
|
232 gftp_text_log (gftp_logging_misc, NULL, "\n");
|
|
233
|
|
234 /* FIXME
|
|
235 if (argc == 3 && strcmp (argv[1], "-d") == 0)
|
|
236 {
|
|
237 if ((pos = strrchr (argv[2], '/')) != NULL)
|
|
238 *pos = '\0';
|
|
239 gftp_text_open (gftp_text_remreq, argv[2], NULL);
|
|
240
|
|
241 if (pos != NULL)
|
|
242 *pos = '/';
|
|
243
|
|
244 gftp_text_mget_file (gftp_text_remreq, pos + 1, NULL);
|
|
245 exit (0);
|
|
246 }
|
|
247 else if (argc == 2)
|
|
248 gftp_text_open (gftp_text_remreq, argv[1], NULL);
|
|
249 */
|
|
250
|
|
251 gftpui_common_init (NULL, gftp_text_locreq,
|
|
252 NULL, gftp_text_remreq);
|
|
253
|
|
254 #if HAVE_LIBREADLINE
|
|
255 g_snprintf (prompt, sizeof (prompt), "%sftp%s> ", GFTPUI_COMMON_COLOR_BLUE, GFTPUI_COMMON_COLOR_DEFAULT);
|
|
256 while ((tempstr = readline (prompt)))
|
|
257 {
|
|
258 if (gftpui_common_process_command (tempstr) == 0)
|
|
259 break;
|
|
260
|
|
261 add_history (tempstr);
|
|
262 free (tempstr);
|
|
263 }
|
|
264 #else
|
|
265 printf ("%sftp%s> ", GFTPUI_COMMON_COLOR_BLUE, GFTPUI_COMMON_COLOR_DEFAULT);
|
|
266 while (fgets (tempstr, sizeof (tempstr), stdin) != NULL)
|
|
267 {
|
|
268 if (gftpui_common_process_command (tempstr) == 0)
|
|
269 break;
|
|
270
|
|
271 printf ("%sftp%s> ", GFTPUI_COMMON_COLOR_BLUE, GFTPUI_COMMON_COLOR_DEFAULT);
|
|
272 }
|
|
273 #endif
|
|
274
|
|
275 return (0);
|
|
276 }
|
|
277
|
|
278 #if 0
|
1
|
279 int
|
|
280 gftp_text_open (gftp_request * request, char *command, gpointer *data)
|
|
281 {
|
|
282 char tempstr[255], *pos;
|
|
283
|
|
284 if (GFTP_IS_CONNECTED (request))
|
|
285 {
|
|
286 gftp_disconnect (request);
|
|
287 }
|
|
288
|
|
289 if (*command == '\0')
|
|
290 {
|
186
|
291 gftp_text_log (gftp_logging_error, request,
|
1
|
292 _("usage: open [[ftp://][user:pass@]ftp-site[:port][/directory]]\n"));
|
|
293 return (1);
|
|
294 }
|
|
295
|
|
296 if (gftp_parse_url (request, command) < 0)
|
173
|
297 return (1);
|
1
|
298
|
169
|
299 if (request->need_userpass)
|
1
|
300 {
|
169
|
301 if (request->username == NULL || *request->username == '\0')
|
1
|
302 {
|
166
|
303 if ((pos = gftp_text_ask_question ("Username [anonymous]", 1, tempstr,
|
|
304 sizeof (tempstr))) != NULL)
|
1
|
305 {
|
166
|
306 gftp_set_username (request, pos);
|
169
|
307 gftp_set_password (request, NULL);
|
1
|
308 }
|
|
309 }
|
169
|
310
|
|
311 if (request->username != NULL &&
|
|
312 strcmp (request->username, "anonymous") != 0 &&
|
|
313 (request->password == NULL || *request->password == '\0'))
|
166
|
314 {
|
169
|
315 if ((pos = gftp_text_ask_question ("Password", 0, tempstr,
|
|
316 sizeof (tempstr))) == NULL)
|
|
317 return (1);
|
|
318 gftp_set_password (request, pos);
|
166
|
319 }
|
1
|
320 }
|
|
321
|
|
322 gftp_connect (request);
|
|
323 return (1);
|
|
324 }
|
|
325
|
|
326
|
|
327 int
|
|
328 gftp_text_mget_file (gftp_request * request, char *command, gpointer *data)
|
|
329 {
|
|
330 gftp_transfer * transfer;
|
|
331 gftp_file * fle;
|
|
332
|
|
333 if (!GFTP_IS_CONNECTED (gftp_text_remreq))
|
|
334 {
|
186
|
335 gftp_text_log (gftp_logging_error, request,
|
1
|
336 _("Error: Not connected to a remote site\n"));
|
|
337 return (1);
|
|
338 }
|
|
339
|
|
340 if (*command == '\0')
|
|
341 {
|
186
|
342 gftp_text_log (gftp_logging_error, request,
|
|
343 _("usage: mget <filespec>\n"));
|
1
|
344 return (1);
|
|
345 }
|
|
346
|
129
|
347 transfer = gftp_tdata_new ();
|
1
|
348 transfer->fromreq = gftp_text_remreq;
|
|
349 transfer->toreq = gftp_text_locreq;
|
|
350
|
|
351 /* FIXME - ask whether to resume/skip/overwrite */
|
|
352 if (gftp_list_files (transfer->fromreq) != 0)
|
|
353 {
|
|
354 transfer->fromreq = transfer->toreq = NULL;
|
|
355 free_tdata (transfer);
|
|
356 return (1);
|
|
357 }
|
|
358 fle = g_malloc0 (sizeof (*fle));
|
|
359 while (gftp_get_next_file (transfer->fromreq, command, fle) > 0)
|
|
360 {
|
|
361 if (strcmp (fle->file, ".") == 0 || strcmp (fle->file, "..") == 0)
|
|
362 {
|
|
363 gftp_file_destroy (fle);
|
|
364 continue;
|
|
365 }
|
|
366 transfer->files = g_list_append (transfer->files, fle);
|
|
367 fle = g_malloc (sizeof (*fle));
|
|
368 }
|
|
369 g_free (fle);
|
|
370 gftp_end_transfer (transfer->fromreq);
|
|
371
|
|
372 if (transfer->files == NULL)
|
|
373 {
|
|
374 transfer->fromreq = transfer->toreq = NULL;
|
|
375 free_tdata (transfer);
|
|
376 return (1);
|
|
377 }
|
|
378
|
|
379 if (gftp_get_all_subdirs (transfer, NULL) != 0)
|
|
380 {
|
|
381 transfer->fromreq = transfer->toreq = NULL;
|
|
382 free_tdata (transfer);
|
|
383 return (1);
|
|
384 }
|
|
385
|
|
386 if (transfer->files == NULL)
|
|
387 {
|
|
388 transfer->fromreq = transfer->toreq = NULL;
|
|
389 free_tdata (transfer);
|
|
390 return (1);
|
|
391 }
|
|
392
|
|
393 gftp_text_transfer_files (transfer);
|
|
394 transfer->fromreq = transfer->toreq = NULL;
|
|
395 free_tdata (transfer);
|
|
396 return (1);
|
|
397 }
|
|
398
|
|
399
|
|
400 int
|
|
401 gftp_text_mput_file (gftp_request * request, char *command, gpointer *data)
|
|
402 {
|
|
403 gftp_transfer * transfer;
|
|
404 gftp_file * fle;
|
|
405
|
|
406 if (!GFTP_IS_CONNECTED (gftp_text_remreq))
|
|
407 {
|
186
|
408 gftp_text_log (gftp_logging_error, request,
|
1
|
409 _("Error: Not connected to a remote site\n"));
|
|
410 return (1);
|
|
411 }
|
|
412
|
|
413 if (*command == '\0')
|
|
414 {
|
186
|
415 gftp_text_log (gftp_logging_error, request,
|
|
416 _("usage: mput <filespec>\n"));
|
1
|
417 return (1);
|
|
418 }
|
|
419
|
129
|
420 transfer = gftp_tdata_new ();
|
1
|
421 transfer->fromreq = gftp_text_locreq;
|
|
422 transfer->toreq = gftp_text_remreq;
|
|
423
|
|
424 if (gftp_list_files (transfer->fromreq) != 0)
|
|
425 {
|
|
426 transfer->fromreq = transfer->toreq = NULL;
|
|
427 free_tdata (transfer);
|
|
428 return (1);
|
|
429 }
|
|
430 fle = g_malloc (sizeof (*fle));
|
|
431 while (gftp_get_next_file (transfer->fromreq, command, fle) > 0)
|
|
432 {
|
|
433 if (strcmp (fle->file, ".") == 0 || strcmp (fle->file, "..") == 0)
|
|
434 {
|
|
435 gftp_file_destroy (fle);
|
|
436 continue;
|
|
437 }
|
|
438 transfer->files = g_list_append (transfer->files, fle);
|
|
439 fle = g_malloc (sizeof (*fle));
|
|
440 }
|
|
441 g_free (fle);
|
|
442 gftp_end_transfer (transfer->fromreq);
|
|
443
|
|
444 if (transfer->files == NULL)
|
|
445 {
|
|
446 transfer->fromreq = transfer->toreq = NULL;
|
|
447 free_tdata (transfer);
|
|
448 return (1);
|
|
449 }
|
|
450
|
|
451 if (gftp_get_all_subdirs (transfer, NULL) != 0)
|
|
452 {
|
|
453 transfer->fromreq = transfer->toreq = NULL;
|
|
454 free_tdata (transfer);
|
|
455 return (1);
|
|
456 }
|
|
457
|
|
458 if (transfer->files == NULL)
|
|
459 {
|
|
460 transfer->fromreq = transfer->toreq = NULL;
|
|
461 free_tdata (transfer);
|
|
462 return (1);
|
|
463 }
|
|
464
|
|
465 gftp_text_transfer_files (transfer);
|
|
466 transfer->fromreq = transfer->toreq = NULL;
|
|
467 free_tdata (transfer);
|
|
468 return (1);
|
|
469 }
|
|
470
|
|
471
|
|
472 int
|
|
473 gftp_text_transfer_files (gftp_transfer * transfer)
|
|
474 {
|
327
|
475 int i, j, sw, tot;
|
|
476 intptr_t preserve_permissions;
|
122
|
477 char buf[8192], *progress = "|/-\\";
|
1
|
478 struct timeval updatetime;
|
|
479 long fromsize, total;
|
|
480 gftp_file * curfle;
|
|
481 ssize_t num_read;
|
182
|
482 mode_t mode;
|
|
483
|
|
484 gftp_lookup_request_option (transfer->fromreq, "preserve_permissions",
|
|
485 &preserve_permissions);
|
1
|
486
|
|
487 for (transfer->curfle = transfer->files;
|
|
488 transfer->curfle != NULL;
|
|
489 transfer->curfle = transfer->curfle->next)
|
|
490 {
|
|
491 curfle = transfer->curfle->data;
|
|
492 if (curfle->transfer_action == GFTP_TRANS_ACTION_SKIP)
|
|
493 continue;
|
|
494
|
|
495 if (curfle->isdir && transfer->toreq->mkdir != NULL)
|
|
496 {
|
|
497 transfer->toreq->mkdir (transfer->toreq, curfle->destfile);
|
|
498 continue;
|
|
499 }
|
|
500
|
|
501 transfer->curtrans = curfle->startsize;
|
58
|
502 fromsize = gftp_transfer_file (transfer->fromreq, curfle->file, -1,
|
1
|
503 curfle->startsize, transfer->toreq, curfle->destfile,
|
58
|
504 -1, curfle->startsize);
|
1
|
505 if (fromsize < 0)
|
|
506 return (1);
|
|
507
|
|
508 gettimeofday (&transfer->starttime, NULL);
|
|
509 memcpy (&transfer->lasttime, &transfer->starttime,
|
|
510 sizeof (transfer->lasttime));
|
|
511 memset (&updatetime, 0, sizeof (updatetime));
|
|
512
|
|
513 total = 0;
|
|
514 i = 0;
|
122
|
515 num_read = -1;
|
1
|
516 while (!cancel && (num_read = gftp_get_next_file_chunk (transfer->fromreq,
|
|
517 buf, sizeof (buf))) > 0)
|
|
518 {
|
|
519 printf ("\r%c ", progress[i++]);
|
|
520 fflush (stdout);
|
|
521 if (progress[i] == '\0')
|
|
522 i = 0;
|
|
523
|
|
524 total += num_read;
|
122
|
525 gftp_calc_kbs (transfer, num_read);
|
1
|
526 if (transfer->lasttime.tv_sec - updatetime.tv_sec >= 1 || total >= fromsize)
|
|
527 {
|
|
528 sw = gftp_text_get_win_size () - 20;
|
|
529 tot = (float) total / (float) fromsize * (float) sw;
|
|
530
|
|
531 if (tot > sw)
|
|
532 tot = sw;
|
|
533 printf ("[");
|
|
534 for (j=0; j<tot; j++)
|
|
535 printf ("=");
|
|
536 for (j=0; j<sw-tot; j++)
|
|
537 printf (" ");
|
|
538 printf ("] @ %.2fKB/s", transfer->kbs);
|
|
539 fflush (stdout);
|
|
540 memcpy (&updatetime, &transfer->lasttime, sizeof (updatetime));
|
|
541 }
|
|
542
|
122
|
543 if (gftp_put_next_file_chunk (transfer->toreq, buf, num_read) < 0)
|
1
|
544 {
|
|
545 num_read = -1;
|
|
546 break;
|
|
547 }
|
|
548 }
|
|
549 printf ("\n");
|
|
550
|
|
551 if (num_read < 0)
|
|
552 {
|
186
|
553 gftp_text_log (gftp_logging_misc, transfer->fromreq,
|
1
|
554 _("Could not download %s\n"), curfle->file);
|
|
555 gftp_disconnect (transfer->fromreq);
|
|
556 gftp_disconnect (transfer->toreq);
|
|
557 }
|
|
558 else
|
|
559 {
|
186
|
560 gftp_text_log (gftp_logging_misc, transfer->fromreq,
|
1
|
561 _("Successfully transferred %s\n"), curfle->file);
|
|
562 gftp_end_transfer (transfer->fromreq);
|
|
563 gftp_end_transfer (transfer->toreq);
|
|
564 }
|
|
565
|
182
|
566 if (!curfle->is_fd && preserve_permissions)
|
|
567 {
|
|
568 if (curfle->attribs)
|
|
569 {
|
|
570 mode = gftp_parse_attribs (curfle->attribs);
|
|
571 if (mode != 0)
|
|
572 gftp_chmod (transfer->toreq, curfle->destfile, mode);
|
|
573 }
|
|
574
|
|
575 if (curfle->datetime != 0)
|
|
576 gftp_set_file_time (transfer->toreq, curfle->destfile,
|
|
577 curfle->datetime);
|
|
578 }
|
1
|
579 }
|
|
580 return (1);
|
|
581 }
|
|
582
|
341
|
583 #endif
|