Skip to content
ftp.c 38.7 KiB
Newer Older
Daniel Stenberg's avatar
Daniel Stenberg committed
/*****************************************************************************
 *                                  _   _ ____  _     
 *  Project                     ___| | | |  _ \| |    
 *                             / __| | | | |_) | |    
 *                            | (__| |_| |  _ <| |___ 
 *                             \___|\___/|_| \_\_____|
 *
 *  The contents of this file are subject to the Mozilla Public License
 *  Version 1.0 (the "License"); you may not use this file except in
 *  compliance with the License. You may obtain a copy of the License at
 *  http://www.mozilla.org/MPL/
 *
 *  Software distributed under the License is distributed on an "AS IS"
 *  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
 *  License for the specific language governing rights and limitations
 *  under the License.
 *
 *  The Original Code is Curl.
 *
 *  The Initial Developer of the Original Code is Daniel Stenberg.
 *
 *  Portions created by the Initial Developer are Copyright (C) 1998.
 *  All Rights Reserved.
 *
 * ------------------------------------------------------------
 * Main author:
Daniel Stenberg's avatar
Daniel Stenberg committed
 * - Daniel Stenberg <daniel@haxx.se>
Daniel Stenberg's avatar
Daniel Stenberg committed
 *
Daniel Stenberg's avatar
Daniel Stenberg committed
 * 	http://curl.haxx.se
Daniel Stenberg's avatar
Daniel Stenberg committed
 *
 * $Source$
 * $Revision$
 * $Date$
 * $Author$
 * $State$
 * $Locker$
 *
 * ------------------------------------------------------------
 ****************************************************************************/

#include "setup.h"

Daniel Stenberg's avatar
Daniel Stenberg committed
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <errno.h>

#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif

#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
#include <winsock.h>
#else /* some kind of unix */
Daniel Stenberg's avatar
Daniel Stenberg committed
#ifdef HAVE_SYS_SOCKET_H
Daniel Stenberg's avatar
Daniel Stenberg committed
#include <sys/socket.h>
Daniel Stenberg's avatar
Daniel Stenberg committed
#endif
#include <sys/types.h>
#ifdef HAVE_NETINET_IN_H
Daniel Stenberg's avatar
Daniel Stenberg committed
#include <netinet/in.h>
#endif
Daniel Stenberg's avatar
Daniel Stenberg committed
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#include <sys/utsname.h>
#ifdef HAVE_NETDB_H
Daniel Stenberg's avatar
Daniel Stenberg committed
#include <netdb.h>
#endif
#endif
Daniel Stenberg's avatar
Daniel Stenberg committed

#if defined(WIN32) && defined(__GNUC__) || defined(__MINGW32__)
#include <errno.h>
#endif

#include <curl/curl.h>
#include "urldata.h"
#include "sendf.h"

#include "if2ip.h"
#include "hostip.h"
#include "progress.h"
#include "download.h"
Daniel Stenberg's avatar
Daniel Stenberg committed
#include "escape.h"
Daniel Stenberg's avatar
Daniel Stenberg committed

/* returns last node in linked list */
static struct curl_slist *slist_get_last(struct curl_slist *list)
{
	struct curl_slist	*item;

	/* if caller passed us a NULL, return now */
	if (!list)
		return NULL;

	/* loop through to find the last item */
	item = list;
	while (item->next) {
		item = item->next;
	}
	return item;
}

/* append a struct to the linked list. It always retunrs the address of the
 * first record, so that you can sure this function as an initialization
 * function as well as an append function. If you find this bothersome,
 * then simply create a separate _init function and call it appropriately from
 * within the proram. */
struct curl_slist *curl_slist_append(struct curl_slist *list, char *data)
{
	struct curl_slist	*last;
	struct curl_slist	*new_item;

	new_item = (struct curl_slist *) malloc(sizeof(struct curl_slist));
	if (new_item) {
		new_item->next = NULL;
		new_item->data = strdup(data);
	}
	else {
		fprintf(stderr, "Cannot allocate memory for QUOTE list.\n");
		exit(-1);
	}

	if (list) {
		last = slist_get_last(list);
		last->next = new_item;
		return list;
	}

	/* if this is the first item, then new_item *is* the list */
	return new_item;
}

/* be nice and clean up resources */
void curl_slist_free_all(struct curl_slist *list)
{
	struct curl_slist	*next;
	struct curl_slist	*item;

	if (!list)
		return;

	item = list;
	do {
		next = item->next;
		
		if (item->data) {
			free(item->data);
		}
		free(item);
		item = next;
	} while (next);
}


static CURLcode AllowServerConnect(struct UrlData *data,
Daniel Stenberg's avatar
Daniel Stenberg committed
                                   int sock)
{
  fd_set rdset;
  struct timeval dt;
  
  FD_ZERO(&rdset);

  FD_SET(sock, &rdset);

  /* we give the server 10 seconds to connect to us */
  dt.tv_sec = 10;
  dt.tv_usec = 0;

  switch ( select(sock+1, &rdset, NULL, NULL, &dt)) {
  case -1: /* error */
    /* let's die here */
    failf(data, "Error while waiting for server connect");
    return CURLE_FTP_PORT_FAILED;
Daniel Stenberg's avatar
Daniel Stenberg committed
  case 0:  /* timeout */
    /* let's die here */
    failf(data, "Timeout while waiting for server connect");
    return CURLE_FTP_PORT_FAILED;
Daniel Stenberg's avatar
Daniel Stenberg committed
  default:
    /* we have received data here */
    {
      int s;
      size_t size = sizeof(struct sockaddr_in);
      struct sockaddr_in add;

      getsockname(sock, (struct sockaddr *) &add, (int *)&size);
      s=accept(sock, (struct sockaddr *) &add, (int *)&size);

      if( -1 == s) {
	/* DIE! */
	failf(data, "Error accept()ing server connect");
	return CURLE_FTP_PORT_FAILED;
Daniel Stenberg's avatar
Daniel Stenberg committed
      }
      infof(data, "Connection accepted from server\n");

      data->secondarysocket = s;
    }
    break;
Loading
Loading full blame…