cURL / Mailing Lists / curl-users / Single Mail

curl-users

DOS port of curl 7.10.5

From: Doug Kaufman <dkaufman_at_rahul.net>
Date: Fri, 4 Jul 2003 17:31:28 -0700 (PDT)

The following patch should allow compilation of a DOS port of curl,
using DJGPP and WATT-32. This was initially done independently of Gisle
Vanem's patch, and then incorporated some ideas from that patch. This
patch allows compilation through the configure script, rather than via
separate makefiles. I included code similar to that in my port of wget
to DOS that takes care of converting illegal filenames. Binary files
should be maintained properly, regardless of whether written directly
to a file or redirected from stdout. I chose to call the initialization
files curl.rc and net.rc as in the lynx port, rather than _curlrc as in
the wget port. This is easy to switch back (as in Gisle's patch) if the
consensus is that _curlrc is preferable. I also made --wdebug a separate
option for using the watt-32 debug code, rather than incorporating it in
the verbose option as in Gisle's patch.

I configured with the following script and put the cert-bundle in the
usual OpenSSL default location rather than in the usual curl default
location, so the file can be shared among the various programs built
with OpenSSL:

#!/bin/sh
CPPFLAGS="-I/dev/env/DJDIR/watt32/inc" \
CFLAGS="-O2 -W -Wall -I/dev/env/DJDIR/watt32/inc" \
LIBS="-L/dev/env/DJDIR/watt32/lib -lwatt" \
./configure \
--prefix="/dev/env/DJDIR" \
--with-ca-bundle="/dev/env/DJDIR/ssl/cert.pem" \
--with-ssl

A precompiled binary is available from my web site at
"http://www.rahul.net/dkaufman/index.html". This is in the United
States. An appropriate notification has been made to the US Bureau of
Industry and Security.
                        Doug

--- lib/share.c.ori 2003-02-06 11:28:16.000000000 -0800
+++ lib/share.c 2003-06-22 15:40:30.000000000 -0800
@@ -27,6 +27,9 @@
 #include <curl/curl.h>
 #include "urldata.h"
 #include "share.h"
+#ifdef __DJGPP__
+#include <string.h>
+#endif /* __DJGPP__ */
 
 /* The last #include file should be: */
 #ifdef MALLOCDEBUG
--- lib/hostip.c.ori 2003-05-13 04:12:16.000000000 -0800
+++ lib/hostip.c 2003-06-22 18:00:38.000000000 -0800
@@ -433,7 +433,7 @@
   char *newbuf;
   struct hostent* copy;
 
- int i;
+ int i=0;
   char *str;
   int len;
 
@@ -454,6 +454,8 @@
   
   copy->h_aliases = (char**)bufptr;
 
+if (orig->h_aliases)
+{
   /* Figure out how many aliases there are */
   for (i = 0; orig->h_aliases[i] != NULL; ++i);
 
@@ -469,6 +471,7 @@
   }
   /* Terminate the alias list with a NULL */
   copy->h_aliases[i] = NULL;
+}
 
   copy->h_addrtype = orig->h_addrtype;
   copy->h_length = orig->h_length;
--- lib/ftp.c.ori 2003-05-13 22:31:00.000000000 -0800
+++ lib/ftp.c 2003-06-24 23:39:32.000000000 -0800
@@ -2055,7 +2055,11 @@
       struct tm buffer;
       tm = (struct tm *)localtime_r(&data->info.filetime, &buffer);
 #else
+#ifdef __DJGPP__
+ tm = localtime((const time_t *)&data->info.filetime);
+#else
       tm = localtime((unsigned long *)&data->info.filetime);
