gftp-text.c
上传用户:tjfeida
上传日期:2013-03-10
资源大小:1917k
文件大小:36k
源码类别:

Ftp客户端

开发平台:

Visual C++

  1. /*****************************************************************************/
  2. /*  gftp-text.c - text port of gftp                                          */
  3. /*  Copyright (C) 1998-2002 Brian Masney <masneyb@gftp.org>                  */
  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. #include "gftp-text.h"
  20. static const char cvsid[] = "$Id: gftp-text.c,v 1.7 2002/11/27 14:29:56 masneyb Exp $";
  21. static gftp_request * gftp_text_locreq = NULL;
  22. static gftp_request * gftp_text_remreq = NULL;
  23. static volatile int cancel = 0;
  24. static int configuration_changed = 0,
  25.            number_commands = 30;
  26. struct _gftp_text_methods gftp_text_methods[] = {
  27.         {N_("about"),  2, gftp_text_about, NULL,
  28.          N_("Shows gFTP information"), NULL},
  29.         {N_("ascii"), 2, gftp_text_ascii, &gftp_text_remreq,
  30.          N_("Sets the current file transfer mode to Ascii (only for FTP)"), NULL},
  31. {N_("binary"), 1, gftp_text_binary, &gftp_text_remreq,
  32.          N_("Sets the current file transfer mode to Binary (only for FTP)"), NULL},
  33.         {N_("cd"),  2, gftp_text_cd,  &gftp_text_remreq,
  34.          N_("Changes the remote working directory"), NULL},
  35.         {N_("chdir"),  3, gftp_text_cd,  &gftp_text_remreq,
  36.          N_("Changes the remote working directory"), NULL},
  37.         {N_("chmod"),  3, gftp_text_chmod, &gftp_text_remreq,
  38.          N_("Changes the permissions of a remote file"), NULL},
  39.         {N_("clear"), 3, gftp_text_clear, NULL,
  40.          N_("Available options: cache"),  gftp_text_clear_show_subhelp},
  41.         {N_("close"),  3, gftp_text_close,  &gftp_text_remreq,
  42.          N_("Disconnects from the remote site"), NULL},
  43.         {N_("delete"),  1, gftp_text_delete, &gftp_text_remreq,
  44.          N_("Removes a remote file"), NULL},
  45.         {N_("get"), 1, gftp_text_mget_file, NULL,
  46.          N_("Downloads remote file(s)"), NULL},
  47.         {N_("help"),  1, gftp_text_help,  NULL,
  48.          N_("Shows this help screen"), NULL},
  49.         {N_("lcd"),  3, gftp_text_cd,  &gftp_text_locreq,
  50.          N_("Changes the local working directory"), NULL},
  51.         {N_("lchdir"),  4, gftp_text_cd,  &gftp_text_locreq,
  52.          N_("Changes the local working directory"), NULL},
  53.         {N_("lchmod"),  4, gftp_text_chmod,  &gftp_text_locreq,
  54.          N_("Changes the permissions of a local file"), NULL},
  55.         {N_("ldelete"), 2, gftp_text_delete,  &gftp_text_locreq,
  56.          N_("Removes a local file"), NULL},
  57. {N_("lls"),  2, gftp_text_ls,  &gftp_text_locreq,
  58.          N_("Shows the directory listing for the current local directory"), NULL},
  59.         {N_("lmkdir"),  2, gftp_text_mkdir,  &gftp_text_locreq,
  60.          N_("Creates a local directory"), NULL},
  61.         {N_("lpwd"),  2, gftp_text_pwd,  &gftp_text_locreq,
  62.          N_("Show current local directory"), NULL},
  63.         {N_("lrename"), 3, gftp_text_rename,  &gftp_text_locreq,
  64.          N_("Rename a local file"), NULL},
  65.         {N_("lrmdir"),  3, gftp_text_rmdir,  &gftp_text_locreq,
  66.          N_("Remove a local directory"), NULL},
  67. {N_("ls"),  2, gftp_text_ls, &gftp_text_remreq,
  68.          N_("Shows the directory listing for the current remote directory"), NULL},
  69.         {N_("mget"), 2, gftp_text_mget_file, NULL,
  70.          N_("Downloads remote file(s)"), NULL},
  71.         {N_("mkdir"),  2, gftp_text_mkdir, &gftp_text_remreq,
  72.          N_("Creates a remote directory"), NULL},
  73.         {N_("mput"), 2, gftp_text_mput_file, NULL,
  74.          N_("Uploads local file(s)"), NULL},
  75.         {N_("open"),  1, gftp_text_open,  &gftp_text_remreq,
  76.          N_("Opens a connection to a remote site"), NULL},
  77.         {N_("put"), 2, gftp_text_mput_file, NULL,
  78.          N_("Uploads local file(s)"), NULL},
  79.         {N_("pwd"),  2, gftp_text_pwd,  &gftp_text_remreq,
  80.          N_("Show current remote directory"), NULL},
  81.         {N_("quit"),  1, gftp_text_quit,  NULL,
  82.          N_("Exit from gFTP"), NULL},
  83.         {N_("rename"),  2, gftp_text_rename, &gftp_text_remreq,
  84.          N_("Rename a remote file"), NULL},
  85.         {N_("rmdir"),  2, gftp_text_rmdir, &gftp_text_remreq,
  86.          N_("Remove a remote directory"), NULL},
  87.         {N_("set"),  1, gftp_text_set,  NULL,
  88.          N_("Show configuration file variables. You can also set variables by set var=val"), gftp_text_set_show_subhelp},
  89.         {NULL,  0, NULL, NULL,  NULL}};
  90. int
  91. main (int argc, char **argv)
  92. {
  93.   gftp_request * request;
  94.   size_t len, cmdlen;
  95.   char *pos, *stpos;
  96.   int i;
  97. #ifdef HAVE_LIBREADLINE
  98.   char *tempstr, prompt[20];
  99. #else
  100.   char tempstr[512];
  101. #endif
  102. #ifdef HAVE_GETTEXT
  103.   setlocale (LC_ALL, "");
  104.   bindtextdomain ("gftp", LOCALE_DIR);
  105.   textdomain ("gftp");
  106. #endif
  107.   signal (SIGCHLD, sig_child);
  108.   signal (SIGPIPE, SIG_IGN); 
  109.   gftp_read_config_file (argv, 0);
  110.   /* SSH doesn't support reading the password with askpass via the command 
  111.      line */
  112.   ssh_use_askpass = sshv2_use_sftp_subsys = 0;
  113.   if (gftp_parse_command_line (&argc, &argv) != 0)
  114.     exit (0);
  115.   gftp_text_remreq = gftp_request_new ();
  116.   gftp_text_remreq->logging_function = gftp_text_log;
  117.   gftp_text_locreq = gftp_request_new ();
  118.   gftp_text_locreq->logging_function = gftp_text_log;
  119.   gftp_protocols[GFTP_LOCAL_NUM].init (gftp_text_locreq);
  120.   if (startup_directory != NULL && *startup_directory != '')
  121.     gftp_set_directory (gftp_text_locreq, startup_directory);
  122.   gftp_connect (gftp_text_locreq);
  123.   gftp_text_log (gftp_logging_misc, NULL, "%s, Copyright (C) 1998-2002 Brian Masney <", version);
  124.   gftp_text_log (gftp_logging_recv, NULL, "masneyb@gftp.org");
  125.   gftp_text_log (gftp_logging_misc, NULL, _(">.nIf you have any questions, comments, or suggestions about this program, please feel free to email them to me. You can always find out the latest news about gFTP from my website at http://www.gftp.org/n"));
  126.   gftp_text_log (gftp_logging_misc, NULL, "n");
  127.   gftp_text_log (gftp_logging_misc, NULL, _("gFTP comes with ABSOLUTELY NO WARRANTY; for details, see the COPYING file. This is free software, and you are welcome to redistribute it under certain conditions; for details, see the COPYING filen"));
  128.   gftp_text_log (gftp_logging_misc, NULL, "n");
  129.   if (argc == 3 && strcmp (argv[1], "-d") == 0)
  130.     {
  131.       if ((pos = strrchr (argv[2], '/')) != NULL)
  132.         *pos = '';
  133.       gftp_text_open (gftp_text_remreq, argv[2], NULL);
  134.       if (pos != NULL)
  135.         *pos = '/';
  136.       gftp_text_mget_file (gftp_text_remreq, pos + 1, NULL);
  137.       exit (0);
  138.     }
  139.   else if (argc == 2)
  140.     gftp_text_open (gftp_text_remreq, argv[1], NULL);
  141. #ifdef HAVE_LIBREADLINE
  142.   g_snprintf (prompt, sizeof (prompt), "%sftp%s> ", COLOR_BLUE, COLOR_DEFAULT);
  143.   while ((tempstr = readline (prompt)))
  144. #else
  145.   printf ("%sftp%s> ", COLOR_BLUE, COLOR_DEFAULT);
  146.   while (fgets (tempstr, sizeof (tempstr), stdin) != NULL)
  147. #endif
  148.     {
  149.       len = strlen (tempstr);
  150.       if (tempstr[len - 1] == 'n')
  151.         tempstr[--len] = '';
  152.       if (tempstr[len - 1] == 'r')
  153.         tempstr[--len] = '';
  154.       for (stpos = tempstr; *stpos == ' '; stpos++);
  155.       for (pos = tempstr + len - 1; 
  156.            (*pos == ' ' || *pos == 't') && pos > tempstr; 
  157.            pos--)
  158.         *pos = '';
  159.       if (*stpos == '')
  160.         {
  161. #ifndef HAVE_LIBREADLINE
  162.           printf ("%sftp%s> ", COLOR_BLUE, COLOR_DEFAULT);
  163. #endif
  164.           continue;
  165.         }
  166. #ifdef HAVE_LIBREADLINE
  167.       add_history (tempstr);
  168. #endif
  169.       if ((pos = strchr (stpos, ' ')) != NULL)
  170.         *pos = '';
  171.       cmdlen = strlen (stpos);
  172.       for (i=0; gftp_text_methods[i].command != NULL; i++)
  173.         {
  174.           if (strcmp (gftp_text_methods[i].command, stpos) == 0)
  175.             break;
  176.           else if (cmdlen >= gftp_text_methods[i].minlen &&
  177.                    strncmp (gftp_text_methods[i].command, stpos, cmdlen) == 0)
  178.             break;
  179.         }
  180.       if (pos != NULL)
  181.         pos++;
  182.       else
  183.         pos = "";
  184.       if (gftp_text_methods[i].command != NULL)
  185.         {
  186.           if (gftp_text_methods[i].request != NULL)
  187.             request = *gftp_text_methods[i].request;
  188.           else
  189.             request = NULL;
  190.           if (gftp_text_methods[i].func (request, pos, NULL) == 0)
  191.             break;
  192.         }
  193.       else
  194.         gftp_text_log (gftp_logging_error, NULL, 
  195.                        _("Error: Command not recognizedn"));
  196. #ifdef HAVE_LIBREADLINE
  197.      free (tempstr);
  198. #else
  199.      printf ("%sftp%s> ", COLOR_BLUE, COLOR_DEFAULT);
  200. #endif
  201.     }
  202.  
  203.   if (logfd != NULL)
  204.     fclose (logfd);
  205.   gftp_text_quit (NULL, NULL, NULL);
  206.   return (0);
  207. }
  208. void
  209. gftp_text_log (gftp_logging_level level, void *ptr, const char *string, ...)
  210. {
  211.   char tempstr[512], *stpos, *endpos;
  212.   va_list argp;
  213.   int sw;
  214.   g_return_if_fail (string != NULL);
  215.   switch (level)
  216.     {
  217.       case gftp_logging_send:
  218.         printf ("%s", COLOR_GREEN);
  219.         break;
  220.       case gftp_logging_recv:
  221.         printf ("%s", COLOR_YELLOW);
  222.         break;
  223.       case gftp_logging_error:
  224.         printf ("%s", COLOR_RED);
  225.         break;
  226.       default:
  227.         printf ("%s", COLOR_DEFAULT);
  228.         break;
  229.     }
  230.   va_start (argp, string);
  231.   g_vsnprintf (tempstr, sizeof (tempstr), string, argp);
  232.   va_end (argp);
  233.   if (logfd != NULL)
  234.     {
  235.       fwrite (tempstr, 1, strlen (tempstr), logfd);
  236.       if (ferror (logfd))
  237.         {
  238.           fclose (logfd);
  239.           logfd = NULL;
  240.         }
  241.       else
  242.         fflush (logfd);
  243.     }
  244.   sw = gftp_text_get_win_size ();
  245.   stpos = tempstr;
  246.   endpos = tempstr + 1;
  247.   do
  248.     {
  249.       if (strlen (stpos) <= sw)
  250.         {
  251.           printf ("%s", stpos);
  252.           break;
  253.         }
  254.       for (endpos = stpos + sw - 1; *endpos != ' ' && endpos > stpos; endpos--);
  255.       if (endpos != stpos)
  256.         {
  257.           *endpos = '';
  258.         }
  259.       printf ("%sn", stpos);
  260.       stpos = endpos + 1;
  261.     }
  262.   while (stpos != endpos);
  263.   
  264.   printf ("%s", COLOR_DEFAULT);
  265. }
  266. int
  267. gftp_text_open (gftp_request * request, char *command, gpointer *data)
  268. {
  269.   char tempstr[255], *pos;
  270.   if (GFTP_IS_CONNECTED (request))
  271.     {
  272.       gftp_disconnect (request);
  273.     }
  274.   if (*command == '')
  275.     {
  276.       gftp_text_log (gftp_logging_error, NULL,
  277.           _("usage: open [[ftp://][user:pass@]ftp-site[:port][/directory]]n"));
  278.       return (1);
  279.     }
  280.   
  281.   if (gftp_parse_url (request, command) < 0)
  282.     {
  283.       gftp_text_log (gftp_logging_error, NULL, 
  284.                      _("Could not parse URL %sn"), command);
  285.       return (1);
  286.     }
  287.   if (GFTP_GET_USERNAME (request) == NULL)
  288.     {
  289.       if ((pos = gftp_text_ask_question ("Username [anonymous]", 1, tempstr, 
  290.                                          sizeof (tempstr))) != NULL)
  291.         {
  292.           gftp_set_username (request, pos);
  293.           if (request->password)
  294.             {
  295.               g_free (request->password);
  296.               request->password = NULL;
  297.             }
  298.         }
  299.       else
  300.         gftp_set_username (request, "anonymous");
  301.     }
  302.   if (strcmp (GFTP_GET_USERNAME (request), "anonymous") != 0 && 
  303.       (request->password == NULL || *request->password == ''))
  304.     {
  305.       if ((pos = gftp_text_ask_question ("Password", 0, tempstr, 
  306.                                          sizeof (tempstr))) == NULL)
  307.         return (1);
  308.       gftp_set_password (request, pos);
  309.     }
  310.   gftp_connect (request);
  311.   return (1);
  312. }
  313. int
  314. gftp_text_close (gftp_request * request, char *command, gpointer *data)
  315. {
  316.   gftp_disconnect (request);
  317.   return (1);
  318. }
  319. int
  320. gftp_text_about (gftp_request * request, char *command, gpointer *data)
  321. {
  322.   char *str;
  323.   gftp_text_log (gftp_logging_misc, NULL,
  324.       "%s. Copyright (C) 1998-2002 Brian Masney <masneyb@gftp.org>n", version);
  325.   str = _("Translated by");
  326.   if (strcmp (str, "Translated by") != 0)
  327.     gftp_text_log (gftp_logging_misc, NULL, "%sn", str);
  328.   return (1);
  329. }
  330. int
  331. gftp_text_quit (gftp_request * request, char *command, gpointer *data)
  332. {
  333.   gftp_clear_cache_files ();
  334.   if (configuration_changed)
  335.     gftp_write_config_file ();
  336.   return (0);
  337. }
  338. int
  339. gftp_text_pwd (gftp_request * request, char *command, gpointer *data)
  340. {
  341.   if (!GFTP_IS_CONNECTED (request))
  342.     {
  343.       gftp_text_log (gftp_logging_error, NULL,
  344.                      _("Error: Not connected to a remote siten"));
  345.       return (1);
  346.     }
  347.   gftp_text_log (gftp_logging_misc, NULL, "%sn", request->directory);
  348.   return (1);
  349. }
  350. int
  351. gftp_text_cd (gftp_request * request, char *command, gpointer *data)
  352. {
  353.   char *newdir = NULL;
  354.   if (!GFTP_IS_CONNECTED (request))
  355.     {
  356.       gftp_text_log (gftp_logging_error, NULL,
  357.                      _("Error: Not connected to a remote siten"));
  358.       return (1);
  359.     }
  360.   else if (*command == '')
  361.     {
  362.       gftp_text_log (gftp_logging_error, NULL, _("usage: chdir <directory>n"));
  363.       return (1);
  364.     }
  365.   else if (request->protonum == GFTP_LOCAL_NUM &&
  366.            (newdir = expand_path (command)) == NULL)
  367.     {
  368.       gftp_text_log (gftp_logging_error, NULL, _("usage: chdir <directory>n"));
  369.       return (1);
  370.     }
  371.   gftp_set_directory (request, newdir != NULL ? newdir : command);
  372.   if (newdir != NULL)
  373.     g_free (newdir);
  374.   return (1);
  375. }
  376. int
  377. gftp_text_mkdir (gftp_request * request, char *command, gpointer *data)
  378. {
  379.   if (!GFTP_IS_CONNECTED (request))
  380.     {
  381.       gftp_text_log (gftp_logging_error, NULL,
  382.                      _("Error: Not connected to a remote siten"));
  383.       return (1);
  384.     }
  385.   if (*command == '')
  386.     {
  387.       gftp_text_log (gftp_logging_error, NULL,
  388.                      _("usage: mkdir <new directory>n"));
  389.     }
  390.   else
  391.     {
  392.       gftp_make_directory (request, command);
  393.     }
  394.   return (1);
  395. }
  396. int
  397. gftp_text_rmdir (gftp_request * request, char *command, gpointer *data)
  398. {
  399.   if (!GFTP_IS_CONNECTED (request))
  400.     {
  401.       gftp_text_log (gftp_logging_error, NULL, 
  402.                      _("Error: Not connected to a remote siten"));
  403.       return (1);
  404.     }
  405.   if (*command == '')
  406.     {
  407.       gftp_text_log (gftp_logging_error, NULL, _("usage: rmdir <directory>n"));
  408.     }
  409.   else
  410.     {
  411.       gftp_remove_directory (request, command);
  412.     }
  413.   return (1);
  414. }
  415. int
  416. gftp_text_delete (gftp_request * request, char *command, gpointer *data)
  417. {
  418.   if (!GFTP_IS_CONNECTED (request))
  419.     {
  420.       gftp_text_log (gftp_logging_error, NULL,
  421.                      _("Error: Not connected to a remote siten"));
  422.       return (1);
  423.     }
  424.   if (*command == '')
  425.     {
  426.       gftp_text_log (gftp_logging_error, NULL,_("usage: delete <file>n"));
  427.     }
  428.   else
  429.     {
  430.       gftp_remove_file (request, command);
  431.     }
  432.   return (1);
  433. }
  434. int
  435. gftp_text_rename (gftp_request * request, char *command, gpointer *data)
  436. {
  437.   char *pos;
  438.   if (!GFTP_IS_CONNECTED (request))
  439.     {
  440.       gftp_text_log (gftp_logging_error, NULL,
  441.                      _("Error: Not connected to a remote siten"));
  442.       return (1);
  443.     }
  444.   if ((pos = strchr (command, ' ')) != NULL)
  445.     *pos++ = '';
  446.   if (*command == '' || pos == NULL || *pos == '')
  447.     {
  448.       gftp_text_log (gftp_logging_error, NULL,
  449.                      _("usage: rename <old name> <new name>n"));
  450.     }
  451.   else
  452.     {
  453.       gftp_rename_file (request, command, pos);
  454.     }
  455.   return (1);
  456. }
  457. int
  458. gftp_text_chmod (gftp_request * request, char *command, gpointer *data)
  459. {
  460.   char *pos;
  461.   if (!GFTP_IS_CONNECTED (request))
  462.     {
  463.       gftp_text_log (gftp_logging_error, NULL,
  464.                      _("Error: Not connected to a remote siten"));
  465.       return (1);
  466.     }
  467.   if ((pos = strchr (command, ' ')) != NULL)
  468.     *pos++ = '';
  469.   if (*command == '' || pos == NULL || *pos == '')
  470.     {
  471.       gftp_text_log (gftp_logging_error, NULL,
  472.                      _("usage: chmod <mode> <file>n"));
  473.     }
  474.   else
  475.     {
  476.       gftp_chmod (request, pos, strtol (command, NULL, 10));
  477.     }
  478.   return (1);
  479. }
  480. int
  481. gftp_text_ls (gftp_request * request, char *command, gpointer *data)
  482. {
  483.   GList * files, * templist, * delitem;
  484.   char *color, buf[20], *filespec;
  485.   int sortcol, sortasds;
  486.   gftp_file * fle;
  487.   time_t curtime;
  488.   time (&curtime);
  489.   if (!GFTP_IS_CONNECTED (request))
  490.     {
  491.       gftp_text_log (gftp_logging_error, NULL,
  492.                      _("Error: Not connected to a remote siten"));
  493.       return (1);
  494.     }
  495.   filespec = *command != '' ? command : NULL;
  496.   if (gftp_list_files (request) != 0)
  497.     return (1);
  498.   files = NULL;
  499.   fle = g_malloc0 (sizeof (*fle));
  500.   while (gftp_get_next_file (request, NULL, fle) > 0)
  501.     {
  502.       if (strcmp (fle->file, ".") == 0)
  503.         {
  504.           gftp_file_destroy (fle);
  505.           continue;
  506.         }
  507.       files = g_list_prepend (files, fle);
  508.       fle = g_malloc0 (sizeof (*fle));
  509.     }
  510.   g_free (fle);
  511.   if (files == NULL)
  512.     return (1);
  513.   if (request == gftp_text_locreq)
  514.     {
  515.       sortcol = local_sortcol;
  516.       sortasds = local_sortasds;
  517.     }
  518.   else
  519.     {
  520.       sortcol = remote_sortcol;
  521.       sortasds = remote_sortasds;
  522.     }
  523.   files = gftp_sort_filelist (files, sortcol, sortasds);
  524.   delitem = NULL;
  525.   for (templist = files; templist != NULL; templist = templist->next)
  526.     {
  527.       if (delitem != NULL)
  528.         {
  529.           fle = delitem->data;
  530.           gftp_file_destroy (fle);
  531.           g_free (fle);
  532.           delitem = NULL;
  533.         }
  534.       fle = templist->data;
  535.       if (*fle->attribs == 'd')
  536.         color = COLOR_BLUE;
  537.       else if (*fle->attribs == 'l')
  538.         color = COLOR_WHITE;
  539.       else if (strchr (fle->attribs, 'x') != NULL)
  540.         color = COLOR_GREEN;
  541.       else
  542.         color = COLOR_DEFAULT;
  543.       if (curtime > fle->datetime + 6 * 30 * 24 * 60 * 60 ||
  544.           curtime < fle->datetime - 60 * 60)
  545.         strftime (buf, sizeof (buf), "%b %d  %Y", localtime (&fle->datetime));
  546.       else
  547.         strftime (buf, sizeof (buf), "%b %d %H:%M", localtime (&fle->datetime));
  548.       
  549. #if defined (_LARGEFILE_SOURCE)
  550.       printf ("%s %8s %8s %10lld %s %s%s%sn", 
  551. #else
  552.       printf ("%s %8s %8s %10ld %s %s%s%sn", 
  553. #endif
  554.               fle->attribs, fle->user, fle->group,
  555.               fle->size, buf, color, fle->file, COLOR_DEFAULT);
  556.       delitem = templist;
  557.     }
  558.   gftp_end_transfer (request);
  559.   if (delitem != NULL)
  560.     {
  561.       fle = delitem->data;
  562.       gftp_file_destroy (fle);
  563.       g_free (fle);
  564.       delitem = NULL;
  565.     }
  566.   if (files != NULL)
  567.     g_list_free (files);
  568.   return (1);
  569. }
  570. int
  571. gftp_text_binary (gftp_request * request, char *command, gpointer *data)
  572. {
  573.   if (!GFTP_IS_CONNECTED (gftp_text_remreq))
  574.     {
  575.       gftp_text_log (gftp_logging_error, NULL,
  576.                      _("Error: Not connected to a remote siten"));
  577.       return (1);
  578.     }
  579.   gftp_set_data_type (gftp_text_remreq, GFTP_TYPE_BINARY);
  580.   gftp_set_data_type (gftp_text_locreq, GFTP_TYPE_BINARY);
  581.   return (1);
  582. }
  583. int
  584. gftp_text_ascii (gftp_request * request, char *command, gpointer *data)
  585. {
  586.   if (!GFTP_IS_CONNECTED (gftp_text_remreq))
  587.     {
  588.       gftp_text_log (gftp_logging_error, NULL,
  589.                      _("Error: Not connected to a remote siten"));
  590.       return (1);
  591.     }
  592.   gftp_set_data_type (gftp_text_remreq, GFTP_TYPE_ASCII);
  593.   gftp_set_data_type (gftp_text_locreq, GFTP_TYPE_ASCII);
  594.   return (1);
  595. }
  596. int
  597. gftp_text_mget_file (gftp_request * request, char *command, gpointer *data)
  598. {
  599.   gftp_transfer * transfer;
  600.   gftp_file * fle;
  601.   if (!GFTP_IS_CONNECTED (gftp_text_remreq))
  602.     {
  603.       gftp_text_log (gftp_logging_error, NULL,
  604.                      _("Error: Not connected to a remote siten"));
  605.       return (1);
  606.     }
  607.   if (*command == '')
  608.     {
  609.       gftp_text_log (gftp_logging_error, NULL, _("usage: mget <filespec>n"));
  610.       return (1);
  611.     }
  612.   transfer = g_malloc0 (sizeof (*transfer));
  613.   transfer->fromreq = gftp_text_remreq;
  614.   transfer->toreq = gftp_text_locreq;
  615.   transfer->transfer_direction = GFTP_DIRECTION_DOWNLOAD;
  616.   /* FIXME - ask whether to resume/skip/overwrite */
  617.   if (gftp_list_files (transfer->fromreq) != 0)
  618.     {
  619.       transfer->fromreq = transfer->toreq = NULL;
  620.       free_tdata (transfer);
  621.       return (1);
  622.     }
  623.   fle = g_malloc0 (sizeof (*fle));
  624.   while (gftp_get_next_file (transfer->fromreq, command, fle) > 0)
  625.     {
  626.       if (strcmp (fle->file, ".") == 0 || strcmp (fle->file, "..") == 0)
  627.         {
  628.           gftp_file_destroy (fle);
  629.           continue;
  630.         }
  631.       transfer->files = g_list_append (transfer->files, fle);
  632.       fle = g_malloc (sizeof (*fle));
  633.     }
  634.   g_free (fle);
  635.   gftp_end_transfer (transfer->fromreq);
  636.   if (transfer->files == NULL)
  637.     {
  638.       transfer->fromreq = transfer->toreq = NULL;
  639.       free_tdata (transfer);
  640.       return (1);
  641.     }
  642.   if (gftp_get_all_subdirs (transfer, NULL) != 0)
  643.     {
  644.       transfer->fromreq = transfer->toreq = NULL;
  645.       free_tdata (transfer);
  646.       return (1);
  647.     }
  648.   if (transfer->files == NULL)
  649.     {
  650.       transfer->fromreq = transfer->toreq = NULL;
  651.       free_tdata (transfer);
  652.       return (1);
  653.     }
  654.   gftp_text_transfer_files (transfer);
  655.   transfer->fromreq = transfer->toreq = NULL;
  656.   free_tdata (transfer);
  657.   return (1);
  658. }
  659. int
  660. gftp_text_mput_file (gftp_request * request, char *command, gpointer *data)
  661. {
  662.   gftp_transfer * transfer;
  663.   gftp_file * fle;
  664.   if (!GFTP_IS_CONNECTED (gftp_text_remreq))
  665.     {
  666.       gftp_text_log (gftp_logging_error, NULL,
  667.                      _("Error: Not connected to a remote siten"));
  668.       return (1);
  669.     }
  670.   if (*command == '')
  671.     {
  672.       gftp_text_log (gftp_logging_error, NULL, _("usage: mput <filespec>n"));
  673.       return (1);
  674.     }
  675.   transfer = g_malloc0 (sizeof (*transfer));
  676.   transfer->fromreq = gftp_text_locreq;
  677.   transfer->toreq = gftp_text_remreq;
  678.   transfer->transfer_direction = GFTP_DIRECTION_UPLOAD;
  679.   if (gftp_list_files (transfer->fromreq) != 0)
  680.     {
  681.       transfer->fromreq = transfer->toreq = NULL;
  682.       free_tdata (transfer);
  683.       return (1);
  684.     }
  685.   fle = g_malloc (sizeof (*fle));
  686.   while (gftp_get_next_file (transfer->fromreq, command, fle) > 0)
  687.     {
  688.       if (strcmp (fle->file, ".") == 0 || strcmp (fle->file, "..") == 0)
  689.         {
  690.           gftp_file_destroy (fle);
  691.           continue;
  692.         }
  693.       transfer->files = g_list_append (transfer->files, fle);
  694.       fle = g_malloc (sizeof (*fle));
  695.     }
  696.   g_free (fle);
  697.   gftp_end_transfer (transfer->fromreq);
  698.   if (transfer->files == NULL)
  699.     {
  700.       transfer->fromreq = transfer->toreq = NULL;
  701.       free_tdata (transfer);
  702.       return (1);
  703.     }
  704.   if (gftp_get_all_subdirs (transfer, NULL) != 0)
  705.     {
  706.       transfer->fromreq = transfer->toreq = NULL;
  707.       free_tdata (transfer);
  708.       return (1);
  709.     }
  710.   if (transfer->files == NULL)
  711.     {
  712.       transfer->fromreq = transfer->toreq = NULL;
  713.       free_tdata (transfer);
  714.       return (1);
  715.     }
  716.   gftp_text_transfer_files (transfer);
  717.   transfer->fromreq = transfer->toreq = NULL;
  718.   free_tdata (transfer);
  719.   return (1);
  720. }
  721. int
  722. gftp_text_transfer_files (gftp_transfer * transfer)
  723. {
  724.   char *tempstr, buf[8192], *progress = "|/-\";
  725.   struct timeval updatetime;
  726.   long fromsize, total;
  727.   gftp_file * curfle;
  728.   int i, j, sw, tot;
  729.   ssize_t num_read;
  730.   for (transfer->curfle = transfer->files;
  731.        transfer->curfle != NULL;
  732.        transfer->curfle = transfer->curfle->next)
  733.     {
  734.       curfle = transfer->curfle->data;
  735.       if (curfle->transfer_action == GFTP_TRANS_ACTION_SKIP)
  736.         continue;
  737.       if (curfle->isdir && transfer->toreq->mkdir != NULL)
  738.         {
  739.           transfer->toreq->mkdir (transfer->toreq, curfle->destfile);
  740.           continue;
  741.         }
  742.       if (maxkbs > 0)
  743.        {
  744.           gftp_text_log (gftp_logging_misc, NULL, 
  745.                          _("File transfer will be throttled to %.2f KB/sn"), 
  746.                          maxkbs);
  747.         }
  748.       transfer->curtrans = curfle->startsize;
  749.       fromsize = gftp_transfer_file (transfer->fromreq, curfle->file, -1,
  750.                                      curfle->startsize, transfer->toreq, curfle->destfile, 
  751.                                      -1, curfle->startsize);
  752.       if (fromsize < 0)
  753.         return (1);
  754.       gettimeofday (&transfer->starttime, NULL);
  755.       memcpy (&transfer->lasttime, &transfer->starttime, 
  756.               sizeof (transfer->lasttime));
  757.       memset (&updatetime, 0, sizeof (updatetime));
  758.   
  759.       total = 0;
  760.       i = 0;
  761.       while (!cancel && (num_read = gftp_get_next_file_chunk (transfer->fromreq,
  762.                                                         buf, sizeof (buf))) > 0)
  763.         {
  764.           printf ("r%c ", progress[i++]);
  765.           fflush (stdout);
  766.           if (progress[i] == '')
  767.             i = 0;
  768.           total += num_read;
  769.           gftp_text_calc_kbs (transfer, num_read);
  770.           if (transfer->lasttime.tv_sec - updatetime.tv_sec >= 1 || total >= fromsize)
  771.             {
  772.               sw = gftp_text_get_win_size () - 20;
  773.               tot = (float) total / (float) fromsize * (float) sw;
  774.                         
  775.               if (tot > sw)
  776.                 tot = sw;
  777.               printf ("[");
  778.               for (j=0; j<tot; j++)
  779.                 printf ("=");
  780.               for (j=0; j<sw-tot; j++)
  781.                 printf (" ");
  782.               printf ("] @ %.2fKB/s", transfer->kbs);
  783.               fflush (stdout);
  784.               memcpy (&updatetime, &transfer->lasttime, sizeof (updatetime));
  785.             }
  786.           if (GFTP_GET_DATA_TYPE (transfer->fromreq) == GFTP_TYPE_ASCII)
  787.             tempstr = gftp_convert_ascii (buf, &num_read, 1);
  788.           else
  789.             tempstr = buf;
  790.           if (gftp_put_next_file_chunk (transfer->toreq, tempstr, num_read) < 0)
  791.             {
  792.               num_read = -1;
  793.               break;
  794.             }
  795.           /* We don't have to free tempstr for a download because new memory is
  796.              not allocated for it in that case */
  797.           if (GFTP_GET_DATA_TYPE (transfer->fromreq) == 
  798.               GFTP_TYPE_ASCII && !transfer->transfer_direction)
  799.             g_free (tempstr);
  800.         }
  801.       printf ("n");
  802.       if (num_read < 0)
  803.         {
  804.           gftp_text_log (gftp_logging_misc, NULL, 
  805.                          _("Could not download %sn"), curfle->file);
  806.           gftp_disconnect (transfer->fromreq);
  807.           gftp_disconnect (transfer->toreq);
  808.         }
  809.       else
  810.         {
  811.           gftp_text_log (gftp_logging_misc, NULL, 
  812.                          _("Successfully transferred %sn"), curfle->file);
  813.           gftp_end_transfer (transfer->fromreq);
  814.           gftp_end_transfer (transfer->toreq);
  815.         }
  816.     }
  817.   return (1);
  818. }
  819. int
  820. gftp_text_help (gftp_request * request, char *command, gpointer *data)
  821. {
  822.   int i, j, ele, numrows, numcols = 6, handled;
  823.   char *pos;
  824.   if (command != NULL && *command != '')
  825.     {
  826.       for (pos = command; *pos != ' ' && *pos != ''; pos++);
  827.       if (*pos == ' ')
  828.         {
  829.           *pos++ = '';
  830.           if (*pos == '')
  831.             pos = NULL;
  832.         }
  833.       else
  834.         pos = NULL;
  835.       for (i=0; gftp_text_methods[i].command != NULL; i++)
  836.         {
  837.           if (strcmp (gftp_text_methods[i].command, command) == 0)
  838.             break;
  839.         }
  840.       if (gftp_text_methods[i].cmd_description != NULL)
  841.         {
  842.           if (pos != NULL && gftp_text_methods[i].subhelp_func != NULL)
  843.             handled = gftp_text_methods[i].subhelp_func (pos);
  844.           else
  845.             handled = 0;
  846.           if (!handled)
  847.             printf ("%sn", _(gftp_text_methods[i].cmd_description));
  848.         }
  849.       else
  850.         *command = '';
  851.     }
  852.   if (command == NULL || *command == '')
  853.     {
  854.       numrows = number_commands / numcols;
  855.       if (number_commands % numcols != 0)
  856.         numrows++;
  857.       printf (_("Supported commands:nn"));
  858.       for (i=0; i<numrows; i++)
  859.         {
  860.           printf ("     ");
  861.           for (j=0; j<numcols; j++)
  862.             { 
  863.               ele = i + j * numrows;
  864.               if (ele >= number_commands)
  865.                 break;
  866.               printf ("%-10s", gftp_text_methods[ele].command);
  867.             }
  868.          printf ("n");
  869.         }
  870.       printf ("n");
  871.     }
  872.   return (1);
  873. }
  874. int
  875. gftp_text_set (gftp_request * request, char *command, gpointer *data)
  876. {
  877.   char *pos, *backpos;
  878.   int i;
  879.   if (command == NULL || *command == '')
  880.     {
  881.       for (i=0; config_file_vars[i].key != NULL; i++)
  882.         {
  883.           if (!(config_file_vars[i].ports_shown & GFTP_PORT_TEXT))
  884.             continue;
  885.           switch (config_file_vars[i].type)
  886.             {
  887.               case CONFIG_CHARTEXT:
  888.                 printf ("%s = %sn", config_file_vars[i].key, 
  889.                         *(char **) config_file_vars[i].var);
  890.                 break;
  891.               case CONFIG_INTTEXT:
  892.               case CONFIG_CHECKBOX:
  893.                 printf ("%s = %dn", config_file_vars[i].key, 
  894.                         *(int *) config_file_vars[i].var);
  895.                 break;
  896.               case CONFIG_FLOATTEXT:
  897.                 printf ("%s = %.2fn", config_file_vars[i].key, 
  898.                         *(float *) config_file_vars[i].var);
  899.                 break;
  900.             }
  901.         }
  902.     }
  903.   else
  904.     {
  905.       if ((pos = strchr (command, '=')) == NULL)
  906.         {
  907.           gftp_text_log (gftp_logging_error, NULL,
  908.                          _("usage: set [variable = value]n"));
  909.           return (1);
  910.         }
  911.       *pos = '';
  912.       for (backpos = pos - 1; 
  913.            (*backpos == ' ' || *backpos == 't') && backpos > command; 
  914.            backpos--)
  915.         *backpos = '';
  916.       for (++pos; *pos == ' ' || *pos == 't'; pos++);
  917.       for (i=0; config_file_vars[i].key != NULL; i++)
  918.         {
  919.           if (strcmp (config_file_vars[i].key, command) == 0)
  920.             break;
  921.            
  922.         }
  923.       if (config_file_vars[i].key == NULL)
  924.         {
  925.           gftp_text_log (gftp_logging_error, NULL,
  926.                          _("Error: Variable %s is not a valid configuration variable.n"), command);
  927.           return (1);
  928.         }
  929.       if (!(config_file_vars[i].ports_shown & GFTP_PORT_TEXT))
  930.         {
  931.           gftp_text_log (gftp_logging_error, NULL,
  932.                          _("Error: Variable %s is not available in the text port of gFTPn"), command);
  933.           return (1);
  934.         }
  935.       configuration_changed = 1;
  936.       switch (config_file_vars[i].type)
  937.         {
  938.           case CONFIG_CHARTEXT:
  939.             if (*(char **) config_file_vars[i].var != NULL)
  940.               g_free (*(char **) config_file_vars[i].var);
  941.             *(char **) config_file_vars[i].var = g_strconcat (pos, NULL);
  942.             break;
  943.           case CONFIG_CHECKBOX:
  944.             *(int *) config_file_vars[i].var = *pos == '1' ? 1 : 0;
  945.             break;
  946.           case CONFIG_INTTEXT:
  947.             *(int *) config_file_vars[i].var = strtol (pos, NULL, 10);
  948.             break;
  949.           case CONFIG_FLOATTEXT:
  950.             *(float *) config_file_vars[i].var = strtod (pos, NULL);
  951.             break;
  952.           default:
  953.             gftp_text_log (gftp_logging_error, NULL,
  954.                            _("Error: You cannot change this variablen"));
  955.             break;
  956.         }
  957.     }
  958.   return (1);
  959. }
  960. int
  961. gftp_text_clear (gftp_request * request, char *command, gpointer *data)
  962. {
  963.   if (strcasecmp (command, "cache") == 0)
  964.     gftp_clear_cache_files ();
  965.   else
  966.     gftp_text_log (gftp_logging_error, NULL, "Invalid argumentn");
  967.   return (1);
  968. }
  969. char *
  970. gftp_text_ask_question (const char *question, int echo, char *buf, size_t size)
  971. {
  972.   struct termios term, oldterm;
  973.   sigset_t sig, sigsave;
  974.   char *pos, *termname;
  975.   FILE *infd, *outfd;
  976.   if (!echo)
  977.     {
  978.       sigemptyset (&sig);
  979.       sigaddset (&sig, SIGINT);
  980.       sigaddset (&sig, SIGTSTP);
  981.       sigprocmask (SIG_BLOCK, &sig, &sigsave);
  982.       termname = ctermid (NULL);
  983.       if ((infd = fopen (termname, "r+")) == NULL)
  984.         {
  985.           
  986.           gftp_text_log (gftp_logging_error, NULL, 
  987.                          "Cannot open controlling terminal %sn", termname);
  988.           return (NULL);
  989.         }
  990.       outfd = infd;
  991.       tcgetattr (0, &term);
  992.       oldterm = term;
  993.       term.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL); 
  994.       tcsetattr (fileno (infd), TCSAFLUSH, &term);
  995.     }
  996.   else
  997.     {
  998.       infd = stdin;
  999.       outfd = stdout;
  1000.     }
  1001.   fprintf (outfd, "%s%s%s: ", COLOR_BLUE, question, COLOR_DEFAULT);
  1002.   if (fgets (buf, size, infd) == NULL)
  1003.     return (NULL);
  1004.   buf[size - 1] = '';
  1005.   if (!echo)
  1006.     {
  1007.       fprintf (outfd, "n");
  1008.       tcsetattr (fileno (infd), TCSAFLUSH, &oldterm);
  1009.       fclose (outfd);
  1010.       sigprocmask (SIG_SETMASK, &sigsave, NULL);
  1011.     }
  1012.   for (pos = buf + strlen (buf) - 1; *pos == ' ' || *pos == 'r' ||
  1013.                                      *pos == 'n'; pos--);
  1014.   *(pos+1) = '';
  1015.   for (pos = buf; *pos == ' '; pos++);  
  1016.   if (*pos == '')
  1017.     return (NULL);
  1018.   return (pos);
  1019. }
  1020. int
  1021. gftp_text_get_win_size (void)
  1022. {
  1023.   struct winsize size;
  1024.   int ret;
  1025.   if (ioctl (0, TIOCGWINSZ, (char *) &size) < 0)
  1026.     ret = 80;
  1027.   else
  1028.     ret = size.ws_col;
  1029.   return (ret);
  1030. }
  1031. void
  1032. gftp_text_calc_kbs (gftp_transfer * tdata, ssize_t num_read)
  1033. {
  1034.   unsigned long waitusecs;
  1035.   double difftime, curkbs;
  1036.   gftp_file * tempfle;
  1037.   struct timeval tv;
  1038.   unsigned long toadd;
  1039.   gettimeofday (&tv, NULL);
  1040.   tempfle = tdata->curfle->data;
  1041.   tdata->trans_bytes += num_read;
  1042.   tdata->curtrans += num_read;
  1043.   tdata->stalled = 0;
  1044.   difftime = (tv.tv_sec - tdata->starttime.tv_sec) + ((double) (tv.tv_usec - tdata->starttime.tv_usec) / 1000000.0);
  1045.   if (difftime == 0)
  1046.     tdata->kbs = (double) tdata->trans_bytes / 1024.0;
  1047.   else
  1048.     tdata->kbs = (double) tdata->trans_bytes / 1024.0 / difftime;
  1049.   difftime = (tv.tv_sec - tdata->lasttime.tv_sec) + ((double) (tv.tv_usec - tdata->lasttime.tv_usec) / 1000000.0);
  1050.   if (difftime <= 0)
  1051.     curkbs = (double) (num_read / 1024.0);
  1052.   else
  1053.     curkbs = (double) (num_read / 1024.0 / difftime);
  1054.   if (tdata->fromreq->maxkbs > 0 && 
  1055.       curkbs > tdata->fromreq->maxkbs)
  1056.     {
  1057.       waitusecs = (double) num_read / 1024.0 / tdata->fromreq->maxkbs * 1000000.0 - difftime;
  1058.       if (waitusecs > 0)
  1059.         {
  1060.           difftime += ((double) waitusecs / 1000000.0);
  1061.           usleep (waitusecs);
  1062.         }
  1063.     }
  1064.   /* I don't call gettimeofday (&tdata->lasttime) here because this will use
  1065.      less system resources. This will be close enough for what we need */
  1066.   difftime += tdata->lasttime.tv_usec / 1000000.0;
  1067.   toadd = (long) difftime;
  1068.   difftime -= toadd;
  1069.   tdata->lasttime.tv_sec += toadd;
  1070.   tdata->lasttime.tv_usec = difftime * 1000000.0;
  1071. }
  1072. void
  1073. sig_child (int signo)
  1074. {
  1075. }
  1076. int
  1077. gftp_text_set_show_subhelp (char *topic)
  1078. {
  1079.   int i;
  1080.   for (i=0; config_file_vars[i].key != NULL; i++)
  1081.     {
  1082.       if (strcmp (topic, config_file_vars[i].key) == 0)
  1083.         {
  1084.           printf ("%sn", config_file_vars[i].comment);
  1085.           return (1);
  1086.         }
  1087.     }
  1088.   return (0);
  1089. }
  1090. int
  1091. gftp_text_clear_show_subhelp (char *topic)
  1092. {
  1093.   if (strcmp (topic, "cache") == 0)
  1094.     {
  1095.       printf (_("Clear the directory cachen"));
  1096.       return (1);
  1097.     }
  1098.   return (0);
  1099. }
  1100. #if !defined (HAVE_GETADDRINFO) || !defined (HAVE_GAI_STRERROR)
  1101. struct hostent *
  1102. r_gethostbyname (const char *name, struct hostent *result_buf, int *h_errnop)
  1103. {
  1104.   struct hostent *hent;
  1105.   if ((hent = gethostbyname (name)) == NULL)
  1106.     {
  1107.       if (h_errnop)
  1108.         *h_errnop = h_errno;
  1109.     }
  1110.   else
  1111.     {
  1112.       *result_buf = *hent;
  1113.       hent = result_buf;
  1114.     }
  1115.   return (hent);
  1116. }
  1117. #endif /* HAVE_GETADDRINFO */
  1118. struct servent *
  1119. r_getservbyname (const char *name, const char *proto,
  1120.                  struct servent *result_buf, int *h_errnop)
  1121. {
  1122.   struct servent *sent;
  1123.   if ((sent = getservbyname (name, proto)) == NULL)
  1124.     {
  1125.       if (h_errnop)
  1126.         *h_errnop = h_errno;
  1127.     }
  1128.   else
  1129.     {
  1130.       *result_buf = *sent;
  1131.       sent = result_buf;
  1132.     }
  1133.   return (sent);
  1134. }