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