+#endif /* __DJGPP__ */
 #endif
       /* format: "Tue, 15 Nov 1994 12:45:26 GMT" */
       strftime(buf, BUFSIZE-1, "Last-Modified: %a, %d %b %Y %H:%M:%S GMT\r\n",
--- lib/getpass.c.ori 2003-01-29 02:17:24.000000000 -0800
+++ lib/getpass.c 2003-06-22 18:29:08.000000000 -0800
@@ -99,7 +99,7 @@
   char infp_fclose = 0;
   FILE *outfp;
   RETSIGTYPE (*sigint)();
-#ifndef __EMX__
+#ifdef SIGTSTP
   RETSIGTYPE (*sigtstp)();
 #endif
   size_t bytes_read;
@@ -119,7 +119,7 @@
   sigint = signal(SIGINT, SIG_IGN);
   /* 20000318 mgs
    * this is needed by the emx system, SIGTSTP is not a supported signal */
-#ifndef __EMX__
+#ifdef SIGTSTP
   sigtstp = signal(SIGTSTP, SIG_IGN);
 #endif
 
@@ -181,7 +181,7 @@
 #endif
   
   signal(SIGINT, sigint);
-#ifndef __EMX__
+#ifdef SIGTSTP
   signal(SIGTSTP, sigtstp);
 #endif
 
--- lib/netrc.c.ori 2003-01-29 02:17:26.000000000 -0800
+++ lib/netrc.c 2003-06-25 19:46:34.000000000 -0800
@@ -88,7 +88,11 @@
   char state_password=0; /* Found a password keyword */
   char state_our_login=0; /* With specific_login, found *our* login name */
 
+#ifdef __DJGPP__
+#define NETRC "net.rc"
+#else
 #define NETRC DOT_CHAR "netrc"
+#endif /* __DJGPP__ */
 
 #if defined(HAVE_GETPWUID) && defined(HAVE_GETEUID)
   struct passwd *pw;
--- lib/setup.h.ori 2003-01-16 13:08:12.000000000 -0800
+++ lib/setup.h 2003-07-03 20:40:56.000000000 -0800
@@ -140,10 +140,23 @@
 #define DOT_CHAR "_"
 
 #else
+#ifdef DJGPP
+#define sclose(x) close_s(x)
+#define sread(x,y,z) read_s(x,y,z)
+#define swrite(x,y,z) write_s(x,y,z)
+#define select(n,r,w,x,t) select_s(n,r,w,x,t)
+#define ioctl(x,y,z) ioctlsocket(x,y,(char *)(z))
+#define IOCTL_3_ARGS
+#include <tcp.h>
+#ifdef word
+#undef word
+#endif
+#else
 #define sclose(x) close(x)
 #define sread(x,y,z) recv(x,y,z,0)
 #define swrite(x,y,z) send(x,y,z,0)
 #define HAVE_ALARM
+#endif
 
 #define PATH_CHAR ":"
 #define DIR_CHAR "/"
--- src/main.c.ori 2003-05-12 04:45:56.000000000 -0800
+++ src/main.c 2003-07-04 17:05:58.000000000 -0800
@@ -85,6 +85,21 @@
 
 #define DEFAULT_MAXREDIRS 50L
 
+#ifdef __DJGPP__
+void *xmalloc(size_t);
+char *msdosify(char *);
+char *rename_if_dos_device_name(char *);
+void xfree(void *);
+#include <limits.h>
+#include <fcntl.h>
+struct pollfd {
+ int fd;
+ int events; /* in param: what to poll for */
+ int revents; /* out param: what events occured */
+ };
+int poll (struct pollfd *, int, int);
+#endif /* __DJGPP__ */
+
 #ifndef __cplusplus /* (rabe) */
 #ifndef typedef_bool
 typedef char bool;
@@ -412,6 +427,9 @@
        " -U/--proxy-user <user[:password]> Specify Proxy authentication\n"
        " -v/--verbose Makes the operation more talkative\n"
        " -V/--version Outputs version number then quits");
