3 * Copyright (c) 1992-2001 by Mike Gleason.
17 char gOurDirectoryPath
[260];
18 char gOurInstallationPath
[260];
20 static int gResolveSig
;
23 #if defined(WIN32) || defined(_WINDOWS)
24 #elif defined(HAVE_SIGSETJMP)
25 sigjmp_buf gGetHostByNameJmp
;
26 #else /* HAVE_SIGSETJMP */
27 jmp_buf gGetHostByNameJmp
;
28 #endif /* HAVE_SIGSETJMP */
31 void *memmove(void *dst0
, void *src0
, size_t length
);
34 static const unsigned char B64EncodeTable
[64] =
36 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
37 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
38 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
39 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
40 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
41 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
42 'w', 'x', 'y', 'z', '0', '1', '2', '3',
43 '4', '5', '6', '7', '8', '9', '+', '/'
46 static const unsigned char B64DecodeTable
[256] =
48 '\177', '\177', '\177', '\177', '\177', '\177', '\177', '\177', /* 000-007 */
49 '\177', '\177', '\177', '\177', '\177', '\177', '\177', '\177', /* 010-017 */
50 '\177', '\177', '\177', '\177', '\177', '\177', '\177', '\177', /* 020-027 */
51 '\177', '\177', '\177', '\177', '\177', '\177', '\177', '\177', /* 030-037 */
52 '\177', '\177', '\177', '\177', '\177', '\177', '\177', '\177', /* 040-047 */
53 '\177', '\177', '\177', '\76', '\177', '\177', '\177', '\77', /* 050-057 */
54 '\64', '\65', '\66', '\67', '\70', '\71', '\72', '\73', /* 060-067 */
55 '\74', '\75', '\177', '\177', '\177', '\100', '\177', '\177', /* 070-077 */
56 '\177', '\0', '\1', '\2', '\3', '\4', '\5', '\6', /* 100-107 */
57 '\7', '\10', '\11', '\12', '\13', '\14', '\15', '\16', /* 110-117 */
58 '\17', '\20', '\21', '\22', '\23', '\24', '\25', '\26', /* 120-127 */
59 '\27', '\30', '\31', '\177', '\177', '\177', '\177', '\177', /* 130-137 */
60 '\177', '\32', '\33', '\34', '\35', '\36', '\37', '\40', /* 140-147 */
61 '\41', '\42', '\43', '\44', '\45', '\46', '\47', '\50', /* 150-157 */
62 '\51', '\52', '\53', '\54', '\55', '\56', '\57', '\60', /* 160-167 */
63 '\61', '\62', '\63', '\177', '\177', '\177', '\177', '\177', /* 170-177 */
64 '\177', '\177', '\177', '\177', '\177', '\177', '\177', '\177', /* 200-207 */
65 '\177', '\177', '\177', '\177', '\177', '\177', '\177', '\177', /* 210-217 */
66 '\177', '\177', '\177', '\177', '\177', '\177', '\177', '\177', /* 220-227 */
67 '\177', '\177', '\177', '\177', '\177', '\177', '\177', '\177', /* 230-237 */
68 '\177', '\177', '\177', '\177', '\177', '\177', '\177', '\177', /* 240-247 */
69 '\177', '\177', '\177', '\177', '\177', '\177', '\177', '\177', /* 250-257 */
70 '\177', '\177', '\177', '\177', '\177', '\177', '\177', '\177', /* 260-267 */
71 '\177', '\177', '\177', '\177', '\177', '\177', '\177', '\177', /* 270-277 */
72 '\177', '\177', '\177', '\177', '\177', '\177', '\177', '\177', /* 300-307 */
73 '\177', '\177', '\177', '\177', '\177', '\177', '\177', '\177', /* 310-317 */
74 '\177', '\177', '\177', '\177', '\177', '\177', '\177', '\177', /* 320-327 */
75 '\177', '\177', '\177', '\177', '\177', '\177', '\177', '\177', /* 330-337 */
76 '\177', '\177', '\177', '\177', '\177', '\177', '\177', '\177', /* 340-347 */
77 '\177', '\177', '\177', '\177', '\177', '\177', '\177', '\177', /* 350-357 */
78 '\177', '\177', '\177', '\177', '\177', '\177', '\177', '\177', /* 360-367 */
79 '\177', '\177', '\177', '\177', '\177', '\177', '\177', '\177', /* 370-377 */
83 ToBase64(void *dst0
, const void *src0
, size_t n
, int terminate
)
86 const unsigned char *src
, *srclim
;
87 unsigned int c0
, c1
, c2
;
94 while (src
< srclim
) {
108 dst
[0] = B64EncodeTable
[ch
& 077];
110 ch
= ((c0
<< 4) & 060) | ((c1
>> 4) & 017);
111 dst
[1] = B64EncodeTable
[ch
& 077];
113 ch
= ((c1
<< 2) & 074) | ((c2
>> 6) & 03);
114 dst
[2] = B64EncodeTable
[ch
& 077];
117 dst
[3] = B64EncodeTable
[ch
& 077];
128 FromBase64(void *dst0
, const void *src0
, size_t n
, int terminate
)
131 const unsigned char *src
, *srclim
;
132 unsigned int c0
, c1
, c2
, c3
;
139 while (src
< srclim
) {
157 ch
= (((unsigned int) B64DecodeTable
[c0
]) << 2) | (((unsigned int) B64DecodeTable
[c1
]) >> 4);
158 dst
[0] = (unsigned char) ch
;
160 ch
= (((unsigned int) B64DecodeTable
[c1
]) << 4) | (((unsigned int) B64DecodeTable
[c2
]) >> 2);
161 dst
[1] = (unsigned char) ch
;
163 ch
= (((unsigned int) B64DecodeTable
[c2
]) << 6) | (((unsigned int) B64DecodeTable
[c3
]));
164 dst
[2] = (unsigned char) ch
;
172 /* This should only be called if the program wouldn't function
173 * usefully without the memory requested.
178 (void) fprintf(stderr
, "Out of memory!\n");
185 MyInetAddr(char *dst
, size_t siz
, char **src
, int i
)
188 #ifndef HAVE_INET_NTOP
192 (void) Strncpy(dst
, "???", siz
);
193 if (src
!= (char **) 0) {
194 ia
= (struct in_addr
*) src
[i
];
195 #ifdef HAVE_INET_NTOP /* Mostly to workaround bug in IRIX 6.5's inet_ntoa */
196 (void) inet_ntop(AF_INET
, ia
, dst
, siz
- 1);
199 if ((cp
!= (char *) 0) && (cp
!= (char *) -1) && (cp
[0] != '\0'))
200 (void) Strncpy(dst
, cp
, siz
);
208 /* On entry, you should have 'host' be set to a symbolic name (like
209 * cse.unl.edu), or set to a numeric address (like 129.93.3.1).
210 * If the function fails, it will return NULL, but if the host was
211 * a numeric style address, you'll have the ip_address to fall back on.
215 GetHostEntry(const char *host
, struct in_addr
*ip_address
)
220 /* See if the host was given in the dotted IP format, like "36.44.0.2."
221 * If it was, inet_addr will convert that to a 32-bit binary value;
222 * it not, inet_addr will return (-1L).
224 ip
.s_addr
= inet_addr(host
);
225 if (ip
.s_addr
!= INADDR_NONE
) {
226 hp
= gethostbyaddr((char *) &ip
, (int) sizeof(ip
), AF_INET
);
228 /* No IP address, so it must be a hostname, like ftp.wustl.edu. */
229 hp
= gethostbyname(host
);
231 ip
= * (struct in_addr
*) hp
->h_addr_list
;
233 if (ip_address
!= NULL
)
240 /* This simplifies a pathname, by converting it to the
241 * equivalent of "cd $dir ; dir=`pwd`". In other words,
242 * if $PWD==/usr/spool/uucp, and you had a path like
243 * "$PWD/../tmp////./../xx/", it would be converted to
247 CompressPath(char *const dst
, const char *const src
, const size_t dsize
)
254 if (src
[0] == '\0') {
261 lim
= d
+ dsize
- 1; /* leave room for nul byte. */
265 if (((s
== src
) || (s
[-1] == '/')) && ((s
[1] == '/') || (s
[1] == '\0'))) {
266 /* Don't copy "./" */
270 } else if (d
< lim
) {
275 } else if (c
== '/') {
276 /* Don't copy multiple slashes. */
284 /* Don't copy multiple slashes. */
286 } else if (c
== '.') {
291 } else if (c
== '\0') {
301 } else if (c
== '\0') {
302 /* Remove trailing slash. */
303 if ((d
[-1] == '/') && (d
> (dst
+ 1)))
307 } else if (d
< lim
) {
315 /* fprintf(stderr, "<%s>\n", dst); */
316 /* Go through and remove .. in the path when we know what the
317 * parent directory is. After we get done with this, the only
318 * .. nodes in the path will be at the front.
323 /* Get the next node in the path. */
332 if ((b
[0] == '.') && (b
[1] == '.')) {
334 /* We don't know what the parent of this
340 if ((a
[0] == '.') && (a
[1] == '.')) {
342 /* Remove the .. node and the one before it. */
343 if ((b
== dst
) && (*dst
== '/'))
344 (void) memmove(b
+ 1, a
+ 3, strlen(a
+ 3) + 1);
346 (void) memmove(b
, a
+ 3, strlen(a
+ 3) + 1);
347 a
= dst
; /* Start over. */
348 } else if (a
[2] == '\0') {
349 /* Remove a trailing .. like: /aaa/bbb/.. */
350 if ((b
<= dst
+ 1) && (*dst
== '/'))
354 a
= dst
; /* Start over. */
356 /* continue processing this node.
357 * It is probably some bogus path,
358 * like ".../", "..foo/", etc.
368 PathCat(char *const dst
, const size_t dsize
, const char *const cwd
, const char *const src
)
374 CompressPath(dst
, src
, dsize
);
377 cp
= Strnpcpy(tmp
, (char *) cwd
, sizeof(tmp
) - 1);
380 (void) Strnpcat(cp
, (char *) src
, sizeof(tmp
) - (cp
- tmp
));
381 CompressPath(dst
, tmp
, dsize
);
387 FileToURL(char *url
, size_t urlsize
, const char *const fn
, const char *const rcwd
, const char *const startdir
, const char *const user
, const char *const pass
, const char *const hname
, const unsigned int port
)
393 /* //<user>:<password>@<host>:<port>/<url-path> */
394 /* Note that if an absolute path is given,
395 * you need to escape the first entry, i.e. /pub -> %2Fpub
397 (void) Strncpy(url
, "ftp://", urlsize
);
399 if ((user
!= NULL
) && (user
[0] != '\0') && (strcmp(user
, "anonymous") != 0) && (strcmp(user
, "ftp") != 0)) {
401 (void) Strncat(url
, user
, urlsize
);
402 if ((pass
!= NULL
) && (pass
[0] != '\0')) {
403 (void) Strncat(url
, ":", urlsize
);
404 (void) Strncat(url
, "PASSWORD", urlsize
);
406 (void) Strncat(url
, "@", urlsize
);
408 (void) Strncat(url
, hname
, urlsize
);
409 if ((port
!= 21) && (port
!= 0)) {
410 (void) sprintf(pbuf
, ":%u", (unsigned int) port
);
411 (void) Strncat(url
, pbuf
, urlsize
);
416 dsize
= urlsize
- ulen
;
417 PathCat(dst
, dsize
, rcwd
, fn
);
418 if ((startdir
!= NULL
) && (startdir
[0] != '\0') && (startdir
[1] /* i.e. not "/" */ != '\0')) {
419 if (strncmp(dst
, startdir
, strlen(startdir
)) == 0) {
420 /* Form relative URL. */
421 memmove(dst
, dst
+ strlen(startdir
), strlen(dst
) - strlen(startdir
) + 1);
422 } else if (isUser
!= 0) {
423 /* Absolute URL, but different from start dir.
424 * Make sure to use %2f as first slash so that
425 * the translation uses "/pub" instead of "pub"
426 * since the / characters are just delimiters.
428 dst
[dsize
- 1] = '\0';
429 dst
[dsize
- 2] = '\0';
430 dst
[dsize
- 3] = '\0';
431 dst
[dsize
- 4] = '\0';
432 memmove(dst
+ 4, dst
+ 1, strlen(dst
+ 1));
446 /* This will abbreviate a string so that it fits into max characters.
447 * It will use ellipses as appropriate. Make sure the string has
448 * at least max + 1 characters allocated for it.
451 AbbrevStr(char *dst
, const char *src
, size_t max
, int mode
)
455 len
= (int) strlen(src
);
456 if (len
> (int) max
) {
458 /* ...Put ellipses at left */
459 (void) strcpy(dst
, "...");
460 (void) Strncat(dst
, (char *) src
+ len
- (int) max
+ 3, max
+ 1);
462 /* Put ellipses at right... */
463 (void) Strncpy(dst
, (char *) src
, max
+ 1);
464 (void) strcpy(dst
+ max
- 3, "...");
467 (void) Strncpy(dst
, (char *) src
, max
+ 1);
475 Path(char *const dst
, const size_t siz
, const char *const parent
, const char *const fname
)
477 (void) Strncpy(dst
, parent
, siz
);
478 (void) Strncat(dst
, LOCAL_PATH_DELIM_STR
, siz
);
479 return (Strncat(dst
, fname
, siz
));
486 OurDirectoryPath(char *const dst
, const size_t siz
, const char *const fname
)
488 return (Path(dst
, siz
, gOurDirectoryPath
, fname
));
489 } /* OurDirectoryPath */
494 OurInstallationPath(char *const dst
, const size_t siz
, const char *const fname
)
496 return (Path(dst
, siz
, gOurInstallationPath
, fname
));
497 } /* OurInstallationPath */
502 /* Create, if necessary, a directory in the user's home directory to
503 * put our incredibly important stuff in.
506 InitOurDirectory(void)
508 #if defined(WIN32) || defined(_WINDOWS)
509 DWORD dwType
, dwSize
;
514 ZeroMemory(gOurDirectoryPath
, (DWORD
) sizeof(gOurDirectoryPath
));
515 ZeroMemory(gOurInstallationPath
, (DWORD
) sizeof(gOurInstallationPath
));
519 "Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\ncftp.exe",
522 &hkey
) == ERROR_SUCCESS
)
524 dwSize
= (DWORD
) (sizeof(gOurInstallationPath
) - 1);
531 (LPBYTE
) gOurInstallationPath
,
532 &dwSize
) == ERROR_SUCCESS
)
534 // This gave us the path to ncftp.exe;
535 // But we use a subdirectory in that directory.
537 cp
= StrRFindLocalPathDelim(gOurInstallationPath
);
539 ZeroMemory(gOurInstallationPath
, (DWORD
) sizeof(gOurInstallationPath
));
541 ZeroMemory(cp
, (DWORD
) (cp
- gOurInstallationPath
));
546 if (gOurInstallationPath
[0] == '\0') {
547 if (GetModuleFileName(NULL
, gOurInstallationPath
, (DWORD
) sizeof(gOurInstallationPath
) - 1) <= 0) {
548 ZeroMemory(gOurInstallationPath
, (DWORD
) sizeof(gOurInstallationPath
));
550 // This gave us the path to the current .exe;
551 // But we use a subdirectory in that directory.
553 cp
= StrRFindLocalPathDelim(gOurInstallationPath
);
555 ZeroMemory(gOurInstallationPath
, (DWORD
) sizeof(gOurInstallationPath
));
557 ZeroMemory(cp
, (DWORD
) (cp
- gOurInstallationPath
));
561 if (gOurInstallationPath
[0] != '\0') {
562 if ((cp
= getenv("NCFTPDIR")) != NULL
) {
565 (void) STRNCPY(gOurDirectoryPath
, cp
);
566 cp
= strrchr(gOurDirectoryPath
, '"');
567 if ((cp
!= NULL
) && (cp
[1] == '\0'))
569 } else if ((cp
= getenv("HOME")) != NULL
) {
572 (void) STRNCPY(gOurDirectoryPath
, cp
);
573 cp
= strrchr(gOurDirectoryPath
, '"');
574 if ((cp
!= NULL
) && (cp
[1] == '\0'))
577 STRNCPY(gOurDirectoryPath
, gOurInstallationPath
);
578 if (gUser
[0] == '\0') {
579 STRNCAT(gOurDirectoryPath
, "\\Users\\default");
581 STRNCAT(gOurDirectoryPath
, "\\Users\\");
582 STRNCAT(gOurDirectoryPath
, gUser
);
585 rc
= MkDirs(gOurDirectoryPath
, 00755);
593 (void) STRNCPY(gOurInstallationPath
, BINDIR
);
595 memset(gOurInstallationPath
, 0, sizeof(gOurInstallationPath
));
598 cp
= getenv("NCFTPDIR");
600 (void) STRNCPY(gOurDirectoryPath
, cp
);
601 } else if (STREQ(gHome
, "/")) {
602 /* Don't create it if you're root and your home directory
603 * is the root directory.
605 * If you are root and you want to store your ncftp
606 * config files, move your home directory somewhere else,
607 * such as /root or /home/root.
609 gOurDirectoryPath
[0] = '\0';
612 (void) Path(gOurDirectoryPath
,
613 sizeof(gOurDirectoryPath
),
619 if (stat(gOurDirectoryPath
, &st
) < 0) {
620 if (mkdir(gOurDirectoryPath
, 00755) < 0) {
621 gOurDirectoryPath
[0] = '\0';
625 } /* InitOurDirectory */
632 #if defined(WIN32) || defined(_WINDOWS)
636 memset(gUser
, 0, sizeof(gUser
));
637 nSize
= sizeof(gUser
) - 1;
638 if (! GetUserName(gUser
, &nSize
))
639 STRNCPY(gUser
, "default");
641 memset(gHome
, 0, sizeof(gHome
));
642 (void) GetTempPath((DWORD
) sizeof(gHome
) - 1, gHome
);
643 cp
= strrchr(gHome
, '\\');
644 if ((cp
!= NULL
) && (cp
[1] == '\0'))
647 memset(gShell
, 0, sizeof(gShell
));
649 struct passwd
*pwptr
;
653 pwptr
= getpwuid(gUid
);
656 envp
= getenv("LOGNAME");
658 (void) fprintf(stderr
, "Who are you?\n");
659 (void) fprintf(stderr
, "You have a user id number of %d, but no username associated with it.\n", (int) gUid
);
660 (void) STRNCPY(gUser
, "unknown");
662 (void) STRNCPY(gUser
, envp
);
665 envp
= getenv("HOME");
667 (void) STRNCPY(gHome
, "/");
669 (void) STRNCPY(gHome
, envp
);
671 envp
= getenv("SHELL");
673 (void) STRNCPY(gShell
, "/bin/sh");
675 (void) STRNCPY(gShell
, envp
);
677 /* Copy home directory. */
678 (void) STRNCPY(gHome
, pwptr
->pw_dir
);
680 /* Copy user name. */
681 (void) STRNCPY(gUser
, pwptr
->pw_name
);
684 (void) STRNCPY(gShell
, pwptr
->pw_shell
);
695 MayUseFirewall(const char *const hn
, int firewallType
, const char *const firewallExceptionList
)
701 #endif /* HAVE_STRSTR */
703 if (firewallType
== kFirewallNotInUse
)
706 if (firewallExceptionList
[0] == '\0') {
707 if (strchr(hn
, '.') == NULL
) {
708 /* Unqualified host name,
709 * assume it is in local domain.
717 if (strchr(hn
, '.') == NULL
) {
718 /* Unqualified host name,
719 * assume it is in local domain.
721 * If "localdomain" is in the exception list,
722 * do not use the firewall for this host.
724 (void) STRNCPY(buf
, firewallExceptionList
);
725 for (parse
= buf
; (tok
= strtok(parse
, ", \n\t\r")) != NULL
; parse
= NULL
) {
726 if (strcmp(tok
, "localdomain") == 0)
733 (void) STRNCPY(buf
, firewallExceptionList
);
734 for (parse
= buf
; (tok
= strtok(parse
, ", \n\t\r")) != NULL
; parse
= NULL
) {
735 /* See if host or domain was from exclusion list
736 * matches the host to open.
738 if (strstr(hn
, tok
) != NULL
)
741 #endif /* HAVE_STRSTR */
743 } /* MayUseFirewall */
748 StrToBool(const char *const s
)
758 case 'f': /* false */
762 case 'o': /* test for "off" and "on" */
774 default: /* 1, 0, -1, other number? */
785 AbsoluteToRelative(char *const dst
, const size_t dsize
, const char *const dir
, const char *const root
, const size_t rootlen
)
788 if (strcmp(dir
, root
) != 0) {
789 if (strcmp(root
, "/") == 0) {
790 (void) Strncpy(dst
, dir
+ 1, dsize
);
791 } else if ((strncmp(root
, dir
, rootlen
) == 0) && (dir
[rootlen
] == '/')) {
792 (void) Strncpy(dst
, dir
+ rootlen
+ 1, dsize
);
794 /* Still absolute. */
795 (void) Strncpy(dst
, dir
, dsize
);
798 } /* AbsoluteToRelative */
803 #if defined(WIN32) || defined(_WINDOWS)
806 /* Some commands may want to jump back to the start too. */
808 CancelGetHostByName(int sigNum
)
811 gResolveSig
= sigNum
;
813 #ifdef HAVE_SIGSETJMP
814 siglongjmp(gGetHostByNameJmp
, (sigNum
!= 0) ? 1 : 0);
815 #else /* HAVE_SIGSETJMP */
816 longjmp(gGetHostByNameJmp
, (sigNum
!= 0) ? 1 : 0);
817 #endif /* HAVE_SIGSETJMP */
818 } /* CancelGetHostByName */
826 GetHostByName(char *const volatile dst
, size_t dsize
, const char *const hn
, int t
)
828 #if defined(WIN32) || defined(_WINDOWS)
832 if (inet_addr(hn
) != (unsigned long) 0xFFFFFFFF) {
833 /* Address is an IP address string, which is what we want. */
834 (void) Strncpy(dst
, hn
, dsize
);
838 hp
= gethostbyname(hn
);
840 (void) memcpy(&ina
.s_addr
, hp
->h_addr_list
[0], (size_t) hp
->h_length
);
841 (void) Strncpy(dst
, inet_ntoa(ina
), dsize
);
847 vsigproc_t osigpipe
, osigint
, osigalrm
;
849 #ifndef HAVE_INET_NTOP
853 #ifdef HAVE_INET_ATON
854 if (inet_aton(hn
, &ina
) != 0) {
855 /* Address is an IP address string, which is what we want. */
856 (void) Strncpy(dst
, hn
, dsize
);
860 if (inet_addr(hn
) != (unsigned long) 0xFFFFFFFF) {
861 /* Address is an IP address string, which is what we want. */
862 (void) Strncpy(dst
, hn
, dsize
);
867 #ifdef HAVE_SIGSETJMP
868 osigpipe
= osigint
= osigalrm
= (sigproc_t
) 0;
869 sj
= sigsetjmp(gGetHostByNameJmp
, 1);
870 #else /* HAVE_SIGSETJMP */
871 osigpipe
= osigint
= osigalrm
= (sigproc_t
) 0;
872 sj
= setjmp(gGetHostByNameJmp
);
873 #endif /* HAVE_SIGSETJMP */
876 /* Caught a signal. */
878 (void) NcSignal(SIGPIPE
, osigpipe
);
879 (void) NcSignal(SIGINT
, osigint
);
880 (void) NcSignal(SIGALRM
, osigalrm
);
882 Trace(0, "Canceled GetHostByName because of signal %d.\n", gResolveSig
);
885 osigpipe
= NcSignal(SIGPIPE
, CancelGetHostByName
);
886 osigint
= NcSignal(SIGINT
, CancelGetHostByName
);
887 osigalrm
= NcSignal(SIGALRM
, CancelGetHostByName
);
889 (void) alarm((unsigned int) t
);
890 hp
= gethostbyname(hn
);
893 (void) NcSignal(SIGPIPE
, osigpipe
);
894 (void) NcSignal(SIGINT
, osigint
);
895 (void) NcSignal(SIGALRM
, osigalrm
);
897 #ifdef HAVE_INET_NTOP /* Mostly to workaround bug in IRIX 6.5's inet_ntoa */
898 (void) memset(dst
, 0, dsize
);
899 (void) inet_ntop(AF_INET
, hp
->h_addr_list
[0], dst
, dsize
- 1);
901 (void) memcpy(&ina
.s_addr
, hp
->h_addr_list
[0], (size_t) hp
->h_length
);
902 (void) Strncpy(dst
, inet_ntoa(ina
), dsize
);
907 #endif /* !Windows */
911 } /* GetHostByName */
916 /* Converts a date string, like "19930602204445" into to a time_t. */
917 time_t UnDate(char *dstr
)
920 return ((time_t) -1);
924 time_t result
= (time_t) -1;
929 /* Copy the whole structure of the 'tm' pointed to by t, so it will
930 * also set all fields we don't specify explicitly to be the same as
931 * they were in t. That way we copy non-standard fields such as
932 * tm_gmtoff, if it exists or not.
936 /* The time we get back from the server is (should be) in UTC. */
937 if (sscanf(dstr
, "%04d%02d%02d%02d%02d%02d",
947 result
= mktime(&ut
);
950 #endif /* HAVE_MKTIME */
957 /* This code is derived from software contributed to Berkeley by
962 * sizeof(word) MUST BE A POWER OF TWO
963 * SO THAT wmask BELOW IS ALL ONES
965 typedef int word
; /* "word" used for optimal copy speed */
967 #define wsize sizeof(word)
968 #define wmask (wsize - 1)
971 * Copy a block of memory, handling overlap.
972 * This is the routine that actually implements
973 * (the portable versions of) bcopy, memcpy, and memmove.
976 memmove(void *dst0
, void *src0
, size_t length
)
978 register char *dst
= (char *) dst0
;
979 register const char *src
= (char *) src0
;
982 if (length
== 0 || dst
== src
) /* nothing to do */
986 * Macros: loop-t-times; and loop-t-times, t>0
988 #define TLOOP(s) if (t) TLOOP1(s)
989 #define TLOOP1(s) do { s; } while (--t)
991 if ((unsigned long)dst
< (unsigned long)src
) {
995 t
= (int)src
; /* only need low bits */
996 if ((t
| (int)dst
) & wmask
) {
998 * Try to align operands. This cannot be done
999 * unless the low bits match.
1001 if ((t
^ (int)dst
) & wmask
|| length
< wsize
)
1004 t
= wsize
- (t
& wmask
);
1006 TLOOP1(*dst
++ = *src
++);
1009 * Copy whole words, then mop up any trailing bytes.
1012 TLOOP(*(word
*)dst
= *(word
*)src
; src
+= wsize
; dst
+= wsize
);
1014 TLOOP(*dst
++ = *src
++);
1017 * Copy backwards. Otherwise essentially the same.
1018 * Alignment works as before, except that it takes
1019 * (t&wmask) bytes to align, not wsize-(t&wmask).
1024 if ((t
| (int)dst
) & wmask
) {
1025 if ((t
^ (int)dst
) & wmask
|| length
<= wsize
)
1030 TLOOP1(*--dst
= *--src
);
1033 TLOOP(src
-= wsize
; dst
-= wsize
; *(word
*)dst
= *(word
*)src
);
1035 TLOOP(*--dst
= *--src
);
1040 #endif /* ! HAVE_MEMMOVE */
1045 #if defined(HAVE_STRCOLL) && !defined(HAVE_STRNCOLL)
1047 strncoll(const char *a
, const char *b
, size_t n
)
1052 char sa
[512], sb
[512];
1054 memset(sa
, 0, sizeof(sa
));
1055 memset(sb
, 0, sizeof(sb
));
1056 (void) strncpy(sa
, a
, n
);
1057 (void) strncpy(sb
, b
, n
);
1058 rc
= (strcoll(sa
, sb
));
1063 n
+= 5; /* enough for a 32-bit zero char. */
1064 ma
= (char *) malloc(n
);
1066 return (0); /* panic */
1067 mb
= (char *) malloc(n
);
1070 return (0); /* panic */
1072 (void) strncpy(ma
, a
, n
);
1073 (void) strncpy(mb
, b
, n
);
1074 rc
= (strcoll(ma
, mb
));
1087 const FTPCIPtr cip
, /* area pointed to may be modified */
1088 char *url
, /* always modified */
1089 LineListPtr cdlist
, /* always modified */
1090 char *fn
, /* always modified */
1098 /* Add a trailing slash, if needed, i.e., convert
1099 * "ftp://ftp.gnu.org/pub/gnu" to
1100 * "ftp://ftp.gnu.org/pub/gnu/"
1102 * We also generalize and assume that if the user specified
1103 * something with a .extension that the user was intending
1104 * to specify a file instead of a directory.
1106 cp
= strrchr(url
, '/');
1107 if ((cp
!= NULL
) && (cp
[1] != '\0') && (strchr(cp
, '.') == NULL
)) {
1109 (void) STRNCPY(urlstr2
, url
);
1110 (void) STRNCAT(urlstr2
, "/");
1113 rc
= FTPDecodeURL(cip
, url
, cdlist
, fn
, fnsize
, NULL
, NULL
);
1115 } /* DecodeDirectoryURL */
1120 #if defined(WIN32) || defined(_WINDOWS)
1121 void SysPerror(const char *const errMsg
)
1126 FORMAT_MESSAGE_FROM_SYSTEM
,
1129 MAKELANGID(LANG_NEUTRAL
, SUBLANG_DEFAULT
),
1131 (DWORD
) sizeof(reason
),
1135 if (reason
[strlen(reason
) - 1] = '\n')
1136 reason
[strlen(reason
) - 1] = '\0';
1137 (void) fprintf(stderr
, "%s: %s\n", errMsg
, reason
);