2002-09-03 07:52:59 -04:00
|
|
|
/***************************************************************************
|
2004-05-24 09:31:28 -04:00
|
|
|
* _ _ ____ _
|
|
|
|
* Project ___| | | | _ \| |
|
|
|
|
* / __| | | | |_) | |
|
|
|
|
* | (__| |_| | _ <| |___
|
1999-12-29 09:20:26 -05:00
|
|
|
* \___|\___/|_| \_\_____|
|
|
|
|
*
|
2005-01-20 17:22:12 -05:00
|
|
|
* Copyright (C) 1998 - 2005, Daniel Stenberg, <daniel@haxx.se>, et al.
|
1999-12-29 09:20:26 -05:00
|
|
|
*
|
2002-09-03 07:52:59 -04:00
|
|
|
* This software is licensed as described in the file COPYING, which
|
|
|
|
* you should have received as part of this distribution. The terms
|
|
|
|
* are also available at http://curl.haxx.se/docs/copyright.html.
|
2004-05-24 09:31:28 -04:00
|
|
|
*
|
2001-01-03 04:29:33 -05:00
|
|
|
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
|
|
|
* copies of the Software, and permit persons to whom the Software is
|
2002-09-03 07:52:59 -04:00
|
|
|
* furnished to do so, under the terms of the COPYING file.
|
1999-12-29 09:20:26 -05:00
|
|
|
*
|
2001-01-03 04:29:33 -05:00
|
|
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
|
|
|
* KIND, either express or implied.
|
1999-12-29 09:20:26 -05:00
|
|
|
*
|
2001-01-03 04:29:33 -05:00
|
|
|
* $Id$
|
2002-09-03 07:52:59 -04:00
|
|
|
***************************************************************************/
|
1999-12-29 09:20:26 -05:00
|
|
|
|
2001-04-18 10:06:47 -04:00
|
|
|
#include "setup.h"
|
|
|
|
|
1999-12-29 09:20:26 -05:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdarg.h>
|
2001-04-18 10:06:47 -04:00
|
|
|
#include <sys/types.h>
|
1999-12-29 09:20:26 -05:00
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <ctype.h>
|
2002-12-05 14:39:17 -05:00
|
|
|
#include <errno.h>
|
1999-12-29 09:20:26 -05:00
|
|
|
|
|
|
|
#include <curl/curl.h>
|
2000-10-09 17:35:40 -04:00
|
|
|
|
1999-12-29 09:20:26 -05:00
|
|
|
#include "urlglob.h"
|
2000-11-21 04:38:41 -05:00
|
|
|
#include "writeout.h"
|
2003-10-16 10:09:39 -04:00
|
|
|
#include "getpass.h"
|
2003-11-07 12:17:15 -05:00
|
|
|
#include "homedir.h"
|
2004-02-12 09:46:12 -05:00
|
|
|
#ifdef USE_MANUAL
|
2004-01-29 08:48:36 -05:00
|
|
|
#include "hugehelp.h"
|
2004-02-12 09:46:12 -05:00
|
|
|
#endif
|
2002-04-08 18:48:25 -04:00
|
|
|
#ifdef USE_ENVIRONMENT
|
|
|
|
#include "writeenv.h"
|
|
|
|
#endif
|
2000-11-21 04:38:41 -05:00
|
|
|
|
2004-10-06 03:50:18 -04:00
|
|
|
#define CURLseparator "--_curl_--"
|
2000-05-09 18:42:53 -04:00
|
|
|
|
2004-03-17 07:46:42 -05:00
|
|
|
#ifdef __NOVELL_LIBC__
|
|
|
|
#include <screen.h>
|
|
|
|
#endif
|
|
|
|
|
2003-06-03 04:07:06 -04:00
|
|
|
#ifdef TIME_WITH_SYS_TIME
|
|
|
|
/* We can include both fine */
|
2003-05-27 18:56:01 -04:00
|
|
|
#include <sys/time.h>
|
2003-06-03 04:07:06 -04:00
|
|
|
#include <time.h>
|
|
|
|
#else
|
|
|
|
#ifdef HAVE_SYS_TIME_H
|
|
|
|
# include <sys/time.h>
|
|
|
|
#else
|
|
|
|
# include <time.h>
|
|
|
|
#endif
|
2003-05-27 18:56:01 -04:00
|
|
|
#endif
|
|
|
|
|
2003-06-03 04:07:06 -04:00
|
|
|
|
1999-12-29 09:20:26 -05:00
|
|
|
#include "version.h"
|
|
|
|
|
|
|
|
#ifdef HAVE_IO_H /* typical win32 habit */
|
|
|
|
#include <io.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef HAVE_UNISTD_H
|
|
|
|
#include <unistd.h>
|
|
|
|
#endif
|
|
|
|
|
2000-06-14 08:52:21 -04:00
|
|
|
#ifdef HAVE_FCNTL_H
|
|
|
|
#include <fcntl.h>
|
|
|
|
#endif
|
|
|
|
|
2001-09-03 08:00:08 -04:00
|
|
|
#ifdef HAVE_UTIME_H
|
2001-10-22 18:15:50 -04:00
|
|
|
#include <utime.h>
|
2001-09-07 05:53:21 -04:00
|
|
|
#else
|
2001-10-22 18:15:50 -04:00
|
|
|
#ifdef HAVE_SYS_UTIME_H
|
|
|
|
#include <sys/utime.h>
|
|
|
|
#endif
|
2002-06-15 17:02:11 -04:00
|
|
|
|
2004-10-18 09:37:18 -04:00
|
|
|
#endif /* HAVE_UTIME_H */
|
2002-06-15 17:02:11 -04:00
|
|
|
|
2004-01-14 02:42:10 -05:00
|
|
|
#ifdef HAVE_LIMITS_H
|
|
|
|
#include <limits.h>
|
|
|
|
#endif
|
|
|
|
|
2002-06-15 17:02:11 -04:00
|
|
|
#ifdef HAVE_SYS_POLL_H
|
|
|
|
#include <sys/poll.h>
|
2001-09-03 08:00:08 -04:00
|
|
|
#endif
|
|
|
|
|
2004-10-18 09:37:18 -04:00
|
|
|
#ifdef HAVE_LOCALE_H
|
|
|
|
#include <locale.h> /* for setlocale() */
|
|
|
|
#endif
|
|
|
|
|
2004-04-30 04:23:50 -04:00
|
|
|
#define ENABLE_CURLX_PRINTF
|
|
|
|
/* make the curlx header define all printf() functions to use the curlx_*
|
|
|
|
versions instead */
|
|
|
|
#include <curlx.h> /* header from the libcurl directory */
|
2004-02-19 03:13:20 -05:00
|
|
|
|
2000-10-09 07:13:17 -04:00
|
|
|
/* The last #include file should be: */
|
2003-06-26 07:33:29 -04:00
|
|
|
#ifdef CURLDEBUG
|
2004-05-12 04:22:04 -04:00
|
|
|
#ifndef CURLTOOLDEBUG
|
|
|
|
#define MEMDEBUG_NODEFINES
|
|
|
|
#endif
|
2003-06-26 07:33:29 -04:00
|
|
|
/* This is low-level hard-hacking memory leak tracking and similar. Using
|
|
|
|
the library level code from this client-side is ugly, but we do this
|
|
|
|
anyway for convenience. */
|
2004-02-19 03:13:20 -05:00
|
|
|
#include "memdebug.h"
|
2000-10-09 07:13:17 -04:00
|
|
|
#endif
|
|
|
|
|
2000-11-28 04:10:43 -05:00
|
|
|
#define DEFAULT_MAXREDIRS 50L
|
2000-11-17 05:08:39 -05:00
|
|
|
|
2003-07-15 19:47:25 -04:00
|
|
|
#ifdef __DJGPP__
|
2004-03-29 07:29:25 -05:00
|
|
|
#include <dos.h>
|
|
|
|
|
2003-07-15 19:47:25 -04:00
|
|
|
char *msdosify(char *);
|
|
|
|
char *rename_if_dos_device_name(char *);
|
2004-03-29 07:29:25 -05:00
|
|
|
|
|
|
|
/* we want to glob our own argv[] */
|
|
|
|
char **__crt0_glob_function (char *arg)
|
|
|
|
{
|
|
|
|
(void)arg;
|
|
|
|
return (char**)0;
|
|
|
|
}
|
2003-07-15 19:47:25 -04:00
|
|
|
#endif /* __DJGPP__ */
|
|
|
|
|
2000-11-28 04:10:43 -05:00
|
|
|
#define CURL_PROGRESS_STATS 0 /* default progress display */
|
|
|
|
#define CURL_PROGRESS_BAR 1
|
|
|
|
|
2004-02-21 10:08:21 -05:00
|
|
|
/**
|
|
|
|
* @def MIN
|
|
|
|
* standard MIN macro
|
|
|
|
*/
|
|
|
|
#ifndef MIN
|
2004-10-06 03:50:18 -04:00
|
|
|
#define MIN(X,Y) (((X) < (Y)) ? (X) : (Y))
|
2004-02-21 10:08:21 -05:00
|
|
|
#endif
|
|
|
|
|
2000-07-25 03:34:04 -04:00
|
|
|
typedef enum {
|
|
|
|
HTTPREQ_UNSPEC,
|
|
|
|
HTTPREQ_GET,
|
|
|
|
HTTPREQ_HEAD,
|
|
|
|
HTTPREQ_POST,
|
|
|
|
HTTPREQ_SIMPLEPOST,
|
|
|
|
HTTPREQ_CUSTOM,
|
|
|
|
HTTPREQ_LAST
|
|
|
|
} HttpReq;
|
|
|
|
|
2000-05-22 10:12:12 -04:00
|
|
|
/* Just a set of bits */
|
|
|
|
#define CONF_DEFAULT 0
|
2000-06-20 05:28:09 -04:00
|
|
|
|
|
|
|
#define CONF_AUTO_REFERER (1<<4) /* the automatic referer-system please! */
|
2000-05-22 10:12:12 -04:00
|
|
|
#define CONF_HEADER (1<<8) /* throw the header out too */
|
|
|
|
#define CONF_NOPROGRESS (1<<10) /* shut off the progress meter */
|
|
|
|
#define CONF_NOBODY (1<<11) /* use HEAD to get http document */
|
|
|
|
#define CONF_FAILONERROR (1<<12) /* no output on http error codes >= 300 */
|
|
|
|
#define CONF_FTPLISTONLY (1<<16) /* Use NLST when listing ftp dir */
|
|
|
|
#define CONF_FTPAPPEND (1<<20) /* Append instead of overwrite on upload! */
|
|
|
|
#define CONF_NETRC (1<<22) /* read user+password from .netrc */
|
|
|
|
#define CONF_FOLLOWLOCATION (1<<23) /* use Location: Luke! */
|
2000-06-14 08:50:38 -04:00
|
|
|
#define CONF_GETTEXT (1<<24) /* use ASCII/text for transfer */
|
2000-05-22 10:12:12 -04:00
|
|
|
#define CONF_MUTE (1<<28) /* force NOPROGRESS */
|
|
|
|
|
2002-05-21 18:18:34 -04:00
|
|
|
#define CONF_NETRC_OPT (1<<29) /* read user+password from either
|
|
|
|
* .netrc or URL*/
|
2003-03-30 23:42:20 -05:00
|
|
|
#define CONF_UNRESTRICTED_AUTH (1<<30)
|
|
|
|
/* Send authentication (user+password) when following
|
|
|
|
* locations, even when hostname changed */
|
2002-05-21 18:18:34 -04:00
|
|
|
|
2000-03-02 18:06:34 -05:00
|
|
|
#ifndef HAVE_STRDUP
|
|
|
|
/* Ultrix doesn't have strdup(), so make a quick clone: */
|
|
|
|
char *strdup(char *str)
|
|
|
|
{
|
|
|
|
int len;
|
|
|
|
char *newstr;
|
|
|
|
|
|
|
|
len = strlen(str);
|
|
|
|
newstr = (char *) malloc((len+1)*sizeof(char));
|
|
|
|
if (!newstr)
|
|
|
|
return (char *)NULL;
|
|
|
|
|
|
|
|
strcpy(newstr,str);
|
|
|
|
|
|
|
|
return newstr;
|
|
|
|
|
|
|
|
}
|
2004-05-24 09:31:28 -04:00
|
|
|
#endif
|
2000-03-02 18:06:34 -05:00
|
|
|
|
2003-01-08 10:04:42 -05:00
|
|
|
#ifdef WIN32
|
|
|
|
#include <direct.h>
|
|
|
|
#define F_OK 0
|
|
|
|
#define mkdir(x,y) (mkdir)(x)
|
|
|
|
#endif
|
|
|
|
|
2004-10-06 03:50:18 -04:00
|
|
|
#ifdef VMS
|
2003-12-03 03:40:39 -05:00
|
|
|
#include "curlmsg_vms.h"
|
2001-08-06 09:19:43 -04:00
|
|
|
#endif
|
|
|
|
|
2004-12-16 11:49:14 -05:00
|
|
|
/* Support uploading and resuming of >2GB files
|
|
|
|
*/
|
|
|
|
#if defined(WIN32) && (SIZEOF_CURL_OFF_T > 4)
|
|
|
|
#define struct_stat struct _stati64
|
|
|
|
#define stat(file,st) _stati64(file,st)
|
|
|
|
#else
|
|
|
|
#define struct_stat struct stat
|
|
|
|
#endif
|
|
|
|
|
2004-11-24 14:34:25 -05:00
|
|
|
#ifdef WIN32
|
2004-10-28 09:13:29 -04:00
|
|
|
/*
|
2004-11-14 08:50:21 -05:00
|
|
|
* Truncate a file handle at a 64-bit position 'where'.
|
|
|
|
* Borland doesn't even support 64-bit types.
|
2004-10-28 09:13:29 -04:00
|
|
|
*/
|
2004-11-14 08:50:21 -05:00
|
|
|
#ifdef __BORLANDC__
|
|
|
|
#define _lseeki64(hnd,ofs,whence) lseek(hnd,ofs,whence)
|
|
|
|
#endif
|
|
|
|
|
2004-11-24 14:34:25 -05:00
|
|
|
static int ftruncate64 (int fd, curl_off_t where)
|
2004-10-28 09:13:29 -04:00
|
|
|
{
|
|
|
|
curl_off_t curr;
|
|
|
|
int rc = 0;
|
|
|
|
|
|
|
|
if ((curr = _lseeki64(fd, 0, SEEK_CUR)) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (_lseeki64(fd, where, SEEK_SET) < 0)
|
|
|
|
return -1;
|
|
|
|
|
2004-12-17 13:31:40 -05:00
|
|
|
if (write(fd, 0, 0) < 0)
|
2004-10-28 09:13:29 -04:00
|
|
|
rc = -1;
|
|
|
|
_lseeki64(fd, curr, SEEK_SET);
|
|
|
|
return rc;
|
|
|
|
}
|
2004-11-24 14:34:25 -05:00
|
|
|
#define ftruncate(fd,where) ftruncate64(fd,where)
|
2004-10-28 09:13:29 -04:00
|
|
|
#endif
|
|
|
|
|
2005-08-15 17:48:28 -04:00
|
|
|
typedef enum {
|
|
|
|
TRACE_BIN, /* tcpdump inspired look */
|
|
|
|
TRACE_ASCII, /* like *BIN but without the hex output */
|
|
|
|
TRACE_PLAIN /* -v/--verbose type */
|
|
|
|
} trace;
|
|
|
|
|
|
|
|
struct Configurable {
|
|
|
|
bool remote_time;
|
|
|
|
char *random_file;
|
|
|
|
char *egd_file;
|
|
|
|
char *useragent;
|
|
|
|
char *cookie; /* single line with specified cookies */
|
|
|
|
char *cookiejar; /* write to this file */
|
|
|
|
char *cookiefile; /* read from this file */
|
|
|
|
bool cookiesession; /* new session? */
|
|
|
|
bool encoding; /* Accept-Encoding please */
|
|
|
|
long authtype; /* auth bitmask */
|
|
|
|
bool use_resume;
|
|
|
|
bool resume_from_current;
|
|
|
|
bool disable_epsv;
|
|
|
|
bool disable_eprt;
|
|
|
|
curl_off_t resume_from;
|
|
|
|
char *postfields;
|
|
|
|
long postfieldsize;
|
|
|
|
char *referer;
|
|
|
|
long timeout;
|
|
|
|
long connecttimeout;
|
|
|
|
long maxredirs;
|
|
|
|
curl_off_t max_filesize;
|
|
|
|
char *headerfile;
|
|
|
|
char *ftpport;
|
|
|
|
char *iface;
|
|
|
|
unsigned short porttouse;
|
|
|
|
char *range;
|
|
|
|
long low_speed_limit;
|
|
|
|
long low_speed_time;
|
|
|
|
bool showerror;
|
|
|
|
char *userpwd;
|
|
|
|
char *proxyuserpwd;
|
|
|
|
char *proxy;
|
|
|
|
bool proxytunnel;
|
|
|
|
long conf;
|
|
|
|
struct getout *url_list; /* point to the first node */
|
|
|
|
struct getout *url_last; /* point to the last/current node */
|
|
|
|
struct getout *url_get; /* point to the node to fill in URL */
|
|
|
|
struct getout *url_out; /* point to the node to fill in outfile */
|
|
|
|
char *cipher_list;
|
|
|
|
char *cert;
|
|
|
|
char *cert_type;
|
|
|
|
char *cacert;
|
|
|
|
char *capath;
|
|
|
|
char *key;
|
|
|
|
char *key_type;
|
|
|
|
char *key_passwd;
|
|
|
|
char *engine;
|
|
|
|
bool list_engines;
|
|
|
|
bool crlf;
|
|
|
|
char *customrequest;
|
|
|
|
char *krb4level;
|
|
|
|
char *trace_dump; /* file to dump the network trace to, or NULL */
|
|
|
|
FILE *trace_stream;
|
|
|
|
bool trace_fopened;
|
|
|
|
trace tracetype;
|
|
|
|
bool tracetime; /* include timestamp? */
|
|
|
|
long httpversion;
|
|
|
|
bool progressmode;
|
|
|
|
bool nobuffer;
|
|
|
|
bool globoff;
|
|
|
|
bool use_httpget;
|
|
|
|
bool insecure_ok; /* set TRUE to allow insecure SSL connects */
|
|
|
|
bool create_dirs;
|
|
|
|
bool ftp_create_dirs;
|
2005-09-04 01:16:06 -04:00
|
|
|
bool ftp_skip_ip;
|
2005-08-15 17:48:28 -04:00
|
|
|
bool proxyntlm;
|
|
|
|
bool proxydigest;
|
|
|
|
bool proxybasic;
|
|
|
|
bool proxyanyauth;
|
|
|
|
char *writeout; /* %-styled format string to output */
|
|
|
|
bool writeenv; /* write results to environment, if available */
|
|
|
|
FILE *errors; /* if stderr redirect is requested */
|
|
|
|
bool errors_fopened;
|
|
|
|
struct curl_slist *quote;
|
|
|
|
struct curl_slist *postquote;
|
|
|
|
struct curl_slist *prequote;
|
|
|
|
long ssl_version;
|
|
|
|
long ip_version;
|
|
|
|
curl_TimeCond timecond;
|
|
|
|
time_t condtime;
|
|
|
|
struct curl_slist *headers;
|
|
|
|
struct curl_httppost *httppost;
|
|
|
|
struct curl_httppost *last_post;
|
|
|
|
struct curl_slist *telnet_options;
|
|
|
|
HttpReq httpreq;
|
|
|
|
|
|
|
|
/* for bandwidth limiting features: */
|
|
|
|
curl_off_t sendpersecond; /* send to peer */
|
|
|
|
curl_off_t recvpersecond; /* receive from peer */
|
|
|
|
struct timeval lastsendtime;
|
|
|
|
size_t lastsendsize;
|
|
|
|
struct timeval lastrecvtime;
|
|
|
|
size_t lastrecvsize;
|
|
|
|
bool ftp_ssl;
|
|
|
|
char *socks5proxy;
|
|
|
|
bool tcp_nodelay;
|
|
|
|
long req_retry; /* number of retries */
|
|
|
|
long retry_delay; /* delay between retries (in seconds) */
|
|
|
|
long retry_maxtime; /* maximum time to keep retrying */
|
|
|
|
|
|
|
|
char *tp_url; /* third party URL */
|
|
|
|
char *tp_user; /* third party userpwd */
|
|
|
|
struct curl_slist *tp_quote;
|
|
|
|
struct curl_slist *tp_postquote;
|
|
|
|
struct curl_slist *tp_prequote;
|
|
|
|
char *ftp_account; /* for ACCT */
|
2005-11-28 18:06:00 -05:00
|
|
|
int ftp_filemethod;
|
2005-08-24 06:57:28 -04:00
|
|
|
|
|
|
|
bool ignorecl; /* --ignore-content-length */
|
2005-08-15 17:48:28 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
#define WARN_PREFIX "Warning: "
|
2005-12-05 09:10:48 -05:00
|
|
|
#define WARN_TEXTWIDTH (79 - (int)strlen(WARN_PREFIX))
|
2005-08-15 17:48:28 -04:00
|
|
|
/* produce this text message to the user unless mute was selected */
|
|
|
|
static void warnf(struct Configurable *config, const char *fmt, ...)
|
|
|
|
{
|
|
|
|
if(!(config->conf & CONF_MUTE)) {
|
|
|
|
va_list ap;
|
|
|
|
int len;
|
|
|
|
char *ptr;
|
|
|
|
char print_buffer[256];
|
|
|
|
|
|
|
|
va_start(ap, fmt);
|
|
|
|
va_start(ap, fmt);
|
|
|
|
len = vsnprintf(print_buffer, sizeof(print_buffer), fmt, ap);
|
|
|
|
va_end(ap);
|
|
|
|
|
|
|
|
ptr = print_buffer;
|
|
|
|
while(len > 0) {
|
|
|
|
fputs(WARN_PREFIX, config->errors);
|
|
|
|
|
|
|
|
if(len > (int)WARN_TEXTWIDTH) {
|
|
|
|
int cut = WARN_TEXTWIDTH-1;
|
|
|
|
|
2005-08-16 03:32:50 -04:00
|
|
|
while(!isspace((int)ptr[cut]) && cut) {
|
2005-08-15 17:48:28 -04:00
|
|
|
cut--;
|
|
|
|
}
|
|
|
|
|
|
|
|
fwrite(ptr, cut + 1, 1, config->errors);
|
|
|
|
fputs("\n", config->errors);
|
|
|
|
ptr += cut+1; /* skip the space too */
|
|
|
|
len -= cut;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
fputs(ptr, config->errors);
|
|
|
|
len = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2000-05-17 17:21:10 -04:00
|
|
|
/*
|
|
|
|
* This is the main global constructor for the app. Call this before
|
|
|
|
* _any_ libcurl usage. If this fails, *NO* libcurl functions may be
|
|
|
|
* used, or havoc may be the result.
|
|
|
|
*/
|
2004-01-29 08:48:36 -05:00
|
|
|
static CURLcode main_init(void)
|
2000-05-17 17:21:10 -04:00
|
|
|
{
|
2001-07-11 21:57:28 -04:00
|
|
|
return curl_global_init(CURL_GLOBAL_DEFAULT);
|
2000-05-17 17:21:10 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This is the main global destructor for the app. Call this after
|
|
|
|
* _all_ libcurl usage is done.
|
|
|
|
*/
|
2004-01-29 08:48:36 -05:00
|
|
|
static void main_free(void)
|
2000-05-17 17:21:10 -04:00
|
|
|
{
|
2001-05-28 11:06:46 -04:00
|
|
|
curl_global_cleanup();
|
2000-05-17 17:21:10 -04:00
|
|
|
}
|
|
|
|
|
2005-08-15 17:48:28 -04:00
|
|
|
static int SetHTTPrequest(struct Configurable *config,
|
|
|
|
HttpReq req, HttpReq *store)
|
2000-07-25 03:34:04 -04:00
|
|
|
{
|
|
|
|
if((*store == HTTPREQ_UNSPEC) ||
|
|
|
|
(*store == req)) {
|
|
|
|
*store = req;
|
2000-11-17 04:47:18 -05:00
|
|
|
return 0;
|
2000-07-25 03:34:04 -04:00
|
|
|
}
|
2005-08-15 17:48:28 -04:00
|
|
|
warnf(config, "You can only select one HTTP request!\n");
|
2000-11-17 04:47:18 -05:00
|
|
|
return 1;
|
2000-07-25 03:34:04 -04:00
|
|
|
}
|
2000-05-17 17:21:10 -04:00
|
|
|
|
2001-08-14 05:16:46 -04:00
|
|
|
static void helpf(const char *fmt, ...)
|
1999-12-29 09:20:26 -05:00
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
if(fmt) {
|
|
|
|
va_start(ap, fmt);
|
|
|
|
fputs("curl: ", stderr); /* prefix it */
|
|
|
|
vfprintf(stderr, fmt, ap);
|
|
|
|
va_end(ap);
|
|
|
|
}
|
2004-02-17 08:46:00 -05:00
|
|
|
fprintf(stderr, "curl: try 'curl --help' "
|
|
|
|
#ifdef USE_MANUAL
|
|
|
|
"or 'curl --manual' "
|
|
|
|
#endif
|
|
|
|
"for more information\n");
|
1999-12-29 09:20:26 -05:00
|
|
|
}
|
|
|
|
|
2001-01-08 02:37:44 -05:00
|
|
|
/*
|
|
|
|
* A chain of these nodes contain URL to get and where to put the URL's
|
|
|
|
* contents.
|
|
|
|
*/
|
|
|
|
struct getout {
|
2003-08-19 19:42:24 -04:00
|
|
|
struct getout *next; /* next one */
|
|
|
|
char *url; /* the URL we deal with */
|
|
|
|
char *outfile; /* where to store the output */
|
|
|
|
char *infile; /* file to upload, if GETOUT_UPLOAD is set */
|
|
|
|
int flags; /* options */
|
2001-01-08 02:37:44 -05:00
|
|
|
};
|
2003-08-19 19:42:24 -04:00
|
|
|
#define GETOUT_OUTFILE (1<<0) /* set when outfile is deemed done */
|
|
|
|
#define GETOUT_URL (1<<1) /* set when URL is deemed done */
|
2001-01-08 02:37:44 -05:00
|
|
|
#define GETOUT_USEREMOTE (1<<2) /* use remote file name locally */
|
2003-08-19 19:42:24 -04:00
|
|
|
#define GETOUT_UPLOAD (1<<3) /* if set, -T has been used */
|
|
|
|
#define GETOUT_NOUPLOAD (1<<4) /* if set, -T "" has been used */
|
|
|
|
|
1999-12-29 09:20:26 -05:00
|
|
|
static void help(void)
|
|
|
|
{
|
2003-08-11 08:04:46 -04:00
|
|
|
int i;
|
2004-12-14 22:03:45 -05:00
|
|
|
static const char * const helptext[]={
|
2003-08-11 08:04:46 -04:00
|
|
|
"Usage: curl [options...] <url>",
|
|
|
|
"Options: (H) means HTTP/HTTPS only, (F) means FTP only",
|
|
|
|
" -a/--append Append to target file when uploading (F)",
|
|
|
|
" -A/--user-agent <string> User-Agent to send to server (H)",
|
2005-10-20 17:19:19 -04:00
|
|
|
" --anyauth Pick \"any\" authentication method (H)",
|
2003-08-11 08:04:46 -04:00
|
|
|
" -b/--cookie <name=string/file> Cookie string or file to read cookies from (H)",
|
2005-10-20 17:19:19 -04:00
|
|
|
" --basic Use HTTP Basic Authentication (H)",
|
2003-08-11 08:04:46 -04:00
|
|
|
" -B/--use-ascii Use ASCII/text transfer",
|
2003-10-29 11:11:36 -05:00
|
|
|
" -c/--cookie-jar <file> Write cookies to this file after operation (H)",
|
|
|
|
" -C/--continue-at <offset> Resumed transfer offset",
|
2003-08-11 08:04:46 -04:00
|
|
|
" -d/--data <data> HTTP POST data (H)",
|
2005-10-20 17:19:19 -04:00
|
|
|
" --data-ascii <data> HTTP POST ASCII data (H)",
|
|
|
|
" --data-binary <data> HTTP POST binary data (H)",
|
|
|
|
" --negotiate Use HTTP Negotiate Authentication (H)",
|
|
|
|
" --digest Use HTTP Digest Authentication (H)",
|
|
|
|
" --disable-eprt Inhibit using EPRT or LPRT (F)",
|
|
|
|
" --disable-epsv Inhibit using EPSV (F)",
|
2003-08-11 08:04:46 -04:00
|
|
|
" -D/--dump-header <file> Write the headers to this file",
|
|
|
|
" --egd-file <file> EGD socket path for random data (SSL)",
|
2005-10-20 17:19:19 -04:00
|
|
|
" --tcp-nodelay Use the TCP_NODELAY option",
|
2002-04-08 18:48:25 -04:00
|
|
|
#ifdef USE_ENVIRONMENT
|
2005-10-20 17:19:19 -04:00
|
|
|
" --environment Write results to environment variables (RISC OS)",
|
2002-04-08 18:48:25 -04:00
|
|
|
#endif
|
2003-10-29 11:11:36 -05:00
|
|
|
" -e/--referer Referer URL (H)",
|
|
|
|
" -E/--cert <cert[:passwd]> Client certificate file and password (SSL)",
|
|
|
|
" --cert-type <type> Certificate file type (DER/PEM/ENG) (SSL)",
|
|
|
|
" --key <key> Private key file name (SSL)",
|
|
|
|
" --key-type <type> Private key file type (DER/PEM/ENG) (SSL)",
|
|
|
|
" --pass <pass> Pass phrase for the private key (SSL)",
|
2004-12-13 11:47:36 -05:00
|
|
|
" --engine <eng> Crypto engine to use (SSL). \"--engine list\" for list",
|
2003-08-11 08:04:46 -04:00
|
|
|
" --cacert <file> CA certificate to verify peer against (SSL)",
|
|
|
|
" --capath <directory> CA directory (made using c_rehash) to verify",
|
|
|
|
" peer against (SSL)",
|
2003-10-29 11:11:36 -05:00
|
|
|
" --ciphers <list> SSL ciphers to use (SSL)",
|
2003-10-30 04:15:47 -05:00
|
|
|
" --compressed Request compressed response (using deflate or gzip)",
|
2003-08-11 08:04:46 -04:00
|
|
|
" --connect-timeout <seconds> Maximum time allowed for connection",
|
2003-10-29 11:11:36 -05:00
|
|
|
" --create-dirs Create necessary local directory hierarchy",
|
2003-10-30 04:15:47 -05:00
|
|
|
" --crlf Convert LF to CRLF in upload",
|
2005-10-20 17:19:19 -04:00
|
|
|
" -f/--fail Fail silently (no output at all) on HTTP errors (H)",
|
2003-08-11 08:04:46 -04:00
|
|
|
" --ftp-create-dirs Create the remote dirs if not present (F)",
|
2005-09-04 01:16:06 -04:00
|
|
|
" --ftp-pasv Use PASV/EPSV instead of PORT (F)",
|
|
|
|
" --ftp-skip-pasv-ip Skip the IP address for PASV (F)\n"
|
2003-11-24 06:59:15 -05:00
|
|
|
" --ftp-ssl Enable SSL/TLS for the ftp transfer (F)",
|
2003-10-29 11:11:36 -05:00
|
|
|
" -F/--form <name=content> Specify HTTP multipart POST data (H)",
|
2005-03-12 14:39:27 -05:00
|
|
|
" --form-string <name=string> Specify HTTP multipart POST data (H)",
|
2003-08-11 08:04:46 -04:00
|
|
|
" -g/--globoff Disable URL sequences and ranges using {} and []",
|
|
|
|
" -G/--get Send the -d data with a HTTP GET (H)",
|
|
|
|
" -h/--help This help text",
|
2003-10-30 04:15:47 -05:00
|
|
|
" -H/--header <line> Custom header to pass to server (H)",
|
2005-08-24 06:57:28 -04:00
|
|
|
" --ignore-content-length Ignore the HTTP Content-Length header",
|
2003-10-29 11:11:36 -05:00
|
|
|
" -i/--include Include protocol headers in the output (H/F)",
|
2003-10-30 04:15:47 -05:00
|
|
|
" -I/--head Show document info only",
|
2003-08-11 08:04:46 -04:00
|
|
|
" -j/--junk-session-cookies Ignore session cookies read from file (H)",
|
2003-10-29 11:11:36 -05:00
|
|
|
" --interface <interface> Specify network interface to use",
|
2003-08-11 08:04:46 -04:00
|
|
|
" --krb4 <level> Enable krb4 with specified security level (F)",
|
2005-10-20 17:19:19 -04:00
|
|
|
" -k/--insecure Allow connections to SSL sites without certs (H)",
|
2003-08-11 08:04:46 -04:00
|
|
|
" -K/--config Specify which config file to read",
|
|
|
|
" -l/--list-only List only names of an FTP directory (F)",
|
2003-10-29 11:11:36 -05:00
|
|
|
" --limit-rate <rate> Limit transfer speed to this rate",
|
2003-08-11 08:04:46 -04:00
|
|
|
" -L/--location Follow Location: hints (H)",
|
2003-10-29 11:11:36 -05:00
|
|
|
" --location-trusted Follow Location: and send authentication even ",
|
|
|
|
" to other hostnames (H)",
|
2003-08-11 08:04:46 -04:00
|
|
|
" -m/--max-time <seconds> Maximum time allowed for the transfer",
|
2003-10-29 11:11:36 -05:00
|
|
|
" --max-redirs <num> Maximum number of redirects allowed (H)",
|
|
|
|
" --max-filesize <bytes> Maximum file size to download (H/F)",
|
|
|
|
" -M/--manual Display the full manual",
|
2003-08-11 08:04:46 -04:00
|
|
|
" -n/--netrc Must read .netrc for user name and password",
|
2003-10-29 11:11:36 -05:00
|
|
|
" --netrc-optional Use either .netrc or URL; overrides -n",
|
2005-10-20 17:19:19 -04:00
|
|
|
" --ntlm Use HTTP NTLM authentication (H)",
|
2003-10-29 11:11:36 -05:00
|
|
|
" -N/--no-buffer Disable buffering of the output stream",
|
2003-08-11 08:04:46 -04:00
|
|
|
" -o/--output <file> Write output to <file> instead of stdout",
|
|
|
|
" -O/--remote-name Write output to a file named as the remote file",
|
2003-10-29 11:11:36 -05:00
|
|
|
" -p/--proxytunnel Operate through a HTTP proxy tunnel (using CONNECT)",
|
2005-10-20 17:19:19 -04:00
|
|
|
" --proxy-anyauth Pick \"any\" proxy authentication method (H)",
|
|
|
|
" --proxy-basic Use Basic authentication on the proxy (H)",
|
|
|
|
" --proxy-digest Use Digest authentication on the proxy (H)",
|
|
|
|
" --proxy-ntlm Use NTLM authentication on the proxy (H)",
|
2003-12-02 13:01:08 -05:00
|
|
|
" -P/--ftp-port <address> Use PORT with address instead of PASV (F)",
|
2003-10-29 11:11:36 -05:00
|
|
|
" -q If used as the first parameter disables .curlrc",
|
|
|
|
" -Q/--quote <cmd> Send command(s) to server before file transfer (F)",
|
2003-08-11 08:04:46 -04:00
|
|
|
" -r/--range <range> Retrieve a byte range from a HTTP/1.1 or FTP server",
|
2003-10-29 11:11:36 -05:00
|
|
|
" --random-file <file> File for reading random data from (SSL)",
|
2003-08-11 08:04:46 -04:00
|
|
|
" -R/--remote-time Set the remote file's time on the local output",
|
2004-10-27 17:29:55 -04:00
|
|
|
" --retry <num> Retry request <num> times if transient problems occur",
|
|
|
|
" --retry-delay <seconds> When retrying, wait this many seconds between each",
|
2004-11-04 11:17:23 -05:00
|
|
|
" --retry-max-time <seconds> Retry only within this period",
|
2003-08-11 08:04:46 -04:00
|
|
|
" -s/--silent Silent mode. Don't output anything",
|
|
|
|
" -S/--show-error Show error. With -s, make curl show errors when they occur",
|
2004-01-30 03:51:24 -05:00
|
|
|
" --socks <host[:port]> Use SOCKS5 proxy on given host + port",
|
2003-10-30 04:15:47 -05:00
|
|
|
" --stderr <file> Where to redirect stderr. - means stdout",
|
2003-08-11 08:04:46 -04:00
|
|
|
" -t/--telnet-option <OPT=val> Set telnet option",
|
2005-01-21 04:32:32 -05:00
|
|
|
" --trace <file> Write a debug trace to the given file",
|
2003-10-29 11:11:36 -05:00
|
|
|
" --trace-ascii <file> Like --trace but without the hex output",
|
2005-05-02 05:38:19 -04:00
|
|
|
" --trace-time Add time stamps to trace/verbose output",
|
2005-01-21 04:32:32 -05:00
|
|
|
" -T/--upload-file <file> Transfer <file> to remote site",
|
|
|
|
" --url <URL> Spet URL to work with",
|
|
|
|
" -u/--user <user[:password]> Set server user and password",
|
|
|
|
" -U/--proxy-user <user[:password]> Set proxy user and password",
|
2003-10-29 11:11:36 -05:00
|
|
|
" -v/--verbose Make the operation more talkative",
|
|
|
|
" -V/--version Show version number and quit",
|
2003-07-05 09:13:49 -04:00
|
|
|
#ifdef __DJGPP__
|
2004-03-29 07:29:25 -05:00
|
|
|
" --wdebug Turn on Watt-32 debugging under DJGPP",
|
2003-07-05 09:13:49 -04:00
|
|
|
#endif
|
2003-08-11 08:04:46 -04:00
|
|
|
" -w/--write-out [format] What to output after completion",
|
2003-10-30 04:15:47 -05:00
|
|
|
" -x/--proxy <host[:port]> Use HTTP proxy on given port",
|
2003-10-29 11:11:36 -05:00
|
|
|
" -X/--request <command> Specify request command to use",
|
2003-08-11 08:04:46 -04:00
|
|
|
" -y/--speed-time Time needed to trig speed-limit abort. Defaults to 30",
|
|
|
|
" -Y/--speed-limit Stop transfer if below speed-limit for 'speed-time' secs",
|
2003-10-29 11:11:36 -05:00
|
|
|
" -z/--time-cond <time> Transfer based on a time condition",
|
|
|
|
" -0/--http1.0 Use HTTP 1.0 (H)",
|
2003-10-30 04:15:47 -05:00
|
|
|
" -1/--tlsv1 Use TLSv1 (SSL)",
|
|
|
|
" -2/--sslv2 Use SSLv2 (SSL)",
|
|
|
|
" -3/--sslv3 Use SSLv3 (SSL)",
|
2005-01-21 04:32:32 -05:00
|
|
|
" --3p-quote like -Q for the source URL for 3rd party transfer (F)",
|
|
|
|
" --3p-url source URL to activate 3rd party transfer (F)",
|
|
|
|
" --3p-user user and password for source 3rd party transfer (F)",
|
2003-09-22 18:29:11 -04:00
|
|
|
" -4/--ipv4 Resolve name to IPv4 address",
|
|
|
|
" -6/--ipv6 Resolve name to IPv6 address",
|
2003-08-11 08:04:46 -04:00
|
|
|
" -#/--progress-bar Display transfer progress as a progress bar",
|
|
|
|
NULL
|
|
|
|
};
|
2004-03-17 07:46:42 -05:00
|
|
|
for(i=0; helptext[i]; i++) {
|
2004-01-29 08:48:36 -05:00
|
|
|
puts(helptext[i]);
|
2004-03-17 07:46:42 -05:00
|
|
|
#ifdef __NOVELL_LIBC__
|
|
|
|
if (i && ((i % 23) == 0))
|
|
|
|
pressanykey();
|
|
|
|
#endif
|
|
|
|
}
|
2002-12-03 07:41:10 -05:00
|
|
|
}
|
1999-12-29 09:20:26 -05:00
|
|
|
|
|
|
|
struct LongShort {
|
2001-08-14 05:16:46 -04:00
|
|
|
const char *letter;
|
|
|
|
const char *lname;
|
1999-12-29 09:20:26 -05:00
|
|
|
bool extraparam;
|
|
|
|
};
|
|
|
|
|
2003-06-26 07:33:29 -04:00
|
|
|
/* global variable to hold info about libcurl */
|
|
|
|
static curl_version_info_data *curlinfo;
|
|
|
|
|
2004-02-12 09:46:12 -05:00
|
|
|
static void parseconfig(const char *filename,
|
|
|
|
struct Configurable *config);
|
2000-02-10 18:03:08 -05:00
|
|
|
static char *my_get_line(FILE *fp);
|
2002-12-03 03:07:52 -05:00
|
|
|
static int create_dir_hierarchy(char *outfile);
|
1999-12-29 09:20:26 -05:00
|
|
|
|
|
|
|
static void GetStr(char **string,
|
2004-10-06 03:50:18 -04:00
|
|
|
char *value)
|
1999-12-29 09:20:26 -05:00
|
|
|
{
|
|
|
|
if(*string)
|
|
|
|
free(*string);
|
2002-08-05 07:15:57 -04:00
|
|
|
if(value)
|
2000-05-22 10:12:12 -04:00
|
|
|
*string = strdup(value);
|
|
|
|
else
|
|
|
|
*string = NULL;
|
1999-12-29 09:20:26 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static char *file2string(FILE *file)
|
|
|
|
{
|
|
|
|
char buffer[256];
|
|
|
|
char *ptr;
|
|
|
|
char *string=NULL;
|
2004-03-08 07:48:09 -05:00
|
|
|
size_t len=0;
|
|
|
|
size_t stringlen;
|
1999-12-29 09:20:26 -05:00
|
|
|
|
|
|
|
if(file) {
|
|
|
|
while(fgets(buffer, sizeof(buffer), file)) {
|
|
|
|
ptr= strchr(buffer, '\r');
|
|
|
|
if(ptr)
|
|
|
|
*ptr=0;
|
|
|
|
ptr= strchr(buffer, '\n');
|
|
|
|
if(ptr)
|
|
|
|
*ptr=0;
|
|
|
|
stringlen=strlen(buffer);
|
|
|
|
if(string)
|
|
|
|
string = realloc(string, len+stringlen+1);
|
|
|
|
else
|
|
|
|
string = malloc(stringlen+1);
|
|
|
|
|
|
|
|
strcpy(string+len, buffer);
|
|
|
|
|
|
|
|
len+=stringlen;
|
|
|
|
}
|
|
|
|
return string;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return NULL; /* no string */
|
|
|
|
}
|
|
|
|
|
2000-08-24 13:56:20 -04:00
|
|
|
static char *file2memory(FILE *file, long *size)
|
|
|
|
{
|
|
|
|
char buffer[1024];
|
|
|
|
char *string=NULL;
|
|
|
|
char *newstring=NULL;
|
2004-03-08 07:56:18 -05:00
|
|
|
size_t len=0;
|
2000-08-24 13:56:20 -04:00
|
|
|
long stringlen=0;
|
|
|
|
|
|
|
|
if(file) {
|
2000-11-21 04:38:41 -05:00
|
|
|
while((len = fread(buffer, 1, sizeof(buffer), file))) {
|
2000-08-24 13:56:20 -04:00
|
|
|
if(string) {
|
|
|
|
newstring = realloc(string, len+stringlen);
|
|
|
|
if(newstring)
|
|
|
|
string = newstring;
|
|
|
|
else
|
|
|
|
break; /* no more strings attached! :-) */
|
|
|
|
}
|
|
|
|
else
|
|
|
|
string = malloc(len);
|
|
|
|
memcpy(&string[stringlen], buffer, len);
|
|
|
|
stringlen+=len;
|
|
|
|
}
|
|
|
|
*size = stringlen;
|
|
|
|
return string;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return NULL; /* no string */
|
|
|
|
}
|
|
|
|
|
2004-01-29 08:48:36 -05:00
|
|
|
static void clean_getout(struct Configurable *config)
|
2001-01-08 10:02:58 -05:00
|
|
|
{
|
|
|
|
struct getout *node=config->url_list;
|
|
|
|
struct getout *next;
|
|
|
|
|
|
|
|
while(node) {
|
|
|
|
next = node->next;
|
|
|
|
if(node->url)
|
|
|
|
free(node->url);
|
|
|
|
if(node->outfile)
|
|
|
|
free(node->outfile);
|
2003-08-19 19:42:24 -04:00
|
|
|
if(node->infile)
|
|
|
|
free(node->infile);
|
2001-01-08 10:02:58 -05:00
|
|
|
free(node);
|
|
|
|
|
|
|
|
node = next; /* GOTO next */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-01-29 08:48:36 -05:00
|
|
|
static struct getout *new_getout(struct Configurable *config)
|
2001-01-08 02:37:44 -05:00
|
|
|
{
|
|
|
|
struct getout *node =malloc(sizeof(struct getout));
|
|
|
|
struct getout *last= config->url_last;
|
|
|
|
if(node) {
|
|
|
|
/* clear the struct */
|
|
|
|
memset(node, 0, sizeof(struct getout));
|
2004-05-24 09:31:28 -04:00
|
|
|
|
2001-01-08 02:37:44 -05:00
|
|
|
/* append this new node last in the list */
|
|
|
|
if(last)
|
|
|
|
last->next = node;
|
|
|
|
else
|
|
|
|
config->url_list = node; /* first node */
|
2004-05-24 09:31:28 -04:00
|
|
|
|
2001-01-08 02:37:44 -05:00
|
|
|
/* move the last pointer */
|
|
|
|
config->url_last = node;
|
|
|
|
}
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
|
2001-10-03 04:00:12 -04:00
|
|
|
/* Structure for storing the information needed to build a multiple files
|
|
|
|
* section
|
|
|
|
*/
|
|
|
|
struct multi_files {
|
|
|
|
struct curl_forms form;
|
|
|
|
struct multi_files *next;
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Add a new list entry possibly with a type_name
|
|
|
|
*/
|
2002-03-11 10:20:56 -05:00
|
|
|
static struct multi_files *
|
|
|
|
AddMultiFiles (const char *file_name,
|
|
|
|
const char *type_name,
|
|
|
|
const char *show_filename,
|
|
|
|
struct multi_files **multi_start,
|
|
|
|
struct multi_files **multi_current)
|
2001-10-03 04:00:12 -04:00
|
|
|
{
|
|
|
|
struct multi_files *multi;
|
|
|
|
struct multi_files *multi_type = NULL;
|
2002-03-11 10:20:56 -05:00
|
|
|
struct multi_files *multi_name = NULL;
|
2001-10-03 04:00:12 -04:00
|
|
|
multi = (struct multi_files *)malloc(sizeof(struct multi_files));
|
|
|
|
if (multi) {
|
|
|
|
memset(multi, 0, sizeof(struct multi_files));
|
|
|
|
multi->form.option = CURLFORM_FILE;
|
|
|
|
multi->form.value = file_name;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return NULL;
|
2002-03-11 10:20:56 -05:00
|
|
|
|
|
|
|
if (!*multi_start)
|
|
|
|
*multi_start = multi;
|
|
|
|
|
2001-10-03 04:00:12 -04:00
|
|
|
if (type_name) {
|
|
|
|
multi_type = (struct multi_files *)malloc(sizeof(struct multi_files));
|
|
|
|
if (multi_type) {
|
|
|
|
memset(multi_type, 0, sizeof(struct multi_files));
|
|
|
|
multi_type->form.option = CURLFORM_CONTENTTYPE;
|
|
|
|
multi_type->form.value = type_name;
|
|
|
|
multi->next = multi_type;
|
2002-03-11 10:20:56 -05:00
|
|
|
|
|
|
|
multi = multi_type;
|
2001-10-03 04:00:12 -04:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
free (multi);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
2002-03-11 10:20:56 -05:00
|
|
|
if (show_filename) {
|
|
|
|
multi_name = (struct multi_files *)malloc(sizeof(struct multi_files));
|
|
|
|
if (multi_name) {
|
|
|
|
memset(multi_name, 0, sizeof(struct multi_files));
|
|