+#ifdef __DJGPP__
+ puts(" --wdebug Turns on WATT-32 debugging under DJGPP");
+#endif /* __DJGPP__ */
   puts(" -w/--write-out [format] What to output after completion\n"
        " -x/--proxy <host[:port]> Use proxy. (Default port is 1080)\n"
        " --random-file <file> File to use for reading random data from (SSL)\n"
@@ -1034,6 +1052,9 @@
     {"5h", "trace-ascii", TRUE},
     {"5i", "limit-rate", TRUE},
     {"5j", "compressed", FALSE}, /* might take an arg someday */
+#ifdef __DJGPP__
+ {"5k", "wdebug", FALSE},
+#endif /* __DJGPP__ */
     {"0", "http1.0", FALSE},
     {"1", "tlsv1", FALSE},
     {"2", "sslv2", FALSE},
@@ -1258,6 +1279,12 @@
          config->encoding ^= TRUE;
          break;
 
+#ifdef __DJGPP__
+ case 'k': /* --wdebug */
+ dbug_init();
+ break;
+#endif /* __DJGPP__ */
+
       default: /* the URL! */
         {
           struct getout *url;
@@ -1779,7 +1806,11 @@
   if(!filename || !*filename) {
     /* NULL or no file name attempts to load .curlrc from the homedir! */
 
+#ifdef __DJGPP__
+#define CURLRC "curl.rc"
+#else
 #define CURLRC DOT_CHAR "curlrc"
+#endif /* __DJGPP__ */
 
     filename = CURLRC; /* sensible default */
     home = curl_getenv("HOME"); /* portable environment reader */
@@ -2579,6 +2610,9 @@
         (url = urls?next_url(urls):(i?NULL:strdup(url)));
         i++) {
       char *outfile;
+#if defined(__DJGPP__)
+ char *file1 = NULL;
+#endif /* __DJGPP__ */
       outfile = outfiles?strdup(outfiles):NULL;
  
       if((urlnode->flags&GETOUT_USEREMOTE) ||
@@ -2602,6 +2636,12 @@
             helpf("Remote file name has no length!\n");
             return CURLE_WRITE_ERROR;
           }
+#if defined(__DJGPP__)
+ file1=xmalloc(PATH_MAX);
+ strcpy(file1, msdosify(outfile));
+ strcpy(outfile, rename_if_dos_device_name(file1));
+ xfree(file1);
+#endif /* __DJGPP__ || __CYGWIN__ */
         }
         else if(urls) {
           /* fill '#1' ... '#9' terms from URL pattern */
@@ -2775,11 +2815,11 @@
       if(!config->errors)
         config->errors = stderr;
 
-#if defined(WIN32) && !defined(__CYGWIN32__)
+#ifdef O_BINARY
       if(!outfile && !(config->conf & CONF_GETTEXT)) {
         /* We get the output to stdout and we have not got the ASCII/text flag,
            then set stdout to be binary */
- setmode( 1, O_BINARY );
+ setmode( fileno(stdout), O_BINARY );
       }
 #endif
 
@@ -3207,3 +3247,132 @@
   return result; /* 0 is fine, -1 is badness */
 }
 
+#ifdef __DJGPP__
+/* The following functions are taken with modification from the DJGPP
+ * port of tar 1.12. They use algorithms originally from DJTAR. */
+
+char *
+msdosify (char *file_name)
+{
+ static char dos_name[PATH_MAX];
+ static char illegal_chars_dos[] = ".+, ;=[]|<>\\\":?*";
+ static char *illegal_chars_w95 = &illegal_chars_dos[8];
+ int idx, dot_idx;
+ char *s = file_name, *d = dos_name;
+ char *illegal_aliens = illegal_chars_dos;
+ size_t len = sizeof (illegal_chars_dos) - 1;
+ int lfn = 0;
+
+ /* Support for Windows 9X VFAT systems, when available. */
+ if (_use_lfn (file_name))
+ lfn = 1;
+ if (lfn)
+ {
+ illegal_aliens = illegal_chars_w95;
+ len -= (illegal_chars_w95 - illegal_chars_dos);
+ }
+
+ /* Get past the drive letter, if any. */
+ if (s[0] >= 'A' && s[0] <= 'z' && s[1] == ':')
+ {
+ *d++ = *s++;
+ *d++ = *s++;
+ }
+
+ for (idx = 0, dot_idx = -1; *s; s++, d++)
+ {
+ if (memchr (illegal_aliens, *s, len))
+ {
+ /* Dots are special: DOS doesn't allow them as the leading
+ character, and a file name cannot have more than a single dot.
+ We leave the first non-leading dot alone, unless it comes too
+ close to the beginning of the name: we want sh.lex.c to become
+ sh_lex.c, not sh.lex-c. */
+ if (*s == '.')
+ {
+ if (idx == 0 && (s[1] == '/' || (s[1] == '.' && s[2] == '/')))
+ {
+ /* Copy "./" and "../" verbatim. */
+ *d++ = *s++;
+ if (*s == '.')
+ *d++ = *s++;
+ *d = *s;
+ }
+ else if (idx == 0)
+ *d = '_';
+ else if (dot_idx >= 0)
+ {
+ if (dot_idx < 5) /* 5 is a heuristic ad-hoc'ery */
+ {
+ d[dot_idx - idx] = '_'; /* replace previous dot */
+ *d = '.';
+ }
+ else
+ *d = '-';
+ }
+ else
+ *d = '.';
+
+ if (*s == '.')
+ dot_idx = idx;
+ }
+ else if (*s == '+' && s[1] == '+')
+ {
+ if (idx - 2 == dot_idx) /* .c++, .h++ etc. */
+ {
+ *d++ = 'x';
+ *d = 'x';
+ }
+ else
+ {
+ /* libg++ etc. */
+ memcpy (d, "plus", 4);
+ d += 3;
+ }
+ s++;
+ idx++;
+ }
+ else
+ *d = '_';
+ }
+ else
+ *d = *s;
+ if (*s == '/')
+ {
+ idx = 0;
+ dot_idx = -1;
+ }
+ else
+ idx++;
+ }
+
+ *d = '\0';
+ return dos_name;
+}
+
+char *
+rename_if_dos_device_name (char *file_name)
+{
+ /* We could have a file whose name is a device on MS-DOS.
+ * Trying to retrieve such a file would fail at best and
+ * wedge us at worst. We need to rename such files. */
+ extern char *basename (const char *);
+ char *base;
+ struct stat st_buf;
+ char fname[PATH_MAX];
+
+ strcpy (fname, file_name);
+ base = basename (fname);
+ if (((stat(base, &st_buf)) == 0) && (S_ISCHR(st_buf.st_mode)))
+ {
+ size_t blen = strlen (base);
+
+ /* Prepend a '_'. */
+ memmove (base + 1, base, blen + 1);
+ base[0] = '_';
+ strcpy (file_name, fname);
+ }
+ return file_name;
+}
+
+#endif /* __DJGPP__ */
--- src/setup.h.ori 2003-04-15 06:05:26.000000000 -0800
+++ src/setup.h 2003-07-04 01:03:36.000000000 -0800
@@ -48,6 +48,13 @@
 #endif
 #endif
 
+#ifdef __DJGPP__
+#include <tcp.h>
+#ifdef word
+#undef word
+#endif
+#endif
+
 #ifdef MALLOCDEBUG
 /* This is an ugly hack for MALLOCDEBUG conditions only. We need to include
    the file here, since it might set the _FILE_OFFSET_BITS define, which must

-- 
Doug Kaufman
Internet: dkaufman_at_rahul.net
-------------------------------------------------------
This SF.Net email sponsored by: Free pre-built ASP.NET sites including
Data Reports, E-commerce, Portals, and Forums are available now.
Download today and enter to win an XBOX or Visual Studio .NET.
http://aspnet.click-url.com/go/psa00100006ave/direct;at.asp_061203_01/01
Received on 2003-07-05