config menu support and cleaned up old stuff
This commit is contained in:
parent
011f3145f9
commit
ba8da3929e
5
Makefile
5
Makefile
|
@ -1,4 +1,4 @@
|
|||
# $Id: Makefile,v 1.34 1999/05/07 21:36:36 werner Exp $
|
||||
# $Id: Makefile,v 1.35 1999/07/01 18:00:07 he Exp $
|
||||
#
|
||||
# Toplevel Makefile for isdn4k-utils
|
||||
#
|
||||
|
@ -114,6 +114,9 @@ endif
|
|||
ifeq ($(CONFIG_FAQ),y)
|
||||
SUBDIRS := $(SUBDIRS) FAQ
|
||||
endif
|
||||
ifeq ($(CONFIG_EUROFILE),y)
|
||||
SUBDIRS := $(SUBDIRS) eurofile
|
||||
endif
|
||||
ifneq ($(SUBDIRS),)
|
||||
ifeq ($(filter lib,$(SUBDIRS)),)
|
||||
SUBDIRS := lib $(SUBDIRS)
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
mainmenu_option next_comment
|
||||
comment 'Options for EuroFile'
|
||||
bool 'EuroFile server daemon' CONFIG_EFTD
|
||||
comment 'Options for eurofile'
|
||||
comment 'eftp4linux, an implementation of the EUROFILE transfer protocol'
|
||||
bool 'eftd, an EUROFILE server / daemon' CONFIG_EFTD
|
||||
if [ "$CONFIG_EFTD" = "y" ]; then
|
||||
CONFIG_EFTD_WUAUTH=${CONFIG_EFTD_WUAUTH:-"y"}
|
||||
bool ' use wu-ftpd authentification' CONFIG_EFTD_WUAUTH
|
||||
bool ' use wu-ftpd authentification for eftd' CONFIG_EFTD_WUAUTH
|
||||
fi
|
||||
bool 'EuroFile client with command line user interface' CONFIG_EFTP
|
||||
bool 'eftp, an EUROFILE client with command line user interface' CONFIG_EFTP
|
||||
if [ "$CONFIG_EFTP" = "y" ]; then
|
||||
CONFIG_EFTP_READLINE=${CONFIG_EFTP_READLINE:-"y"}
|
||||
bool ' support command line editing with GNU readline' CONFIG_EFTP_READLINE
|
||||
bool ' command line editing with GNU readline for eftp' CONFIG_EFTP_READLINE
|
||||
fi
|
||||
endmenu
|
||||
|
|
|
@ -1,23 +1,71 @@
|
|||
$Id: README.CVS,v 1.2 1999/06/29 18:37:13 he Exp $
|
||||
$Id: README.CVS,v 1.3 1999/07/01 18:00:16 he Exp $
|
||||
|
||||
From version 0.0.11, eftp4linux is added to the isdn4linux cvs
|
||||
repository. This will allow bug fixes to be faster distributed. It
|
||||
will also increase availability because the isdn4linux repository
|
||||
are available from several sources.
|
||||
will also increase availability.
|
||||
|
||||
As long as it is considered alpha, it will only appear in the isdn4k-utils
|
||||
configuration menu if the "CONFIG_EXPERIMENTAL" option is set.
|
||||
(Currently, it even will not appear in the menu at all because
|
||||
eftp4linux is not added to the isdn4k-utils main config menu and
|
||||
main makefile yet).
|
||||
|
||||
You can still cd to the eurofile subdirectory (as described in the
|
||||
INSTALL file) and compile eftp4linux stand-alone, but you will not
|
||||
inherit the isdn4k-utils main menu config options then.
|
||||
|
||||
As long as it is alpha, it also might not be included with the beta-releases
|
||||
of the isdn4k-utils package. But in turn, stand-alone snapshots from
|
||||
the eftp4linux package will contiune to be distributed from the
|
||||
the eftp4linux package will contiune to be distributed from
|
||||
ftp://ftp.hamburg.pop.de/pub/local/linux/i4l-eft/.
|
||||
However, not every change commited to cvs will be distrinuted on the
|
||||
However, not every change commited to cvs will be distributed on the
|
||||
ftp server. Only when important changes (important new features or
|
||||
imporatnt bug fixes) are present or when sufficiently
|
||||
important bug fixes) are present or when sufficiently
|
||||
many less important changes have accumulated, a new stand-alone release
|
||||
will be made.
|
||||
|
||||
|
||||
How to get a new versions from the CVS server
|
||||
=============================================
|
||||
|
||||
If you already mirror the isdn4k-utils from the isdn4linux cvs server,
|
||||
you don't need to do anything special. eftp4linux should appear in the
|
||||
new eurofile subdirectory of the isdn4k-utils packages after your next
|
||||
cvs update.
|
||||
|
||||
But you do not need to mirror the whole isdn4k-utils package just for
|
||||
getting the most actual eftp4linux sources. eftp4linux will continue
|
||||
to be installable stand-alone and it is sufficient to only mirror
|
||||
the eftp4linux part of the isdn4linux CVS repository.
|
||||
|
||||
If you want to do so, type
|
||||
|
||||
cvs --version
|
||||
|
||||
from the shell. If this does not work (or the reported version number
|
||||
is too low), you need to install cvs 1.8 or newer on your system.
|
||||
|
||||
Create a dirctory
|
||||
|
||||
mkdir ~/i4ldev
|
||||
cd ~/i4ldev
|
||||
|
||||
Next, do a
|
||||
export CVSROOT=:pserver:guest@cvs.isdn4linux.de:/i4ldev
|
||||
cvs login
|
||||
|
||||
and enter an arbitray password if asked for. (csh or tcsh users need
|
||||
to type the equivalent setenv command instead of export).
|
||||
|
||||
Initially check out the eurofile source tree by
|
||||
|
||||
cvs -z3 checkout isdn4k-utils/eurofile
|
||||
|
||||
|
||||
If you later want to update your local copy, simply do
|
||||
|
||||
cd ~/i4ldev/isdn4k-utils/eurofile
|
||||
cvs -z3 update -dP .
|
||||
|
||||
whenever you like. That's all. Type "make clean; make" to compile
|
||||
the updated version.
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
$Id: FAQ,v 1.1 1999/06/30 16:50:57 he Exp $
|
||||
$Id: FAQ,v 1.2 1999/07/01 18:00:20 he Exp $
|
||||
|
||||
QUESTION: How can I control the amount of debugging output?
|
||||
=========
|
||||
|
||||
ANSWER:
|
||||
|
||||
eftd.c and eftp.c contain set a global variable tdu_stderr_mask.
|
||||
The eftd server now also allows to
|
||||
control the amount of debugging output via command line arguments,
|
||||
refer to the eftd(8) man page for further info.
|
||||
|
||||
eftd.c and eftp.c contain a global variable tdu_stderr_mask.
|
||||
Locate this and change the comment characters (/* .. */). For only
|
||||
logging Error events, the final active statement should be
|
||||
|
||||
|
@ -14,9 +18,6 @@ logging Error events, the final active statement should be
|
|||
To remove isdnlog output to stderr, you can also comment out the
|
||||
'tdu_open_isdtlog()' statement.
|
||||
|
||||
The eftd server now also allows to
|
||||
control the amount of debugging output via command line arguments,
|
||||
refer to the eftd(8) man page for further info.
|
||||
|
||||
|
||||
QUESTION: I don't want anonymous users to dial in without a MSN
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
$Id: INTERWORKING,v 1.1 1999/06/30 16:50:58 he Exp $
|
||||
$Id: INTERWORKING,v 1.2 1999/07/01 18:00:21 he Exp $
|
||||
|
||||
The following classes of inter-working problems have been identified
|
||||
====================================================================
|
||||
|
@ -112,7 +112,7 @@ BIANCA ISDN
|
|||
|
||||
(As BIANCA supports unix, the developers might have been aware of the
|
||||
case sensitiveness problems. But unfortunately, I don't have any
|
||||
logs from BIANCA sessions where a long nameed file was tried to be
|
||||
logs from BIANCA sessions where a long name file was tried to be
|
||||
downloaded.
|
||||
|
||||
|
||||
|
@ -163,4 +163,3 @@ Should the .. directory be present in the file generated in response
|
|||
to an [S]LIST request? AVM/Fritz clients generate this entry locally
|
||||
which causes .. to be displayed twice if the server also included a ..
|
||||
entry in the SLIST response file.
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
$Id: INTERWORKING.de,v 1.1 1999/06/30 16:50:58 he Exp $
|
||||
$Id: INTERWORKING.de,v 1.2 1999/07/01 18:00:24 he Exp $
|
||||
|
||||
Bisher ist Interworking der 0.0.2-Version mit den folgenden
|
||||
Protokollimplementierungen offenbar (teilweise) erfolgreich gewesen.
|
||||
|
@ -12,4 +12,7 @@ Protokollimplementierungen offenbar (teilweise) erfolgreich gewesen.
|
|||
(wobei trotzdem Probleme wie unten beschrieben auftreten können,
|
||||
genaueres steht im File INTERWORKING in der Distribution)
|
||||
|
||||
|
||||
In Version 0.0.9 wurde ein Fehler entdeckt, der in allen vorherigen
|
||||
Versionen auch schon drin war und zu Problemen führen kann, wenn lange
|
||||
Dateien (ab ca 255000 bytes, bei manchen gegenstellen auch wesentlich
|
||||
später) führen kann.
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
$Id: PROBLEMS-2.1.114,v 1.1 1999/06/30 16:51:00 he Exp $
|
||||
$Id: PROBLEMS-2.1.114,v 1.2 1999/07/01 18:00:25 he Exp $
|
||||
|
||||
Known problems observed when using X.25 on top of isdn with kernel 2.1.126
|
||||
==========================================================================
|
||||
Known problems observed when using X.25 on top of isdn with kernels
|
||||
===================================================================
|
||||
|
||||
The X.25 PLP implementation was originally designed to be used on top
|
||||
of a synchronous line (accessed via an X.25 network device driver)
|
||||
|
@ -27,28 +27,18 @@ the syslog. This does not indicate any problem and can be ignored.
|
|||
When establishing the first X.25 connection on a link, there is a
|
||||
delay of some seconds until the link becomes established. This is only
|
||||
a performance problem and harmless. Furthermore, this is fixed with
|
||||
recent isdn4linux versions from the isdn4linux CVS tree.
|
||||
recent isdn4linux versions from the isdn4linux CVS tree. Kernel
|
||||
2.2.10 still contains this outdated isdn4linux version.
|
||||
|
||||
Problems related to the X.25 PLP implementation:
|
||||
================================================
|
||||
|
||||
isdn B channels are not closed automatically when the X.25 PLP
|
||||
connection is closed. If you are lucky, your peer does it. Thus,
|
||||
connection is closed. If you are lucky, your peer does it. eftd
|
||||
and the eftp.sh shell script also try to close connection. But this
|
||||
might sometime fail due to bugs. Thus,
|
||||
monitor your isdn connections while using X.25 on top of isdn4linux
|
||||
(i.e. by watching syslog messages or by an isdn monitor program).
|
||||
You need to close the B channel connection by hand (using the
|
||||
You can close the B channel connection by hand (using the
|
||||
"isdnctrl hangup" command) or rely on the isdn network interface's
|
||||
hangup timeout. The scripts provided with this this test distribution
|
||||
try to provide workourounds for this.
|
||||
|
||||
Kernels prior to 2.1.125 have a bug in include/linux/x25.h which
|
||||
has been reported to cause compilation problems on glibc2 systems.
|
||||
|
||||
2.1.127 introduced changes that broke current i4l CVS isdn subsystem.
|
||||
Until this is fixed, only use cvs isdn with 2.1.126 or older.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
hangup timeout.
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
.\" $Id: efthosts.5,v 1.1 1999/06/30 16:51:06 he Exp $
|
||||
.\" $Id: efthosts.5,v 1.2 1999/07/01 18:00:26 he Exp $
|
||||
.\" SCCSID: @(#)$Original-Id: ftphosts.5,v 1.2 1997/01/10 06:27:02 sob Exp $
|
||||
.\" based on ftphosts.5 1.2 1/26/93
|
||||
.\"
|
||||
.TH ftphosts 5
|
||||
.TH efthosts 5
|
||||
.SH Name
|
||||
ftphosts \- ftpd individual user host access file
|
||||
efthosts \- eftd individual user host access file
|
||||
.SH Description
|
||||
The ftphosts file is used to allow or deny access to certain
|
||||
The efthosts file is used to allow or deny access to certain
|
||||
accounts from various hosts.
|
||||
.SH Access Capabilities
|
||||
.TP 0.5i
|
||||
|
@ -16,10 +16,8 @@ Only allow host(s) matching <addrglob> to log in as <username>.
|
|||
.B deny <username> <addrglob> [<addrglob> ...]
|
||||
Always deny host(s) matching <addrglob> to log in as <username>.
|
||||
.SH Files
|
||||
FTPLIB/ftphosts
|
||||
/etc/isdn/efthosts
|
||||
.SH See Also
|
||||
.BR ftpd(8) ,
|
||||
.BR ftpaccess(5) ,
|
||||
.BR ftplog(5) ,
|
||||
.BR ftpconversions(5) ,
|
||||
.BR ftpshut(8)
|
||||
.BR eftd(8) ,
|
||||
.BR eftaccess(5) ,
|
||||
.BR eft_wuauth(5)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
$Id: eftp,v 1.1 1999/06/30 16:51:06 he Exp $
|
||||
$Id: eftp,v 1.2 1999/07/01 18:00:27 he Exp $
|
||||
|
||||
Sorry, rather incomplete and not in man page format.
|
||||
|
||||
|
@ -24,7 +24,7 @@ options:
|
|||
|
||||
-i ISDN_NO
|
||||
specify the isdn no of the remote EUROFILE
|
||||
server to connect to. The server will try to
|
||||
server to connect to. The client will try to
|
||||
set up an isdn connection to this number and
|
||||
an X.25 DTE-DTE connection on top of this.
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#$Id: Makefile,v 1.1 1999/06/30 17:19:08 he Exp $
|
||||
#$Id: Makefile,v 1.2 1999/07/01 18:00:31 he Exp $
|
||||
# This Makefile uses GNU-make extensions
|
||||
|
||||
default: eftp
|
||||
|
@ -25,13 +25,6 @@ endif
|
|||
|
||||
ifeq ($(CONFIG_EFTP_READLINE),y)
|
||||
READLINE_CFLAGS=-DCONFIG_EFTP_READLINE
|
||||
# only needed for old implementation
|
||||
# READLINE_O=read_line.o
|
||||
# read_line.o: read_line.c read_line.h
|
||||
# cc $(CFLAGS) -c $(READLINE_CFLAGS) read_line.c -o read_line.o
|
||||
#
|
||||
#
|
||||
#READLINE_LDFLAGS=$(READLINE_O) -L/usr/local/lib -lncurses -lreadline
|
||||
READLINE_LDFLAGS= -lncurses -lreadline
|
||||
endif
|
||||
|
||||
|
@ -45,3 +38,4 @@ clean:
|
|||
rm -f eftp *.o
|
||||
|
||||
.PHONY: clean default
|
||||
|
||||
|
|
|
@ -1,709 +0,0 @@
|
|||
- [chg] eftp.c moved processing of cmd line outside readline_callback_handler
|
||||
(avoids interaction with command executions that prompt for
|
||||
secondary data)
|
||||
|
||||
Unfortunatly, that did not help. Why?
|
||||
|
||||
/* $Id: eftp.c.alternate_rl,v 1.1 1999/06/30 17:19:11 he Exp $ */
|
||||
/*
|
||||
Copyright 1997 by Henner Eisen
|
||||
|
||||
This code is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
CAUTION: this description is somewhat outdated.
|
||||
|
||||
|
||||
This is an experimental and incomplete program. The purpose of
|
||||
this program is NOT to provide a perfect eft (EUROFILE transfer) client
|
||||
for isdn4linux. It's more intended to be a demonstration
|
||||
|
||||
- to show, how X.25 sockets can be used to connect to a remote computer
|
||||
using the ISO-8208 (X.25 DTE-DTE) protocol on top of isdn4linux.
|
||||
- to test data transfer on top of x.25 on top of isdn4linux
|
||||
if your isdn peer can run an eft server.
|
||||
- to give some insights to the EUROFILE protocol (there is no public
|
||||
documentation available anywhere else).
|
||||
|
||||
The whole eft protocol is implemented inside a library, usable via the
|
||||
interface defined in eft.h. My intention is to continue developing
|
||||
and maintaining the core eft protocol implementation. Based on the library,
|
||||
uers are welcome to write other eft clients (and servers).
|
||||
(Think, i.e., about a kde version, http-to-eft gateway, or just a more
|
||||
sophisticated command line interface than this one).
|
||||
|
||||
This program does not close low layer isdn connections by itsself. PLEASE
|
||||
monitor the isdn connection when you are using this program (this is
|
||||
because the current linux x.25 was initially nor intended for DTE-DTE
|
||||
mode on top of isdn, thus, it doesn't close the link after the x.25
|
||||
connections are cleared). If the connection isn't cleared by your peer
|
||||
after the end of your eft session, use the "isdnctrl hangup" command to
|
||||
do this manually. Or use a script wrapper (such as eftp.sh).
|
||||
|
||||
And security was not a primary issue when writing this program (i.e.
|
||||
buffer overflow checks might be missing where necessary). Thus, a bad guy
|
||||
might exploit all kinds of bugs in order to break into your system.
|
||||
|
||||
As this program is not tested well, please ask the operator of
|
||||
your remote eft server before trying to connect to it.
|
||||
Until now, this client hasn't caused any harm, but as testing was very
|
||||
limited, I cannot guaranty this.
|
||||
|
||||
|
||||
Now, if you want to test it, do the following:
|
||||
|
||||
|
||||
Set up an outgoing isdn network interface, configured for encap x25iface,
|
||||
l2_prot x75i and your eft serving peer's remote phone number.
|
||||
|
||||
Create an appropriate x25 route to this interface.
|
||||
|
||||
(You can use the "ix25test" script to do all of that).
|
||||
|
||||
Assuming your user name on the eft server is "myname" and your password is
|
||||
"mypass" and the X.25 address that is routed to your isdn interface is "05".
|
||||
Type
|
||||
|
||||
eftp 05 myname/mypass
|
||||
|
||||
from the shell's prompt.
|
||||
|
||||
This will try to connect to the remote eft server. A lot of debugging
|
||||
output (protocol trace) will appear on your terminal while this is going on.
|
||||
|
||||
If the connection was successful you can type
|
||||
|
||||
dir *
|
||||
|
||||
from the "eftp>" prompt. You should get a listing of the server's directory.
|
||||
Assuming the directory contains a file "TEST.GIF" type
|
||||
|
||||
get TEST.GIF
|
||||
|
||||
to download that file to your computer. The transfer header of the file
|
||||
received is not evaluated, just skipped. The contents of the transferred
|
||||
file is written to your disk as received (i.e. neither owner nor
|
||||
permissions of the file are retreived from the transfer header, no code
|
||||
conversion for text files is performed, ...).
|
||||
|
||||
Do submit a file to the remote computer type
|
||||
|
||||
put FILE
|
||||
|
||||
Furthermore, there are two other commands, namely "quit" and "help".
|
||||
|
||||
Good luck.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/x25.h>
|
||||
/* for error mask setting */
|
||||
#include <tdu_user.h>
|
||||
#include <eft.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <glob.h>
|
||||
#include <fnmatch.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#define MAX_COMMAND_LINE_LEN 4096
|
||||
|
||||
/* is in net/x25.h, not in the public header file linux/x25.h. Why?*/
|
||||
#ifndef X25_MAX_CUD_LEN
|
||||
#define X25_MAX_CUD_LEN 128
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef CONFIG_EFTP_READLINE
|
||||
|
||||
#include <readline/readline.h>
|
||||
#include <readline/history.h>
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
If multi_prompt is 0, the mget and mput commands prompt for each matching
|
||||
filename. Otherwise, they just transmit all matching files.
|
||||
*/
|
||||
static int multi_prompt = 0;
|
||||
|
||||
/*
|
||||
Prompts for "y" or "n" if multi_prompt != 0,
|
||||
returns 1 for "y" or 0 for "n".
|
||||
If stdin is not a TTY, it returns 1 always.
|
||||
*/
|
||||
static int multi_prompt_yes(char* cmdname, char* filename)
|
||||
{
|
||||
int c,r;
|
||||
if( !multi_prompt || !isatty(STDIN_FILENO)) return 1;
|
||||
while(1) {
|
||||
fprintf(stderr,"%s %s (y/n)? ",cmdname,filename);
|
||||
fflush(stderr);
|
||||
r = c = tolower(getchar());
|
||||
while(c!='\n' && c!=EOF)
|
||||
c = getchar();
|
||||
// fprintf(stderr,"\n");
|
||||
if('y' == r) return 1;
|
||||
if('n' == r) return 0;
|
||||
}
|
||||
/* not reached */
|
||||
}
|
||||
|
||||
/*
|
||||
* A simple parser for the eftp command line
|
||||
*/
|
||||
/*
|
||||
* FIXME: return values of local commands (!, lcd, lpwd, ldir)
|
||||
*/
|
||||
int process_cmd_line (struct eft *eft, unsigned char *buf)
|
||||
{
|
||||
static int mget_case_ignore = 0;
|
||||
char **pp = (char **) & buf, *c, *arg1, *arg2, *obuf=buf, *cmd;
|
||||
|
||||
int ret = 1, count, r;
|
||||
|
||||
if( *buf == '!' ){
|
||||
r = system(buf+1);
|
||||
if( (r<0) || (r==127) ){
|
||||
perror("system()");
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
c = strsep(pp," \t\n");
|
||||
arg1 = strsep(pp," \t\n");
|
||||
arg2 = strsep(pp," \t\n");
|
||||
if( arg2 == 0 || *arg2 == 0) arg2 = arg1;
|
||||
|
||||
if( c == NULL ) return -1;
|
||||
if( strcmp(c, "dir") == 0 ){
|
||||
if( (arg1 == NULL) || (*arg1 == 0) ) arg1 = "*";
|
||||
ret = eft_dir_fd ( eft, 1, arg1, 0 );
|
||||
} else if( strcmp(c, "xdir") == 0 ){
|
||||
if( (arg1 == NULL) || (*arg1 == 0) ) arg1 = "*";
|
||||
ret = eft_xdir_txt ( eft, arg1 );
|
||||
} else if( strcmp(c, "msg") == 0 ){
|
||||
if( (arg1 == NULL) || (*arg1 == 0) ) {
|
||||
/* FIXME: secondary prompt can cause interaction
|
||||
* problems with readline library.
|
||||
* Not a showstopper, as "msg" is pretty useless
|
||||
* and the meessage can alternativly be supplied
|
||||
* as a command argument */
|
||||
eft_prompt("EFT-Message: ");
|
||||
count = read( STDIN_FILENO, obuf, 254);
|
||||
if ( count < 0 ) {
|
||||
perror("while reading msg line");
|
||||
} else {
|
||||
obuf[count] = 0;
|
||||
ret = eft_msg ( eft, obuf );
|
||||
}
|
||||
} else {
|
||||
ret = eft_msg ( eft, arg1 );
|
||||
}
|
||||
} else if( strcmp(c, "get") == 0 ) {
|
||||
if( (arg1 == NULL) || (*arg1 == 0) ){
|
||||
fprintf(stderr,"eftp get: file name is missing\n");
|
||||
return 0;
|
||||
}
|
||||
ret = eft_load( eft, arg2, arg1 );
|
||||
} else if( strcmp(c, "put") == 0 ) {
|
||||
if( (arg1 == NULL) || (*arg1 == 0) ){
|
||||
fprintf(stderr,"eftp put: file name is missing\n");
|
||||
return 0;
|
||||
}
|
||||
ret = eft_save( eft, arg2, arg1 );
|
||||
|
||||
/* Is this necessary as the same functionality is
|
||||
* provided by !ls ? Maybe, if we could provide
|
||||
* the local output in the same format as dir/xdir
|
||||
*/
|
||||
} else if( (strcmp(c, "ldir") == 0) ||
|
||||
(strcmp(c, "lls") == 0) ) {
|
||||
ret = 0; /* Local problems should not cause a disconnect */
|
||||
if(! arg1) arg1="";
|
||||
cmd = (char*)malloc(strlen(c)+strlen(arg1)+2);
|
||||
if( cmd ){
|
||||
sprintf(cmd,"%s %s",c+1,arg1);
|
||||
r = system(cmd);
|
||||
if( (r<0) || (r==127) ){
|
||||
perror("system()");
|
||||
}
|
||||
free(cmd);
|
||||
}
|
||||
} else if( strcmp(c, "lcd") == 0 ) {
|
||||
char* cwd = NULL;
|
||||
ret = 0;
|
||||
if(arg1 && *arg1) {
|
||||
if( strcmp(arg1,"~") == 0 ){
|
||||
r = chdir(getenv("HOME"));
|
||||
} else {
|
||||
r = chdir(arg1);
|
||||
}
|
||||
if(r<0){
|
||||
perror("chdir()");
|
||||
}
|
||||
}
|
||||
cwd = getcwd(NULL,0);
|
||||
printf("Local directory now %s\n",cwd);
|
||||
} else if( strcmp(c, "mput") == 0 ) {
|
||||
glob_t glob_result;
|
||||
int r;
|
||||
size_t i;
|
||||
char* p = arg1;
|
||||
if( (arg1 == NULL) || (*arg1 == 0) ) {
|
||||
fprintf(stderr,"eftp mput: file name pattern is missing\n");
|
||||
return 0;
|
||||
}
|
||||
while(p) {
|
||||
r = glob(p,0,NULL,&glob_result);
|
||||
for(i=0; i<glob_result.gl_pathc; i++) {
|
||||
if( multi_prompt_yes("mput", glob_result.gl_pathv[i]) ) {
|
||||
ret = eft_save( eft, glob_result.gl_pathv[i],
|
||||
glob_result.gl_pathv[i] );
|
||||
if(ret) return ret; /* or should we ignore it? */
|
||||
}
|
||||
}
|
||||
if(arg1 == arg2) /* only one argument */
|
||||
p = NULL;
|
||||
else if(p == arg1) /* at least two arguments */
|
||||
p = arg2;
|
||||
else p = strsep(pp," \t\n"); /* more arguments */
|
||||
}
|
||||
return 0;
|
||||
} else if( strcmp(c, "mget") == 0 ) {
|
||||
char* p = arg1;
|
||||
if( (arg1 == NULL) || (*arg1 == 0) ) {
|
||||
fprintf(stderr,"eftp mget: file name pattern is missing\n");
|
||||
return 0;
|
||||
}
|
||||
while(p) {
|
||||
FILE* f = tmpfile();
|
||||
int tmp_fd = fileno(f);
|
||||
char s[1024];
|
||||
ret = eft_dir_fd ( eft, tmp_fd, p, 0 );
|
||||
fflush(f);
|
||||
fseek(f,0,SEEK_SET);
|
||||
while(fgets(s,sizeof(s),f))
|
||||
{
|
||||
char* fname = strtok(s," \t\n");
|
||||
if( 0 == fnmatch(p, fname,
|
||||
mget_case_ignore? FNM_CASEFOLD:0) ) {
|
||||
if( multi_prompt_yes("mget",fname) ) {
|
||||
ret = eft_load( eft, fname, fname );
|
||||
if(ret) return ret; /* or should we ignore it? */
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
if(arg1 == arg2) /* only one argument */
|
||||
p = NULL;
|
||||
else if(p == arg1) /* at least two arguments */
|
||||
p = arg2;
|
||||
else p = strsep(pp," \t\n"); /* more arguments */
|
||||
}
|
||||
return 0;
|
||||
} else if( strcmp(c, "prompt") == 0 ) {
|
||||
if( (arg1 == NULL) || (*arg1 == 0) )
|
||||
multi_prompt = !multi_prompt;
|
||||
else if( strcmp(arg1,"on") == 0)
|
||||
multi_prompt = 1;
|
||||
else if( strcmp(arg1,"off") == 0)
|
||||
multi_prompt = 0;
|
||||
else {
|
||||
fprintf(stderr,"eftp prompt: need \"on\" or \"off\" or no argument\n");
|
||||
return 0;
|
||||
}
|
||||
fprintf(stderr,"Interactive mode %s.\n", multi_prompt? "on":"off");
|
||||
ret = 0;
|
||||
} else if( strcmp(c, "case") == 0 ) {
|
||||
if( (arg1 == NULL) || (*arg1 == 0) )
|
||||
mget_case_ignore = !mget_case_ignore;
|
||||
else if( strcmp(arg1,"on") == 0)
|
||||
mget_case_ignore = 1;
|
||||
else if( strcmp(arg1,"off") == 0)
|
||||
mget_case_ignore = 0;
|
||||
else {
|
||||
fprintf(stderr,"eftp case: need \"on\" or \"off\" or no argument\n");
|
||||
return 0;
|
||||
}
|
||||
fprintf(stderr,"Case mapping %s.\n", mget_case_ignore? "on":"off");
|
||||
ret = 0;
|
||||
} else if( strcmp(c, "quit") == 0 ||
|
||||
strcmp(c, "close") == 0 ||
|
||||
strcmp(c, "stop") == 0 ||
|
||||
strcmp(c, "end") == 0 ||
|
||||
strcmp(c, "exit") == 0 ||
|
||||
strcmp(c, "bye") == 0 ) {
|
||||
return -1;
|
||||
} else if( strcmp(c, "help") == 0 || strcmp(c,"?") == 0 ) {
|
||||
fprintf(stderr, "known commands:\n"
|
||||
"get FILE [LOCAL_NAME] get file from remote\n"
|
||||
"dir PATTERN get directory from remote\n"
|
||||
"xdir PATTERN get directory with extended information from remote\n"
|
||||
"put FILE [REMOTE_NAME] put file to remote\n"
|
||||
"list list all directories\n"
|
||||
"slist list all subdirectories\n"
|
||||
"cd [DIR] change working directory\n"
|
||||
"mkdir DIR make remote directory\n"
|
||||
"pwd print working directory\n"
|
||||
"msg MESSAGE submit a printable message\n"
|
||||
"lcd [DIR] change local directory\n"
|
||||
"lls list local directory\n"
|
||||
"! COMMAND execute shell command\n"
|
||||
"mput PATTERN put multiple files to remote\n"
|
||||
"mget PATTERN get multiple files from remote\n"
|
||||
"prompt [on|off] set or toggle interactive prompting for mget and mput\n"
|
||||
"case [on|off] set or toggle mget case sensitivity\n"
|
||||
"quit close connections and quit\n"
|
||||
"(mkdir and list are not supported by most servers, many even don't\n"
|
||||
" support xdir, slist, cd, pwd, nor msg)\n"
|
||||
);
|
||||
} else if( strcmp(c, "list") == 0 ) {
|
||||
ret = eft_list_fd( eft, 1, 0 );
|
||||
} else if( strcmp(c, "slist") == 0 ) {
|
||||
ret = eft_slist_fd( eft, 1, 0 );
|
||||
} else if( strcmp(c, "cd") == 0 ) {
|
||||
if( (arg1 == NULL) || (*arg1 == 0) ) arg1 = NULL;
|
||||
ret = eft_cd( eft, arg1 );
|
||||
} else if( strcmp(c, "pwd") == 0 ) {
|
||||
char dir[EFT_MAX_FSTORE_LEN+1];
|
||||
ret = eft_getcwd( eft, dir );
|
||||
if(ret>=0) printf("Current filestore is %s\n",dir);
|
||||
} else if( strcmp(c, "mkdir") == 0 ) {
|
||||
if( (arg1 == NULL) || (*arg1 == 0) ){
|
||||
fprintf(stderr,"eftp mkdir: dir name is missing\n");
|
||||
return 0;
|
||||
}
|
||||
ret = eft_mkdir( eft, arg1 );
|
||||
} else {
|
||||
fprintf( stderr, "unknown command, type \"?\" or \"help\"\n");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static struct eft *eft;
|
||||
|
||||
#ifdef CONFIG_EFTP_READLINE
|
||||
|
||||
static char * eftp_command = NULL;
|
||||
|
||||
static void readline_callback_handler(void)
|
||||
{
|
||||
static char* line_read = NULL;
|
||||
|
||||
/* If the buffer has already been allocated, return the memory
|
||||
to the free pool. */
|
||||
if( line_read ) {
|
||||
free(line_read);
|
||||
line_read = (char *)NULL;
|
||||
}
|
||||
if( *rl_line_buffer ) {
|
||||
line_read = strdup(rl_line_buffer);
|
||||
add_history(line_read);
|
||||
eftp_command = line_read;
|
||||
rl_callback_handler_remove();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct sockaddr_x25 x25bind, x25connect;
|
||||
int s, count, on=1, selval;
|
||||
|
||||
fd_set rfds;
|
||||
|
||||
unsigned char * ident;
|
||||
char * buf; /* Has to be dynamic memory for getdelim() */
|
||||
size_t buflen = MAX_COMMAND_LINE_LEN;
|
||||
struct x25_calluserdata cud;
|
||||
struct x25_facilities facilities;
|
||||
pid_t pid;
|
||||
struct linger ling = { 1 /* Linger active */,
|
||||
500 /* wait up to 5 seconds on close */ };
|
||||
sigset_t sig_pipe = 1 << (SIGPIPE-1);
|
||||
|
||||
buf = (char*)malloc(buflen);
|
||||
|
||||
printf("\nThis is ALPHA test software (incomplete, non-protocol-"
|
||||
"conformant, buggy, etc).\n\n ABSOLUTELEY NO WARRENTY!\n\n"
|
||||
"Ask the operator of the peer eft server for permission "
|
||||
"to connect with\nthis experimental client before doing "
|
||||
"so!\n\n"
|
||||
"Copyright 1997 by Henner Eisen (eis@baty.hanse.de)\n"
|
||||
"The GNU (Library) General Public License, Version 2, applies.\n\n\n");
|
||||
|
||||
if (argc < 2 || argc > 3) {
|
||||
perror("usage: eftp X25_ADDRESS [ USER/PASSWORD ]");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* First section of this program establishes an X.25 DTE-DTE
|
||||
* connection to the remote eft server using the socket interface.
|
||||
* Several set ups have to be performed before.
|
||||
*/
|
||||
|
||||
x25bind.sx25_family = AF_X25;
|
||||
strcpy(x25bind.sx25_addr.x25_addr, "" );
|
||||
|
||||
x25connect.sx25_family = AF_X25;
|
||||
strcpy(x25connect.sx25_addr.x25_addr, "");
|
||||
|
||||
s = socket(AF_X25, SOCK_SEQPACKET, 0);
|
||||
if (s < 0) {
|
||||
perror("eftp: socket creation failed");
|
||||
fprintf(stderr,"\t(Maybe your kernel was not compiled with "
|
||||
"X.25 PLP support enabled\n"
|
||||
"\tor it was compiled as a module but the x25 "
|
||||
"module is not loaded)\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* In order to recognize the lower layer SBV messages we need
|
||||
to be aware of the Q-bit included with each X.25 packet,
|
||||
*/
|
||||
if (setsockopt(s, SOL_X25, X25_QBITINCL, &on, sizeof(on)) < 0 ) {
|
||||
perror("eftp: setsockopt() failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* eft requires a packet size of (at least) 1024 bytes
|
||||
*/
|
||||
if( ioctl( s, SIOCX25GFACILITIES, &facilities ) != 0 ){
|
||||
perror("eftp: SIOCX25GFACILITIES failed");
|
||||
return 1;
|
||||
}
|
||||
printf("current facilies wi %d wo %d pi %d po %d\n",
|
||||
facilities.winsize_in,
|
||||
facilities.winsize_out,
|
||||
facilities.pacsize_in,
|
||||
facilities.pacsize_out);
|
||||
|
||||
facilities.winsize_in = 7;
|
||||
/* avm server hangs with outgoing winsize=7 */
|
||||
facilities.winsize_out = 6;
|
||||
facilities.pacsize_in = X25_PS1024;
|
||||
facilities.pacsize_out = X25_PS1024;
|
||||
|
||||
printf("requested facilies wi %d wo %d pi %d po %d\n",
|
||||
facilities.winsize_in,
|
||||
facilities.winsize_out,
|
||||
facilities.pacsize_in,
|
||||
facilities.pacsize_out);
|
||||
|
||||
/* Unfortunatly, this doesn't work with kernels up to at least 2.1.90
|
||||
unless the socket is in the listen state (x.25 kernel bug)
|
||||
unless af_x25.c is patched. */
|
||||
printf("Trying to set X.25 facilities on socket ...\n");
|
||||
if( ioctl( s, SIOCX25SFACILITIES, &facilities ) != 0 ){
|
||||
perror("eftp: SIOCX25SFACILITIES failed");
|
||||
return 1;
|
||||
}
|
||||
/*
|
||||
* request of eft service is indicated to the server by a special
|
||||
* direct call user data string in our x25 call request packet
|
||||
*/
|
||||
cud.cuddata[0] = 0;
|
||||
cud.cuddata[1] = 0;
|
||||
cud.cuddata[2] = 0;
|
||||
cud.cuddata[3] = 0;
|
||||
strncpy( cud.cuddata+4, "EUROSFT92", X25_MAX_CUD_LEN-4 );
|
||||
cud.cudlength = 13;
|
||||
if( ioctl( s, SIOCX25SCALLUSERDATA, &cud ) != 0 ){
|
||||
perror("eftp: SIOCX25SCALLUSERDATA failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* connect to destination x25 address of socket: The address is not
|
||||
needed by eft when operating over isdn in X.25-DTE-DTE mode. But as
|
||||
we currently cannot set the ISDN number of our peer from this
|
||||
programm we use x25 addresses to select different peers. The mapping
|
||||
X25 address -> peer's ISDN number must be set up by assigning
|
||||
the peer's ISDN number as the outgoing number to an isdn network
|
||||
interface (using the isdnctrl utility) and by setting up an
|
||||
X.25 route (using the x25route utility) that associates an
|
||||
x25 address with that network interface.
|
||||
*/
|
||||
|
||||
if (bind(s, (struct sockaddr *)&x25bind, sizeof (x25bind)) < 0) {
|
||||
perror("eftp: unable to bind address to socket");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if( argv[1][0] ){
|
||||
fprintf(stderr, "Setting up isdn x25 network interface\n");
|
||||
if( eft_get_x25route(&x25connect,argv[1]) ){
|
||||
perror("eftp: unable get an x25route to isdn interfaces\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "Trying to establish X.25 DTE-DTE connection to "
|
||||
"x25 address \"%s\" ...\n", x25connect.sx25_addr.x25_addr);
|
||||
if (connect(s, (struct sockaddr *)&x25connect, sizeof (x25connect)) < 0) {
|
||||
perror("eftp: Unable to connect to remote host");
|
||||
return 1;
|
||||
}
|
||||
fprintf(stderr,"eftp: X.25 connection established.\n");
|
||||
if( ioctl( s, SIOCX25GFACILITIES, &facilities ) != 0 ){
|
||||
perror("eftp: SIOCX25GFACILITIES failed");
|
||||
return 1;
|
||||
}
|
||||
printf("active facilies wi %d wo %d pi %d po %d\n",
|
||||
facilities.winsize_in,
|
||||
facilities.winsize_out,
|
||||
facilities.pacsize_in,
|
||||
facilities.pacsize_out);
|
||||
|
||||
/*
|
||||
* Now, the x.25 DTE-DTE connection is up. On top of that,
|
||||
* the higer layer eft connection needs to be established.
|
||||
* There are several higer layers, but this is taken care of
|
||||
* be the eft_connect() function.
|
||||
*/
|
||||
|
||||
eft = eft_make_instance();
|
||||
|
||||
/* for uid/password */
|
||||
if( argc == 3 ) {
|
||||
ident = argv[2];
|
||||
} else {
|
||||
ident = NULL;
|
||||
}
|
||||
|
||||
/* This specifies the amount of (debugging) output printed to stderr*/
|
||||
/* tdu_stderr_mask = TDU_LOG_FH | TDU_LOG_REW | TDU_LOG_ERR; */
|
||||
tdu_stderr_mask = TDU_LOG_ERR | TDU_LOG_IER | TDU_LOG_OER /*| TDU_LOG_DBG
|
||||
| TDU_LOG_HASH | TDU_LOG_TMP */ ;
|
||||
#if 0
|
||||
/* for maximum amount of debugging output use */
|
||||
tdu_stderr_mask = -1 /* ^ TDU_LOG_TMP ^ TDU_LOG_TRC */;
|
||||
/* */
|
||||
#endif
|
||||
/* Attach the connected x.25 socket to the eft protocol state
|
||||
* machine */
|
||||
eft_attach_socket(eft,s);
|
||||
/*
|
||||
* block SIGPIPE such that peer initiated disconnects will
|
||||
* result in write error indications
|
||||
*/
|
||||
if( sigprocmask(SIG_BLOCK, &sig_pipe, NULL) )
|
||||
perror("sigprocmask()");
|
||||
setsockopt(s,SOL_SOCKET,SO_LINGER,&ling,sizeof(ling));
|
||||
|
||||
/* and finally establish logical eft connection */
|
||||
if( eft_connect( eft, ident) < 0 ) {
|
||||
fprintf(stderr, "eftp: connection failed\n");
|
||||
goto Ende;
|
||||
}
|
||||
fprintf(stderr,"eftp: successfully logged in.\n");
|
||||
|
||||
/*
|
||||
* Now the main loop processing commands from stdin
|
||||
*/
|
||||
#ifdef CONFIG_EFTP_READLINE
|
||||
|
||||
rl_readline_name = "eftp";
|
||||
rl_inhibit_completion = 1;
|
||||
|
||||
if(isatty(STDIN_FILENO)) {
|
||||
int disconnect_please = 0;
|
||||
|
||||
rl_callback_handler_install("eftp> ",readline_callback_handler);
|
||||
while ( !disconnect_please && eft_is_up(eft) ) {
|
||||
FD_ZERO(&rfds);
|
||||
FD_SET(STDIN_FILENO, &rfds);
|
||||
selval = eft_select(eft, STDIN_FILENO+1,
|
||||
&rfds, NULL, NULL, NULL);
|
||||
if( selval < 0 ) {
|
||||
disconnect_please = 1;
|
||||
} else {
|
||||
rl_callback_read_char();
|
||||
if( eftp_command ){
|
||||
int r;
|
||||
if( (r=process_cmd_line(eft, eftp_command)) < 0 ){
|
||||
fprintf(stderr,"eftp cmd execution error %d<0\n",r);
|
||||
disconnect_please = 1;
|
||||
}
|
||||
eftp_command = NULL;
|
||||
rl_callback_handler_install("eftp> ",readline_callback_handler);
|
||||
}
|
||||
}
|
||||
}
|
||||
rl_callback_handler_remove();
|
||||
} else /* use the old style loop if stdin is not a tty */
|
||||
#endif
|
||||
{
|
||||
while ( eft_is_up(eft) ) {
|
||||
FD_ZERO(&rfds);
|
||||
FD_SET(STDIN_FILENO, &rfds);
|
||||
eft_prompt("eftp> ");
|
||||
selval = eft_select(eft, STDIN_FILENO+1,
|
||||
&rfds, NULL, NULL, NULL);
|
||||
fprintf(stderr,"aft_sel\n");
|
||||
if( selval < 0 ) goto disconnect;
|
||||
/* FIXME: replace this by a non-blocking version */
|
||||
#ifdef HAVE_GETDELIM
|
||||
/*
|
||||
* getline()/getdelim() is a GNU extension:
|
||||
* it reads whole lines like fgets(), but it's safer.
|
||||
*/
|
||||
count = getdelim( &buf, &buflen, '\n' , stdin );
|
||||
#else
|
||||
/* In case you don't have getdelim(). */
|
||||
count = fgets( buf, buflen, stdin )? strlen(buf) : -1;
|
||||
#endif
|
||||
if ( count < 0 ) {
|
||||
perror("while reading cmd line, count<0");
|
||||
goto disconnect;
|
||||
} else {
|
||||
int r;
|
||||
if( (r=process_cmd_line(eft, buf)) < 0 ){
|
||||
fprintf(stderr,"cmd execution error %d<0\n",r);
|
||||
goto disconnect;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* ??? fclose(my_stdin) ??? */
|
||||
}
|
||||
|
||||
disconnect:
|
||||
printf("eftp: requesting eft_disconnect()\n");
|
||||
eft_disconnect( eft );
|
||||
close(s);
|
||||
if( argv[1][0] ) eft_release_route( &x25connect, argv[1] );
|
||||
|
||||
Ende: pid = getpid();
|
||||
|
||||
printf( "eftp (pid %d) terminating\n", pid);
|
||||
return 0;
|
||||
}
|
|
@ -1,197 +0,0 @@
|
|||
/* $Id: read_line.c,v 1.1 1999/06/30 17:19:12 he Exp $ */
|
||||
/*
|
||||
Copyright 1998 by Michael Mauch <michael.mauch@gmx.de>
|
||||
|
||||
This code is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
Interface to the readline library for line editing and history.
|
||||
|
||||
Most parts are snippets from the man pages / info files for readline.
|
||||
It works on the console and in rxvt if linked with readline-2.2.1 and
|
||||
ncurses-4.2-5; I don't know about other versions.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <termios.h>
|
||||
#include <readline/readline.h>
|
||||
#include <readline/history.h>
|
||||
#include "read_line.h"
|
||||
|
||||
#if 0
|
||||
/* old stuff removed from eftp.c */
|
||||
#include "read_line.h"
|
||||
void eft_read_line_prompt(char* s)
|
||||
{
|
||||
read_line_prompt_string = s;
|
||||
eft_prompt(s);
|
||||
}
|
||||
|
||||
#define eft_prompt eft_read_line_prompt
|
||||
#endif
|
||||
|
||||
|
||||
char* read_line_prompt_string = NULL;
|
||||
|
||||
|
||||
/*
|
||||
Set the `O_NONBLOCK' flag of FD if VALUE is nonzero,
|
||||
or clear the flag if VALUE is 0.
|
||||
Return 0 on success, or -1 on error with `errno' set.
|
||||
*/
|
||||
static int set_nonblock_flag (int fd, int value)
|
||||
{
|
||||
int oldflags = fcntl (fd, F_GETFL, 0);
|
||||
/* If reading the flags failed, return error indication now. */
|
||||
if (oldflags == -1)
|
||||
return -1;
|
||||
/* Set just the flag we want to set. */
|
||||
if (value != 0)
|
||||
oldflags |= O_NONBLOCK;
|
||||
else
|
||||
oldflags &= ~O_NONBLOCK;
|
||||
/* Store modified flag word in the descriptor. */
|
||||
return fcntl (fd, F_SETFL, oldflags);
|
||||
}
|
||||
|
||||
|
||||
static void set_echo_flag (int fd, int value)
|
||||
{
|
||||
struct termios tattr;
|
||||
tcgetattr (fd, &tattr);
|
||||
if(value)
|
||||
tattr.c_lflag |= ECHO;
|
||||
else
|
||||
tattr.c_lflag &= ~ECHO;
|
||||
tcsetattr (fd, TCSANOW, &tattr);
|
||||
}
|
||||
|
||||
|
||||
static struct termios* saved_attributes;
|
||||
|
||||
static void reset_input_mode (void)
|
||||
{
|
||||
if(saved_attributes)
|
||||
{
|
||||
tcsetattr (STDIN_FILENO, TCSADRAIN, saved_attributes);
|
||||
set_nonblock_flag(STDIN_FILENO,1);
|
||||
}
|
||||
}
|
||||
|
||||
void read_line_exit (void)
|
||||
{
|
||||
reset_input_mode();
|
||||
}
|
||||
|
||||
|
||||
static void set_input_mode (void)
|
||||
{
|
||||
struct termios tattr;
|
||||
|
||||
/* If stdin is not a terminal, read_line() will call read(),
|
||||
so don't do anything to the terminal here. */
|
||||
if(!isatty (STDIN_FILENO))
|
||||
return;
|
||||
|
||||
if(!saved_attributes)
|
||||
{
|
||||
saved_attributes = (struct termios*)malloc(sizeof(struct termios));
|
||||
if(!saved_attributes)
|
||||
{
|
||||
fprintf(stderr,"\nout of memory in read_line.c::set_input_mode()\n");
|
||||
return;
|
||||
}
|
||||
/* Save the terminal attributes so we can restore them later. */
|
||||
tcgetattr (STDIN_FILENO, saved_attributes);
|
||||
atexit (reset_input_mode);
|
||||
}
|
||||
|
||||
/* Set the funny terminal modes. */
|
||||
tcgetattr (STDIN_FILENO, &tattr);
|
||||
tattr.c_lflag &= ~(ICANON);
|
||||
tattr.c_cc[VMIN] = 1; /* read() only one character */
|
||||
tattr.c_cc[VTIME] = 0; /* return immediately from read() */
|
||||
tcsetattr (STDIN_FILENO, TCSADRAIN, &tattr);
|
||||
}
|
||||
|
||||
|
||||
static int read_line_init_done = 0;
|
||||
|
||||
|
||||
void read_line_init (void)
|
||||
{
|
||||
if( !read_line_init_done ) {
|
||||
set_input_mode();
|
||||
read_line_init_done = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* A drop-in replacement for the read function,
|
||||
* with history and command line editing.
|
||||
*/
|
||||
ssize_t read_line (int fd, void *buf, size_t count)
|
||||
{
|
||||
/* A static variable for holding the line. */
|
||||
static char* line_read = NULL;
|
||||
static char* prompt_string = NULL;
|
||||
|
||||
if( (fd != STDIN_FILENO) || !isatty(STDIN_FILENO) )
|
||||
return read(fd, buf, count);
|
||||
|
||||
if( !read_line_init_done )
|
||||
read_line_init();
|
||||
|
||||
/* If the buffer has already been allocated, return the memory
|
||||
to the free pool. */
|
||||
if( line_read ) {
|
||||
free(line_read);
|
||||
line_read = (char *)NULL;
|
||||
}
|
||||
|
||||
set_echo_flag(STDIN_FILENO,1);
|
||||
|
||||
if(read_line_prompt_string)
|
||||
{
|
||||
if(prompt_string)
|
||||
free(prompt_string);
|
||||
prompt_string = (char*)malloc(strlen(read_line_prompt_string)+2);
|
||||
if(!prompt_string)
|
||||
{
|
||||
fprintf(stderr,"\nout of memory in read_line.c::read_line()\n");
|
||||
return 0;
|
||||
}
|
||||
sprintf(prompt_string,"\r%s",read_line_prompt_string);
|
||||
}
|
||||
|
||||
/* Get a line from the user. */
|
||||
line_read = readline(prompt_string?:"");
|
||||
set_echo_flag(STDIN_FILENO,0);
|
||||
|
||||
/* If the line has any text in it, save it on the history. */
|
||||
if( line_read && *line_read ) {
|
||||
add_history(line_read);
|
||||
strncpy(buf, line_read, count);
|
||||
return strlen(line_read);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
|
||||
|
||||
#ifndef CONFIG_EFTP_READLINE
|
||||
#define read_line read
|
||||
#define read_line_init() do{}while(0)
|
||||
#define read_line_exit() do{}while(0)
|
||||
#else
|
||||
|
||||
/*
|
||||
* Set read_line_prompt_string to the whole string displayed
|
||||
* on the command line.
|
||||
*/
|
||||
extern char* read_line_prompt_string;
|
||||
|
||||
/*
|
||||
* Call this at the start of the program.
|
||||
*/
|
||||
void read_line_init (void);
|
||||
|
||||
/*
|
||||
* Call read_line_exit() to reset the terminal to its normal state.
|
||||
* This is done automatically at the end of the program, but if you want/need
|
||||
* to temporarily disable the read_line terminal modes, use read_line_exit()
|
||||
* (and read_line_init() to start the read_line terminal mode again).
|
||||
*/
|
||||
void read_line_exit (void);
|
||||
|
||||
/*
|
||||
* A drop-in replacement for the read function,
|
||||
* with history and command line editing.
|
||||
*/
|
||||
ssize_t read_line (int fd, void *buf, size_t count);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
#
|
||||
# $Id: config.in,v 1.27 1999/05/07 21:35:15 werner Exp $
|
||||
# $Id: config.in,v 1.28 1999/07/01 18:00:02 he Exp $
|
||||
#
|
||||
# The whole configuration stuff is borrowed from the kernel
|
||||
# configuration.
|
||||
|
@ -119,6 +119,20 @@ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
|
|||
bool 'capifax' CONFIG_CAPIFAX
|
||||
bool 'rcapid' CONFIG_RCAPID
|
||||
fi
|
||||
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
|
||||
# we need to check for the presence of the eurofile subdirectory
|
||||
# as long as it is listed in the distexclude file
|
||||
if [ -d eurofile ]; then
|
||||
bool 'eurofile' CONFIG_EUROFILE
|
||||
# The source command fails and causes an error in the
|
||||
# configure script when eurofile directory is not
|
||||
# present -- even inside this if branch.
|
||||
# Thus, it is left commented out until eurofile is
|
||||
# removed from the distexclude file.
|
||||
# Uncomment the next line for trying the eurofile sub menu
|
||||
# source eurofile/.Config.in
|
||||
fi
|
||||
fi
|
||||
endmenu
|
||||
mainmenu_option nextcomment
|
||||
comment 'Documentation'
|
||||
|
|
Loading…
Reference in New Issue