1998-12-29 17:27:59 +03:00
|
|
|
/* $NetBSD: util.c,v 1.37 1998/12/29 14:27:59 lukem Exp $ */
|
1998-07-10 08:39:03 +04:00
|
|
|
|
|
|
|
/*-
|
|
|
|
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* This code is derived from software contributed to The NetBSD Foundation
|
|
|
|
* by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
|
|
|
|
* NASA Ames Research Center.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
* 3. All advertising materials mentioning features or use of this software
|
|
|
|
* must display the following acknowledgement:
|
|
|
|
* This product includes software developed by the NetBSD
|
|
|
|
* Foundation, Inc. and its contributors.
|
|
|
|
* 4. Neither the name of The NetBSD Foundation nor the names of its
|
|
|
|
* contributors may be used to endorse or promote products derived
|
|
|
|
* from this software without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
|
|
|
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
|
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
|
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
|
|
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
1997-01-19 17:19:02 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Copyright (c) 1985, 1989, 1993, 1994
|
|
|
|
* The Regents of the University of California. All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
* 3. All advertising materials mentioning features or use of this software
|
|
|
|
* must display the following acknowledgement:
|
|
|
|
* This product includes software developed by the University of
|
|
|
|
* California, Berkeley and its contributors.
|
|
|
|
* 4. Neither the name of the University nor the names of its contributors
|
|
|
|
* may be used to endorse or promote products derived from this software
|
|
|
|
* without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
|
|
* SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
1997-07-20 13:45:35 +04:00
|
|
|
#include <sys/cdefs.h>
|
1997-01-19 17:19:02 +03:00
|
|
|
#ifndef lint
|
1998-12-29 17:27:59 +03:00
|
|
|
__RCSID("$NetBSD: util.c,v 1.37 1998/12/29 14:27:59 lukem Exp $");
|
1997-01-19 17:19:02 +03:00
|
|
|
#endif /* not lint */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* FTP User Program -- Misc support routines
|
|
|
|
*/
|
1998-07-10 08:39:03 +04:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/socket.h>
|
1997-01-19 17:19:02 +03:00
|
|
|
#include <sys/ioctl.h>
|
|
|
|
#include <sys/time.h>
|
|
|
|
#include <arpa/ftp.h>
|
|
|
|
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <err.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <glob.h>
|
1998-05-20 04:55:52 +04:00
|
|
|
#include <termios.h>
|
|
|
|
#include <signal.h>
|
1997-07-20 13:45:35 +04:00
|
|
|
#include <limits.h>
|
1997-04-14 13:09:15 +04:00
|
|
|
#include <pwd.h>
|
1997-01-19 17:19:02 +03:00
|
|
|
#include <stdio.h>
|
1997-07-20 13:45:35 +04:00
|
|
|
#include <stdlib.h>
|
1997-01-19 17:19:02 +03:00
|
|
|
#include <string.h>
|
|
|
|
#include <time.h>
|
1997-11-01 17:36:49 +03:00
|
|
|
#include <tzfile.h>
|
1997-01-19 17:19:02 +03:00
|
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
#include "ftp_var.h"
|
|
|
|
#include "pathnames.h"
|
|
|
|
|
1998-11-18 10:24:25 +03:00
|
|
|
#ifndef HAVE_TIMEGM
|
|
|
|
static time_t sub_mkgmt __P((struct tm *tm));
|
|
|
|
#endif
|
|
|
|
|
1997-01-19 17:19:02 +03:00
|
|
|
/*
|
|
|
|
* Connect to peer server and
|
|
|
|
* auto-login, if possible.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
setpeer(argc, argv)
|
|
|
|
int argc;
|
|
|
|
char *argv[];
|
|
|
|
{
|
|
|
|
char *host;
|
1998-01-18 17:23:33 +03:00
|
|
|
in_port_t port;
|
1997-01-19 17:19:02 +03:00
|
|
|
|
|
|
|
if (connected) {
|
1998-06-04 12:28:35 +04:00
|
|
|
fprintf(ttyout, "Already connected to %s, use close first.\n",
|
1997-03-13 09:23:11 +03:00
|
|
|
hostname);
|
1997-01-19 17:19:02 +03:00
|
|
|
code = -1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (argc < 2)
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)another(&argc, &argv, "to");
|
1997-01-19 17:19:02 +03:00
|
|
|
if (argc < 2 || argc > 3) {
|
1998-06-04 12:28:35 +04:00
|
|
|
fprintf(ttyout, "usage: %s host-name [port]\n", argv[0]);
|
1997-01-19 17:19:02 +03:00
|
|
|
code = -1;
|
|
|
|
return;
|
|
|
|
}
|
1997-08-18 14:20:13 +04:00
|
|
|
if (gatemode)
|
|
|
|
port = gateport;
|
|
|
|
else
|
|
|
|
port = ftpport;
|
1997-01-19 17:19:02 +03:00
|
|
|
if (argc > 2) {
|
1997-07-20 13:45:35 +04:00
|
|
|
char *ep;
|
|
|
|
long nport;
|
|
|
|
|
|
|
|
nport = strtol(argv[2], &ep, 10);
|
1998-01-19 01:09:39 +03:00
|
|
|
if (nport < 1 || nport > MAX_IN_PORT_T || *ep != '\0') {
|
1998-06-04 12:28:35 +04:00
|
|
|
fprintf(ttyout, "%s: bad port number '%s'.\n",
|
|
|
|
argv[1], argv[2]);
|
|
|
|
fprintf(ttyout, "usage: %s host-name [port]\n",
|
|
|
|
argv[0]);
|
1997-01-19 17:19:02 +03:00
|
|
|
code = -1;
|
|
|
|
return;
|
|
|
|
}
|
1998-01-18 17:23:33 +03:00
|
|
|
port = htons((in_port_t)nport);
|
1997-01-19 17:19:02 +03:00
|
|
|
}
|
1997-08-18 14:20:13 +04:00
|
|
|
|
|
|
|
if (gatemode) {
|
|
|
|
if (gateserver == NULL || *gateserver == '\0')
|
|
|
|
errx(1, "gateserver not defined (shouldn't happen)");
|
|
|
|
host = hookup(gateserver, port);
|
|
|
|
} else
|
|
|
|
host = hookup(argv[1], port);
|
|
|
|
|
1997-01-19 17:19:02 +03:00
|
|
|
if (host) {
|
|
|
|
int overbose;
|
|
|
|
|
1997-08-18 14:20:13 +04:00
|
|
|
if (gatemode) {
|
|
|
|
if (command("PASSERVE %s", argv[1]) != COMPLETE)
|
|
|
|
return;
|
|
|
|
if (verbose)
|
1998-06-04 12:28:35 +04:00
|
|
|
fprintf(ttyout,
|
|
|
|
"Connected via pass-through server %s\n",
|
1997-08-18 14:20:13 +04:00
|
|
|
gateserver);
|
|
|
|
}
|
|
|
|
|
1997-01-19 17:19:02 +03:00
|
|
|
connected = 1;
|
|
|
|
/*
|
|
|
|
* Set up defaults for FTP.
|
|
|
|
*/
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)strcpy(typename, "ascii"), type = TYPE_A;
|
1997-01-19 17:19:02 +03:00
|
|
|
curtype = TYPE_A;
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)strcpy(formname, "non-print"), form = FORM_N;
|
|
|
|
(void)strcpy(modename, "stream"), mode = MODE_S;
|
|
|
|
(void)strcpy(structname, "file"), stru = STRU_F;
|
|
|
|
(void)strcpy(bytename, "8"), bytesize = 8;
|
1997-01-19 17:19:02 +03:00
|
|
|
if (autologin)
|
1998-07-22 20:06:27 +04:00
|
|
|
(void)ftp_login(argv[1], NULL, NULL);
|
1997-01-19 17:19:02 +03:00
|
|
|
|
|
|
|
overbose = verbose;
|
|
|
|
if (debug == 0)
|
|
|
|
verbose = -1;
|
|
|
|
if (command("SYST") == COMPLETE && overbose) {
|
|
|
|
char *cp, c;
|
|
|
|
c = 0;
|
1998-06-04 12:28:35 +04:00
|
|
|
cp = strchr(reply_string + 4, ' ');
|
1997-01-19 17:19:02 +03:00
|
|
|
if (cp == NULL)
|
1998-06-04 12:28:35 +04:00
|
|
|
cp = strchr(reply_string + 4, '\r');
|
1997-01-19 17:19:02 +03:00
|
|
|
if (cp) {
|
|
|
|
if (cp[-1] == '.')
|
|
|
|
cp--;
|
|
|
|
c = *cp;
|
|
|
|
*cp = '\0';
|
|
|
|
}
|
|
|
|
|
1998-06-04 12:28:35 +04:00
|
|
|
fprintf(ttyout, "Remote system type is %s.\n",
|
|
|
|
reply_string + 4);
|
1997-01-19 17:19:02 +03:00
|
|
|
if (cp)
|
|
|
|
*cp = c;
|
|
|
|
}
|
|
|
|
if (!strncmp(reply_string, "215 UNIX Type: L8", 17)) {
|
|
|
|
if (proxy)
|
|
|
|
unix_proxy = 1;
|
|
|
|
else
|
|
|
|
unix_server = 1;
|
|
|
|
/*
|
|
|
|
* Set type to 0 (not specified by user),
|
|
|
|
* meaning binary by default, but don't bother
|
|
|
|
* telling server. We can use binary
|
|
|
|
* for text files unless changed by the user.
|
|
|
|
*/
|
|
|
|
type = 0;
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)strcpy(typename, "binary");
|
1997-01-19 17:19:02 +03:00
|
|
|
if (overbose)
|
1998-06-04 12:28:35 +04:00
|
|
|
fprintf(ttyout,
|
|
|
|
"Using %s mode to transfer files.\n",
|
1997-01-19 17:19:02 +03:00
|
|
|
typename);
|
|
|
|
} else {
|
|
|
|
if (proxy)
|
|
|
|
unix_proxy = 0;
|
|
|
|
else
|
|
|
|
unix_server = 0;
|
|
|
|
if (overbose &&
|
|
|
|
!strncmp(reply_string, "215 TOPS20", 10))
|
1998-06-04 12:28:35 +04:00
|
|
|
fputs(
|
|
|
|
"Remember to set tenex mode when transferring binary files from this machine.\n",
|
|
|
|
ttyout);
|
1997-01-19 17:19:02 +03:00
|
|
|
}
|
|
|
|
verbose = overbose;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1997-04-14 13:09:15 +04:00
|
|
|
/*
|
|
|
|
* login to remote host, using given username & password if supplied
|
|
|
|
*/
|
|
|
|
int
|
1998-07-22 20:06:27 +04:00
|
|
|
ftp_login(host, user, pass)
|
1997-04-14 13:09:15 +04:00
|
|
|
const char *host;
|
1998-07-27 01:47:47 +04:00
|
|
|
const char *user, *pass;
|
1997-04-14 13:09:15 +04:00
|
|
|
{
|
|
|
|
char tmp[80];
|
1998-07-27 01:47:47 +04:00
|
|
|
const char *acct;
|
1998-08-03 05:49:25 +04:00
|
|
|
char anonpass[MAXLOGNAME + 2]; /* "user@" */
|
1997-09-21 05:06:30 +04:00
|
|
|
struct passwd *pw;
|
1997-04-14 13:09:15 +04:00
|
|
|
int n, aflag = 0;
|
|
|
|
|
|
|
|
acct = NULL;
|
|
|
|
if (user == NULL) {
|
|
|
|
if (ruserpass(host, &user, &pass, &acct) < 0) {
|
|
|
|
code = -1;
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set up arguments for an anonymous FTP session, if necessary.
|
|
|
|
*/
|
|
|
|
if ((user == NULL || pass == NULL) && anonftp) {
|
|
|
|
memset(anonpass, 0, sizeof(anonpass));
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set up anonymous login password.
|
|
|
|
*/
|
1998-08-03 05:49:25 +04:00
|
|
|
if ((pass = getenv("FTPANONPASS")) == NULL) {
|
|
|
|
if ((pass = getlogin()) == NULL) {
|
|
|
|
if ((pw = getpwuid(getuid())) == NULL)
|
|
|
|
pass = "anonymous";
|
|
|
|
else
|
|
|
|
pass = pw->pw_name;
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* Every anonymous FTP server I've encountered
|
|
|
|
* will accept the string "username@", and will
|
|
|
|
* append the hostname itself. We do this by default
|
|
|
|
* since many servers are picky about not having
|
|
|
|
* a FQDN in the anonymous password.
|
|
|
|
* - thorpej@netbsd.org
|
|
|
|
*/
|
|
|
|
snprintf(anonpass, sizeof(anonpass) - 1, "%s@", pass);
|
|
|
|
pass = anonpass;
|
1997-09-21 05:06:30 +04:00
|
|
|
}
|
1997-06-11 01:59:58 +04:00
|
|
|
user = "anonymous"; /* as per RFC 1635 */
|
1997-04-14 13:09:15 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
while (user == NULL) {
|
1998-07-27 01:47:47 +04:00
|
|
|
const char *myname = getlogin();
|
1997-04-14 13:09:15 +04:00
|
|
|
|
1997-09-21 05:06:30 +04:00
|
|
|
if (myname == NULL && (pw = getpwuid(getuid())) != NULL)
|
|
|
|
myname = pw->pw_name;
|
1997-04-14 13:09:15 +04:00
|
|
|
if (myname)
|
1998-06-04 12:28:35 +04:00
|
|
|
fprintf(ttyout, "Name (%s:%s): ", host, myname);
|
1997-04-14 13:09:15 +04:00
|
|
|
else
|
1998-06-04 12:28:35 +04:00
|
|
|
fprintf(ttyout, "Name (%s): ", host);
|
1998-01-18 17:23:33 +03:00
|
|
|
*tmp = '\0';
|
1997-04-14 13:09:15 +04:00
|
|
|
(void)fgets(tmp, sizeof(tmp) - 1, stdin);
|
|
|
|
tmp[strlen(tmp) - 1] = '\0';
|
|
|
|
if (*tmp == '\0')
|
|
|
|
user = myname;
|
|
|
|
else
|
|
|
|
user = tmp;
|
|
|
|
}
|
|
|
|
n = command("USER %s", user);
|
|
|
|
if (n == CONTINUE) {
|
|
|
|
if (pass == NULL)
|
|
|
|
pass = getpass("Password:");
|
|
|
|
n = command("PASS %s", pass);
|
|
|
|
}
|
|
|
|
if (n == CONTINUE) {
|
|
|
|
aflag++;
|
|
|
|
if (acct == NULL)
|
|
|
|
acct = getpass("Account:");
|
|
|
|
n = command("ACCT %s", acct);
|
|
|
|
}
|
|
|
|
if ((n != COMPLETE) ||
|
|
|
|
(!aflag && acct != NULL && command("ACCT %s", acct) != COMPLETE)) {
|
|
|
|
warnx("Login failed.");
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
if (proxy)
|
|
|
|
return (1);
|
|
|
|
connected = -1;
|
|
|
|
for (n = 0; n < macnum; ++n) {
|
|
|
|
if (!strcmp("init", macros[n].mac_name)) {
|
|
|
|
(void)strcpy(line, "$init");
|
|
|
|
makeargv();
|
|
|
|
domacro(margc, margv);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return (1);
|
|
|
|
}
|
|
|
|
|
1997-01-19 17:19:02 +03:00
|
|
|
/*
|
1997-03-13 09:23:11 +03:00
|
|
|
* `another' gets another argument, and stores the new argc and argv.
|
1997-01-19 17:19:02 +03:00
|
|
|
* It reverts to the top level (via main.c's intr()) on EOF/error.
|
|
|
|
*
|
|
|
|
* Returns false if no new arguments have been added.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
another(pargc, pargv, prompt)
|
|
|
|
int *pargc;
|
|
|
|
char ***pargv;
|
|
|
|
const char *prompt;
|
|
|
|
{
|
|
|
|
int len = strlen(line), ret;
|
|
|
|
|
|
|
|
if (len >= sizeof(line) - 3) {
|
1998-06-04 12:28:35 +04:00
|
|
|
fputs("sorry, arguments too long.\n", ttyout);
|
1997-01-19 17:19:02 +03:00
|
|
|
intr();
|
|
|
|
}
|
1998-06-04 12:28:35 +04:00
|
|
|
fprintf(ttyout, "(%s) ", prompt);
|
1997-01-19 17:19:02 +03:00
|
|
|
line[len++] = ' ';
|
|
|
|
if (fgets(&line[len], sizeof(line) - len, stdin) == NULL)
|
|
|
|
intr();
|
|
|
|
len += strlen(&line[len]);
|
|
|
|
if (len > 0 && line[len - 1] == '\n')
|
|
|
|
line[len - 1] = '\0';
|
|
|
|
makeargv();
|
|
|
|
ret = margc > *pargc;
|
|
|
|
*pargc = margc;
|
|
|
|
*pargv = margv;
|
|
|
|
return (ret);
|
|
|
|
}
|
|
|
|
|
1997-03-13 09:23:11 +03:00
|
|
|
/*
|
|
|
|
* glob files given in argv[] from the remote server.
|
|
|
|
* if errbuf isn't NULL, store error messages there instead
|
|
|
|
* of writing to the screen.
|
|
|
|
*/
|
1997-01-19 17:19:02 +03:00
|
|
|
char *
|
1997-03-13 09:23:11 +03:00
|
|
|
remglob(argv, doswitch, errbuf)
|
1997-01-19 17:19:02 +03:00
|
|
|
char *argv[];
|
|
|
|
int doswitch;
|
1997-03-13 09:23:11 +03:00
|
|
|
char **errbuf;
|
1997-01-19 17:19:02 +03:00
|
|
|
{
|
|
|
|
char temp[MAXPATHLEN];
|
|
|
|
static char buf[MAXPATHLEN];
|
|
|
|
static FILE *ftemp = NULL;
|
|
|
|
static char **args;
|
|
|
|
int oldverbose, oldhash, fd;
|
|
|
|
char *cp, *mode;
|
|
|
|
|
|
|
|
if (!mflag) {
|
1997-03-13 09:23:11 +03:00
|
|
|
if (!doglob)
|
1997-01-19 17:19:02 +03:00
|
|
|
args = NULL;
|
|
|
|
else {
|
|
|
|
if (ftemp) {
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)fclose(ftemp);
|
1997-01-19 17:19:02 +03:00
|
|
|
ftemp = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
if (!doglob) {
|
|
|
|
if (args == NULL)
|
|
|
|
args = argv;
|
|
|
|
if ((cp = *++args) == NULL)
|
|
|
|
args = NULL;
|
|
|
|
return (cp);
|
|
|
|
}
|
|
|
|
if (ftemp == NULL) {
|
1997-08-23 11:32:50 +04:00
|
|
|
(void)snprintf(temp, sizeof(temp), "%s/%s", tmpdir, TMPFILE);
|
1997-03-13 09:23:11 +03:00
|
|
|
if ((fd = mkstemp(temp)) < 0) {
|
1997-01-19 17:19:02 +03:00
|
|
|
warn("unable to create temporary file %s", temp);
|
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
close(fd);
|
1997-03-13 09:23:11 +03:00
|
|
|
oldverbose = verbose;
|
|
|
|
verbose = (errbuf != NULL) ? -1 : 0;
|
|
|
|
oldhash = hash;
|
|
|
|
hash = 0;
|
|
|
|
if (doswitch)
|
1997-01-19 17:19:02 +03:00
|
|
|
pswitch(!proxy);
|
|
|
|
for (mode = "w"; *++argv != NULL; mode = "a")
|
1997-08-18 14:20:13 +04:00
|
|
|
recvrequest("NLST", temp, *argv, mode, 0, 0);
|
1997-03-13 09:23:11 +03:00
|
|
|
if ((code / 100) != COMPLETE) {
|
|
|
|
if (errbuf != NULL)
|
|
|
|
*errbuf = reply_string;
|
|
|
|
}
|
|
|
|
if (doswitch)
|
1997-01-19 17:19:02 +03:00
|
|
|
pswitch(!proxy);
|
1997-03-13 09:23:11 +03:00
|
|
|
verbose = oldverbose;
|
|
|
|
hash = oldhash;
|
1997-01-19 17:19:02 +03:00
|
|
|
ftemp = fopen(temp, "r");
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)unlink(temp);
|
1997-01-19 17:19:02 +03:00
|
|
|
if (ftemp == NULL) {
|
1997-03-13 09:23:11 +03:00
|
|
|
if (errbuf == NULL)
|
1998-06-04 12:28:35 +04:00
|
|
|
fputs(
|
|
|
|
"can't find list of remote files, oops.\n",
|
|
|
|
ttyout);
|
1997-03-13 09:23:11 +03:00
|
|
|
else
|
|
|
|
*errbuf =
|
|
|
|
"can't find list of remote files, oops.";
|
1997-01-19 17:19:02 +03:00
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
}
|
1997-03-13 09:23:11 +03:00
|
|
|
if (fgets(buf, sizeof(buf), ftemp) == NULL) {
|
|
|
|
(void)fclose(ftemp);
|
|
|
|
ftemp = NULL;
|
1997-01-19 17:19:02 +03:00
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
if ((cp = strchr(buf, '\n')) != NULL)
|
|
|
|
*cp = '\0';
|
|
|
|
return (buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
confirm(cmd, file)
|
|
|
|
const char *cmd, *file;
|
|
|
|
{
|
|
|
|
char line[BUFSIZ];
|
|
|
|
|
|
|
|
if (!interactive || confirmrest)
|
|
|
|
return (1);
|
1998-06-04 12:28:35 +04:00
|
|
|
fprintf(ttyout, "%s %s? ", cmd, file);
|
|
|
|
(void)fflush(ttyout);
|
1997-01-19 17:19:02 +03:00
|
|
|
if (fgets(line, sizeof(line), stdin) == NULL)
|
|
|
|
return (0);
|
|
|
|
switch (tolower(*line)) {
|
|
|
|
case 'n':
|
|
|
|
return (0);
|
|
|
|
case 'p':
|
|
|
|
interactive = 0;
|
1998-06-04 12:28:35 +04:00
|
|
|
fputs("Interactive mode: off.\n", ttyout);
|
1997-01-19 17:19:02 +03:00
|
|
|
break;
|
|
|
|
case 'a':
|
|
|
|
confirmrest = 1;
|
1998-06-04 12:28:35 +04:00
|
|
|
fprintf(ttyout, "Prompting off for duration of %s.\n",
|
|
|
|
cmd);
|
1997-01-19 17:19:02 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
return (1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Glob a local file name specification with
|
|
|
|
* the expectation of a single return value.
|
|
|
|
* Can't control multiple values being expanded
|
|
|
|
* from the expression, we return only the first.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
globulize(cpp)
|
|
|
|
char **cpp;
|
|
|
|
{
|
|
|
|
glob_t gl;
|
|
|
|
int flags;
|
|
|
|
|
|
|
|
if (!doglob)
|
|
|
|
return (1);
|
|
|
|
|
1998-06-20 02:58:04 +04:00
|
|
|
flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_TILDE;
|
1997-01-19 17:19:02 +03:00
|
|
|
memset(&gl, 0, sizeof(gl));
|
|
|
|
if (glob(*cpp, flags, NULL, &gl) ||
|
|
|
|
gl.gl_pathc == 0) {
|
|
|
|
warnx("%s: not found", *cpp);
|
|
|
|
globfree(&gl);
|
|
|
|
return (0);
|
|
|
|
}
|
1997-08-18 14:20:13 +04:00
|
|
|
/* XXX: caller should check if *cpp changed, and
|
|
|
|
* free(*cpp) if that is the case
|
|
|
|
*/
|
1998-08-03 05:49:25 +04:00
|
|
|
*cpp = xstrdup(gl.gl_pathv[0]);
|
1997-01-19 17:19:02 +03:00
|
|
|
globfree(&gl);
|
|
|
|
return (1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* determine size of remote file
|
|
|
|
*/
|
|
|
|
off_t
|
|
|
|
remotesize(file, noisy)
|
|
|
|
const char *file;
|
|
|
|
int noisy;
|
|
|
|
{
|
|
|
|
int overbose;
|
|
|
|
off_t size;
|
|
|
|
|
|
|
|
overbose = verbose;
|
|
|
|
size = -1;
|
|
|
|
if (debug == 0)
|
|
|
|
verbose = -1;
|
1997-07-21 18:03:48 +04:00
|
|
|
if (command("SIZE %s", file) == COMPLETE) {
|
|
|
|
char *cp, *ep;
|
|
|
|
|
|
|
|
cp = strchr(reply_string, ' ');
|
|
|
|
if (cp != NULL) {
|
|
|
|
cp++;
|
1998-08-08 09:06:56 +04:00
|
|
|
#ifndef NO_QUAD
|
1997-07-21 18:03:48 +04:00
|
|
|
size = strtoq(cp, &ep, 10);
|
1998-08-08 09:06:56 +04:00
|
|
|
#else
|
|
|
|
size = strtol(cp, &ep, 10);
|
1998-05-20 04:55:52 +04:00
|
|
|
#endif
|
|
|
|
if (*ep != '\0' && !isspace((unsigned char)*ep))
|
1997-07-21 18:03:48 +04:00
|
|
|
size = -1;
|
|
|
|
}
|
1998-06-04 12:28:35 +04:00
|
|
|
} else if (noisy && debug == 0) {
|
|
|
|
fputs(reply_string, ttyout);
|
|
|
|
putc('\n', ttyout);
|
|
|
|
}
|
1997-01-19 17:19:02 +03:00
|
|
|
verbose = overbose;
|
|
|
|
return (size);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* determine last modification time (in GMT) of remote file
|
|
|
|
*/
|
|
|
|
time_t
|
|
|
|
remotemodtime(file, noisy)
|
|
|
|
const char *file;
|
|
|
|
int noisy;
|
|
|
|
{
|
|
|
|
int overbose;
|
|
|
|
time_t rtime;
|
1997-09-21 05:06:30 +04:00
|
|
|
int ocode;
|
1997-01-19 17:19:02 +03:00
|
|
|
|
|
|
|
overbose = verbose;
|
1997-09-21 05:06:30 +04:00
|
|
|
ocode = code;
|
1997-01-19 17:19:02 +03:00
|
|
|
rtime = -1;
|
|
|
|
if (debug == 0)
|
|
|
|
verbose = -1;
|
|
|
|
if (command("MDTM %s", file) == COMPLETE) {
|
|
|
|
struct tm timebuf;
|
|
|
|
int yy, mo, day, hour, min, sec;
|
|
|
|
sscanf(reply_string, "%*s %04d%02d%02d%02d%02d%02d", &yy, &mo,
|
|
|
|
&day, &hour, &min, &sec);
|
|
|
|
memset(&timebuf, 0, sizeof(timebuf));
|
|
|
|
timebuf.tm_sec = sec;
|
|
|
|
timebuf.tm_min = min;
|
|
|
|
timebuf.tm_hour = hour;
|
|
|
|
timebuf.tm_mday = day;
|
|
|
|
timebuf.tm_mon = mo - 1;
|
1998-02-04 18:23:54 +03:00
|
|
|
timebuf.tm_year = yy - TM_YEAR_BASE;
|
1997-01-19 17:19:02 +03:00
|
|
|
timebuf.tm_isdst = -1;
|
1998-11-18 10:24:25 +03:00
|
|
|
rtime = mkgmtime(&timebuf);
|
1997-01-19 17:19:02 +03:00
|
|
|
if (rtime == -1 && (noisy || debug != 0))
|
1998-06-04 12:28:35 +04:00
|
|
|
fprintf(ttyout, "Can't convert %s to a time.\n",
|
|
|
|
reply_string);
|
|
|
|
} else if (noisy && debug == 0) {
|
|
|
|
fputs(reply_string, ttyout);
|
|
|
|
putc('\n', ttyout);
|
|
|
|
}
|
1997-01-19 17:19:02 +03:00
|
|
|
verbose = overbose;
|
1997-09-21 05:06:30 +04:00
|
|
|
if (rtime == -1)
|
|
|
|
code = ocode;
|
1997-01-19 17:19:02 +03:00
|
|
|
return (rtime);
|
|
|
|
}
|
|
|
|
|
1998-11-18 10:24:25 +03:00
|
|
|
/*
|
|
|
|
* UTC version of mktime(3)
|
|
|
|
*/
|
|
|
|
#ifdef HAVE_TIMEGM
|
|
|
|
time_t
|
|
|
|
mkgmtime(tm)
|
|
|
|
struct tm *tm;
|
|
|
|
{
|
|
|
|
|
|
|
|
/* This is very clean, but not portable at all. */
|
1998-12-29 17:27:59 +03:00
|
|
|
return (timegm(tm));
|
1998-11-18 10:24:25 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
#else /* not HAVE_TIMEGM */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This code is not portable, but works on most Unix-like systems.
|
|
|
|
* If the local timezone has no summer time, using mktime(3) function
|
|
|
|
* and adjusting offset would be usable (adjusting leap seconds
|
|
|
|
* is still required, though), but the assumption is not always true.
|
|
|
|
*
|
|
|
|
* Anyway, no portable and correct implementation of UTC to time_t
|
|
|
|
* conversion exists....
|
|
|
|
*/
|
|
|
|
|
|
|
|
static time_t
|
|
|
|
sub_mkgmt(tm)
|
|
|
|
struct tm *tm;
|
|
|
|
{
|
|
|
|
int y, nleapdays;
|
|
|
|
time_t t;
|
|
|
|
/* days before the month */
|
|
|
|
static const unsigned short moff[12] = {
|
|
|
|
0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* XXX This code assumes the given time to be normalized.
|
|
|
|
* Normalizing here is impossible in case the given time is a leap
|
|
|
|
* second but the local time library is ignorant of leap seconds.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* minimal sanity checking not to access outside of the array */
|
|
|
|
if ((unsigned) tm->tm_mon >= 12)
|
|
|
|
return (time_t) -1;
|
|
|
|
if (tm->tm_year < EPOCH_YEAR - TM_YEAR_BASE)
|
|
|
|
return (time_t) -1;
|
|
|
|
|
|
|
|
y = tm->tm_year + TM_YEAR_BASE - (tm->tm_mon < 2);
|
|
|
|
nleapdays = y / 4 - y / 100 + y / 400 -
|
|
|
|
((EPOCH_YEAR-1) / 4 - (EPOCH_YEAR-1) / 100 + (EPOCH_YEAR-1) / 400);
|
|
|
|
t = ((((time_t) (tm->tm_year - (EPOCH_YEAR - TM_YEAR_BASE)) * 365 +
|
|
|
|
moff[tm->tm_mon] + tm->tm_mday - 1 + nleapdays) * 24 +
|
|
|
|
tm->tm_hour) * 60 + tm->tm_min) * 60 + tm->tm_sec;
|
|
|
|
|
1998-12-29 17:27:59 +03:00
|
|
|
return (t < 0 ? (time_t) -1 : t);
|
1998-11-18 10:24:25 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
time_t
|
|
|
|
mkgmtime(tm)
|
|
|
|
struct tm *tm;
|
|
|
|
{
|
|
|
|
time_t t, t2;
|
|
|
|
struct tm *tm2;
|
|
|
|
int sec;
|
|
|
|
|
|
|
|
/* Do the first guess. */
|
|
|
|
if ((t = sub_mkgmt(tm)) == (time_t) -1)
|
|
|
|
return (time_t) -1;
|
|
|
|
|
|
|
|
/* save value in case *tm is overwritten by gmtime() */
|
|
|
|
sec = tm->tm_sec;
|
|
|
|
|
|
|
|
tm2 = gmtime(&t);
|
|
|
|
if ((t2 = sub_mkgmt(tm2)) == (time_t) -1)
|
|
|
|
return (time_t) -1;
|
|
|
|
|
|
|
|
if (t2 < t || tm2->tm_sec != sec) {
|
|
|
|
/*
|
|
|
|
* Adjust for leap seconds.
|
|
|
|
*
|
|
|
|
* real time_t time
|
|
|
|
* |
|
|
|
|
* tm
|
|
|
|
* / ... (a) first sub_mkgmt() conversion
|
|
|
|
* t
|
|
|
|
* |
|
|
|
|
* tm2
|
|
|
|
* / ... (b) second sub_mkgmt() conversion
|
|
|
|
* t2
|
|
|
|
* --->time
|
|
|
|
*/
|
|
|
|
/*
|
|
|
|
* Do the second guess, assuming (a) and (b) are almost equal.
|
|
|
|
*/
|
|
|
|
t += t - t2;
|
|
|
|
tm2 = gmtime(&t);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Either (a) or (b), may include one or two extra
|
|
|
|
* leap seconds. Try t, t + 2, t - 2, t + 1, and t - 1.
|
|
|
|
*/
|
|
|
|
if (tm2->tm_sec == sec
|
|
|
|
|| (t += 2, tm2 = gmtime(&t), tm2->tm_sec == sec)
|
|
|
|
|| (t -= 4, tm2 = gmtime(&t), tm2->tm_sec == sec)
|
|
|
|
|| (t += 3, tm2 = gmtime(&t), tm2->tm_sec == sec)
|
|
|
|
|| (t -= 2, tm2 = gmtime(&t), tm2->tm_sec == sec))
|
|
|
|
; /* found */
|
|
|
|
else {
|
|
|
|
/*
|
|
|
|
* Not found.
|
|
|
|
*/
|
|
|
|
if (sec >= 60)
|
|
|
|
/*
|
|
|
|
* The given time is a leap second
|
|
|
|
* (sec 60 or 61), but the time library
|
|
|
|
* is ignorant of the leap second.
|
|
|
|
*/
|
|
|
|
; /* treat sec 60 as 59,
|
|
|
|
sec 61 as 0 of the next minute */
|
|
|
|
else
|
|
|
|
/* The given time may not be normalized. */
|
|
|
|
t++; /* restore t */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1998-12-29 17:27:59 +03:00
|
|
|
return (t < 0 ? (time_t) -1 : t);
|
1998-11-18 10:24:25 +03:00
|
|
|
}
|
|
|
|
#endif /* not HAVE_TIMEGM */
|
|
|
|
|
1997-12-13 02:34:56 +03:00
|
|
|
#ifndef SMALL
|
1997-07-20 13:45:35 +04:00
|
|
|
|
1998-06-04 12:28:35 +04:00
|
|
|
/*
|
|
|
|
* return non-zero if we're the current foreground process
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
foregroundproc()
|
[Yet Another Huge Ftp Commit - hopefully the last for a while,
barring any more little things people want added ...]
New features:
* progressmeter is now asynchronous, so "stalled" transfers can be
detected. "- stalled -" is displayed instead of the ETA in this case.
When the xfer resumes, the time that the xfer was stalled for is
factored out of the ETA. It is debatable whether this is better than
not factoring it out, but I like it this way (I.e, if it stalls for 8
seconds and the ETA was 30 seconds, when it resumes the ETA will still
be 30 seconds).
* verbosity can be disabled on the command line (-V), so that in auto-fetch
mode the only lines displayed will be a description of the file, and
the progress bar (if possible)
* if the screen is resized (and detected via the SIGWINCH signal), the
progress bar will rescale automatically.
Bugs fixed:
* progress bar will not use the last character on the line, as this can
cause problems on some terminals
* screen dimensions (via ioctl(TIOCWINSZ)) should use stdout not stdin
* progressmeter() used some vars before initialising them
* ^D will quit now. [fixes bin/3162]
* use hstrerror() to generate error message for host name lookup failure.
* use getcwd instead of getwd (it should have been OK, but why tempt fate?)
* auto-fetch transfers will always return a positive exit value upon failure
or interruption, relative to the file's position in argv[].
* remote completion of / will work, without putting a leading "///".
This is actually a bug in ftpd(1), where "NLST /" prefixes all names
with "//", but fixing every ftpd(1) is not an option...
1997-02-01 13:44:54 +03:00
|
|
|
{
|
1997-06-11 01:59:58 +04:00
|
|
|
static pid_t pgrp = -1;
|
|
|
|
int ctty_pgrp;
|
[Yet Another Huge Ftp Commit - hopefully the last for a while,
barring any more little things people want added ...]
New features:
* progressmeter is now asynchronous, so "stalled" transfers can be
detected. "- stalled -" is displayed instead of the ETA in this case.
When the xfer resumes, the time that the xfer was stalled for is
factored out of the ETA. It is debatable whether this is better than
not factoring it out, but I like it this way (I.e, if it stalls for 8
seconds and the ETA was 30 seconds, when it resumes the ETA will still
be 30 seconds).
* verbosity can be disabled on the command line (-V), so that in auto-fetch
mode the only lines displayed will be a description of the file, and
the progress bar (if possible)
* if the screen is resized (and detected via the SIGWINCH signal), the
progress bar will rescale automatically.
Bugs fixed:
* progress bar will not use the last character on the line, as this can
cause problems on some terminals
* screen dimensions (via ioctl(TIOCWINSZ)) should use stdout not stdin
* progressmeter() used some vars before initialising them
* ^D will quit now. [fixes bin/3162]
* use hstrerror() to generate error message for host name lookup failure.
* use getcwd instead of getwd (it should have been OK, but why tempt fate?)
* auto-fetch transfers will always return a positive exit value upon failure
or interruption, relative to the file's position in argv[].
* remote completion of / will work, without putting a leading "///".
This is actually a bug in ftpd(1), where "NLST /" prefixes all names
with "//", but fixing every ftpd(1) is not an option...
1997-02-01 13:44:54 +03:00
|
|
|
|
1997-06-11 01:59:58 +04:00
|
|
|
if (pgrp == -1)
|
|
|
|
pgrp = getpgrp();
|
|
|
|
|
1998-06-04 12:28:35 +04:00
|
|
|
return ((ioctl(fileno(ttyout), TIOCGPGRP, &ctty_pgrp) != -1 &&
|
|
|
|
ctty_pgrp == (int)pgrp));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void updateprogressmeter __P((int));
|
|
|
|
|
|
|
|
static void
|
|
|
|
updateprogressmeter(dummy)
|
|
|
|
int dummy;
|
|
|
|
{
|
|
|
|
|
1997-06-11 01:59:58 +04:00
|
|
|
/*
|
|
|
|
* print progress bar only if we are foreground process.
|
|
|
|
*/
|
1998-06-04 12:28:35 +04:00
|
|
|
if (foregroundproc())
|
1997-06-11 01:59:58 +04:00
|
|
|
progressmeter(0);
|
[Yet Another Huge Ftp Commit - hopefully the last for a while,
barring any more little things people want added ...]
New features:
* progressmeter is now asynchronous, so "stalled" transfers can be
detected. "- stalled -" is displayed instead of the ETA in this case.
When the xfer resumes, the time that the xfer was stalled for is
factored out of the ETA. It is debatable whether this is better than
not factoring it out, but I like it this way (I.e, if it stalls for 8
seconds and the ETA was 30 seconds, when it resumes the ETA will still
be 30 seconds).
* verbosity can be disabled on the command line (-V), so that in auto-fetch
mode the only lines displayed will be a description of the file, and
the progress bar (if possible)
* if the screen is resized (and detected via the SIGWINCH signal), the
progress bar will rescale automatically.
Bugs fixed:
* progress bar will not use the last character on the line, as this can
cause problems on some terminals
* screen dimensions (via ioctl(TIOCWINSZ)) should use stdout not stdin
* progressmeter() used some vars before initialising them
* ^D will quit now. [fixes bin/3162]
* use hstrerror() to generate error message for host name lookup failure.
* use getcwd instead of getwd (it should have been OK, but why tempt fate?)
* auto-fetch transfers will always return a positive exit value upon failure
or interruption, relative to the file's position in argv[].
* remote completion of / will work, without putting a leading "///".
This is actually a bug in ftpd(1), where "NLST /" prefixes all names
with "//", but fixing every ftpd(1) is not an option...
1997-02-01 13:44:54 +03:00
|
|
|
}
|
1997-12-13 02:34:56 +03:00
|
|
|
#endif /* SMALL */
|
[Yet Another Huge Ftp Commit - hopefully the last for a while,
barring any more little things people want added ...]
New features:
* progressmeter is now asynchronous, so "stalled" transfers can be
detected. "- stalled -" is displayed instead of the ETA in this case.
When the xfer resumes, the time that the xfer was stalled for is
factored out of the ETA. It is debatable whether this is better than
not factoring it out, but I like it this way (I.e, if it stalls for 8
seconds and the ETA was 30 seconds, when it resumes the ETA will still
be 30 seconds).
* verbosity can be disabled on the command line (-V), so that in auto-fetch
mode the only lines displayed will be a description of the file, and
the progress bar (if possible)
* if the screen is resized (and detected via the SIGWINCH signal), the
progress bar will rescale automatically.
Bugs fixed:
* progress bar will not use the last character on the line, as this can
cause problems on some terminals
* screen dimensions (via ioctl(TIOCWINSZ)) should use stdout not stdin
* progressmeter() used some vars before initialising them
* ^D will quit now. [fixes bin/3162]
* use hstrerror() to generate error message for host name lookup failure.
* use getcwd instead of getwd (it should have been OK, but why tempt fate?)
* auto-fetch transfers will always return a positive exit value upon failure
or interruption, relative to the file's position in argv[].
* remote completion of / will work, without putting a leading "///".
This is actually a bug in ftpd(1), where "NLST /" prefixes all names
with "//", but fixing every ftpd(1) is not an option...
1997-02-01 13:44:54 +03:00
|
|
|
|
1997-01-19 17:19:02 +03:00
|
|
|
/*
|
|
|
|
* Display a transfer progress bar if progress is non-zero.
|
[Yet Another Huge Ftp Commit - hopefully the last for a while,
barring any more little things people want added ...]
New features:
* progressmeter is now asynchronous, so "stalled" transfers can be
detected. "- stalled -" is displayed instead of the ETA in this case.
When the xfer resumes, the time that the xfer was stalled for is
factored out of the ETA. It is debatable whether this is better than
not factoring it out, but I like it this way (I.e, if it stalls for 8
seconds and the ETA was 30 seconds, when it resumes the ETA will still
be 30 seconds).
* verbosity can be disabled on the command line (-V), so that in auto-fetch
mode the only lines displayed will be a description of the file, and
the progress bar (if possible)
* if the screen is resized (and detected via the SIGWINCH signal), the
progress bar will rescale automatically.
Bugs fixed:
* progress bar will not use the last character on the line, as this can
cause problems on some terminals
* screen dimensions (via ioctl(TIOCWINSZ)) should use stdout not stdin
* progressmeter() used some vars before initialising them
* ^D will quit now. [fixes bin/3162]
* use hstrerror() to generate error message for host name lookup failure.
* use getcwd instead of getwd (it should have been OK, but why tempt fate?)
* auto-fetch transfers will always return a positive exit value upon failure
or interruption, relative to the file's position in argv[].
* remote completion of / will work, without putting a leading "///".
This is actually a bug in ftpd(1), where "NLST /" prefixes all names
with "//", but fixing every ftpd(1) is not an option...
1997-02-01 13:44:54 +03:00
|
|
|
* SIGALRM is hijacked for use by this function.
|
|
|
|
* - Before the transfer, set filesize to size of file (or -1 if unknown),
|
|
|
|
* and call with flag = -1. This starts the once per second timer,
|
|
|
|
* and a call to updateprogressmeter() upon SIGALRM.
|
|
|
|
* - During the transfer, updateprogressmeter will call progressmeter
|
|
|
|
* with flag = 0
|
|
|
|
* - After the transfer, call with flag = 1
|
1997-01-19 17:19:02 +03:00
|
|
|
*/
|
|
|
|
static struct timeval start;
|
1998-01-20 07:39:34 +03:00
|
|
|
static struct timeval lastupdate;
|
1997-01-19 17:19:02 +03:00
|
|
|
|
|
|
|
void
|
|
|
|
progressmeter(flag)
|
|
|
|
int flag;
|
|
|
|
{
|
1997-12-13 02:34:56 +03:00
|
|
|
#ifndef SMALL
|
[Yet Another Huge Ftp Commit - hopefully the last for a while,
barring any more little things people want added ...]
New features:
* progressmeter is now asynchronous, so "stalled" transfers can be
detected. "- stalled -" is displayed instead of the ETA in this case.
When the xfer resumes, the time that the xfer was stalled for is
factored out of the ETA. It is debatable whether this is better than
not factoring it out, but I like it this way (I.e, if it stalls for 8
seconds and the ETA was 30 seconds, when it resumes the ETA will still
be 30 seconds).
* verbosity can be disabled on the command line (-V), so that in auto-fetch
mode the only lines displayed will be a description of the file, and
the progress bar (if possible)
* if the screen is resized (and detected via the SIGWINCH signal), the
progress bar will rescale automatically.
Bugs fixed:
* progress bar will not use the last character on the line, as this can
cause problems on some terminals
* screen dimensions (via ioctl(TIOCWINSZ)) should use stdout not stdin
* progressmeter() used some vars before initialising them
* ^D will quit now. [fixes bin/3162]
* use hstrerror() to generate error message for host name lookup failure.
* use getcwd instead of getwd (it should have been OK, but why tempt fate?)
* auto-fetch transfers will always return a positive exit value upon failure
or interruption, relative to the file's position in argv[].
* remote completion of / will work, without putting a leading "///".
This is actually a bug in ftpd(1), where "NLST /" prefixes all names
with "//", but fixing every ftpd(1) is not an option...
1997-02-01 13:44:54 +03:00
|
|
|
/*
|
|
|
|
* List of order of magnitude prefixes.
|
|
|
|
* The last is `P', as 2^64 = 16384 Petabytes
|
|
|
|
*/
|
1998-09-28 13:03:22 +04:00
|
|
|
static const char prefixes[] = "BKMGTP";
|
[Yet Another Huge Ftp Commit - hopefully the last for a while,
barring any more little things people want added ...]
New features:
* progressmeter is now asynchronous, so "stalled" transfers can be
detected. "- stalled -" is displayed instead of the ETA in this case.
When the xfer resumes, the time that the xfer was stalled for is
factored out of the ETA. It is debatable whether this is better than
not factoring it out, but I like it this way (I.e, if it stalls for 8
seconds and the ETA was 30 seconds, when it resumes the ETA will still
be 30 seconds).
* verbosity can be disabled on the command line (-V), so that in auto-fetch
mode the only lines displayed will be a description of the file, and
the progress bar (if possible)
* if the screen is resized (and detected via the SIGWINCH signal), the
progress bar will rescale automatically.
Bugs fixed:
* progress bar will not use the last character on the line, as this can
cause problems on some terminals
* screen dimensions (via ioctl(TIOCWINSZ)) should use stdout not stdin
* progressmeter() used some vars before initialising them
* ^D will quit now. [fixes bin/3162]
* use hstrerror() to generate error message for host name lookup failure.
* use getcwd instead of getwd (it should have been OK, but why tempt fate?)
* auto-fetch transfers will always return a positive exit value upon failure
or interruption, relative to the file's position in argv[].
* remote completion of / will work, without putting a leading "///".
This is actually a bug in ftpd(1), where "NLST /" prefixes all names
with "//", but fixing every ftpd(1) is not an option...
1997-02-01 13:44:54 +03:00
|
|
|
|
|
|
|
static off_t lastsize;
|
|
|
|
struct timeval now, td, wait;
|
1998-09-28 13:03:22 +04:00
|
|
|
off_t cursize, abbrevsize, bytespersec;
|
1997-11-01 17:36:49 +03:00
|
|
|
double elapsed;
|
|
|
|
int ratio, barlength, i, len, remaining;
|
[Yet Another Huge Ftp Commit - hopefully the last for a while,
barring any more little things people want added ...]
New features:
* progressmeter is now asynchronous, so "stalled" transfers can be
detected. "- stalled -" is displayed instead of the ETA in this case.
When the xfer resumes, the time that the xfer was stalled for is
factored out of the ETA. It is debatable whether this is better than
not factoring it out, but I like it this way (I.e, if it stalls for 8
seconds and the ETA was 30 seconds, when it resumes the ETA will still
be 30 seconds).
* verbosity can be disabled on the command line (-V), so that in auto-fetch
mode the only lines displayed will be a description of the file, and
the progress bar (if possible)
* if the screen is resized (and detected via the SIGWINCH signal), the
progress bar will rescale automatically.
Bugs fixed:
* progress bar will not use the last character on the line, as this can
cause problems on some terminals
* screen dimensions (via ioctl(TIOCWINSZ)) should use stdout not stdin
* progressmeter() used some vars before initialising them
* ^D will quit now. [fixes bin/3162]
* use hstrerror() to generate error message for host name lookup failure.
* use getcwd instead of getwd (it should have been OK, but why tempt fate?)
* auto-fetch transfers will always return a positive exit value upon failure
or interruption, relative to the file's position in argv[].
* remote completion of / will work, without putting a leading "///".
This is actually a bug in ftpd(1), where "NLST /" prefixes all names
with "//", but fixing every ftpd(1) is not an option...
1997-02-01 13:44:54 +03:00
|
|
|
char buf[256];
|
1997-01-19 17:19:02 +03:00
|
|
|
|
1997-10-11 16:05:15 +04:00
|
|
|
len = 0;
|
|
|
|
|
[Yet Another Huge Ftp Commit - hopefully the last for a while,
barring any more little things people want added ...]
New features:
* progressmeter is now asynchronous, so "stalled" transfers can be
detected. "- stalled -" is displayed instead of the ETA in this case.
When the xfer resumes, the time that the xfer was stalled for is
factored out of the ETA. It is debatable whether this is better than
not factoring it out, but I like it this way (I.e, if it stalls for 8
seconds and the ETA was 30 seconds, when it resumes the ETA will still
be 30 seconds).
* verbosity can be disabled on the command line (-V), so that in auto-fetch
mode the only lines displayed will be a description of the file, and
the progress bar (if possible)
* if the screen is resized (and detected via the SIGWINCH signal), the
progress bar will rescale automatically.
Bugs fixed:
* progress bar will not use the last character on the line, as this can
cause problems on some terminals
* screen dimensions (via ioctl(TIOCWINSZ)) should use stdout not stdin
* progressmeter() used some vars before initialising them
* ^D will quit now. [fixes bin/3162]
* use hstrerror() to generate error message for host name lookup failure.
* use getcwd instead of getwd (it should have been OK, but why tempt fate?)
* auto-fetch transfers will always return a positive exit value upon failure
or interruption, relative to the file's position in argv[].
* remote completion of / will work, without putting a leading "///".
This is actually a bug in ftpd(1), where "NLST /" prefixes all names
with "//", but fixing every ftpd(1) is not an option...
1997-02-01 13:44:54 +03:00
|
|
|
if (flag == -1) {
|
1998-01-18 17:23:33 +03:00
|
|
|
(void)gettimeofday(&start, NULL);
|
[Yet Another Huge Ftp Commit - hopefully the last for a while,
barring any more little things people want added ...]
New features:
* progressmeter is now asynchronous, so "stalled" transfers can be
detected. "- stalled -" is displayed instead of the ETA in this case.
When the xfer resumes, the time that the xfer was stalled for is
factored out of the ETA. It is debatable whether this is better than
not factoring it out, but I like it this way (I.e, if it stalls for 8
seconds and the ETA was 30 seconds, when it resumes the ETA will still
be 30 seconds).
* verbosity can be disabled on the command line (-V), so that in auto-fetch
mode the only lines displayed will be a description of the file, and
the progress bar (if possible)
* if the screen is resized (and detected via the SIGWINCH signal), the
progress bar will rescale automatically.
Bugs fixed:
* progress bar will not use the last character on the line, as this can
cause problems on some terminals
* screen dimensions (via ioctl(TIOCWINSZ)) should use stdout not stdin
* progressmeter() used some vars before initialising them
* ^D will quit now. [fixes bin/3162]
* use hstrerror() to generate error message for host name lookup failure.
* use getcwd instead of getwd (it should have been OK, but why tempt fate?)
* auto-fetch transfers will always return a positive exit value upon failure
or interruption, relative to the file's position in argv[].
* remote completion of / will work, without putting a leading "///".
This is actually a bug in ftpd(1), where "NLST /" prefixes all names
with "//", but fixing every ftpd(1) is not an option...
1997-02-01 13:44:54 +03:00
|
|
|
lastupdate = start;
|
|
|
|
lastsize = restart_point;
|
|
|
|
}
|
1998-01-18 17:23:33 +03:00
|
|
|
(void)gettimeofday(&now, NULL);
|
1997-01-30 06:36:26 +03:00
|
|
|
if (!progress || filesize <= 0)
|
1997-01-19 17:19:02 +03:00
|
|
|
return;
|
|
|
|
cursize = bytes + restart_point;
|
|
|
|
|
1998-09-28 13:03:22 +04:00
|
|
|
ratio = (int)((double)cursize * 100.0 / (double)filesize);
|
1997-01-19 17:19:02 +03:00
|
|
|
ratio = MAX(ratio, 0);
|
|
|
|
ratio = MIN(ratio, 100);
|
1997-10-11 16:05:15 +04:00
|
|
|
len += snprintf(buf + len, sizeof(buf) - len, "\r%3d%% ", ratio);
|
1997-01-19 17:19:02 +03:00
|
|
|
|
1998-09-28 13:03:22 +04:00
|
|
|
barlength = ttywidth - 42;
|
1997-01-19 17:19:02 +03:00
|
|
|
if (barlength > 0) {
|
|
|
|
i = barlength * ratio / 100;
|
1997-10-11 16:05:15 +04:00
|
|
|
len += snprintf(buf + len, sizeof(buf) - len,
|
[Yet Another Huge Ftp Commit - hopefully the last for a while,
barring any more little things people want added ...]
New features:
* progressmeter is now asynchronous, so "stalled" transfers can be
detected. "- stalled -" is displayed instead of the ETA in this case.
When the xfer resumes, the time that the xfer was stalled for is
factored out of the ETA. It is debatable whether this is better than
not factoring it out, but I like it this way (I.e, if it stalls for 8
seconds and the ETA was 30 seconds, when it resumes the ETA will still
be 30 seconds).
* verbosity can be disabled on the command line (-V), so that in auto-fetch
mode the only lines displayed will be a description of the file, and
the progress bar (if possible)
* if the screen is resized (and detected via the SIGWINCH signal), the
progress bar will rescale automatically.
Bugs fixed:
* progress bar will not use the last character on the line, as this can
cause problems on some terminals
* screen dimensions (via ioctl(TIOCWINSZ)) should use stdout not stdin
* progressmeter() used some vars before initialising them
* ^D will quit now. [fixes bin/3162]
* use hstrerror() to generate error message for host name lookup failure.
* use getcwd instead of getwd (it should have been OK, but why tempt fate?)
* auto-fetch transfers will always return a positive exit value upon failure
or interruption, relative to the file's position in argv[].
* remote completion of / will work, without putting a leading "///".
This is actually a bug in ftpd(1), where "NLST /" prefixes all names
with "//", but fixing every ftpd(1) is not an option...
1997-02-01 13:44:54 +03:00
|
|
|
"|%.*s%*s|", i,
|
1997-01-19 17:19:02 +03:00
|
|
|
"*****************************************************************************"
|
|
|
|
"*****************************************************************************",
|
|
|
|
barlength - i, "");
|
|
|
|
}
|
|
|
|
|
|
|
|
abbrevsize = cursize;
|
1998-09-28 13:03:22 +04:00
|
|
|
for (i = 0; abbrevsize >= 100000 && i < sizeof(prefixes); i++)
|
1997-01-19 17:19:02 +03:00
|
|
|
abbrevsize >>= 10;
|
1997-10-11 16:05:15 +04:00
|
|
|
len += snprintf(buf + len, sizeof(buf) - len,
|
1998-08-08 09:06:56 +04:00
|
|
|
#ifndef NO_QUAD
|
|
|
|
" %5qd %c%c ", (long long)abbrevsize,
|
|
|
|
#else
|
|
|
|
" %5ld %c%c ", (long)abbrevsize,
|
|
|
|
#endif
|
1998-09-28 13:03:22 +04:00
|
|
|
i == 0 ? ' ' : prefixes[i],
|
|
|
|
i == 0 ? ' ' : 'B');
|
1997-01-19 17:19:02 +03:00
|
|
|
|
[Yet Another Huge Ftp Commit - hopefully the last for a while,
barring any more little things people want added ...]
New features:
* progressmeter is now asynchronous, so "stalled" transfers can be
detected. "- stalled -" is displayed instead of the ETA in this case.
When the xfer resumes, the time that the xfer was stalled for is
factored out of the ETA. It is debatable whether this is better than
not factoring it out, but I like it this way (I.e, if it stalls for 8
seconds and the ETA was 30 seconds, when it resumes the ETA will still
be 30 seconds).
* verbosity can be disabled on the command line (-V), so that in auto-fetch
mode the only lines displayed will be a description of the file, and
the progress bar (if possible)
* if the screen is resized (and detected via the SIGWINCH signal), the
progress bar will rescale automatically.
Bugs fixed:
* progress bar will not use the last character on the line, as this can
cause problems on some terminals
* screen dimensions (via ioctl(TIOCWINSZ)) should use stdout not stdin
* progressmeter() used some vars before initialising them
* ^D will quit now. [fixes bin/3162]
* use hstrerror() to generate error message for host name lookup failure.
* use getcwd instead of getwd (it should have been OK, but why tempt fate?)
* auto-fetch transfers will always return a positive exit value upon failure
or interruption, relative to the file's position in argv[].
* remote completion of / will work, without putting a leading "///".
This is actually a bug in ftpd(1), where "NLST /" prefixes all names
with "//", but fixing every ftpd(1) is not an option...
1997-02-01 13:44:54 +03:00
|
|
|
timersub(&now, &lastupdate, &wait);
|
|
|
|
if (cursize > lastsize) {
|
|
|
|
lastupdate = now;
|
|
|
|
lastsize = cursize;
|
|
|
|
if (wait.tv_sec >= STALLTIME) { /* fudge out stalled time */
|
|
|
|
start.tv_sec += wait.tv_sec;
|
|
|
|
start.tv_usec += wait.tv_usec;
|
|
|
|
}
|
|
|
|
wait.tv_sec = 0;
|
|
|
|
}
|
|
|
|
|
1997-01-19 17:19:02 +03:00
|
|
|
timersub(&now, &start, &td);
|
|
|
|
elapsed = td.tv_sec + (td.tv_usec / 1000000.0);
|
[Yet Another Huge Ftp Commit - hopefully the last for a while,
barring any more little things people want added ...]
New features:
* progressmeter is now asynchronous, so "stalled" transfers can be
detected. "- stalled -" is displayed instead of the ETA in this case.
When the xfer resumes, the time that the xfer was stalled for is
factored out of the ETA. It is debatable whether this is better than
not factoring it out, but I like it this way (I.e, if it stalls for 8
seconds and the ETA was 30 seconds, when it resumes the ETA will still
be 30 seconds).
* verbosity can be disabled on the command line (-V), so that in auto-fetch
mode the only lines displayed will be a description of the file, and
the progress bar (if possible)
* if the screen is resized (and detected via the SIGWINCH signal), the
progress bar will rescale automatically.
Bugs fixed:
* progress bar will not use the last character on the line, as this can
cause problems on some terminals
* screen dimensions (via ioctl(TIOCWINSZ)) should use stdout not stdin
* progressmeter() used some vars before initialising them
* ^D will quit now. [fixes bin/3162]
* use hstrerror() to generate error message for host name lookup failure.
* use getcwd instead of getwd (it should have been OK, but why tempt fate?)
* auto-fetch transfers will always return a positive exit value upon failure
or interruption, relative to the file's position in argv[].
* remote completion of / will work, without putting a leading "///".
This is actually a bug in ftpd(1), where "NLST /" prefixes all names
with "//", but fixing every ftpd(1) is not an option...
1997-02-01 13:44:54 +03:00
|
|
|
|
1998-09-28 13:03:22 +04:00
|
|
|
bytespersec = 0;
|
|
|
|
if (bytes > 0) {
|
|
|
|
bytespersec = bytes;
|
|
|
|
if (elapsed > 0.0)
|
|
|
|
bytespersec /= elapsed;
|
|
|
|
}
|
|
|
|
for (i = 0; bytespersec >= 100000 && i < sizeof(prefixes); i++)
|
|
|
|
bytespersec >>= 10;
|
|
|
|
len += snprintf(buf + len, sizeof(buf) - len,
|
|
|
|
#ifndef NO_QUAD
|
|
|
|
" %5qd %c%s ", (long long)bytespersec,
|
|
|
|
#else
|
|
|
|
" %5ld %c%s ", (long)bytespersec,
|
|
|
|
#endif
|
|
|
|
prefixes[i],
|
|
|
|
i == 0 ? "/s " : "B/s");
|
|
|
|
|
1997-05-12 15:41:13 +04:00
|
|
|
if (bytes <= 0 || elapsed <= 0.0 || cursize > filesize) {
|
1997-10-11 16:05:15 +04:00
|
|
|
len += snprintf(buf + len, sizeof(buf) - len,
|
[Yet Another Huge Ftp Commit - hopefully the last for a while,
barring any more little things people want added ...]
New features:
* progressmeter is now asynchronous, so "stalled" transfers can be
detected. "- stalled -" is displayed instead of the ETA in this case.
When the xfer resumes, the time that the xfer was stalled for is
factored out of the ETA. It is debatable whether this is better than
not factoring it out, but I like it this way (I.e, if it stalls for 8
seconds and the ETA was 30 seconds, when it resumes the ETA will still
be 30 seconds).
* verbosity can be disabled on the command line (-V), so that in auto-fetch
mode the only lines displayed will be a description of the file, and
the progress bar (if possible)
* if the screen is resized (and detected via the SIGWINCH signal), the
progress bar will rescale automatically.
Bugs fixed:
* progress bar will not use the last character on the line, as this can
cause problems on some terminals
* screen dimensions (via ioctl(TIOCWINSZ)) should use stdout not stdin
* progressmeter() used some vars before initialising them
* ^D will quit now. [fixes bin/3162]
* use hstrerror() to generate error message for host name lookup failure.
* use getcwd instead of getwd (it should have been OK, but why tempt fate?)
* auto-fetch transfers will always return a positive exit value upon failure
or interruption, relative to the file's position in argv[].
* remote completion of / will work, without putting a leading "///".
This is actually a bug in ftpd(1), where "NLST /" prefixes all names
with "//", but fixing every ftpd(1) is not an option...
1997-02-01 13:44:54 +03:00
|
|
|
" --:-- ETA");
|
|
|
|
} else if (wait.tv_sec >= STALLTIME) {
|
1997-10-11 16:05:15 +04:00
|
|
|
len += snprintf(buf + len, sizeof(buf) - len,
|
[Yet Another Huge Ftp Commit - hopefully the last for a while,
barring any more little things people want added ...]
New features:
* progressmeter is now asynchronous, so "stalled" transfers can be
detected. "- stalled -" is displayed instead of the ETA in this case.
When the xfer resumes, the time that the xfer was stalled for is
factored out of the ETA. It is debatable whether this is better than
not factoring it out, but I like it this way (I.e, if it stalls for 8
seconds and the ETA was 30 seconds, when it resumes the ETA will still
be 30 seconds).
* verbosity can be disabled on the command line (-V), so that in auto-fetch
mode the only lines displayed will be a description of the file, and
the progress bar (if possible)
* if the screen is resized (and detected via the SIGWINCH signal), the
progress bar will rescale automatically.
Bugs fixed:
* progress bar will not use the last character on the line, as this can
cause problems on some terminals
* screen dimensions (via ioctl(TIOCWINSZ)) should use stdout not stdin
* progressmeter() used some vars before initialising them
* ^D will quit now. [fixes bin/3162]
* use hstrerror() to generate error message for host name lookup failure.
* use getcwd instead of getwd (it should have been OK, but why tempt fate?)
* auto-fetch transfers will always return a positive exit value upon failure
or interruption, relative to the file's position in argv[].
* remote completion of / will work, without putting a leading "///".
This is actually a bug in ftpd(1), where "NLST /" prefixes all names
with "//", but fixing every ftpd(1) is not an option...
1997-02-01 13:44:54 +03:00
|
|
|
" - stalled -");
|
1997-01-19 17:19:02 +03:00
|
|
|
} else {
|
1997-11-01 17:36:49 +03:00
|
|
|
remaining = (int)
|
|
|
|
((filesize - restart_point) / (bytes / elapsed) - elapsed);
|
|
|
|
if (remaining >= 100 * SECSPERHOUR)
|
1997-10-11 16:05:15 +04:00
|
|
|
len += snprintf(buf + len, sizeof(buf) - len,
|
|
|
|
" --:-- ETA");
|
|
|
|
else {
|
1997-11-01 17:36:49 +03:00
|
|
|
i = remaining / SECSPERHOUR;
|
1997-10-11 16:05:15 +04:00
|
|
|
if (i)
|
|
|
|
len += snprintf(buf + len, sizeof(buf) - len,
|
|
|
|
"%2d:", i);
|
|
|
|
else
|
|
|
|
len += snprintf(buf + len, sizeof(buf) - len,
|
|
|
|
" ");
|
1997-11-01 17:36:49 +03:00
|
|
|
i = remaining % SECSPERHOUR;
|
1997-10-11 16:05:15 +04:00
|
|
|
len += snprintf(buf + len, sizeof(buf) - len,
|
|
|
|
"%02d:%02d ETA", i / 60, i % 60);
|
|
|
|
}
|
1997-01-19 17:19:02 +03:00
|
|
|
}
|
1998-06-04 12:28:35 +04:00
|
|
|
(void)write(fileno(ttyout), buf, len);
|
1997-01-19 17:19:02 +03:00
|
|
|
|
[Yet Another Huge Ftp Commit - hopefully the last for a while,
barring any more little things people want added ...]
New features:
* progressmeter is now asynchronous, so "stalled" transfers can be
detected. "- stalled -" is displayed instead of the ETA in this case.
When the xfer resumes, the time that the xfer was stalled for is
factored out of the ETA. It is debatable whether this is better than
not factoring it out, but I like it this way (I.e, if it stalls for 8
seconds and the ETA was 30 seconds, when it resumes the ETA will still
be 30 seconds).
* verbosity can be disabled on the command line (-V), so that in auto-fetch
mode the only lines displayed will be a description of the file, and
the progress bar (if possible)
* if the screen is resized (and detected via the SIGWINCH signal), the
progress bar will rescale automatically.
Bugs fixed:
* progress bar will not use the last character on the line, as this can
cause problems on some terminals
* screen dimensions (via ioctl(TIOCWINSZ)) should use stdout not stdin
* progressmeter() used some vars before initialising them
* ^D will quit now. [fixes bin/3162]
* use hstrerror() to generate error message for host name lookup failure.
* use getcwd instead of getwd (it should have been OK, but why tempt fate?)
* auto-fetch transfers will always return a positive exit value upon failure
or interruption, relative to the file's position in argv[].
* remote completion of / will work, without putting a leading "///".
This is actually a bug in ftpd(1), where "NLST /" prefixes all names
with "//", but fixing every ftpd(1) is not an option...
1997-02-01 13:44:54 +03:00
|
|
|
if (flag == -1) {
|
1998-08-08 10:46:01 +04:00
|
|
|
(void)xsignal(SIGALRM, updateprogressmeter);
|
[Yet Another Huge Ftp Commit - hopefully the last for a while,
barring any more little things people want added ...]
New features:
* progressmeter is now asynchronous, so "stalled" transfers can be
detected. "- stalled -" is displayed instead of the ETA in this case.
When the xfer resumes, the time that the xfer was stalled for is
factored out of the ETA. It is debatable whether this is better than
not factoring it out, but I like it this way (I.e, if it stalls for 8
seconds and the ETA was 30 seconds, when it resumes the ETA will still
be 30 seconds).
* verbosity can be disabled on the command line (-V), so that in auto-fetch
mode the only lines displayed will be a description of the file, and
the progress bar (if possible)
* if the screen is resized (and detected via the SIGWINCH signal), the
progress bar will rescale automatically.
Bugs fixed:
* progress bar will not use the last character on the line, as this can
cause problems on some terminals
* screen dimensions (via ioctl(TIOCWINSZ)) should use stdout not stdin
* progressmeter() used some vars before initialising them
* ^D will quit now. [fixes bin/3162]
* use hstrerror() to generate error message for host name lookup failure.
* use getcwd instead of getwd (it should have been OK, but why tempt fate?)
* auto-fetch transfers will always return a positive exit value upon failure
or interruption, relative to the file's position in argv[].
* remote completion of / will work, without putting a leading "///".
This is actually a bug in ftpd(1), where "NLST /" prefixes all names
with "//", but fixing every ftpd(1) is not an option...
1997-02-01 13:44:54 +03:00
|
|
|
alarmtimer(1); /* set alarm timer for 1 Hz */
|
|
|
|
} else if (flag == 1) {
|
1998-08-08 10:46:01 +04:00
|
|
|
(void)xsignal(SIGALRM, SIG_DFL);
|
[Yet Another Huge Ftp Commit - hopefully the last for a while,
barring any more little things people want added ...]
New features:
* progressmeter is now asynchronous, so "stalled" transfers can be
detected. "- stalled -" is displayed instead of the ETA in this case.
When the xfer resumes, the time that the xfer was stalled for is
factored out of the ETA. It is debatable whether this is better than
not factoring it out, but I like it this way (I.e, if it stalls for 8
seconds and the ETA was 30 seconds, when it resumes the ETA will still
be 30 seconds).
* verbosity can be disabled on the command line (-V), so that in auto-fetch
mode the only lines displayed will be a description of the file, and
the progress bar (if possible)
* if the screen is resized (and detected via the SIGWINCH signal), the
progress bar will rescale automatically.
Bugs fixed:
* progress bar will not use the last character on the line, as this can
cause problems on some terminals
* screen dimensions (via ioctl(TIOCWINSZ)) should use stdout not stdin
* progressmeter() used some vars before initialising them
* ^D will quit now. [fixes bin/3162]
* use hstrerror() to generate error message for host name lookup failure.
* use getcwd instead of getwd (it should have been OK, but why tempt fate?)
* auto-fetch transfers will always return a positive exit value upon failure
or interruption, relative to the file's position in argv[].
* remote completion of / will work, without putting a leading "///".
This is actually a bug in ftpd(1), where "NLST /" prefixes all names
with "//", but fixing every ftpd(1) is not an option...
1997-02-01 13:44:54 +03:00
|
|
|
alarmtimer(0);
|
1998-06-04 12:28:35 +04:00
|
|
|
(void)putc('\n', ttyout);
|
[Yet Another Huge Ftp Commit - hopefully the last for a while,
barring any more little things people want added ...]
New features:
* progressmeter is now asynchronous, so "stalled" transfers can be
detected. "- stalled -" is displayed instead of the ETA in this case.
When the xfer resumes, the time that the xfer was stalled for is
factored out of the ETA. It is debatable whether this is better than
not factoring it out, but I like it this way (I.e, if it stalls for 8
seconds and the ETA was 30 seconds, when it resumes the ETA will still
be 30 seconds).
* verbosity can be disabled on the command line (-V), so that in auto-fetch
mode the only lines displayed will be a description of the file, and
the progress bar (if possible)
* if the screen is resized (and detected via the SIGWINCH signal), the
progress bar will rescale automatically.
Bugs fixed:
* progress bar will not use the last character on the line, as this can
cause problems on some terminals
* screen dimensions (via ioctl(TIOCWINSZ)) should use stdout not stdin
* progressmeter() used some vars before initialising them
* ^D will quit now. [fixes bin/3162]
* use hstrerror() to generate error message for host name lookup failure.
* use getcwd instead of getwd (it should have been OK, but why tempt fate?)
* auto-fetch transfers will always return a positive exit value upon failure
or interruption, relative to the file's position in argv[].
* remote completion of / will work, without putting a leading "///".
This is actually a bug in ftpd(1), where "NLST /" prefixes all names
with "//", but fixing every ftpd(1) is not an option...
1997-02-01 13:44:54 +03:00
|
|
|
}
|
1998-06-04 12:28:35 +04:00
|
|
|
fflush(ttyout);
|
1997-12-13 02:34:56 +03:00
|
|
|
#endif /* SMALL */
|
1997-01-19 17:19:02 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Display transfer statistics.
|
|
|
|
* Requires start to be initialised by progressmeter(-1),
|
|
|
|
* direction to be defined by xfer routines, and filesize and bytes
|
|
|
|
* to be updated by xfer routines
|
1998-06-04 12:28:35 +04:00
|
|
|
* If siginfo is nonzero, an ETA is displayed, and the output goes to stderr
|
|
|
|
* instead of ttyout.
|
1997-01-19 17:19:02 +03:00
|
|
|
*/
|
|
|
|
void
|
|
|
|
ptransfer(siginfo)
|
|
|
|
int siginfo;
|
|
|
|
{
|
1997-12-13 02:34:56 +03:00
|
|
|
#ifndef SMALL
|
1998-01-20 07:39:34 +03:00
|
|
|
struct timeval now, td, wait;
|
1997-01-19 17:19:02 +03:00
|
|
|
double elapsed;
|
1998-09-28 13:03:22 +04:00
|
|
|
off_t bytespersec;
|
1997-11-01 17:36:49 +03:00
|
|
|
int meg, remaining, hh, len;
|
1997-01-19 17:19:02 +03:00
|
|
|
char buf[100];
|
|
|
|
|
|
|
|
if (!verbose && !siginfo)
|
|
|
|
return;
|
|
|
|
|
1998-01-18 17:23:33 +03:00
|
|
|
(void)gettimeofday(&now, NULL);
|
1997-01-19 17:19:02 +03:00
|
|
|
timersub(&now, &start, &td);
|
|
|
|
elapsed = td.tv_sec + (td.tv_usec / 1000000.0);
|
1998-09-28 13:03:22 +04:00
|
|
|
bytespersec = 0;
|
1997-01-19 17:19:02 +03:00
|
|
|
meg = 0;
|
1998-09-28 13:03:22 +04:00
|
|
|
if (bytes > 0) {
|
|
|
|
bytespersec = bytes;
|
|
|
|
if (elapsed > 0.0)
|
|
|
|
bytespersec /= elapsed;
|
|
|
|
if (bytespersec > (1024 * 1024))
|
|
|
|
meg = 1;
|
|
|
|
}
|
1997-11-01 17:36:49 +03:00
|
|
|
len = 0;
|
|
|
|
len += snprintf(buf + len, sizeof(buf) - len,
|
1998-05-20 04:55:52 +04:00
|
|
|
#ifndef NO_QUAD
|
|
|
|
"%qd byte%s %s in ", (long long)bytes,
|
|
|
|
#else
|
|
|
|
"%ld byte%s %s in ", (long)bytes,
|
|
|
|
#endif
|
|
|
|
bytes == 1 ? "" : "s", direction);
|
1998-01-20 07:39:34 +03:00
|
|
|
remaining = (int)elapsed;
|
|
|
|
if (remaining > SECSPERDAY) {
|
|
|
|
int days;
|
|
|
|
|
|
|
|
days = remaining / SECSPERDAY;
|
|
|
|
remaining %= SECSPERDAY;
|
|
|
|
len += snprintf(buf + len, sizeof(buf) - len,
|
|
|
|
"%d day%s ", days, days == 1 ? "" : "s");
|
|
|
|
}
|
|
|
|
hh = remaining / SECSPERHOUR;
|
|
|
|
remaining %= SECSPERHOUR;
|
|
|
|
if (hh)
|
|
|
|
len += snprintf(buf + len, sizeof(buf) - len, "%2d:", hh);
|
|
|
|
len += snprintf(buf + len, sizeof(buf) - len,
|
|
|
|
"%02d:%02d (%.2f %sB/s)", remaining / 60, remaining % 60,
|
1998-09-28 13:03:22 +04:00
|
|
|
bytespersec / (1024.0 * (meg ? 1024.0 : 1.0)),
|
1998-01-20 07:39:34 +03:00
|
|
|
meg ? "M" : "K");
|
|
|
|
|
1997-05-12 15:41:13 +04:00
|
|
|
if (siginfo && bytes > 0 && elapsed > 0.0 && filesize >= 0
|
|
|
|
&& bytes + restart_point <= filesize) {
|
1997-01-19 17:19:02 +03:00
|
|
|
remaining = (int)((filesize - restart_point) /
|
|
|
|
(bytes / elapsed) - elapsed);
|
1997-11-01 17:36:49 +03:00
|
|
|
hh = remaining / SECSPERHOUR;
|
|
|
|
remaining %= SECSPERHOUR;
|
1998-01-20 07:39:34 +03:00
|
|
|
len += snprintf(buf + len, sizeof(buf) - len, " ETA: ");
|
|
|
|
if (hh)
|
|
|
|
len += snprintf(buf + len, sizeof(buf) - len, "%2d:",
|
|
|
|
hh);
|
1997-11-01 17:36:49 +03:00
|
|
|
len += snprintf(buf + len, sizeof(buf) - len,
|
1998-01-20 07:39:34 +03:00
|
|
|
"%02d:%02d", remaining / 60, remaining % 60);
|
|
|
|
timersub(&now, &lastupdate, &wait);
|
|
|
|
if (wait.tv_sec >= STALLTIME)
|
|
|
|
len += snprintf(buf + len, sizeof(buf) - len,
|
|
|
|
" (stalled)");
|
1997-01-19 17:19:02 +03:00
|
|
|
}
|
1998-01-20 07:39:34 +03:00
|
|
|
len += snprintf(buf + len, sizeof(buf) - len, "\n");
|
1998-06-04 12:28:35 +04:00
|
|
|
(void)write(siginfo ? STDERR_FILENO : fileno(ttyout), buf, len);
|
1997-12-13 02:34:56 +03:00
|
|
|
#endif /* SMALL */
|
1997-01-19 17:19:02 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* List words in stringlist, vertically arranged
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
list_vertical(sl)
|
|
|
|
StringList *sl;
|
|
|
|
{
|
|
|
|
int i, j, w;
|
|
|
|
int columns, width, lines, items;
|
|
|
|
char *p;
|
|
|
|
|
|
|
|
width = items = 0;
|
|
|
|
|
|
|
|
for (i = 0 ; i < sl->sl_cur ; i++) {
|
|
|
|
w = strlen(sl->sl_str[i]);
|
|
|
|
if (w > width)
|
|
|
|
width = w;
|
|
|
|
}
|
|
|
|
width = (width + 8) &~ 7;
|
|
|
|
|
|
|
|
columns = ttywidth / width;
|
|
|
|
if (columns == 0)
|
|
|
|
columns = 1;
|
|
|
|
lines = (sl->sl_cur + columns - 1) / columns;
|
|
|
|
for (i = 0; i < lines; i++) {
|
|
|
|
for (j = 0; j < columns; j++) {
|
|
|
|
p = sl->sl_str[j * lines + i];
|
|
|
|
if (p)
|
1998-06-04 12:28:35 +04:00
|
|
|
fputs(p, ttyout);
|
1997-01-19 17:19:02 +03:00
|
|
|
if (j * lines + i + lines >= sl->sl_cur) {
|
1998-06-04 12:28:35 +04:00
|
|
|
putc('\n', ttyout);
|
1997-01-19 17:19:02 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
w = strlen(p);
|
|
|
|
while (w < width) {
|
|
|
|
w = (w + 8) &~ 7;
|
1998-06-04 12:28:35 +04:00
|
|
|
(void)putc('\t', ttyout);
|
1997-01-19 17:19:02 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
[Yet Another Huge Ftp Commit - hopefully the last for a while,
barring any more little things people want added ...]
New features:
* progressmeter is now asynchronous, so "stalled" transfers can be
detected. "- stalled -" is displayed instead of the ETA in this case.
When the xfer resumes, the time that the xfer was stalled for is
factored out of the ETA. It is debatable whether this is better than
not factoring it out, but I like it this way (I.e, if it stalls for 8
seconds and the ETA was 30 seconds, when it resumes the ETA will still
be 30 seconds).
* verbosity can be disabled on the command line (-V), so that in auto-fetch
mode the only lines displayed will be a description of the file, and
the progress bar (if possible)
* if the screen is resized (and detected via the SIGWINCH signal), the
progress bar will rescale automatically.
Bugs fixed:
* progress bar will not use the last character on the line, as this can
cause problems on some terminals
* screen dimensions (via ioctl(TIOCWINSZ)) should use stdout not stdin
* progressmeter() used some vars before initialising them
* ^D will quit now. [fixes bin/3162]
* use hstrerror() to generate error message for host name lookup failure.
* use getcwd instead of getwd (it should have been OK, but why tempt fate?)
* auto-fetch transfers will always return a positive exit value upon failure
or interruption, relative to the file's position in argv[].
* remote completion of / will work, without putting a leading "///".
This is actually a bug in ftpd(1), where "NLST /" prefixes all names
with "//", but fixing every ftpd(1) is not an option...
1997-02-01 13:44:54 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Update the global ttywidth value, using TIOCGWINSZ.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
setttywidth(a)
|
|
|
|
int a;
|
|
|
|
{
|
|
|
|
struct winsize winsize;
|
|
|
|
|
1998-09-28 13:03:22 +04:00
|
|
|
if (ioctl(fileno(ttyout), TIOCGWINSZ, &winsize) != -1 &&
|
|
|
|
winsize.ws_col != 0)
|
[Yet Another Huge Ftp Commit - hopefully the last for a while,
barring any more little things people want added ...]
New features:
* progressmeter is now asynchronous, so "stalled" transfers can be
detected. "- stalled -" is displayed instead of the ETA in this case.
When the xfer resumes, the time that the xfer was stalled for is
factored out of the ETA. It is debatable whether this is better than
not factoring it out, but I like it this way (I.e, if it stalls for 8
seconds and the ETA was 30 seconds, when it resumes the ETA will still
be 30 seconds).
* verbosity can be disabled on the command line (-V), so that in auto-fetch
mode the only lines displayed will be a description of the file, and
the progress bar (if possible)
* if the screen is resized (and detected via the SIGWINCH signal), the
progress bar will rescale automatically.
Bugs fixed:
* progress bar will not use the last character on the line, as this can
cause problems on some terminals
* screen dimensions (via ioctl(TIOCWINSZ)) should use stdout not stdin
* progressmeter() used some vars before initialising them
* ^D will quit now. [fixes bin/3162]
* use hstrerror() to generate error message for host name lookup failure.
* use getcwd instead of getwd (it should have been OK, but why tempt fate?)
* auto-fetch transfers will always return a positive exit value upon failure
or interruption, relative to the file's position in argv[].
* remote completion of / will work, without putting a leading "///".
This is actually a bug in ftpd(1), where "NLST /" prefixes all names
with "//", but fixing every ftpd(1) is not an option...
1997-02-01 13:44:54 +03:00
|
|
|
ttywidth = winsize.ws_col;
|
|
|
|
else
|
|
|
|
ttywidth = 80;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set the SIGALRM interval timer for wait seconds, 0 to disable.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
alarmtimer(wait)
|
|
|
|
int wait;
|
|
|
|
{
|
|
|
|
struct itimerval itv;
|
|
|
|
|
|
|
|
itv.it_value.tv_sec = wait;
|
|
|
|
itv.it_value.tv_usec = 0;
|
|
|
|
itv.it_interval = itv.it_value;
|
|
|
|
setitimer(ITIMER_REAL, &itv, NULL);
|
|
|
|
}
|
1997-04-05 07:27:32 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Setup or cleanup EditLine structures
|
|
|
|
*/
|
|
|
|
#ifndef SMALL
|
|
|
|
void
|
|
|
|
controlediting()
|
|
|
|
{
|
|
|
|
if (editing && el == NULL && hist == NULL) {
|
1997-10-14 20:31:22 +04:00
|
|
|
HistEvent ev;
|
1998-07-29 06:46:26 +04:00
|
|
|
int editmode;
|
1997-10-14 20:31:22 +04:00
|
|
|
|
1998-06-04 12:28:35 +04:00
|
|
|
el = el_init(__progname, stdin, ttyout, stderr);
|
1998-05-20 04:55:52 +04:00
|
|
|
/* init editline */
|
1997-04-05 07:27:32 +04:00
|
|
|
hist = history_init(); /* init the builtin history */
|
1998-05-20 04:55:52 +04:00
|
|
|
history(hist, &ev, H_SETSIZE, 100);/* remember 100 events */
|
1997-04-05 07:27:32 +04:00
|
|
|
el_set(el, EL_HIST, history, hist); /* use history */
|
|
|
|
|
|
|
|
el_set(el, EL_EDITOR, "emacs"); /* default editor is emacs */
|
|
|
|
el_set(el, EL_PROMPT, prompt); /* set the prompt function */
|
|
|
|
|
|
|
|
/* add local file completion, bind to TAB */
|
|
|
|
el_set(el, EL_ADDFN, "ftp-complete",
|
|
|
|
"Context sensitive argument completion",
|
|
|
|
complete);
|
|
|
|
el_set(el, EL_BIND, "^I", "ftp-complete", NULL);
|
|
|
|
el_source(el, NULL); /* read ~/.editrc */
|
1998-07-29 06:46:26 +04:00
|
|
|
if ((el_get(el, EL_EDITMODE, &editmode) != -1) && editmode == 0)
|
|
|
|
editing = 0; /* the user doesn't want editing,
|
|
|
|
* so disable, and let statement
|
|
|
|
* below cleanup */
|
|
|
|
else
|
|
|
|
el_set(el, EL_SIGNAL, 1);
|
|
|
|
}
|
|
|
|
if (!editing) {
|
1997-04-05 07:27:32 +04:00
|
|
|
if (hist) {
|
|
|
|
history_end(hist);
|
|
|
|
hist = NULL;
|
|
|
|
}
|
|
|
|
if (el) {
|
|
|
|
el_end(el);
|
|
|
|
el = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif /* !SMALL */
|
1998-07-10 08:39:03 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Parse the specified socket buffer size.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
getsockbufsize(arg)
|
|
|
|
const char *arg;
|
|
|
|
{
|
|
|
|
char *cp;
|
|
|
|
int val;
|
|
|
|
|
1998-11-06 19:52:42 +03:00
|
|
|
if (!isdigit((unsigned char)arg[0]))
|
1998-07-10 08:39:03 +04:00
|
|
|
return (-1);
|
|
|
|
|
|
|
|
val = strtol(arg, &cp, 10);
|
|
|
|
if (cp != NULL) {
|
|
|
|
if (cp[1] != '\0')
|
|
|
|
return (-1);
|
|
|
|
if (cp[0] == 'k')
|
|
|
|
val *= 1024;
|
|
|
|
if (cp[0] == 'm')
|
|
|
|
val *= 1024 * 1024;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (val < 0)
|
|
|
|
return (-1);
|
|
|
|
|
|
|
|
return (val);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set up socket buffer sizes before a connection is made.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
setupsockbufsize(sock)
|
|
|
|
int sock;
|
|
|
|
{
|
|
|
|
static int sndbuf_default, rcvbuf_default;
|
|
|
|
int len, size;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Get the default socket buffer sizes if we don't already
|
|
|
|
* have them. It doesn't matter which socket we do this
|
|
|
|
* to, because on the first call no socket buffer sizes
|
|
|
|
* will have been modified, so we are guaranteed to get
|
|
|
|
* the system defaults.
|
|
|
|
*/
|
|
|
|
if (sndbuf_default == 0) {
|
|
|
|
len = sizeof(sndbuf_default);
|
|
|
|
if (getsockopt(sock, SOL_SOCKET, SO_SNDBUF, &sndbuf_default,
|
|
|
|
&len) < 0)
|
|
|
|
err(1, "unable to get default sndbuf size");
|
|
|
|
len = sizeof(rcvbuf_default);
|
|
|
|
if (getsockopt(sock, SOL_SOCKET, SO_RCVBUF, &rcvbuf_default,
|
|
|
|
&len) < 0)
|
|
|
|
err(1, "unable to get default rcvbuf size");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
size = sndbuf_size ? sndbuf_size : sndbuf_default;
|
|
|
|
if (setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size)) < 0)
|
|
|
|
warn("unable to set sndbuf size %d", size);
|
|
|
|
|
|
|
|
size = rcvbuf_size ? rcvbuf_size : rcvbuf_default;
|
|
|
|
if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)) < 0)
|
|
|
|
warn("unable to set rcvbuf size %d", size);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If the socket buffer sizes were not set manually (i.e. came from a
|
|
|
|
* configuration file), reset them so the right thing will happen on
|
|
|
|
* subsequent connections.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
resetsockbufsize()
|
|
|
|
{
|
|
|
|
|
|
|
|
if (sndbuf_manual == 0)
|
|
|
|
sndbuf_size = 0;
|
|
|
|
if (rcvbuf_manual == 0)
|
|
|
|
rcvbuf_size = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Internal version of connect(2); sets socket buffer sizes first.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
xconnect(sock, name, namelen)
|
|
|
|
int sock;
|
|
|
|
const struct sockaddr *name;
|
|
|
|
int namelen;
|
|
|
|
{
|
|
|
|
|
|
|
|
setupsockbufsize(sock);
|
|
|
|
return (connect(sock, name, namelen));
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Internal version of listen(2); sets socket buffer sizes first.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
xlisten(sock, backlog)
|
|
|
|
int sock, backlog;
|
|
|
|
{
|
|
|
|
|
|
|
|
setupsockbufsize(sock);
|
|
|
|
return (listen(sock, backlog));
|
|
|
|
}
|
1998-08-03 05:49:25 +04:00
|
|
|
|
|
|
|
void *
|
|
|
|
xmalloc(size)
|
|
|
|
size_t size;
|
|
|
|
{
|
|
|
|
void *p;
|
|
|
|
|
|
|
|
p = malloc(size);
|
|
|
|
if (p == NULL)
|
|
|
|
err(1, "Unable to allocate %ld bytes of memory", (long)size);
|
|
|
|
return (p);
|
|
|
|
}
|
|
|
|
|
|
|
|
char *
|
|
|
|
xstrdup(str)
|
|
|
|
const char *str;
|
|
|
|
{
|
|
|
|
char *s;
|
|
|
|
|
|
|
|
if (str == NULL)
|
|
|
|
errx(1, "xstrdup() called with NULL argument");
|
|
|
|
s = strdup(str);
|
|
|
|
if (s == NULL)
|
|
|
|
err(1, "Unable to allocate memory for string copy");
|
|
|
|
return (s);
|
|
|
|
}
|
1998-08-08 10:46:01 +04:00
|
|
|
|
|
|
|
sig_t
|
|
|
|
xsignal(sig, func)
|
|
|
|
int sig;
|
|
|
|
void (*func) __P((int));
|
|
|
|
{
|
|
|
|
struct sigaction act, oact;
|
|
|
|
|
|
|
|
act.sa_handler = func;
|
|
|
|
sigemptyset(&act.sa_mask);
|
|
|
|
act.sa_flags = SA_RESTART;
|
|
|
|
if (sigaction(sig, &act, &oact) < 0)
|
|
|
|
return (SIG_ERR);
|
|
|
|
return (oact.sa_handler);
|
|
|
|
}
|