Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b8ce93c8bd | ||
|
|
7bef99df0f | ||
|
|
d31ec2ab61 | ||
|
|
1ee60bade6 | ||
|
|
20589ca203 | ||
|
|
517e207709 | ||
|
|
5d4b23a5c1 | ||
|
|
c6124785a9 | ||
|
|
f2bcb2c71e | ||
|
|
e05e55a64a |
BIN
.downloads/ncpfs-0.10.tgz
Normal file
BIN
.downloads/ncpfs-0.10.tgz
Normal file
Binary file not shown.
BIN
.downloads/ncpfs-0.11.tgz
Normal file
BIN
.downloads/ncpfs-0.11.tgz
Normal file
Binary file not shown.
BIN
.downloads/ncpfs-0.12.tgz
Normal file
BIN
.downloads/ncpfs-0.12.tgz
Normal file
Binary file not shown.
BIN
.downloads/ncpfs-0.13.tgz
Normal file
BIN
.downloads/ncpfs-0.13.tgz
Normal file
Binary file not shown.
BIN
.downloads/ncpfs-0.14.tgz
Normal file
BIN
.downloads/ncpfs-0.14.tgz
Normal file
Binary file not shown.
BIN
.downloads/ncpfs-0.15.tgz
Normal file
BIN
.downloads/ncpfs-0.15.tgz
Normal file
Binary file not shown.
BIN
.downloads/ncpfs-0.6.tgz
Normal file
BIN
.downloads/ncpfs-0.6.tgz
Normal file
Binary file not shown.
BIN
.downloads/ncpfs-0.7.tgz
Normal file
BIN
.downloads/ncpfs-0.7.tgz
Normal file
Binary file not shown.
BIN
.downloads/ncpfs-0.8.tgz
Normal file
BIN
.downloads/ncpfs-0.8.tgz
Normal file
Binary file not shown.
BIN
.downloads/ncpfs-0.9.tgz
Normal file
BIN
.downloads/ncpfs-0.9.tgz
Normal file
Binary file not shown.
23
BUGS
23
BUGS
@@ -3,11 +3,7 @@ them to be bugs.
|
||||
|
||||
But there are really problems that might be fixed in the future.
|
||||
|
||||
Invalid directory timestamps:
|
||||
I did not yet find out how to get valid timestamps for directories
|
||||
from a NetWare server. So I simply return 0, which means 01.01.70. If
|
||||
anybody knows how to get these values, please mail
|
||||
lendecke@namu01.gwdg.de.
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
'df' returns 0:
|
||||
Free disk space is distributed among the volumes in NetWare. df is
|
||||
@@ -15,3 +11,20 @@ only able to report one number per mounted filesystem. As connections
|
||||
are quite expensive for NetWare (with lwared that might change ...), I
|
||||
rejected the alternative to mount only a single volume for a unix
|
||||
mount point. So I simply return 0.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
If you use Linux 1.2.x, In your kernel log there will appear messages
|
||||
like
|
||||
|
||||
Nov 25 16:09:08 lx01 kernel: alloc_skb called nonatomically from interrupt 0000002e
|
||||
|
||||
These are a bit annoying, but completely harmless.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
ncpfs has a problem with NetWare 4.1, when files are created. I think
|
||||
NW4.1 does not like some of the creation mode bits. If somebody with
|
||||
access to a NW4.1 server could compile the kernel module for 1.2 with
|
||||
-DDEBUG_NCP=2, and send me the syslog output gzipped/uuencoded, I
|
||||
might find out more about that problem.
|
||||
|
||||
24
Changes
Normal file
24
Changes
Normal file
@@ -0,0 +1,24 @@
|
||||
I only began this file with ncpfs-0.12. If you're interested in older
|
||||
versions, you can find them on linux01.gwdg.de:/pub/ncpfs/old.
|
||||
|
||||
ncpfs-0.14 -> ncpfs-0.15
|
||||
|
||||
- A bug fixed that made normal mounting impossible. It was too late
|
||||
yesterday. Sorry
|
||||
- Manpage for pserver.c
|
||||
|
||||
ncpfs-0.13 -> ncpfs-0.14
|
||||
|
||||
- Improvements of manual pages by B. Galliart <bgallia@luc.edu> and
|
||||
Terry Dawson <terry@perf.no.itg.telecom.com.au>
|
||||
- fsinfo
|
||||
- pserver.c. Please see this as ALPHA software. There is no
|
||||
documentation, and it is not tested enough. But it might be useful for
|
||||
you.
|
||||
|
||||
ncpfs-0.12 -> ncpfs-0.13
|
||||
|
||||
- support for automatic loading of ncpfs.o by kerneld.
|
||||
Thanks to Steven N. Hirsch <hirsch@emba.uvm.edu>.
|
||||
- A subtle problem in the read routines has been removed by Uwe Bonnes
|
||||
<bon@elektron.ikp.physik.th-darmstadt.de>. Thanks a lot.
|
||||
84
Makefile
84
Makefile
@@ -2,76 +2,60 @@
|
||||
# Makefile for the linux ncp-filesystem routines.
|
||||
#
|
||||
|
||||
INCLUDES = -I/usr/src/linux/include
|
||||
# KERNEL = 1.2
|
||||
|
||||
CFLAGS = -Wall -Wstrict-prototypes -O2 -DMODULE -fomit-frame-pointer \
|
||||
$(INCLUDES) \
|
||||
# -DDEBUG_NCP=2 -DDEBUG_NCP_MALLOC
|
||||
# -DDEBUG_NCP_MALLOC
|
||||
TOPDIR = $(shell pwd)
|
||||
|
||||
CC = gcc -D__KERNEL__ -I.
|
||||
AS = as
|
||||
ARCH = i386
|
||||
BINDIR = /usr/local/bin
|
||||
INTERM_BINDIR = $(TOPDIR)/bin
|
||||
SUBDIRS = util ipx-0.75 man
|
||||
|
||||
.c.s:
|
||||
$(CC) $(CFLAGS) -S $<
|
||||
.c.o:
|
||||
$(CC) $(CFLAGS) -c $<
|
||||
.s.o:
|
||||
$(AS) -o $*.o $<
|
||||
#
|
||||
# The following 2 lines are for those who use Kernel version 1.2.x.
|
||||
# If you have a kernel later than 1.3.53, please comment out the
|
||||
# the following lines. You have to recompile your kernel
|
||||
# and say 'y' when 'make config' asks you for IPX and ncpfs.
|
||||
#
|
||||
#SUBDIRS += kernel-1.2/src
|
||||
#INCLUDES = -I$(TOPDIR)/kernel-1.2
|
||||
|
||||
OBJS= dir.o inode.o file.o sock.o ioctl.o ncplib.o
|
||||
# If you are using kerneld to autoload ncp support,
|
||||
# uncomment this (kerneld is in linux since about 1.3.57):
|
||||
# KERNELD = -DHAVE_KERNELD
|
||||
|
||||
all: ncpfs.o ncpmount ncptest
|
||||
export INCLUDES BINDIR INTERM_BINDIR KERNELD
|
||||
|
||||
ncpfs.o: $(OBJS)
|
||||
$(LD) -r -o ncpfs.o $(OBJS)
|
||||
|
||||
ncplib.o: ncplib.c ncplib.h
|
||||
$(CC) $(CFLAGS) -finline-functions -c $<
|
||||
|
||||
ncpmount: ncpmount.o ncplib_user.o nwcrypt.o
|
||||
gcc -o ncpmount ncpmount.o ncplib_user.o nwcrypt.o
|
||||
|
||||
ncpmount.o: ncpmount.c
|
||||
gcc -c ncpmount.c -Wall -I. -g
|
||||
|
||||
ncptest: ncptest.o ncplib_user.o nwcrypt.o
|
||||
gcc -o ncptest ncptest.o ncplib_user.o nwcrypt.o
|
||||
|
||||
ncptest.o: ncptest.c
|
||||
gcc -c ncptest.c -Wall -I. -g
|
||||
|
||||
ncplib_user.o: ncplib_user.c ncplib_user.h
|
||||
gcc -c ncplib_user.c -Wall -I. -g
|
||||
|
||||
nwcrypt.o: nwcrypt.c
|
||||
gcc -c -O2 -Wall nwcrypt.c
|
||||
all:
|
||||
for i in $(SUBDIRS); do make -C $$i; done
|
||||
|
||||
dep:
|
||||
$(CPP) -M $(INCLUDES) *.c > .depend
|
||||
for i in $(SUBDIRS); do make -C $$i dep; done
|
||||
|
||||
install:
|
||||
for i in $(SUBDIRS); do make -C $$i install; done
|
||||
|
||||
clean:
|
||||
rm -f *.o *~
|
||||
rm -f `find . -type f -name '*.o' -print`
|
||||
rm -f `find . -type f -name '*~' -print`
|
||||
rm -f `find . -type f -name '.depend' -print`
|
||||
rm -f `find . -type f -name '*.out' -print`
|
||||
for i in $(SUBDIRS); do make -C $$i clean; done
|
||||
|
||||
realclean: clean
|
||||
rm -f ncpmount ncptest .depend $(DISTFILE) *.out
|
||||
rm -fr $(INTERM_BINDIR)/* ncpfs.tgz
|
||||
make -C util realclean
|
||||
|
||||
modules: ncpfs.o
|
||||
|
||||
SRCPATH=$(shell pwd)
|
||||
SRCDIR=$(shell basename $(SRCPATH))
|
||||
DISTFILE=$(SRCDIR).tgz
|
||||
BACKUPFILE=ncpfs01.tgz
|
||||
HOME=/home/me
|
||||
|
||||
backup:
|
||||
(rm -f $(DISTFILE); cd ..; tar cvf - $(SRCDIR) | gzip -1 \
|
||||
> $(HOME)/tarz/backup/$(BACKUPFILE))
|
||||
(cd $(HOME)/tarz/backup; ls -l $(BACKUPFILE); mcopy $(BACKUPFILE) a:)
|
||||
dist: tgz
|
||||
make dep
|
||||
make all
|
||||
|
||||
dist: realclean
|
||||
rm -fr mnt
|
||||
tgz: realclean
|
||||
(cd ..; \
|
||||
tar cvf - $(SRCDIR) | \
|
||||
gzip -9 > $(DISTFILE); \
|
||||
|
||||
87
README
87
README
@@ -1,26 +1,49 @@
|
||||
This is version 0.5 of ncpfs, a free NetWare client for Linux. For me
|
||||
it works with 1.3.39, although this version has severe problems with
|
||||
the socket layer. Your connection will block after you have sent 64k
|
||||
of requests to the server. Alan Cox told me he would like to have that
|
||||
fixed in 1.3.42 or so.
|
||||
This is ncpfs, a free NetWare client filesystem for Linux. Besides
|
||||
some little utilities it also contains nprint, which enables you to
|
||||
print on NetWare print queues.
|
||||
|
||||
I know that this piece of software is VERY incomplete, I have to
|
||||
apologize for that. But I thought I should make it publically
|
||||
available, because I have tried to ask several people about the legal
|
||||
status of the code. I did not get very satisfying answers. So I publish
|
||||
ncpfs to open it for criticism. If nobody complains, I will go on
|
||||
working.
|
||||
INSTALLATION
|
||||
|
||||
To install ncpfs, just type 'make', 'insmod ncpfs.o' and then
|
||||
'ncpmount server mount-point'.
|
||||
The installation of ncpfs depends on the kernel version you are
|
||||
using. For kernel 1.2, you should simply type 'make' and look at
|
||||
what's in the bin/ directory after that. Please be sure that your
|
||||
kernel resides in /usr/src/linux, because the file
|
||||
kernel-1.2/src/sock.c has to refer directly to it.
|
||||
|
||||
Please note that your IPX system has to be configured correctly. There
|
||||
has to be a route to the internal network of your server. Please see
|
||||
the file start_ipx for an example.
|
||||
If you use Kernel 1.3, please be sure that you use at least
|
||||
1.3.54. ncpfs does NOT work with any earlier 1.3.x kernel, especially
|
||||
not with 1.3.53, although this one has a fs/ncpfs/ subdirectory.
|
||||
|
||||
If you use Kernel 1.3.54 or later, you might have to recompile your
|
||||
kernel. With these kernels, the kernel part of ncpfs is already
|
||||
included in the main source tree. If you want to use ncpfs, you should
|
||||
say 'y' to 'make config' when you are asked for IPX, and again when it
|
||||
asks for ncpfs. After you have rebooted with the new kernel, 'cat
|
||||
/proc/filesystems' should show you a line saying that the kernel knows
|
||||
ncpfs.
|
||||
|
||||
With Kernel 1.3.54 or later you also have to modify the Makefile in the
|
||||
directory you found this README in. Please see the Makefile for the
|
||||
necessary modifications. Then typing 'make' should work with no
|
||||
problem.
|
||||
|
||||
|
||||
USING NCPFS
|
||||
|
||||
Please note that your IPX system has to be configured correctly. If
|
||||
you want to take the 'Plug-and-Play' route, you can simply say
|
||||
'ipx_configure --auto_interface=on --auto_primary=on'. If ncpmount
|
||||
does not work immediately, you should wait for about 1 minute and try
|
||||
again. In that period, an IPX packet should have passed by and your
|
||||
network interface should have configured itself automatically.
|
||||
|
||||
If all that does not work and you want to do the configuration by
|
||||
hand, note that there has to be a route to the internal network of
|
||||
your server. Please see the file util/start_ipx for an example.
|
||||
|
||||
I use tools written by Greg Page, Caldera. I hope I did not do too
|
||||
much harm to their business. For your convenience I included the file
|
||||
ipx.tar made available by Caldera.
|
||||
much harm to their business. For your convenience I included the
|
||||
contents of the file ipx.tar made available by Caldera.
|
||||
|
||||
My main source of information is a book written in german by Manfred
|
||||
Hill and Ralf Zessin, "Netzwerkprogrammierung in C", IWT Verlag GmbH,
|
||||
@@ -30,7 +53,7 @@ programming. If you know about the concepts and possibilities of NCP,
|
||||
Ralph Brown's interrupt list becomes much more readable. It's much
|
||||
easier to find undocumented information if you know what to look for!
|
||||
|
||||
For the curious: the file ncplib_user.[ch] is a library that makes it
|
||||
For the curious: the files ncplib.[ch] are a library that makes it
|
||||
possible to send NCP requests to the server over a mounted
|
||||
directory. I use it to keep the encryption stuff out of the kernel by
|
||||
logging in from user space. Look at the file ncptest.c for other
|
||||
@@ -40,6 +63,21 @@ free NetWare API for Linux! I would be happy to receive your comments
|
||||
on this.
|
||||
|
||||
|
||||
THANKS
|
||||
|
||||
I do not want to leave those unmentioned, who have helped me with
|
||||
ncpfs.
|
||||
|
||||
The most enthusiastic user and tester is certainly Uwe Bonnes
|
||||
<bon@elektron.ikp.physik.th-darmstadt.de>. So far he's the only one
|
||||
who has contributed something, namely manpages and corretions to
|
||||
existing manpages.
|
||||
|
||||
Ales Dyrak has written lwared, which was the initial start for ncpfs.
|
||||
|
||||
Alan Cox has found some bugs I would probably never have found.
|
||||
|
||||
|
||||
LIMITATIONS (compare these with smbfs :-)
|
||||
|
||||
The limitations ncpfs has are the natural limitations of the NCP
|
||||
@@ -61,3 +99,14 @@ different. You can never know when the client will access the file-id
|
||||
you offered, so you would have to cache the inode numbers
|
||||
indefinitely long. I think this should not be done in kernel mode, as
|
||||
it would require an unlimited amount of RAM.
|
||||
|
||||
Those who looked at the kernel code a bit closer will have found out
|
||||
that the last section is a little white lie. As I found out after the
|
||||
first version of ncpfs, NetWare does indeed offer something like inode
|
||||
numbers, although are only unique per volume. So one way to make ncpfs
|
||||
re-exportable by nfs is to allocate a superblock per volume and show
|
||||
the inode numbers to the user. I was just too lazy to do this
|
||||
yet. Maybe once we will force Novell to make NetWare NFS
|
||||
affordable... ;-)
|
||||
|
||||
Have fun with ncpfs!
|
||||
|
||||
81
ioctl.c
81
ioctl.c
@@ -1,81 +0,0 @@
|
||||
/*
|
||||
* ioctl.c
|
||||
*
|
||||
* Copyright (C) 1995 by Volker Lendecke
|
||||
*
|
||||
*/
|
||||
/* #include <linux/module.h>*/
|
||||
|
||||
#include <asm/segment.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/ncp_fs.h>
|
||||
#include <linux/ioctl.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/ncp.h>
|
||||
|
||||
int
|
||||
ncp_ioctl (struct inode * inode, struct file * filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
int result;
|
||||
struct ncp_ioctl_request request;
|
||||
struct ncp_server *server;
|
||||
|
||||
switch(cmd) {
|
||||
case NCP_IOC_NCPREQUEST:
|
||||
|
||||
if (!suser()) {
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
if ((result = verify_area(VERIFY_READ, (char *)arg,
|
||||
sizeof(request))) != 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
memcpy_fromfs(&request, (struct ncp_ioctl_request *)arg,
|
||||
sizeof(request));
|
||||
|
||||
if ( (request.function > 255)
|
||||
|| (request.size >
|
||||
NCP_PACKET_SIZE - sizeof(struct ncp_request_header))) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((result = verify_area(VERIFY_WRITE, (char *)request.data,
|
||||
NCP_PACKET_SIZE)) != 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
server = NCP_SERVER(inode);
|
||||
ncp_lock_server(server);
|
||||
|
||||
/* FIXME: We hack around in the server's structures
|
||||
here to be able to use ncp_request */
|
||||
|
||||
server->has_subfunction = 0;
|
||||
server->current_size =
|
||||
request.size + sizeof(struct ncp_request_header);
|
||||
memcpy_fromfs(&(server->
|
||||
packet[sizeof(struct ncp_request_header)]),
|
||||
request.data, request.size);
|
||||
|
||||
|
||||
ncp_request(server, request.function);
|
||||
|
||||
DPRINTK("ncp_ioctl: copy %d bytes\n",
|
||||
server->reply_size);
|
||||
memcpy_tofs(request.data, server->packet,
|
||||
server->reply_size);
|
||||
|
||||
ncp_unlock_server(server);
|
||||
|
||||
return server->reply_size;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
30
ipx-0.75/Makefile
Normal file
30
ipx-0.75/Makefile
Normal file
@@ -0,0 +1,30 @@
|
||||
CFLAGS = -O2 -Wall
|
||||
UTILS = $(INTERM_BINDIR)/ipx_configure $(INTERM_BINDIR)/ipx_interface \
|
||||
$(INTERM_BINDIR)/ipx_internal_net $(INTERM_BINDIR)/ipx_route
|
||||
|
||||
all: $(UTILS)
|
||||
|
||||
$(INTERM_BINDIR)/ipx_configure: ipx_configure.o
|
||||
$(CC) -s -o $(INTERM_BINDIR)/ipx_configure ipx_configure.o
|
||||
|
||||
$(INTERM_BINDIR)/ipx_interface: ipx_interface.o
|
||||
$(CC) -s -o $(INTERM_BINDIR)/ipx_interface ipx_interface.o
|
||||
|
||||
$(INTERM_BINDIR)/ipx_internal_net: ipx_internal_net.o
|
||||
$(CC) -s -o $(INTERM_BINDIR)/ipx_internal_net ipx_internal_net.o
|
||||
|
||||
$(INTERM_BINDIR)/ipx_route: ipx_route.o
|
||||
$(CC) -s -o $(INTERM_BINDIR)/ipx_route ipx_route.o
|
||||
|
||||
dep:
|
||||
$(CPP) -M $(INCLUDES) *.c > .depend
|
||||
|
||||
clean:
|
||||
rm -f $(UTILS) *.o rip sap ipxrcv ipxsend
|
||||
|
||||
install: $(UTILS)
|
||||
for i in $(UTILS); \
|
||||
do \
|
||||
install --strip $$i $(BINDIR); \
|
||||
done
|
||||
|
||||
65
ipx-0.75/README
Normal file
65
ipx-0.75/README
Normal file
@@ -0,0 +1,65 @@
|
||||
This file contains a very short introduction to the IPX implementation
|
||||
on Linux. Feel free to forward comments (especially suggested additions)
|
||||
to greg@caldera.com.
|
||||
|
||||
The following are important definitions in understanding the descriptions
|
||||
in this README file.
|
||||
|
||||
IPX Interface - This is the item to which IPX sockets are bound.
|
||||
An IPX interface corresponds to an IPX Network Number which corresponds
|
||||
to a physical device and frame type. A sample IPX Interface would be:
|
||||
Network Number: 0x00ABCDEF
|
||||
Device: Eth0
|
||||
Frame Type: 802.2.
|
||||
The particular interface is selected during binding by using the
|
||||
Network Number (see sample code below).
|
||||
|
||||
Primary Interface - The interface that is selected by default when
|
||||
binding a socket. This is selected when binding by using
|
||||
a network number of 0 (see sample code below).
|
||||
|
||||
Internal Network - This is a special kind of IPX interface that does
|
||||
not have a physical device or frame type. It is used to provide
|
||||
a route-independent address for service providers. Internal network
|
||||
numbers are optional; however, when one is present it is also the
|
||||
Primary Interface.
|
||||
|
||||
This tar file contains the following IPX utilities:
|
||||
|
||||
ipx_interface.c
|
||||
This program is used to create an IPX interface.
|
||||
|
||||
ipx_internal_net.c
|
||||
This program is used to create an IPX Internal Network number.
|
||||
|
||||
ipx_route.c
|
||||
This program creates an IPX route.
|
||||
|
||||
ipx_configure.c
|
||||
This program is used to read/write two configuration parameters:
|
||||
AUTO INTERFACE CREATE - IPX should/shouldn't automatically create
|
||||
an IPX interface when it discovers one that has not been
|
||||
registered via ipx_interface above.
|
||||
AUTO PRIMARY SELECT - IPX should/shouldn't automatically select
|
||||
a primary interface when it one an interface exists and
|
||||
none are designated as the primary. Manual designation
|
||||
is performed via ipx_interface.
|
||||
|
||||
By default, these are both turned off.
|
||||
|
||||
The following are sample IPX programs:
|
||||
|
||||
ipxrcv.c and ipxsend.c
|
||||
ipxsend will send a single packet to an instance of ipxrcv running on the
|
||||
same machine. It uses getsockname(2) to determine the address to which to
|
||||
send the packet.
|
||||
rip.c
|
||||
rip passively monitors the rip traffic on the attached IPX network.
|
||||
sap.c
|
||||
sap passively monitors the sap traffic on the attached IPX network.
|
||||
|
||||
There are three files in /proc/net that relate to IPX.
|
||||
ipx_interface contains the list of IPX interfaces.
|
||||
ipx_route contains the list of IPX routes.
|
||||
ipx contains the list of IPX sockets in use.
|
||||
|
||||
125
ipx-0.75/ipx_configure.c
Normal file
125
ipx-0.75/ipx_configure.c
Normal file
@@ -0,0 +1,125 @@
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
#include <getopt.h>
|
||||
#include <strings.h>
|
||||
#include <linux/ipx.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
struct option options[] = {
|
||||
{ "auto_primary", required_argument, NULL, 1 },
|
||||
{ "auto_interface", required_argument, NULL, 2 },
|
||||
{ "help", no_argument, NULL, 3},
|
||||
{ NULL, 0, NULL, 0 }
|
||||
};
|
||||
|
||||
char *progname;
|
||||
|
||||
void
|
||||
usage(void)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Usage: %s --auto_primary=[on|off]\n\
|
||||
Usage: %s --auto_interface=[on|off]\n\
|
||||
Usage: %s --help\n\
|
||||
Usage: %s\n", progname, progname, progname, progname);
|
||||
}
|
||||
|
||||
int
|
||||
map_string_to_bool(char *optarg)
|
||||
{
|
||||
if ((strcasecmp(optarg, "ON") == 0) ||
|
||||
(strcasecmp(optarg, "TRUE") == 0) ||
|
||||
(strcasecmp(optarg, "SET") == 0) ||
|
||||
(strcasecmp(optarg, "YES") == 0)) {
|
||||
return 1;
|
||||
} else if ((strcasecmp(optarg, "OFF") == 0) ||
|
||||
(strcasecmp(optarg, "FALSE") == 0) ||
|
||||
(strcasecmp(optarg, "CLEAR") == 0) ||
|
||||
(strcasecmp(optarg, "NO") == 0)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int s;
|
||||
int result;
|
||||
char errmsg[80];
|
||||
char val;
|
||||
int option_index = 0;
|
||||
int got_auto_pri = 0;
|
||||
int got_auto_itf = 0;
|
||||
ipx_config_data data;
|
||||
|
||||
progname = argv[0];
|
||||
|
||||
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||
if (s < 0) {
|
||||
sprintf(errmsg, "%s: socket", progname);
|
||||
perror(errmsg);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
sprintf(errmsg, "%s: ioctl", progname);
|
||||
while ((result = getopt_long(argc, argv, "", options,
|
||||
&option_index)) != -1) {
|
||||
switch (result) {
|
||||
case 1:
|
||||
if (got_auto_pri)
|
||||
break;
|
||||
got_auto_pri++;
|
||||
|
||||
val = map_string_to_bool(optarg);
|
||||
if (val < 0) {
|
||||
usage();
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
result = ioctl(s, SIOCAIPXPRISLT, &val);
|
||||
if (result < 0) {
|
||||
perror(errmsg);
|
||||
exit(-1);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (got_auto_itf)
|
||||
break;
|
||||
got_auto_itf++;
|
||||
|
||||
val = map_string_to_bool(optarg);
|
||||
if (val < 0) {
|
||||
usage();
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
result = ioctl(s, SIOCAIPXITFCRT, &val);
|
||||
if (result < 0) {
|
||||
perror(errmsg);
|
||||
exit(-1);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
usage();
|
||||
break;
|
||||
}
|
||||
}
|
||||
result = ioctl(s, SIOCIPXCFGDATA, &data);
|
||||
if (result < 0) {
|
||||
perror(errmsg);
|
||||
exit(-1);
|
||||
}
|
||||
if (argc == 1) {
|
||||
fprintf(stdout, "Auto Primary Select is %s\n\
|
||||
Auto Interface Create is %s\n",
|
||||
(data.ipxcfg_auto_select_primary) ? "ON" : "OFF",
|
||||
(data.ipxcfg_auto_create_interfaces) ? "ON" : "OFF");
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
303
ipx-0.75/ipx_interface.c
Normal file
303
ipx-0.75/ipx_interface.c
Normal file
@@ -0,0 +1,303 @@
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
#include <netinet/in.h>
|
||||
#include <linux/ipx.h>
|
||||
#include <linux/if.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
static struct ifreq id;
|
||||
static char *progname;
|
||||
|
||||
void
|
||||
usage(void)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s add [-p] device frame_type [net_number]\n\
|
||||
Usage: %s del device frame_type\n\
|
||||
Usage: %s check device frame_type\n", progname, progname, progname);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
struct frame_type {
|
||||
char *ft_name;
|
||||
unsigned char ft_val;
|
||||
} frame_types[] = {
|
||||
{"802.2", IPX_FRAME_8022},
|
||||
{"802.3", IPX_FRAME_8023},
|
||||
{"SNAP", IPX_FRAME_SNAP},
|
||||
{"EtherII", IPX_FRAME_ETHERII}
|
||||
};
|
||||
|
||||
#define NFTYPES (sizeof(frame_types)/sizeof(struct frame_type))
|
||||
|
||||
int
|
||||
lookup_frame_type(char *frame)
|
||||
{
|
||||
int j;
|
||||
|
||||
for (j = 0; (j < NFTYPES) &&
|
||||
(strcasecmp(frame_types[j].ft_name, frame));
|
||||
j++)
|
||||
;
|
||||
|
||||
if (j != NFTYPES)
|
||||
return j;
|
||||
|
||||
fprintf(stderr, "%s: Frame type must be", progname);
|
||||
for (j = 0; j < NFTYPES; j++) {
|
||||
fprintf(stderr, "%s%s",
|
||||
(j == NFTYPES-1) ? " or " : " ",
|
||||
frame_types[j].ft_name);
|
||||
}
|
||||
fprintf(stderr, ".\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
ipx_add_interface(int argc, char **argv)
|
||||
{
|
||||
struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)&id.ifr_addr;
|
||||
int s;
|
||||
int result;
|
||||
unsigned long netnum;
|
||||
char errmsg[80];
|
||||
int i, fti = 0;
|
||||
char c;
|
||||
|
||||
sipx->sipx_special = IPX_SPECIAL_NONE;
|
||||
sipx->sipx_network = 0L;
|
||||
sipx->sipx_type = IPX_FRAME_NONE;
|
||||
while ((c = getopt(argc, argv, "p")) > 0) {
|
||||
switch (c) {
|
||||
case 'p': sipx->sipx_special = IPX_PRIMARY; break;
|
||||
}
|
||||
}
|
||||
|
||||
if (((i = (argc - optind)) < 2) || (i > 3)) {
|
||||
usage();
|
||||
}
|
||||
|
||||
for (i = optind; i < argc; i++) {
|
||||
switch (i-optind) {
|
||||
case 0: /* Physical Device - Required */
|
||||
strcpy(id.ifr_name, argv[i]);
|
||||
break;
|
||||
case 1: /* Frame Type - Required */
|
||||
fti = lookup_frame_type(argv[i]);
|
||||
if (fti < 0)
|
||||
exit(-1);
|
||||
sipx->sipx_type = frame_types[fti].ft_val;
|
||||
break;
|
||||
|
||||
case 2: /* Network Number - Optional */
|
||||
netnum = strtoul(argv[i], (char **)NULL, 16);
|
||||
if (netnum == 0xffffffffL) {
|
||||
fprintf(stderr,
|
||||
"%s: Inappropriate network number %08lX\n",
|
||||
progname, netnum);
|
||||
exit(-1);
|
||||
}
|
||||
sipx->sipx_network = htonl(netnum);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||
if (s < 0) {
|
||||
sprintf(errmsg, "%s: socket", progname);
|
||||
perror(errmsg);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
i = 0;
|
||||
sipx->sipx_family = AF_IPX;
|
||||
sipx->sipx_action = IPX_CRTITF;
|
||||
do {
|
||||
result = ioctl(s, SIOCSIFADDR, &id);
|
||||
i++;
|
||||
} while ((i < 5) && (result < 0) && (errno == EAGAIN));
|
||||
|
||||
if (result == 0) exit(0);
|
||||
|
||||
switch (errno) {
|
||||
case EEXIST:
|
||||
fprintf(stderr, "%s: Primary network already selected.\n",
|
||||
progname);
|
||||
break;
|
||||
case EADDRINUSE:
|
||||
fprintf(stderr, "%s: Network number (%08lX) already in use.\n",
|
||||
progname, htonl(sipx->sipx_network));
|
||||
break;
|
||||
case EPROTONOSUPPORT:
|
||||
fprintf(stderr, "%s: Invalid frame type (%s).\n",
|
||||
progname, frame_types[fti].ft_name);
|
||||
break;
|
||||
case ENODEV:
|
||||
fprintf(stderr, "%s: No such device (%s).\n", progname,
|
||||
id.ifr_name);
|
||||
break;
|
||||
case ENETDOWN:
|
||||
fprintf(stderr, "%s: Requested device (%s) is down.\n", progname,
|
||||
id.ifr_name);
|
||||
break;
|
||||
case EINVAL:
|
||||
fprintf(stderr, "%s: Invalid device (%s).\n", progname,
|
||||
id.ifr_name);
|
||||
break;
|
||||
case EAGAIN:
|
||||
fprintf(stderr,
|
||||
"%s: Insufficient memory to create interface.\n",
|
||||
progname);
|
||||
break;
|
||||
default:
|
||||
sprintf(errmsg, "%s: ioctl", progname);
|
||||
perror(errmsg);
|
||||
break;
|
||||
}
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
int
|
||||
ipx_del_interface(int argc, char **argv)
|
||||
{
|
||||
struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)&id.ifr_addr;
|
||||
int s;
|
||||
int result;
|
||||
char errmsg[80];
|
||||
int fti;
|
||||
|
||||
if (argc != 3) {
|
||||
usage();
|
||||
}
|
||||
|
||||
sipx->sipx_network = 0L;
|
||||
strcpy(id.ifr_name, argv[1]);
|
||||
fti = lookup_frame_type(argv[2]);
|
||||
if (fti < 0)
|
||||
exit(-1);
|
||||
sipx->sipx_type = frame_types[fti].ft_val;
|
||||
|
||||
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||
if (s < 0) {
|
||||
sprintf(errmsg, "%s: socket", progname);
|
||||
perror(errmsg);
|
||||
exit(-1);
|
||||
}
|
||||
sipx->sipx_action = IPX_DLTITF;
|
||||
sipx->sipx_family = AF_IPX;
|
||||
result = ioctl(s, SIOCSIFADDR, &id);
|
||||
if (result == 0) exit(0);
|
||||
|
||||
switch (errno) {
|
||||
case EPROTONOSUPPORT:
|
||||
fprintf(stderr, "%s: Invalid frame type (%s).\n",
|
||||
progname, frame_types[fti].ft_name);
|
||||
break;
|
||||
case ENODEV:
|
||||
fprintf(stderr, "%s: No such device (%s).\n", progname,
|
||||
id.ifr_name);
|
||||
break;
|
||||
case EINVAL:
|
||||
fprintf(stderr, "%s: No such IPX interface %s %s.\n", progname,
|
||||
id.ifr_name, frame_types[fti].ft_name);
|
||||
break;
|
||||
default:
|
||||
sprintf(errmsg, "%s: ioctl", progname);
|
||||
perror(errmsg);
|
||||
break;
|
||||
}
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
int
|
||||
ipx_check_interface(int argc, char **argv)
|
||||
{
|
||||
struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)&id.ifr_addr;
|
||||
int s;
|
||||
int result;
|
||||
char errmsg[80];
|
||||
int fti;
|
||||
|
||||
if (argc != 3) {
|
||||
usage();
|
||||
}
|
||||
|
||||
sipx->sipx_network = 0L;
|
||||
strcpy(id.ifr_name, argv[1]);
|
||||
fti = lookup_frame_type(argv[2]);
|
||||
if (fti < 0)
|
||||
exit(-1);
|
||||
sipx->sipx_type = frame_types[fti].ft_val;
|
||||
|
||||
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||
if (s < 0) {
|
||||
sprintf(errmsg, "%s: socket", progname);
|
||||
perror(errmsg);
|
||||
exit(-1);
|
||||
}
|
||||
sipx->sipx_family = AF_IPX;
|
||||
result = ioctl(s, SIOCGIFADDR, &id);
|
||||
if (result == 0) {
|
||||
printf(
|
||||
"IPX Address for (%s, %s) is %08lX:%02X%02X%02X%02X%02X%02X.\n",
|
||||
argv[1], frame_types[fti].ft_name,
|
||||
htonl(sipx->sipx_network), sipx->sipx_node[0],
|
||||
sipx->sipx_node[1], sipx->sipx_node[2],
|
||||
sipx->sipx_node[3], sipx->sipx_node[4],
|
||||
sipx->sipx_node[5]);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
switch (errno) {
|
||||
case EPROTONOSUPPORT:
|
||||
fprintf(stderr, "%s: Invalid frame type (%s).\n",
|
||||
progname, frame_types[fti].ft_name);
|
||||
break;
|
||||
case ENODEV:
|
||||
fprintf(stderr, "%s: No such device (%s).\n", progname,
|
||||
id.ifr_name);
|
||||
break;
|
||||
case EADDRNOTAVAIL:
|
||||
fprintf(stderr, "%s: No such IPX interface %s %s.\n", progname,
|
||||
id.ifr_name, frame_types[fti].ft_name);
|
||||
break;
|
||||
default:
|
||||
sprintf(errmsg, "%s: ioctl", progname);
|
||||
perror(errmsg);
|
||||
break;
|
||||
}
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
|
||||
progname = argv[0];
|
||||
if (argc < 2) {
|
||||
usage();
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (strncasecmp(argv[1], "add", 3) == 0) {
|
||||
for (i = 1; i < (argc-1); i++)
|
||||
argv[i] = argv[i+1];
|
||||
ipx_add_interface(argc-1, argv);
|
||||
} else if (strncasecmp(argv[1], "del", 3) == 0) {
|
||||
for (i = 1; i < (argc-1); i++)
|
||||
argv[i] = argv[i+1];
|
||||
ipx_del_interface(argc-1, argv);
|
||||
} else if (strncasecmp(argv[1], "check", 5) == 0) {
|
||||
for (i = 1; i < (argc-1); i++)
|
||||
argv[i] = argv[i+1];
|
||||
ipx_check_interface(argc-1, argv);
|
||||
}
|
||||
usage();
|
||||
return 0;
|
||||
}
|
||||
195
ipx-0.75/ipx_internal_net.c
Normal file
195
ipx-0.75/ipx_internal_net.c
Normal file
@@ -0,0 +1,195 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <strings.h>
|
||||
#include <netinet/in.h>
|
||||
#include <linux/ipx.h>
|
||||
#include <linux/if.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
static struct ifreq id;
|
||||
static char *progname;
|
||||
|
||||
void
|
||||
usage(void)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s add net_number(hex) node(hex)\n\
|
||||
Usage: %s del\n", progname, progname);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
int
|
||||
map_char_to_val(char dig)
|
||||
{
|
||||
char digit = tolower(dig);
|
||||
if ((digit >= '0') && (digit <= '9')) {
|
||||
return digit - '0';
|
||||
} else if ((digit >= 'a') && (digit <= 'f')) {
|
||||
return (10 + (digit - 'a'));
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
ipx_add_internal_net(int argc, char **argv)
|
||||
{
|
||||
struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)&id.ifr_addr;
|
||||
int s;
|
||||
int result;
|
||||
unsigned long netnum;
|
||||
char errmsg[80];
|
||||
int nodelen;
|
||||
char *node;
|
||||
char tmpnode[13];
|
||||
unsigned char *tout;
|
||||
char *tin;
|
||||
int i;
|
||||
|
||||
if (argc != 3) {
|
||||
usage();
|
||||
}
|
||||
|
||||
netnum = strtoul(argv[1], (char **)NULL, 16);
|
||||
if ((netnum == 0L) || (netnum == 0xffffffffL)) {
|
||||
fprintf(stderr, "%s: Inappropriate network number %08lX\n",
|
||||
progname, netnum);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
node = argv[2];
|
||||
nodelen = strlen(node);
|
||||
if (nodelen > 12) {
|
||||
fprintf(stderr, "%s: Node length is too long (> 12).\n", progname);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
for (i = 0; (i < nodelen) && isxdigit(node[i]); i++)
|
||||
;
|
||||
|
||||
if (i < nodelen) {
|
||||
fprintf(stderr, "%s: Invalid value in node, must be hex digits.\n",
|
||||
progname);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
strcpy(tmpnode, "000000000000");
|
||||
memcpy(&(tmpnode[12-nodelen]), node, nodelen);
|
||||
for (tin = tmpnode, tout = sipx->sipx_node; *tin != '\0'; tin += 2, tout++) {
|
||||
*tout = (unsigned char) map_char_to_val(*tin);
|
||||
*tout <<= 4;
|
||||
*tout |= (unsigned char) map_char_to_val(*(tin+1));
|
||||
}
|
||||
|
||||
if ((memcmp(sipx->sipx_node, "\0\0\0\0\0\0\0\0", IPX_NODE_LEN) == 0) ||
|
||||
(memcmp(sipx->sipx_node, "\377\377\377\377\377\377", IPX_NODE_LEN) == 0)){
|
||||
fprintf(stderr, "%s: Node is invalid.\n", progname);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
sipx->sipx_network = htonl(netnum);
|
||||
sipx->sipx_type = IPX_FRAME_NONE;
|
||||
sipx->sipx_special = IPX_INTERNAL;
|
||||
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||
if (s < 0) {
|
||||
sprintf(errmsg, "%s: socket", progname);
|
||||
perror(errmsg);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
sipx->sipx_family = AF_IPX;
|
||||
sipx->sipx_action = IPX_CRTITF;
|
||||
i = 0;
|
||||
do {
|
||||
result = ioctl(s, SIOCSIFADDR, &id);
|
||||
i++;
|
||||
} while ((i < 5) && (result < 0) && (errno == EAGAIN));
|
||||
|
||||
if (result == 0) exit(0);
|
||||
|
||||
switch (errno) {
|
||||
case EEXIST:
|
||||
fprintf(stderr, "%s: Primary network already selected.\n",
|
||||
progname);
|
||||
break;
|
||||
case EADDRINUSE:
|
||||
fprintf(stderr, "%s: Network number (%08lX) already in use.\n",
|
||||
progname, htonl(sipx->sipx_network));
|
||||
break;
|
||||
case EAGAIN:
|
||||
fprintf(stderr,
|
||||
"%s: Insufficient memory to create internal net.\n",
|
||||
progname);
|
||||
break;
|
||||
default:
|
||||
sprintf(errmsg, "%s: ioctl", progname);
|
||||
perror(errmsg);
|
||||
break;
|
||||
}
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
int
|
||||
ipx_del_internal_net(int argc, char **argv)
|
||||
{
|
||||
struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)&id.ifr_addr;
|
||||
int s;
|
||||
int result;
|
||||
char errmsg[80];
|
||||
|
||||
if (argc != 1) {
|
||||
usage();
|
||||
}
|
||||
|
||||
sipx->sipx_network = 0L;
|
||||
sipx->sipx_special = IPX_INTERNAL;
|
||||
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||
if (s < 0) {
|
||||
sprintf(errmsg, "%s: socket", progname);
|
||||
perror(errmsg);
|
||||
exit(-1);
|
||||
}
|
||||
sipx->sipx_family = AF_IPX;
|
||||
sipx->sipx_action = IPX_DLTITF;
|
||||
result = ioctl(s, SIOCSIFADDR, &id);
|
||||
if (result == 0) exit(0);
|
||||
|
||||
switch (errno) {
|
||||
case ENOENT:
|
||||
fprintf(stderr, "%s: No internal network configured.\n", progname);
|
||||
break;
|
||||
default:
|
||||
sprintf(errmsg, "%s: ioctl", progname);
|
||||
perror(errmsg);
|
||||
break;
|
||||
}
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
|
||||
progname = argv[0];
|
||||
if (argc < 2) {
|
||||
usage();
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (strncasecmp(argv[1], "add", 3) == 0) {
|
||||
for (i = 1; i < (argc-1); i++)
|
||||
argv[i] = argv[i+1];
|
||||
ipx_add_internal_net(argc-1, argv);
|
||||
} else if (strncasecmp(argv[1], "del", 3) == 0) {
|
||||
for (i = 1; i < (argc-1); i++)
|
||||
argv[i] = argv[i+1];
|
||||
ipx_del_internal_net(argc-1, argv);
|
||||
}
|
||||
usage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
215
ipx-0.75/ipx_route.c
Normal file
215
ipx-0.75/ipx_route.c
Normal file
@@ -0,0 +1,215 @@
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <strings.h>
|
||||
#include <netinet/in.h>
|
||||
#include <linux/ipx.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/route.h>
|
||||
|
||||
static struct rtentry rd;
|
||||
static char *progname;
|
||||
|
||||
int
|
||||
map_char_to_val(char dig)
|
||||
{
|
||||
char digit = tolower(dig);
|
||||
if ((digit >= '0') && (digit <= '9')) {
|
||||
return digit - '0';
|
||||
} else if ((digit >= 'a') && (digit <= 'f')) {
|
||||
return (10 + (digit - 'a'));
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
usage(void)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Usage: %s add network(hex) router_network(hex) router_node(hex)\n\
|
||||
Usage: %s del network(hex)\n", progname, progname);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
int
|
||||
ipx_add_route(int argc, char **argv)
|
||||
{
|
||||
/* Router */
|
||||
struct sockaddr_ipx *sr = (struct sockaddr_ipx *)&rd.rt_gateway;
|
||||
/* Target */
|
||||
struct sockaddr_ipx *st = (struct sockaddr_ipx *)&rd.rt_dst;
|
||||
int s;
|
||||
int result;
|
||||
int nodelen;
|
||||
int i;
|
||||
unsigned long netnum;
|
||||
char errmsg[80];
|
||||
char *node;
|
||||
char *tin;
|
||||
char tmpnode[13];
|
||||
unsigned char *tout;
|
||||
|
||||
if (argc != 4)
|
||||
usage();
|
||||
|
||||
/* Network Number */
|
||||
netnum = strtoul(argv[1], (char **)NULL, 16);
|
||||
if ((netnum == 0xffffffffL) || (netnum == 0L)) {
|
||||
fprintf(stderr, "%s: Inappropriate network number %08lX\n",
|
||||
progname, netnum);
|
||||
exit(-1);
|
||||
}
|
||||
rd.rt_flags = RTF_GATEWAY;
|
||||
st->sipx_network = htonl(netnum);
|
||||
|
||||
/* Router Network Number */
|
||||
netnum = strtoul(argv[2], (char **)NULL, 16);
|
||||
if ((netnum == 0xffffffffL) || (netnum == 0L)) {
|
||||
fprintf(stderr, "%s: Inappropriate network number %08lX\n",
|
||||
progname, netnum);
|
||||
exit(-1);
|
||||
}
|
||||
sr->sipx_network = htonl(netnum);
|
||||
|
||||
/* Router Node */
|
||||
node = argv[3];
|
||||
nodelen = strlen(node);
|
||||
if (nodelen > 12) {
|
||||
fprintf(stderr, "%s: Node length is too long (> 12).\n",
|
||||
progname);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
for (i = 0; (i < nodelen) && isxdigit(node[i]); i++)
|
||||
;
|
||||
|
||||
if (i < nodelen) {
|
||||
fprintf(stderr, "%s: Invalid value in node, must be hex digits.\n",
|
||||
progname);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
strcpy(tmpnode, "000000000000");
|
||||
memcpy(&(tmpnode[12-nodelen]), node, nodelen);
|
||||
for (tin = tmpnode, tout = sr->sipx_node; *tin != '\0'; tin += 2, tout++) {
|
||||
*tout = (unsigned char) map_char_to_val(*tin);
|
||||
*tout <<= 4;
|
||||
*tout |= (unsigned char) map_char_to_val(*(tin+1));
|
||||
}
|
||||
|
||||
if ((memcmp(sr->sipx_node, "\0\0\0\0\0\0\0\0", IPX_NODE_LEN) == 0) ||
|
||||
(memcmp(sr->sipx_node, "\377\377\377\377\377\377", IPX_NODE_LEN) == 0)){
|
||||
fprintf(stderr, "%s: Node (%s) is invalid.\n", progname, tmpnode);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||
if (s < 0) {
|
||||
sprintf(errmsg, "%s: socket", progname);
|
||||
perror(errmsg);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
sr->sipx_family = st->sipx_family = AF_IPX;
|
||||
i = 0;
|
||||
do {
|
||||
result = ioctl(s, SIOCADDRT, &rd);
|
||||
i++;
|
||||
} while ((i < 5) && (result < 0) && (errno == EAGAIN));
|
||||
|
||||
if (result == 0) exit(0);
|
||||
|
||||
switch (errno) {
|
||||
case ENETUNREACH:
|
||||
fprintf(stderr, "%s: Router network (%08lX) not reachable.\n",
|
||||
progname, htonl(sr->sipx_network));
|
||||
break;
|
||||
default:
|
||||
sprintf(errmsg, "%s: ioctl", progname);
|
||||
perror(errmsg);
|
||||
break;
|
||||
}
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
int
|
||||
ipx_del_route(int argc, char **argv)
|
||||
{
|
||||
/* Router */
|
||||
struct sockaddr_ipx *sr = (struct sockaddr_ipx *)&rd.rt_gateway;
|
||||
/* Target */
|
||||
struct sockaddr_ipx *st = (struct sockaddr_ipx *)&rd.rt_dst;
|
||||
int s;
|
||||
int result;
|
||||
unsigned long netnum;
|
||||
char errmsg[80];
|
||||
|
||||
if (argc != 2) {
|
||||
usage();
|
||||
}
|
||||
|
||||
rd.rt_flags = RTF_GATEWAY;
|
||||
/* Network Number */
|
||||
netnum = strtoul(argv[1], (char **)NULL, 16);
|
||||
if ((netnum == 0xffffffffL) || (netnum == 0L)) {
|
||||
fprintf(stderr, "%s: Inappropriate network number %08lX.\n",
|
||||
progname, netnum);
|
||||
exit(-1);
|
||||
}
|
||||
st->sipx_network = htonl(netnum);
|
||||
|
||||
st->sipx_family = sr->sipx_family = AF_IPX;
|
||||
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||
if (s < 0) {
|
||||
sprintf(errmsg, "%s: socket", progname);
|
||||
perror(errmsg);
|
||||
exit(-1);
|
||||
}
|
||||
result = ioctl(s, SIOCDELRT, &rd);
|
||||
if (result == 0) exit(0);
|
||||
|
||||
switch (errno) {
|
||||
case ENOENT:
|
||||
fprintf(stderr, "%s: Route not found for network %08lX.\n",
|
||||
progname, netnum);
|
||||
break;
|
||||
case EPERM:
|
||||
fprintf(stderr, "%s: Network %08lX is directly connected.\n",
|
||||
progname, netnum);
|
||||
break;
|
||||
default:
|
||||
sprintf(errmsg, "%s: ioctl", progname);
|
||||
perror(errmsg);
|
||||
break;
|
||||
}
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
|
||||
progname = argv[0];
|
||||
if (argc < 2) {
|
||||
usage();
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (strncasecmp(argv[1], "add", 3) == 0) {
|
||||
for (i = 1; i < (argc-1); i++)
|
||||
argv[i] = argv[i+1];
|
||||
ipx_add_route(argc-1, argv);
|
||||
} else if (strncasecmp(argv[1], "del", 3) == 0) {
|
||||
for (i = 1; i < (argc-1); i++)
|
||||
argv[i] = argv[i+1];
|
||||
ipx_del_route(argc-1, argv);
|
||||
}
|
||||
usage();
|
||||
return 0;
|
||||
}
|
||||
52
ipx-0.75/ipxrcv.c
Normal file
52
ipx-0.75/ipxrcv.c
Normal file
@@ -0,0 +1,52 @@
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <linux/ipx.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <errno.h>
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
struct sockaddr_ipx sipx;
|
||||
int s;
|
||||
int result;
|
||||
char msg[100];
|
||||
int len;
|
||||
|
||||
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||
if (s < 0) {
|
||||
perror("IPX: socket: ");
|
||||
exit(-1);
|
||||
}
|
||||
sipx.sipx_family = AF_IPX;
|
||||
sipx.sipx_network = 0;
|
||||
sipx.sipx_port = htons(0x5000);
|
||||
sipx.sipx_type = 17;
|
||||
len = sizeof(sipx);
|
||||
result = bind(s, (struct sockaddr *)&sipx, sizeof(sipx));
|
||||
if (result < 0) {
|
||||
perror("IPX: bind: ");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
msg[0] = '\0';
|
||||
result = recvfrom(s, msg, sizeof(msg), 0, (struct sockaddr *)&sipx,
|
||||
&len);
|
||||
if (result < 0) {
|
||||
perror("IPX: recvfrom: ");
|
||||
}
|
||||
|
||||
printf("From %08lX:%02X%02X%02X%02X%02X%02X:%04X\n",
|
||||
htonl(sipx.sipx_network),
|
||||
sipx.sipx_node[0], sipx.sipx_node[1],
|
||||
sipx.sipx_node[2], sipx.sipx_node[3],
|
||||
sipx.sipx_node[4], sipx.sipx_node[5],
|
||||
htons(sipx.sipx_port));
|
||||
printf("\tGot \"%s\"\n", msg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
46
ipx-0.75/ipxsend.c
Normal file
46
ipx-0.75/ipxsend.c
Normal file
@@ -0,0 +1,46 @@
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <linux/ipx.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <errno.h>
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
struct sockaddr_ipx sipx;
|
||||
int s;
|
||||
int result;
|
||||
char msg[100] = "Hi Mom";
|
||||
int len = sizeof(sipx);
|
||||
|
||||
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||
if (s < 0) {
|
||||
perror("IPX: socket: ");
|
||||
exit(-1);
|
||||
}
|
||||
sipx.sipx_family = AF_IPX;
|
||||
sipx.sipx_network = 0;
|
||||
sipx.sipx_port = 0;
|
||||
sipx.sipx_type = 17;
|
||||
|
||||
result = bind(s, (struct sockaddr *)&sipx, sizeof(sipx));
|
||||
if (result < 0) {
|
||||
perror("IPX: bind: ");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
result = getsockname(s, (struct sockaddr *)&sipx, &len);
|
||||
sipx.sipx_port = htons(0x5000);
|
||||
result = sendto(s, msg, sizeof(msg), 0, (struct sockaddr *)&sipx,
|
||||
sizeof(sipx));
|
||||
if (result < 0) {
|
||||
perror("IPX: send: ");
|
||||
exit(-1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
68
ipx-0.75/rip.c
Normal file
68
ipx-0.75/rip.c
Normal file
@@ -0,0 +1,68 @@
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <linux/ipx.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <errno.h>
|
||||
|
||||
struct rip_data {
|
||||
unsigned long rip_net;
|
||||
unsigned short rip_hops __attribute__ ((packed));
|
||||
unsigned short rip_ticks __attribute__ ((packed));
|
||||
};
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
struct sockaddr_ipx sipx;
|
||||
int result;
|
||||
int s;
|
||||
char msg[1024];
|
||||
int len;
|
||||
char *bptr;
|
||||
struct rip_data *rp;
|
||||
|
||||
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||
if (s < 0) {
|
||||
perror("IPX: socket: ");
|
||||
exit(-1);
|
||||
}
|
||||
sipx.sipx_family = AF_IPX;
|
||||
sipx.sipx_network = 0;
|
||||
sipx.sipx_port = htons(0x453);
|
||||
sipx.sipx_type = 17;
|
||||
result = bind(s, (struct sockaddr *)&sipx, sizeof(sipx));
|
||||
if (result < 0) {
|
||||
perror("IPX: bind: ");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
while (1) {
|
||||
len = sizeof(sipx);
|
||||
result = recvfrom(s, msg, sizeof(msg), 0,
|
||||
(struct sockaddr *)&sipx, &len);
|
||||
if (result < 0) {
|
||||
perror("IPX: recvfrom");
|
||||
exit(-1);
|
||||
}
|
||||
bptr = msg;
|
||||
result -= 2;
|
||||
printf("RIP packet from: %08lX:%02X%02X%02X%02X%02X%02X\n",
|
||||
htonl(sipx.sipx_network),
|
||||
sipx.sipx_node[0], sipx.sipx_node[1],
|
||||
sipx.sipx_node[2], sipx.sipx_node[3],
|
||||
sipx.sipx_node[4], sipx.sipx_node[5]);
|
||||
bptr += 2;
|
||||
rp = (struct rip_data *) bptr;
|
||||
while (result >= sizeof(struct rip_data)) {
|
||||
printf("\tNET: %08lX HOPS: %d\n", ntohl(rp->rip_net),
|
||||
ntohs(rp->rip_hops));
|
||||
result -= sizeof(struct rip_data);
|
||||
rp++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
96
ipx-0.75/sap.c
Normal file
96
ipx-0.75/sap.c
Normal file
@@ -0,0 +1,96 @@
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <linux/ipx.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
struct sap_data {
|
||||
unsigned short sap_type __attribute__ ((packed));
|
||||
char sap_name[48] __attribute__ ((packed));
|
||||
unsigned long sap_net __attribute__ ((packed));
|
||||
unsigned char sap_node[6] __attribute__ ((packed));
|
||||
unsigned short sap_sock __attribute__ ((packed));
|
||||
unsigned short sap_hops __attribute__ ((packed));
|
||||
};
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int s;
|
||||
int result;
|
||||
struct sockaddr_ipx sipx;
|
||||
char msg[1024];
|
||||
long val = 0;
|
||||
int len;
|
||||
char *bptr;
|
||||
struct sap_data *sp;
|
||||
|
||||
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||
if (s < 0) {
|
||||
perror("IPX: socket: ");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
result = setsockopt(s, SOL_SOCKET, SO_DEBUG, &val, 4);
|
||||
if (result < 0) {
|
||||
perror("IPX: setsockopt: ");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
sipx.sipx_family = PF_IPX;
|
||||
sipx.sipx_network = 0L;
|
||||
sipx.sipx_port = htons(0x452);
|
||||
sipx.sipx_type = 17;
|
||||
|
||||
result = bind(s, (struct sockaddr *)&sipx, sizeof(sipx));
|
||||
if (result < 0) {
|
||||
perror("IPX: bind: ");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
while (1) {
|
||||
len = 1024;
|
||||
result = recvfrom(s, msg, sizeof(msg), 0,
|
||||
(struct sockaddr *)&sipx, &len);
|
||||
if (result < 0) {
|
||||
perror("IPX: recvfrom: ");
|
||||
exit(-1);
|
||||
}
|
||||
bptr = msg;
|
||||
result -= 2;
|
||||
printf("SAP: OP is %x %x\n", bptr[0], bptr[1]);
|
||||
printf("Length is %d\n", result);
|
||||
if (bptr[1] != 2)
|
||||
continue;
|
||||
|
||||
bptr += 2;
|
||||
sp = (struct sap_data *) bptr;
|
||||
while (result >= sizeof(struct sap_data)) {
|
||||
int i;
|
||||
|
||||
sp->sap_name[32] = '\0';
|
||||
for (i = 31; (i > 0) && (sp->sap_name[i] == '_'); i--);
|
||||
i++;
|
||||
sp->sap_name[i] = '\0';
|
||||
printf("NAME: %s TYPE: %x HOPS: %x\n", sp->sap_name,
|
||||
ntohs(sp->sap_type), ntohs(sp->sap_hops));
|
||||
printf("%lx:%x %x %x %x %x %x: %x\n",
|
||||
ntohl(sp->sap_net),
|
||||
sp->sap_node[0],
|
||||
sp->sap_node[1],
|
||||
sp->sap_node[2],
|
||||
sp->sap_node[3],
|
||||
sp->sap_node[4],
|
||||
sp->sap_node[5],
|
||||
ntohs(sp->sap_sock));
|
||||
result -= sizeof(struct sap_data);
|
||||
sp++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
53
ipxutil.h
53
ipxutil.h
@@ -1,53 +0,0 @@
|
||||
|
||||
/*
|
||||
|
||||
IPX support library
|
||||
|
||||
Copyright (C) 1994, 1995 Ales Dryak <e-mail: A.Dryak@sh.cvut.cz>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
*/
|
||||
#ifndef __IPXUTIL_H__
|
||||
|
||||
#define __IPXUTIL_H__
|
||||
|
||||
#include <string.h>
|
||||
#include <linux/ipx.h>
|
||||
|
||||
#define IPX_SAP_PTYPE (0x04)
|
||||
#define IPX_SAP_PORT (0x0452)
|
||||
|
||||
#define IPX_SAP_FILE_SERVER (0x004)
|
||||
|
||||
#define IPX_BROADCAST_NODE "\xff\xff\xff\xff\xff\xff"
|
||||
#define IPX_THIS_NODE "\0\0\0\0\0\0"
|
||||
|
||||
|
||||
typedef unsigned long IPXNet;
|
||||
typedef unsigned short IPXPort;
|
||||
typedef unsigned char IPXNode[IPX_NODE_LEN];
|
||||
|
||||
void ipx_print_node(IPXNode node);
|
||||
void ipx_print_network(IPXNet net);
|
||||
void ipx_print_port(IPXPort port);
|
||||
void ipx_print_saddr(struct sockaddr_ipx* sipx);
|
||||
|
||||
static __inline__ void
|
||||
ipx_assign_node(IPXNode dest, IPXNode src) {
|
||||
memcpy(dest, src, IPX_NODE_LEN);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -9,6 +9,7 @@
|
||||
#define _LINUX_NCP_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/ipx.h>
|
||||
|
||||
#define NCP_PTYPE (0x11)
|
||||
#define NCP_PORT (0x0451)
|
||||
@@ -45,11 +46,15 @@ struct ncp_reply_header {
|
||||
#define NCP_BINDERY_USER (0x0001)
|
||||
#define NCP_BINDERY_UGROUP (0x0002)
|
||||
#define NCP_BINDERY_PQUEUE (0x0003)
|
||||
#define NCP_BINDERY_FSERVER (0x0004)
|
||||
#define NCP_BINDERY_NAME_LEN (48)
|
||||
struct ncp_bindery_object {
|
||||
__u32 object_id;
|
||||
__u16 object_type;
|
||||
__u8 object_name[NCP_BINDERY_NAME_LEN];
|
||||
__u8 object_flags;
|
||||
__u8 object_security;
|
||||
__u8 object_has_prop;
|
||||
};
|
||||
|
||||
struct nw_property {
|
||||
@@ -58,6 +63,11 @@ struct nw_property {
|
||||
__u8 property_flag;
|
||||
};
|
||||
|
||||
struct prop_net_address {
|
||||
__u32 network __attribute__ ((packed));
|
||||
__u8 node[IPX_NODE_LEN] __attribute__ ((packed));
|
||||
__u16 port __attribute__ ((packed));
|
||||
};
|
||||
|
||||
#define NCP_VOLNAME_LEN (16)
|
||||
#define NCP_NUMBER_OF_VOLUMES (64)
|
||||
@@ -177,6 +187,39 @@ struct nw_info_struct
|
||||
__u8 entryName[256] __attribute__ ((packed));
|
||||
};
|
||||
|
||||
/* modify mask - use with MODIFY_DOS_INFO structure */
|
||||
#define DM_ATTRIBUTES (0x0002L)
|
||||
#define DM_CREATE_DATE (0x0004L)
|
||||
#define DM_CREATE_TIME (0x0008L)
|
||||
#define DM_CREATOR_ID (0x0010L)
|
||||
#define DM_ARCHIVE_DATE (0x0020L)
|
||||
#define DM_ARCHIVE_TIME (0x0040L)
|
||||
#define DM_ARCHIVER_ID (0x0080L)
|
||||
#define DM_MODIFY_DATE (0x0100L)
|
||||
#define DM_MODIFY_TIME (0x0200L)
|
||||
#define DM_MODIFIER_ID (0x0400L)
|
||||
#define DM_LAST_ACCESS_DATE (0x0800L)
|
||||
#define DM_INHERITED_RIGHTS_MASK (0x1000L)
|
||||
#define DM_MAXIMUM_SPACE (0x2000L)
|
||||
|
||||
struct nw_modify_dos_info
|
||||
{
|
||||
__u32 attributes __attribute__ ((packed));
|
||||
__u16 creationDate __attribute__ ((packed));
|
||||
__u16 creationTime __attribute__ ((packed));
|
||||
__u32 creatorID __attribute__ ((packed));
|
||||
__u16 modifyDate __attribute__ ((packed));
|
||||
__u16 modifyTime __attribute__ ((packed));
|
||||
__u32 modifierID __attribute__ ((packed));
|
||||
__u16 archiveDate __attribute__ ((packed));
|
||||
__u16 archiveTime __attribute__ ((packed));
|
||||
__u32 archiverID __attribute__ ((packed));
|
||||
__u16 lastAccessDate __attribute__ ((packed));
|
||||
__u16 inheritanceGrantMask __attribute__ ((packed));
|
||||
__u16 inheritanceRevokeMask __attribute__ ((packed));
|
||||
__u32 maximumSpace __attribute__ ((packed));
|
||||
};
|
||||
|
||||
struct nw_file_info {
|
||||
struct nw_info_struct i;
|
||||
int opened;
|
||||
@@ -229,16 +272,23 @@ struct queue_job {
|
||||
|
||||
/* ClientRecordArea for print jobs */
|
||||
|
||||
#define KEEP_ON 0x0400
|
||||
#define NO_FORM_FEED 0x0800
|
||||
#define NOTIFICATION 0x1000
|
||||
#define DELETE_FILE 0x2000
|
||||
#define EXPAND_TABS 0x4000
|
||||
#define PRINT_BANNER 0x8000
|
||||
|
||||
struct print_job_record {
|
||||
__u8 Version __attribute__ ((packed));
|
||||
__u16 TabSize __attribute__ ((packed));
|
||||
__u8 TabSize __attribute__ ((packed));
|
||||
__u16 Copies __attribute__ ((packed));
|
||||
__u8 CtrlFlags __attribute__ ((packed));
|
||||
__u16 CtrlFlags __attribute__ ((packed));
|
||||
__u16 Lines __attribute__ ((packed));
|
||||
__u16 Rows __attribute__ ((packed));
|
||||
char FormName[16] __attribute__ ((packed));
|
||||
__u8 Reserved[6] __attribute__ ((packed));
|
||||
char Banner[13] __attribute__ ((packed));
|
||||
char BannerName[13] __attribute__ ((packed));
|
||||
char FnameBanner[13] __attribute__ ((packed));
|
||||
char FnameHeader[14] __attribute__ ((packed));
|
||||
char Path[80] __attribute__ ((packed));
|
||||
@@ -26,7 +26,25 @@ struct ncp_ioctl_request {
|
||||
char *data;
|
||||
};
|
||||
|
||||
struct ncp_fs_info {
|
||||
int version;
|
||||
struct sockaddr_ipx addr;
|
||||
uid_t mounted_uid;
|
||||
int connection; /* Connection number the server assigned us */
|
||||
int buffer_size; /* The negotiated buffer size, to be
|
||||
used for read/write requests! */
|
||||
|
||||
/* Not used yet, but here some day the namespace numbers will be
|
||||
stored. */
|
||||
int volume_number;
|
||||
__u32 directory_id;
|
||||
};
|
||||
|
||||
#define NCP_IOC_NCPREQUEST _IOR('n', 1, unsigned char *)
|
||||
#define NCP_IOC_GETMOUNTUID _IOR('u', 1, uid_t)
|
||||
|
||||
#define NCP_GET_FS_INFO_VERSION (1)
|
||||
#define NCP_IOC_GET_FS_INFO _IOWR('i', 1, unsigned char *)
|
||||
|
||||
/*
|
||||
* The packet size to allocate. One page should be enough.
|
||||
@@ -57,10 +75,6 @@ struct ncp_ioctl_request {
|
||||
#define NCP_FINFO(inode) (&(NCP_INOP(inode)->finfo))
|
||||
#define NCP_ISTRUCT(inode) (&(NCP_FINFO(inode)->i))
|
||||
|
||||
static inline int min(int a, int b) {
|
||||
return a<b ? a : b;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_NCP_MALLOC
|
||||
|
||||
#include <linux/malloc.h>
|
||||
@@ -13,10 +13,10 @@
|
||||
#ifdef __KERNEL__
|
||||
|
||||
enum ncp_inode_state {
|
||||
INODE_VALID = 19, /* Inode currently in use */
|
||||
INODE_LOOKED_UP, /* directly before iget */
|
||||
INODE_CACHED, /* in a path to an inode which is in use */
|
||||
INODE_INVALID
|
||||
NCP_INODE_VALID = 19, /* Inode currently in use */
|
||||
NCP_INODE_LOOKED_UP, /* directly before iget */
|
||||
NCP_INODE_CACHED, /* in a path to an inode which is in use */
|
||||
NCP_INODE_INVALID
|
||||
};
|
||||
|
||||
/*
|
||||
65
kernel-1.2/src/Makefile
Normal file
65
kernel-1.2/src/Makefile
Normal file
@@ -0,0 +1,65 @@
|
||||
#
|
||||
# Makefile for the linux ncp-filesystem routines.
|
||||
#
|
||||
|
||||
CFLAGS = -Wall -Wstrict-prototypes -O2 -DMODULE -fomit-frame-pointer \
|
||||
$(INCLUDES) \
|
||||
# -DDEBUG_NCP=1 -DDEBUG_NCP_MALLOC
|
||||
# -DDEBUG_NCP_MALLOC
|
||||
|
||||
CC = gcc -D__KERNEL__ -I.
|
||||
AS = as
|
||||
ARCH = i386
|
||||
|
||||
.c.s:
|
||||
$(CC) $(CFLAGS) -S $<
|
||||
.c.o:
|
||||
$(CC) $(CFLAGS) -c $<
|
||||
.s.o:
|
||||
$(AS) -o $*.o $<
|
||||
|
||||
OBJS= dir.o inode.o file.o sock.o ioctl.o ncplib_kernel.o mmap.o
|
||||
|
||||
all: $(INTERM_BINDIR)/ncpfs.o
|
||||
|
||||
$(INTERM_BINDIR)/ncpfs.o: $(OBJS)
|
||||
$(LD) -r -o $@ $(OBJS)
|
||||
|
||||
ncplib_kernel.o: ncplib_kernel.c ncplib_kernel.h
|
||||
$(CC) $(CFLAGS) -finline-functions -c $<
|
||||
|
||||
dep:
|
||||
$(CPP) -M $(INCLUDES) *.c > .depend
|
||||
|
||||
clean:
|
||||
rm -f *.o *~
|
||||
|
||||
realclean: clean
|
||||
rm -f ncpmount ncptest .depend $(DISTFILE) *.out
|
||||
|
||||
modules: ncpfs.o
|
||||
|
||||
SRCPATH=$(shell pwd)
|
||||
SRCDIR=$(shell basename $(SRCPATH))
|
||||
DISTFILE=$(SRCDIR).tgz
|
||||
BACKUPFILE=ncpfs01.tgz
|
||||
HOME=/home/me
|
||||
|
||||
backup:
|
||||
(rm -f $(DISTFILE); cd ..; tar cvf - $(SRCDIR) | gzip -1 \
|
||||
> $(HOME)/tarz/backup/$(BACKUPFILE))
|
||||
(cd $(HOME)/tarz/backup; ls -l $(BACKUPFILE); mcopy $(BACKUPFILE) a:)
|
||||
|
||||
dist: realclean
|
||||
rm -fr mnt
|
||||
(cd ..; \
|
||||
tar cvf - $(SRCDIR) | \
|
||||
gzip -9 > $(DISTFILE); \
|
||||
mv $(DISTFILE) $(SRCDIR))
|
||||
|
||||
#
|
||||
# include a dependency file if one exists
|
||||
#
|
||||
ifeq (.depend,$(wildcard .depend))
|
||||
include .depend
|
||||
endif
|
||||
@@ -5,7 +5,11 @@
|
||||
*
|
||||
*/
|
||||
|
||||
/* #include <linux/module.h>*/
|
||||
#include <linux/config.h>
|
||||
#ifdef MODULE
|
||||
#include <linux/module.h>
|
||||
#include <linux/version.h>
|
||||
#endif
|
||||
|
||||
#include <linux/sched.h>
|
||||
#include <linux/errno.h>
|
||||
@@ -16,7 +20,7 @@
|
||||
#include <linux/ncp_fs.h>
|
||||
#include <asm/segment.h>
|
||||
#include <linux/errno.h>
|
||||
#include "ncplib.h"
|
||||
#include "ncplib_kernel.h"
|
||||
|
||||
struct ncp_dirent {
|
||||
struct nw_info_struct i;
|
||||
@@ -29,7 +33,8 @@ ncp_dir_read(struct inode *inode, struct file *filp, char *buf, int count);
|
||||
|
||||
static int
|
||||
ncp_readdir(struct inode *inode, struct file *filp,
|
||||
void *dirent, filldir_t filldir);
|
||||
struct dirent *dirent, int count);
|
||||
|
||||
static int
|
||||
ncp_read_volume_list(struct ncp_server *server, int start_with,
|
||||
int cache_size);
|
||||
@@ -68,9 +73,12 @@ ncp_rename(struct inode *old_dir, const char *old_name, int old_len,
|
||||
static inline void
|
||||
str_upper(char *name)
|
||||
{
|
||||
while (*name) {
|
||||
while (*name)
|
||||
{
|
||||
if (*name >= 'a' && *name <= 'z')
|
||||
{
|
||||
*name -= ('a' - 'A');
|
||||
}
|
||||
name++;
|
||||
}
|
||||
}
|
||||
@@ -78,9 +86,12 @@ str_upper(char *name)
|
||||
static inline void
|
||||
str_lower(char *name)
|
||||
{
|
||||
while (*name) {
|
||||
while (*name)
|
||||
{
|
||||
if (*name >= 'A' && *name <= 'Z')
|
||||
{
|
||||
*name += ('a' - 'A');
|
||||
}
|
||||
name ++;
|
||||
}
|
||||
}
|
||||
@@ -92,7 +103,7 @@ static struct file_operations ncp_dir_operations = {
|
||||
ncp_readdir, /* readdir */
|
||||
NULL, /* select - default */
|
||||
ncp_ioctl, /* ioctl - default */
|
||||
NULL, /* mmap */
|
||||
NULL, /* mmap */
|
||||
NULL, /* no special open code */
|
||||
NULL, /* no special release code */
|
||||
NULL /* fsync */
|
||||
@@ -124,6 +135,9 @@ ncp_dir_read(struct inode *inode, struct file *filp, char *buf, int count)
|
||||
return -EISDIR;
|
||||
}
|
||||
|
||||
#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
|
||||
#define ROUND_UP(x) (((x)+3) & ~3)
|
||||
|
||||
/* In ncpfs, we have unique inodes across all mounted filesystems, for
|
||||
all inodes that are in memory. That's why it's enough to index the
|
||||
directory cache by the inode number. */
|
||||
@@ -136,7 +150,7 @@ static struct ncp_dirent* c_entry = NULL;
|
||||
|
||||
static int
|
||||
ncp_readdir(struct inode *inode, struct file *filp,
|
||||
void *dirent, filldir_t filldir)
|
||||
struct dirent *dirent, int count)
|
||||
{
|
||||
int result, i = 0;
|
||||
int index = 0;
|
||||
@@ -144,11 +158,24 @@ ncp_readdir(struct inode *inode, struct file *filp,
|
||||
struct ncp_server *server = NCP_SERVER(inode);
|
||||
struct ncp_inode_info *dir = (struct ncp_inode_info *)(inode->i_ino);
|
||||
|
||||
int filldir(struct dirent *dirent,
|
||||
const char *name, int len,
|
||||
int f_pos, ino_t ino)
|
||||
{
|
||||
memcpy_tofs(dirent->d_name, name, len);
|
||||
put_fs_byte(0, &(dirent->d_name[len]));
|
||||
put_fs_long(ino, &dirent->d_ino);
|
||||
put_fs_word(len, &dirent->d_reclen);
|
||||
put_fs_word(f_pos, &dirent->d_off);
|
||||
return 1;
|
||||
}
|
||||
|
||||
DDPRINTK("ncp_readdir: filp->f_pos = %d\n", (int)filp->f_pos);
|
||||
DDPRINTK("ncp_readdir: inode->i_ino = %ld, c_ino = %ld\n",
|
||||
inode->i_ino, c_ino);
|
||||
|
||||
if (!inode || !S_ISDIR(inode->i_mode)) {
|
||||
if (!inode || !S_ISDIR(inode->i_mode))
|
||||
{
|
||||
printk("ncp_readdir: inode is NULL or not a directory\n");
|
||||
return -EBADF;
|
||||
}
|
||||
@@ -157,32 +184,40 @@ ncp_readdir(struct inode *inode, struct file *filp,
|
||||
{
|
||||
i = sizeof (struct ncp_dirent) * NCP_READDIR_CACHE_SIZE;
|
||||
c_entry = (struct ncp_dirent *) ncp_kmalloc(i, GFP_KERNEL);
|
||||
if (c_entry == NULL) {
|
||||
if (c_entry == NULL)
|
||||
{
|
||||
printk("ncp_readdir: no MEMORY for cache\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
if (filp->f_pos == 0) {
|
||||
if (filp->f_pos == 0)
|
||||
{
|
||||
ncp_invalid_dir_cache(inode->i_ino);
|
||||
if (filldir(dirent,".",1, filp->f_pos, (int)dir) < 0) {
|
||||
if (filldir(dirent,".",1, filp->f_pos, (int)dir) < 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
filp->f_pos += 1;
|
||||
return ROUND_UP(NAME_OFFSET(dirent)+i+1);
|
||||
}
|
||||
|
||||
if (filp->f_pos == 1) {
|
||||
if (filldir(dirent,"..",2, filp->f_pos, (int)(dir->dir)) < 0) {
|
||||
if (filp->f_pos == 1)
|
||||
{
|
||||
if (filldir(dirent,"..",2, filp->f_pos, (int)(dir->dir)) < 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
filp->f_pos += 1;
|
||||
return ROUND_UP(NAME_OFFSET(dirent)+i+1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (inode->i_ino == c_ino) {
|
||||
for (i = 0; i < c_size; i++) {
|
||||
if (filp->f_pos == c_entry[i].f_pos) {
|
||||
if (inode->i_ino == c_ino)
|
||||
{
|
||||
for (i = 0; i < c_size; i++)
|
||||
{
|
||||
if (filp->f_pos == c_entry[i].f_pos)
|
||||
{
|
||||
entry = &c_entry[i];
|
||||
c_last_returned_index = i;
|
||||
index = i;
|
||||
@@ -190,33 +225,38 @@ ncp_readdir(struct inode *inode, struct file *filp,
|
||||
}
|
||||
}
|
||||
if ((entry == NULL) && c_seen_eof)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (entry == NULL) {
|
||||
DPRINTK("ncp_readdir: Not found in cache.\n");
|
||||
|
||||
if (inode->i_ino == (int)&(server->root)) {
|
||||
if (entry == NULL)
|
||||
{
|
||||
DDPRINTK("ncp_readdir: Not found in cache.\n");
|
||||
|
||||
if (inode->i_ino == (int)&(server->root))
|
||||
{
|
||||
result = ncp_read_volume_list(server, filp->f_pos,
|
||||
NCP_READDIR_CACHE_SIZE);
|
||||
DPRINTK("ncp_read_volume_list returned %d\n", result);
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
result = ncp_do_readdir(server, inode, filp->f_pos,
|
||||
NCP_READDIR_CACHE_SIZE,
|
||||
c_entry);
|
||||
DPRINTK("ncp_readdir returned %d\n", result);
|
||||
}
|
||||
|
||||
|
||||
if (result < 0) {
|
||||
|
||||
if (result < 0)
|
||||
{
|
||||
c_ino = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
if (result > 0) {
|
||||
if (result > 0)
|
||||
{
|
||||
c_seen_eof = (result < NCP_READDIR_CACHE_SIZE);
|
||||
c_ino = inode->i_ino;
|
||||
c_size = result;
|
||||
@@ -224,19 +264,21 @@ ncp_readdir(struct inode *inode, struct file *filp,
|
||||
c_last_returned_index = 0;
|
||||
index = 0;
|
||||
|
||||
for (i = 0; i < c_size; i++) {
|
||||
for (i = 0; i < c_size; i++)
|
||||
{
|
||||
str_lower(c_entry[i].i.entryName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (entry == NULL) {
|
||||
if (entry == NULL)
|
||||
{
|
||||
/* Nothing found, even from a ncp call */
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (index < c_size) {
|
||||
|
||||
if (index < c_size)
|
||||
{
|
||||
/* We found it. For getwd(), we have to return the
|
||||
correct inode in d_ino if the inode is currently in
|
||||
use. Otherwise the inode number does not
|
||||
@@ -244,12 +286,12 @@ ncp_readdir(struct inode *inode, struct file *filp,
|
||||
|
||||
struct ncp_inode_info *ino_info;
|
||||
ino_info = ncp_find_inode(inode, entry->i.entryName);
|
||||
|
||||
|
||||
/* Some programs seem to be confused about a zero
|
||||
inode number, so we set it to one. Thanks to
|
||||
Gordon Chaffee for this one. */
|
||||
if (ino_info == NULL) {
|
||||
if (ino_info == NULL)
|
||||
{
|
||||
ino_info = (struct ncp_inode_info *) 1;
|
||||
}
|
||||
|
||||
@@ -257,19 +299,15 @@ ncp_readdir(struct inode *inode, struct file *filp,
|
||||
DDPRINTK("ncp_readdir: entry->f_pos = %ld\n", entry->f_pos);
|
||||
|
||||
if (filldir(dirent, entry->i.entryName, entry->i.nameLen,
|
||||
entry->f_pos, (ino_t)ino_info) < 0) {
|
||||
break;
|
||||
entry->f_pos, (ino_t)ino_info) < 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( (inode->i_ino != c_ino)
|
||||
|| (entry->f_pos != filp->f_pos)) {
|
||||
/* Someone has destroyed the cache while we slept
|
||||
in filldir */
|
||||
break;
|
||||
}
|
||||
filp->f_pos += 1;
|
||||
index += 1;
|
||||
entry += 1;
|
||||
return ROUND_UP(NAME_OFFSET(dirent)+i+1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -283,33 +321,42 @@ ncp_read_volume_list(struct ncp_server *server, int fpos, int cache_size)
|
||||
int i;
|
||||
|
||||
#if 1
|
||||
if (fpos < 2) {
|
||||
if (fpos < 2)
|
||||
{
|
||||
printk("OOPS, we expect fpos >= 2");
|
||||
fpos = 2;
|
||||
}
|
||||
fpos = 2;
|
||||
#endif
|
||||
|
||||
for (i=0; i<NCP_NUMBER_OF_VOLUMES; i++) {
|
||||
|
||||
for (i=0; i<NCP_NUMBER_OF_VOLUMES; i++)
|
||||
{
|
||||
struct ncp_volume_info info;
|
||||
|
||||
if (ncp_get_volume_info_with_number(server, i, &info) != 0) {
|
||||
if (ncp_get_volume_info_with_number(server, i, &info) != 0)
|
||||
{
|
||||
return total_count;
|
||||
}
|
||||
|
||||
if (strlen(info.volume_name) > 0) {
|
||||
if (total_count < fpos) {
|
||||
if (strlen(info.volume_name) > 0)
|
||||
{
|
||||
if (total_count < fpos)
|
||||
{
|
||||
DPRINTK("ncp_read_volumes: skipped vol: %s\n",
|
||||
info.volume_name);
|
||||
} else if (total_count >= fpos + cache_size) {
|
||||
}
|
||||
else if (total_count >= fpos + cache_size)
|
||||
{
|
||||
return (total_count - fpos);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINTK("ncp_read_volumes: found vol: %s\n",
|
||||
info.volume_name);
|
||||
|
||||
if (ncp_do_lookup(server, NULL,
|
||||
info.volume_name,
|
||||
&(entry->i)) != 0) {
|
||||
&(entry->i)) != 0)
|
||||
{
|
||||
printk("ncpfs: could not lookup vol "
|
||||
"%s\n", info.volume_name);
|
||||
continue;
|
||||
@@ -321,7 +368,6 @@ ncp_read_volume_list(struct ncp_server *server, int fpos, int cache_size)
|
||||
total_count += 1;
|
||||
}
|
||||
}
|
||||
|
||||
return (total_count - fpos);
|
||||
}
|
||||
|
||||
@@ -329,41 +375,63 @@ static int
|
||||
ncp_do_readdir(struct ncp_server *server, struct inode *dir, int fpos,
|
||||
int cache_size, struct ncp_dirent *entry)
|
||||
{
|
||||
struct nw_search_sequence seq;
|
||||
int total_count = 2;
|
||||
static struct nw_search_sequence seq;
|
||||
static struct inode *last_dir;
|
||||
static int total_count;
|
||||
|
||||
#if 1
|
||||
if (fpos < 2) {
|
||||
if (fpos < 2)
|
||||
{
|
||||
printk("OOPS, we expect fpos >= 2");
|
||||
fpos = 2;
|
||||
}
|
||||
fpos = 2;
|
||||
#endif
|
||||
DPRINTK("ncp_do_readdir: fpos = %d\n", fpos);
|
||||
|
||||
if (ncp_initialize_search(server, NCP_ISTRUCT(dir), &seq) != 0) {
|
||||
DPRINTK("ncp_init_search failed\n");
|
||||
return total_count - fpos;
|
||||
if (fpos == 2)
|
||||
{
|
||||
last_dir = NULL;
|
||||
total_count = 2;
|
||||
}
|
||||
|
||||
while (total_count < fpos + cache_size) {
|
||||
if ((fpos != total_count) || (dir != last_dir))
|
||||
{
|
||||
total_count = 2;
|
||||
last_dir = dir;
|
||||
|
||||
DPRINTK("ncp_do_readdir: re-used seq for %s\n",
|
||||
NCP_ISTRUCT(dir)->entryName);
|
||||
|
||||
if (ncp_initialize_search(server, NCP_ISTRUCT(dir), &seq)!=0)
|
||||
{
|
||||
DPRINTK("ncp_init_search failed\n");
|
||||
return total_count - fpos;
|
||||
}
|
||||
}
|
||||
|
||||
while (total_count < fpos + cache_size)
|
||||
{
|
||||
if (ncp_search_for_file_or_subdir(server, &seq,
|
||||
&(entry->i)) != 0) {
|
||||
&(entry->i)) != 0)
|
||||
{
|
||||
return total_count - fpos;
|
||||
}
|
||||
|
||||
if (total_count < fpos) {
|
||||
if (total_count < fpos)
|
||||
{
|
||||
DPRINTK("ncp_do_readdir: skipped file: %s\n",
|
||||
entry->i.entryName);
|
||||
} else {
|
||||
DPRINTK("ncp_do_readdir: found file: %s\n",
|
||||
entry->i.entryName);
|
||||
}
|
||||
else
|
||||
{
|
||||
DDPRINTK("ncp_do_r: file: %s, f_pos=%d,total_count=%d",
|
||||
entry->i.entryName, fpos, total_count);
|
||||
entry->s = seq;
|
||||
entry->f_pos = total_count;
|
||||
entry += 1;
|
||||
}
|
||||
total_count += 1;
|
||||
}
|
||||
|
||||
return (total_count - fpos);
|
||||
}
|
||||
|
||||
@@ -377,7 +445,8 @@ ncp_init_dir_cache(void)
|
||||
void
|
||||
ncp_invalid_dir_cache(unsigned long ino)
|
||||
{
|
||||
if (ino == c_ino) {
|
||||
if (ino == c_ino)
|
||||
{
|
||||
c_ino = 0;
|
||||
c_seen_eof = 0;
|
||||
}
|
||||
@@ -389,7 +458,9 @@ ncp_free_dir_cache(void)
|
||||
DPRINTK("ncp_free_dir_cache: enter\n");
|
||||
|
||||
if (c_entry == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ncp_kfree_s(c_entry,
|
||||
sizeof(struct ncp_dirent) * NCP_READDIR_CACHE_SIZE);
|
||||
@@ -406,12 +477,14 @@ ncp_iget(struct inode *dir, struct nw_file_info *finfo)
|
||||
struct ncp_inode_info *new_inode_info;
|
||||
struct ncp_inode_info *root;
|
||||
|
||||
if (!dir) {
|
||||
if (dir == NULL)
|
||||
{
|
||||
printk("ncp_iget: dir is NULL\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!finfo) {
|
||||
if (finfo == NULL)
|
||||
{
|
||||
printk("ncp_iget: finfo is NULL\n");
|
||||
return NULL;
|
||||
}
|
||||
@@ -419,13 +492,14 @@ ncp_iget(struct inode *dir, struct nw_file_info *finfo)
|
||||
new_inode_info = ncp_kmalloc(sizeof(struct ncp_inode_info),
|
||||
GFP_KERNEL);
|
||||
|
||||
if (new_inode_info == NULL) {
|
||||
if (new_inode_info == NULL)
|
||||
{
|
||||
printk("ncp_iget: could not alloc mem for %s\n",
|
||||
finfo->i.entryName);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
new_inode_info->state = INODE_LOOKED_UP;
|
||||
new_inode_info->state = NCP_INODE_LOOKED_UP;
|
||||
new_inode_info->nused = 0;
|
||||
new_inode_info->dir = NCP_INOP(dir);
|
||||
new_inode_info->finfo = *finfo;
|
||||
@@ -443,7 +517,8 @@ ncp_iget(struct inode *dir, struct nw_file_info *finfo)
|
||||
root->next->prev = new_inode_info;
|
||||
root->next = new_inode_info;
|
||||
|
||||
if (!(inode = iget(dir->i_sb, (int)new_inode_info))) {
|
||||
if (!(inode = iget(dir->i_sb, (int)new_inode_info)))
|
||||
{
|
||||
printk("ncp_iget: iget failed!");
|
||||
return NULL;
|
||||
}
|
||||
@@ -454,13 +529,15 @@ ncp_iget(struct inode *dir, struct nw_file_info *finfo)
|
||||
void
|
||||
ncp_free_inode_info(struct ncp_inode_info *i)
|
||||
{
|
||||
if (i == NULL) {
|
||||
if (i == NULL)
|
||||
{
|
||||
printk("ncp_free_inode: i == NULL\n");
|
||||
return;
|
||||
}
|
||||
|
||||
i->state = INODE_CACHED;
|
||||
while ((i->nused == 0) && (i->state == INODE_CACHED)) {
|
||||
i->state = NCP_INODE_CACHED;
|
||||
while ((i->nused == 0) && (i->state == NCP_INODE_CACHED))
|
||||
{
|
||||
struct ncp_inode_info *dir = i->dir;
|
||||
|
||||
i->next->prev = i->prev;
|
||||
@@ -485,19 +562,19 @@ ncp_init_root(struct ncp_server *server)
|
||||
struct nw_info_struct *i = &(root->finfo.i);
|
||||
unsigned short dummy;
|
||||
|
||||
DPRINTK("ncp_init_root: server %s\n", server->m.server_name);
|
||||
DPRINTK("ncp_init_root: i = %x\n", (int)i);
|
||||
|
||||
root->finfo.opened = 0;
|
||||
i->attributes = aDIR;
|
||||
i->dataStreamSize = 1024;
|
||||
i->volNumber = NCP_NUMBER_OF_VOLUMES+1; /* illegal volnum */
|
||||
ncp_date_unix2dos(0, &(i->creationTime), &(i->creationDate));
|
||||
ncp_date_unix2dos(0, &(i->modifyTime), &(i->modifyDate));
|
||||
ncp_date_unix2dos(0, &dummy, &(i->lastAccessDate));
|
||||
i->nameLen = 0;
|
||||
i->entryName[0] = '\0';
|
||||
|
||||
root->state = INODE_LOOKED_UP;
|
||||
root->state = NCP_INODE_LOOKED_UP;
|
||||
root->nused = 1;
|
||||
root->dir = root;
|
||||
root->next = root->prev = root;
|
||||
@@ -513,11 +590,13 @@ ncp_free_all_inodes(struct ncp_server *server)
|
||||
#if 1
|
||||
struct ncp_inode_info *root = &(server->root);
|
||||
|
||||
if (root->next != root) {
|
||||
if (root->next != root)
|
||||
{
|
||||
printk("ncp_free_all_inodes: INODES LEFT!!!\n");
|
||||
}
|
||||
|
||||
while (root->next != root) {
|
||||
while (root->next != root)
|
||||
{
|
||||
printk("ncp_free_all_inodes: freeing inode\n");
|
||||
ncp_free_inode_info(root->next);
|
||||
/* In case we have an endless loop.. */
|
||||
@@ -538,17 +617,23 @@ ncp_find_inode(struct inode *dir, const char *name)
|
||||
struct nw_info_struct *dir_info = NCP_ISTRUCT(dir);
|
||||
struct ncp_inode_info *result = &(server->root);
|
||||
|
||||
if (name == NULL) {
|
||||
if (name == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
do {
|
||||
if ( (result->finfo.i.DosDirNum == dir_info->DosDirNum)
|
||||
do
|
||||
{
|
||||
if ( (result->dir->finfo.i.DosDirNum == dir_info->DosDirNum)
|
||||
&& (result->dir->finfo.i.volNumber == dir_info->volNumber)
|
||||
&& (strcmp(result->finfo.i.entryName, name) == 0))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
result = result->next;
|
||||
|
||||
} while (result != &(server->root));
|
||||
}
|
||||
while (result != &(server->root));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -562,9 +647,12 @@ ncp_lookup(struct inode *dir, const char *__name, int len,
|
||||
struct ncp_inode_info *result_info;
|
||||
int found_in_cache;
|
||||
|
||||
char name[len+1];
|
||||
|
||||
*result = NULL;
|
||||
|
||||
if (!dir || !S_ISDIR(dir->i_mode)) {
|
||||
if (!dir || !S_ISDIR(dir->i_mode))
|
||||
{
|
||||
printk("ncp_lookup: inode is NULL or not a directory.\n");
|
||||
iput(dir);
|
||||
return -ENOENT;
|
||||
@@ -575,27 +663,45 @@ ncp_lookup(struct inode *dir, const char *__name, int len,
|
||||
server = NCP_SERVER(dir);
|
||||
|
||||
/* Fast cheat for . */
|
||||
if (len == 0 || (len == 1 && __name[0] == '.')) {
|
||||
if (len == 0 || (len == 1 && __name[0] == '.'))
|
||||
{
|
||||
*result = dir;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ..and for .. */
|
||||
if (len == 2 && __name[0] == '.' && __name[1] == '.') {
|
||||
*result = iget(dir->i_sb, (int)(NCP_INOP(dir)->dir));
|
||||
if (len == 2 && __name[0] == '.' && __name[1] == '.')
|
||||
{
|
||||
struct ncp_inode_info *parent = NCP_INOP(dir)->dir;
|
||||
|
||||
if (parent->state == NCP_INODE_CACHED)
|
||||
{
|
||||
parent->state = NCP_INODE_LOOKED_UP;
|
||||
}
|
||||
|
||||
*result = iget(dir->i_sb, (int)parent);
|
||||
iput(dir);
|
||||
if (*result == 0)
|
||||
{
|
||||
return -EACCES;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
result_info = ncp_find_inode(dir, __name);
|
||||
memcpy(name, __name, len);
|
||||
name[len] = 0;
|
||||
|
||||
if (result_info != 0) {
|
||||
result_info = ncp_find_inode(dir, name);
|
||||
|
||||
if (result_info->state == INODE_CACHED)
|
||||
result_info->state = INODE_LOOKED_UP;
|
||||
if (result_info != 0)
|
||||
{
|
||||
if (result_info->state == NCP_INODE_CACHED)
|
||||
{
|
||||
result_info->state = NCP_INODE_LOOKED_UP;
|
||||
}
|
||||
|
||||
/* Here we convert the inode_info address into an
|
||||
inode number */
|
||||
@@ -603,7 +709,8 @@ ncp_lookup(struct inode *dir, const char *__name, int len,
|
||||
*result = iget(dir->i_sb, (int)result_info);
|
||||
iput(dir);
|
||||
|
||||
if (*result == NULL) {
|
||||
if (*result == NULL)
|
||||
{
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
@@ -615,40 +722,41 @@ ncp_lookup(struct inode *dir, const char *__name, int len,
|
||||
|
||||
found_in_cache = 0;
|
||||
|
||||
if (dir->i_ino == c_ino) {
|
||||
if (dir->i_ino == c_ino)
|
||||
{
|
||||
int first = c_last_returned_index;
|
||||
int i;
|
||||
|
||||
i = first;
|
||||
do {
|
||||
do
|
||||
{
|
||||
DDPRINTK("ncp_lookup: trying index: %d, name: %s\n",
|
||||
i, c_entry[i].i.entryName);
|
||||
if (strcmp(c_entry[i].i.entryName, __name) == 0) {
|
||||
|
||||
if (strcmp(c_entry[i].i.entryName, name) == 0)
|
||||
{
|
||||
DPRINTK("ncp_lookup: found in cache!\n");
|
||||
finfo.i = c_entry[i].i;
|
||||
found_in_cache = 1;
|
||||
break;
|
||||
}
|
||||
i = (i + 1) % c_size;
|
||||
} while (i != first);
|
||||
}
|
||||
while (i != first);
|
||||
}
|
||||
|
||||
if (found_in_cache == 0) {
|
||||
|
||||
char this_name[len+1];
|
||||
|
||||
memcpy(this_name, __name, len);
|
||||
this_name[len] = 0;
|
||||
str_upper(this_name);
|
||||
if (found_in_cache == 0)
|
||||
{
|
||||
str_upper(name);
|
||||
|
||||
DDPRINTK("ncp_lookup: do_lookup on %s/%s\n",
|
||||
NCP_ISTRUCT(dir)->entryName, this_name);
|
||||
NCP_ISTRUCT(dir)->entryName, name);
|
||||
|
||||
if (ncp_do_lookup(server,
|
||||
dir->i_ino == (int)&(NCP_SERVER(dir)->root)
|
||||
? NULL : NCP_ISTRUCT(dir),
|
||||
this_name,
|
||||
&(finfo.i)) != 0) {
|
||||
name, &(finfo.i)) != 0)
|
||||
{
|
||||
iput(dir);
|
||||
return -ENOENT;
|
||||
}
|
||||
@@ -657,7 +765,8 @@ ncp_lookup(struct inode *dir, const char *__name, int len,
|
||||
finfo.opened = 0;
|
||||
str_lower(finfo.i.entryName);
|
||||
|
||||
if (!(*result = ncp_iget(dir, &finfo))) {
|
||||
if (!(*result = ncp_iget(dir, &finfo)))
|
||||
{
|
||||
iput(dir);
|
||||
return -EACCES;
|
||||
}
|
||||
@@ -675,7 +784,8 @@ ncp_create(struct inode *dir, const char *name, int len, int mode,
|
||||
|
||||
*result = NULL;
|
||||
|
||||
if (!dir || !S_ISDIR(dir->i_mode)) {
|
||||
if (!dir || !S_ISDIR(dir->i_mode))
|
||||
{
|
||||
printk("ncp_create: inode is NULL or not a directory\n");
|
||||
iput(dir);
|
||||
return -ENOENT;
|
||||
@@ -689,7 +799,8 @@ ncp_create(struct inode *dir, const char *name, int len, int mode,
|
||||
NCP_ISTRUCT(dir), _name,
|
||||
OC_MODE_CREATE|OC_MODE_OPEN,
|
||||
0, AR_READ|AR_WRITE,
|
||||
&finfo) != 0) {
|
||||
&finfo) != 0)
|
||||
{
|
||||
iput(dir);
|
||||
return -EACCES;
|
||||
}
|
||||
@@ -699,7 +810,8 @@ ncp_create(struct inode *dir, const char *name, int len, int mode,
|
||||
str_lower(finfo.i.entryName);
|
||||
finfo.access = O_RDWR;
|
||||
|
||||
if (!(*result = ncp_iget(dir, &finfo)) < 0) {
|
||||
if (!(*result = ncp_iget(dir, &finfo)) < 0)
|
||||
{
|
||||
ncp_close_file(NCP_SERVER(dir), finfo.file_handle);
|
||||
iput(dir);
|
||||
return -EINVAL;
|
||||
@@ -716,11 +828,20 @@ ncp_mkdir(struct inode *dir, const char *name, int len, int mode)
|
||||
struct nw_file_info new_dir;
|
||||
__u8 _name[len+1];
|
||||
|
||||
if ( (name[0] == '.')
|
||||
&& ( (len == 1)
|
||||
|| ( (len == 2)
|
||||
&& (name[1] == '.'))))
|
||||
{
|
||||
return -EEXIST;
|
||||
}
|
||||
|
||||
strncpy(_name, name, len);
|
||||
_name[len] = '\0';
|
||||
str_upper(_name);
|
||||
|
||||
if (!dir || !S_ISDIR(dir->i_mode)) {
|
||||
if (!dir || !S_ISDIR(dir->i_mode))
|
||||
{
|
||||
printk("ncp_mkdir: inode is NULL or not a directory\n");
|
||||
iput(dir);
|
||||
return -ENOENT;
|
||||
@@ -729,9 +850,12 @@ ncp_mkdir(struct inode *dir, const char *name, int len, int mode)
|
||||
if (ncp_open_create_file_or_subdir(NCP_SERVER(dir),
|
||||
NCP_ISTRUCT(dir), _name,
|
||||
OC_MODE_CREATE, aDIR, 0xffff,
|
||||
&new_dir) != 0) {
|
||||
&new_dir) != 0)
|
||||
{
|
||||
error = -EACCES;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
error = 0;
|
||||
ncp_invalid_dir_cache(dir->i_ino);
|
||||
}
|
||||
@@ -746,12 +870,14 @@ ncp_rmdir(struct inode *dir, const char *name, int len)
|
||||
int error;
|
||||
__u8 _name[len+1];
|
||||
|
||||
if (!dir || !S_ISDIR(dir->i_mode)) {
|
||||
if (!dir || !S_ISDIR(dir->i_mode))
|
||||
{
|
||||
printk("ncp_rmdir: inode is NULL or not a directory\n");
|
||||
iput(dir);
|
||||
return -ENOENT;
|
||||
}
|
||||
if (ncp_find_inode(dir, name) != NULL) {
|
||||
if (ncp_find_inode(dir, name) != NULL)
|
||||
{
|
||||
error = -EBUSY;
|
||||
}
|
||||
else
|
||||
@@ -763,7 +889,8 @@ ncp_rmdir(struct inode *dir, const char *name, int len)
|
||||
|
||||
if ((error = ncp_del_file_or_subdir(NCP_SERVER(dir),
|
||||
NCP_ISTRUCT(dir),
|
||||
_name)) == 0) {
|
||||
_name)) == 0)
|
||||
{
|
||||
ncp_invalid_dir_cache(dir->i_ino);
|
||||
}
|
||||
else
|
||||
@@ -781,24 +908,26 @@ ncp_unlink(struct inode *dir, const char *name, int len)
|
||||
int error;
|
||||
__u8 _name[len+1];
|
||||
|
||||
if (!dir || !S_ISDIR(dir->i_mode)) {
|
||||
if (!dir || !S_ISDIR(dir->i_mode))
|
||||
{
|
||||
printk("ncp_unlink: inode is NULL or not a directory\n");
|
||||
iput(dir);
|
||||
return -ENOENT;
|
||||
}
|
||||
if (ncp_find_inode(dir, name) != NULL) {
|
||||
if (ncp_find_inode(dir, name) != NULL)
|
||||
{
|
||||
error = -EBUSY;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
strncpy(_name, name, len);
|
||||
_name[len] = '\0';
|
||||
str_upper(_name);
|
||||
|
||||
if ((error = ncp_del_file_or_subdir(NCP_SERVER(dir),
|
||||
NCP_ISTRUCT(dir),
|
||||
_name)) == 0) {
|
||||
_name)) == 0)
|
||||
{
|
||||
ncp_invalid_dir_cache(dir->i_ino);
|
||||
}
|
||||
else
|
||||
@@ -818,20 +947,23 @@ ncp_rename(struct inode *old_dir, const char *old_name, int old_len,
|
||||
char _old_name[old_len+1];
|
||||
char _new_name[new_len+1];
|
||||
|
||||
if (!old_dir || !S_ISDIR(old_dir->i_mode)) {
|
||||
if (!old_dir || !S_ISDIR(old_dir->i_mode))
|
||||
{
|
||||
printk("ncp_rename: old inode is NULL or not a directory\n");
|
||||
res = -ENOENT;
|
||||
goto finished;
|
||||
}
|
||||
|
||||
if (!new_dir || !S_ISDIR(new_dir->i_mode)) {
|
||||
if (!new_dir || !S_ISDIR(new_dir->i_mode))
|
||||
{
|
||||
printk("ncp_rename: new inode is NULL or not a directory\n");
|
||||
res = -ENOENT;
|
||||
goto finished;
|
||||
}
|
||||
|
||||
if ( (ncp_find_inode(old_dir, old_name) != NULL)
|
||||
|| (ncp_find_inode(new_dir, new_name) != NULL)) {
|
||||
|| (ncp_find_inode(new_dir, new_name) != NULL))
|
||||
{
|
||||
res = -EBUSY;
|
||||
goto finished;
|
||||
}
|
||||
@@ -841,14 +973,15 @@ ncp_rename(struct inode *old_dir, const char *old_name, int old_len,
|
||||
str_upper(_old_name);
|
||||
|
||||
strncpy(_new_name, new_name, new_len);
|
||||
_new_name[old_len] = '\0';
|
||||
_new_name[new_len] = '\0';
|
||||
str_upper(_new_name);
|
||||
|
||||
res = ncp_ren_or_mov_file_or_subdir(NCP_SERVER(old_dir),
|
||||
NCP_ISTRUCT(old_dir), _old_name,
|
||||
NCP_ISTRUCT(new_dir), _new_name);
|
||||
|
||||
if (res == 0) {
|
||||
if (res == 0)
|
||||
{
|
||||
ncp_invalid_dir_cache(old_dir->i_ino);
|
||||
ncp_invalid_dir_cache(new_dir->i_ino);
|
||||
}
|
||||
@@ -5,7 +5,11 @@
|
||||
*
|
||||
*/
|
||||
|
||||
/* #include <linux/module.h>*/
|
||||
#include <linux/config.h>
|
||||
#ifdef MODULE
|
||||
#include <linux/module.h>
|
||||
#include <linux/version.h>
|
||||
#endif
|
||||
|
||||
#include <asm/segment.h>
|
||||
#include <asm/system.h>
|
||||
@@ -17,9 +21,14 @@
|
||||
#include <linux/stat.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/ncp_fs.h>
|
||||
#include "ncplib.h"
|
||||
#include "ncplib_kernel.h"
|
||||
#include <linux/malloc.h>
|
||||
|
||||
static inline int min(int a, int b)
|
||||
{
|
||||
return a<b ? a : b;
|
||||
}
|
||||
|
||||
static int
|
||||
ncp_fsync(struct inode *inode, struct file *file)
|
||||
{
|
||||
@@ -31,7 +40,8 @@ ncp_make_open(struct inode *i, int right)
|
||||
{
|
||||
struct nw_file_info *finfo;
|
||||
|
||||
if (i == NULL) {
|
||||
if (i == NULL)
|
||||
{
|
||||
printk("ncp_make_open: got NULL inode\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -40,23 +50,27 @@ ncp_make_open(struct inode *i, int right)
|
||||
|
||||
DPRINTK("ncp_make_open: dirent->opened = %d\n", finfo->opened);
|
||||
|
||||
if (finfo->opened == 0) {
|
||||
|
||||
if (finfo->opened == 0)
|
||||
{
|
||||
/* tries max. rights */
|
||||
if (ncp_open_create_file_or_subdir(NCP_SERVER(i),
|
||||
NULL, NULL,
|
||||
OC_MODE_OPEN, 0,
|
||||
AR_READ | AR_WRITE,
|
||||
finfo) == 0) {
|
||||
finfo) == 0)
|
||||
{
|
||||
finfo->access = O_RDWR;
|
||||
}
|
||||
else if (ncp_open_create_file_or_subdir(NCP_SERVER(i),
|
||||
NULL, NULL,
|
||||
OC_MODE_OPEN, 0,
|
||||
AR_READ,
|
||||
finfo) == 0) {
|
||||
finfo) == 0)
|
||||
{
|
||||
finfo->access = O_RDONLY;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
return -EACCES;
|
||||
}
|
||||
}
|
||||
@@ -74,18 +88,20 @@ ncp_make_open(struct inode *i, int right)
|
||||
static int
|
||||
ncp_file_read(struct inode *inode, struct file *file, char *buf, int count)
|
||||
{
|
||||
int bufsize, to_read, already_read;
|
||||
int bufsize, already_read;
|
||||
off_t pos;
|
||||
int errno;
|
||||
|
||||
DPRINTK("ncp_file_read: enter %s\n", NCP_ISTRUCT(inode)->entryName);
|
||||
|
||||
if (!inode) {
|
||||
if (inode == NULL)
|
||||
{
|
||||
DPRINTK("ncp_file_read: inode = NULL\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!S_ISREG(inode->i_mode)) {
|
||||
if (!S_ISREG(inode->i_mode))
|
||||
{
|
||||
DPRINTK("ncp_file_read: read from non-file, mode %07o\n",
|
||||
inode->i_mode);
|
||||
return -EINVAL;
|
||||
@@ -94,33 +110,34 @@ ncp_file_read(struct inode *inode, struct file *file, char *buf, int count)
|
||||
pos = file->f_pos;
|
||||
|
||||
if (pos + count > inode->i_size)
|
||||
{
|
||||
count = inode->i_size - pos;
|
||||
}
|
||||
|
||||
if (count <= 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((errno = ncp_make_open(inode, O_RDONLY)) != 0)
|
||||
{
|
||||
return errno;
|
||||
}
|
||||
|
||||
bufsize = NCP_SERVER(inode)->buffer_size;
|
||||
|
||||
already_read = 0;
|
||||
|
||||
/* First read in as much as possible for each bufsize. */
|
||||
while (already_read < count) {
|
||||
|
||||
while (already_read < count)
|
||||
{
|
||||
int read_this_time;
|
||||
|
||||
if ((pos % bufsize) != 0) {
|
||||
to_read = bufsize - (pos % bufsize);
|
||||
} else {
|
||||
to_read = bufsize;
|
||||
}
|
||||
|
||||
to_read = min(to_read, count - already_read);
|
||||
int to_read = min(bufsize - (pos % bufsize),
|
||||
count - already_read);
|
||||
|
||||
if (ncp_read(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle,
|
||||
pos, to_read, buf, &read_this_time) != 0) {
|
||||
pos, to_read, buf, &read_this_time) != 0)
|
||||
{
|
||||
return -EIO; /* This is not exact, i know.. */
|
||||
}
|
||||
|
||||
@@ -128,14 +145,19 @@ ncp_file_read(struct inode *inode, struct file *file, char *buf, int count)
|
||||
buf += read_this_time;
|
||||
already_read += read_this_time;
|
||||
|
||||
if (read_this_time < to_read) {
|
||||
if (read_this_time < to_read)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
file->f_pos = pos;
|
||||
|
||||
if (!IS_RDONLY(inode)) inode->i_atime = CURRENT_TIME;
|
||||
if (!IS_RDONLY(inode))
|
||||
{
|
||||
inode->i_atime = CURRENT_TIME;
|
||||
}
|
||||
|
||||
inode->i_dirt = 1;
|
||||
|
||||
DPRINTK("ncp_file_read: exit %s\n", NCP_ISTRUCT(inode)->entryName);
|
||||
@@ -144,19 +166,21 @@ ncp_file_read(struct inode *inode, struct file *file, char *buf, int count)
|
||||
}
|
||||
|
||||
static int
|
||||
ncp_file_write(struct inode *inode, struct file *file, const char *buf,
|
||||
ncp_file_write(struct inode *inode, struct file *file, char *buf,
|
||||
int count)
|
||||
{
|
||||
int bufsize, to_write, already_written;
|
||||
int bufsize, already_written;
|
||||
off_t pos;
|
||||
int errno;
|
||||
|
||||
if (!inode) {
|
||||
if (inode == NULL)
|
||||
{
|
||||
DPRINTK("ncp_file_write: inode = NULL\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!S_ISREG(inode->i_mode)) {
|
||||
if (!S_ISREG(inode->i_mode))
|
||||
{
|
||||
DPRINTK("ncp_file_write: write to non-file, mode %07o\n",
|
||||
inode->i_mode);
|
||||
return -EINVAL;
|
||||
@@ -165,33 +189,35 @@ ncp_file_write(struct inode *inode, struct file *file, const char *buf,
|
||||
DPRINTK("ncp_file_write: enter %s\n", NCP_ISTRUCT(inode)->entryName);
|
||||
|
||||
if (count <= 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((errno = ncp_make_open(inode, O_RDWR)) != 0)
|
||||
{
|
||||
return errno;
|
||||
}
|
||||
|
||||
pos = file->f_pos;
|
||||
|
||||
if (file->f_flags & O_APPEND)
|
||||
{
|
||||
pos = inode->i_size;
|
||||
}
|
||||
|
||||
bufsize = NCP_SERVER(inode)->buffer_size;
|
||||
|
||||
already_written = 0;
|
||||
|
||||
while (already_written < count) {
|
||||
|
||||
while (already_written < count)
|
||||
{
|
||||
int written_this_time;
|
||||
int to_write = min(bufsize - (pos % bufsize),
|
||||
count - already_written);
|
||||
|
||||
if ((pos % bufsize) != 0) {
|
||||
to_write = bufsize - (pos % bufsize);
|
||||
} else {
|
||||
to_write = bufsize;
|
||||
}
|
||||
|
||||
to_write = min(to_write, count - already_written);
|
||||
if (ncp_write(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle,
|
||||
pos, to_write, buf, &written_this_time) != 0) {
|
||||
pos, to_write, buf, &written_this_time) != 0)
|
||||
{
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
@@ -199,7 +225,8 @@ ncp_file_write(struct inode *inode, struct file *file, const char *buf,
|
||||
buf += written_this_time;
|
||||
already_written += written_this_time;
|
||||
|
||||
if (written_this_time < to_write) {
|
||||
if (written_this_time < to_write)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -209,7 +236,8 @@ ncp_file_write(struct inode *inode, struct file *file, const char *buf,
|
||||
|
||||
file->f_pos = pos;
|
||||
|
||||
if (pos > inode->i_size) {
|
||||
if (pos > inode->i_size)
|
||||
{
|
||||
inode->i_size = pos;
|
||||
}
|
||||
|
||||
@@ -225,7 +253,7 @@ static struct file_operations ncp_file_operations = {
|
||||
NULL, /* readdir - bad */
|
||||
NULL, /* select - default */
|
||||
ncp_ioctl, /* ioctl */
|
||||
NULL, /* mmap */
|
||||
ncp_mmap, /* mmap */
|
||||
NULL, /* open */
|
||||
NULL, /* release */
|
||||
ncp_fsync, /* fsync */
|
||||
@@ -5,7 +5,14 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#ifdef MODULE
|
||||
#include <linux/module.h>
|
||||
#include <linux/version.h>
|
||||
#else
|
||||
#define MOD_INC_USE_COUNT
|
||||
#define MOD_DEC_USE_COUNT
|
||||
#endif
|
||||
|
||||
#include <asm/system.h>
|
||||
#include <asm/segment.h>
|
||||
@@ -20,14 +27,14 @@
|
||||
#include <linux/locks.h>
|
||||
#include <linux/fcntl.h>
|
||||
#include <linux/malloc.h>
|
||||
#include "ncplib.h"
|
||||
#include "ncplib_kernel.h"
|
||||
|
||||
extern int close_fp(struct file *filp);
|
||||
|
||||
static void ncp_put_inode(struct inode *);
|
||||
static void ncp_read_inode(struct inode *);
|
||||
static void ncp_put_super(struct super_block *);
|
||||
static void ncp_statfs(struct super_block *sb, struct statfs *buf, int bufsiz);
|
||||
static void ncp_statfs(struct super_block *sb, struct statfs *stat);
|
||||
static int ncp_notify_change(struct inode *inode, struct iattr *attr);
|
||||
|
||||
static struct super_operations ncp_sops = {
|
||||
@@ -39,7 +46,7 @@ static struct super_operations ncp_sops = {
|
||||
NULL, /* write superblock */
|
||||
ncp_statfs, /* stat filesystem */
|
||||
NULL
|
||||
};
|
||||
};
|
||||
|
||||
/* ncp_read_inode: Called from iget, it only traverses the allocated
|
||||
ncp_inode_info's and initializes the inode from the data found
|
||||
@@ -61,20 +68,25 @@ ncp_read_inode(struct inode *inode)
|
||||
struct ncp_inode_info *root = &(NCP_SERVER(inode)->root);
|
||||
struct ncp_inode_info *check_info = root;
|
||||
|
||||
do {
|
||||
if (inode_info == check_info) {
|
||||
if (check_info->state == INODE_LOOKED_UP) {
|
||||
do
|
||||
{
|
||||
if (inode_info == check_info)
|
||||
{
|
||||
if (check_info->state == NCP_INODE_LOOKED_UP)
|
||||
{
|
||||
DDPRINTK("ncp_read_inode: found it!\n");
|
||||
goto good;
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
printk("ncp_read_inode: "
|
||||
"state != INODE_LOOKED_UP\n");
|
||||
"state != NCP_INODE_LOOKED_UP\n");
|
||||
goto good;
|
||||
}
|
||||
}
|
||||
check_info = check_info->next;
|
||||
} while (check_info != root);
|
||||
}
|
||||
while (check_info != root);
|
||||
|
||||
/* Ok, now we're in trouble. The inode info is not there. What
|
||||
should we do now??? */
|
||||
@@ -85,17 +97,18 @@ ncp_read_inode(struct inode *inode)
|
||||
DDPRINTK("ncp_read_inode: read entry %s\n",
|
||||
inode_info->finfo.i.entryName);
|
||||
#endif
|
||||
inode_info->state = INODE_VALID;
|
||||
inode_info->state = NCP_INODE_VALID;
|
||||
|
||||
NCP_INOP(inode) = inode_info;
|
||||
|
||||
if (NCP_ISTRUCT(inode)->attributes & aDIR) {
|
||||
if (NCP_ISTRUCT(inode)->attributes & aDIR)
|
||||
{
|
||||
inode->i_mode = NCP_SERVER(inode)->m.dir_mode;
|
||||
/* for directories in dataStreamSize seems to be some
|
||||
Object ID ??? */
|
||||
inode->i_size = 0;
|
||||
inode->i_size = 512;
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
inode->i_mode = NCP_SERVER(inode)->m.file_mode;
|
||||
inode->i_size = NCP_ISTRUCT(inode)->dataStreamSize;
|
||||
@@ -108,11 +121,16 @@ ncp_read_inode(struct inode *inode)
|
||||
inode->i_gid = NCP_SERVER(inode)->m.gid;
|
||||
inode->i_blksize = 1024;
|
||||
inode->i_rdev = 0;
|
||||
|
||||
if ((inode->i_blksize != 0) && (inode->i_size != 0))
|
||||
{
|
||||
inode->i_blocks =
|
||||
(inode->i_size - 1) / inode->i_blksize + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
inode->i_blocks = 0;
|
||||
}
|
||||
|
||||
inode->i_mtime = ncp_date_dos2unix(NCP_ISTRUCT(inode)->modifyTime,
|
||||
NCP_ISTRUCT(inode)->modifyDate);
|
||||
@@ -122,12 +140,17 @@ ncp_read_inode(struct inode *inode)
|
||||
NCP_ISTRUCT(inode)->lastAccessDate);
|
||||
|
||||
if (S_ISREG(inode->i_mode))
|
||||
{
|
||||
inode->i_op = &ncp_file_inode_operations;
|
||||
}
|
||||
else if (S_ISDIR(inode->i_mode))
|
||||
{
|
||||
inode->i_op = &ncp_dir_inode_operations;
|
||||
}
|
||||
else
|
||||
{
|
||||
inode->i_op = NULL;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -135,19 +158,24 @@ ncp_put_inode(struct inode *inode)
|
||||
{
|
||||
struct nw_file_info *finfo = NCP_FINFO(inode);
|
||||
|
||||
if (finfo->opened != 0) {
|
||||
|
||||
if (ncp_close_file(NCP_SERVER(inode), finfo->file_handle)!=0) {
|
||||
if (finfo->opened != 0)
|
||||
{
|
||||
if (ncp_close_file(NCP_SERVER(inode), finfo->file_handle)!=0)
|
||||
{
|
||||
/* We can't do anything but complain. */
|
||||
printk("ncp_put_inode: could not close\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DDPRINTK("ncp_put_inode: put %s\n",
|
||||
finfo->i.entryName);
|
||||
|
||||
ncp_free_inode_info(NCP_INOP(inode));
|
||||
|
||||
if (S_ISDIR(inode->i_mode)) {
|
||||
DPRINTK("ncp_put_inode: put directory %ld\n",
|
||||
inode->i_ino);
|
||||
if (S_ISDIR(inode->i_mode))
|
||||
{
|
||||
DDPRINTK("ncp_put_inode: put directory %ld\n",
|
||||
inode->i_ino);
|
||||
ncp_invalid_dir_cache(inode->i_ino);
|
||||
}
|
||||
|
||||
@@ -161,25 +189,27 @@ ncp_read_super(struct super_block *sb, void *raw_data, int silent)
|
||||
struct ncp_server *server;
|
||||
struct file *ncp_filp;
|
||||
struct file *wdog_filp;
|
||||
kdev_t dev = sb->s_dev;
|
||||
dev_t dev = sb->s_dev;
|
||||
int error;
|
||||
|
||||
if (!data) {
|
||||
if (data == NULL)
|
||||
{
|
||||
printk("ncp_read_super: missing data argument\n");
|
||||
sb->s_dev = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (data->version != NCP_MOUNT_VERSION) {
|
||||
if (data->version != NCP_MOUNT_VERSION)
|
||||
{
|
||||
printk("ncp warning: mount version %s than kernel\n",
|
||||
(data->version < NCP_MOUNT_VERSION) ?
|
||||
"older" : "newer");
|
||||
}
|
||||
|
||||
|
||||
if ( (data->ncp_fd >= NR_OPEN)
|
||||
|| ((ncp_filp = current->files->fd[data->ncp_fd]) == NULL)
|
||||
|| (!S_ISSOCK(ncp_filp->f_inode->i_mode))) {
|
||||
|| (!S_ISSOCK(ncp_filp->f_inode->i_mode)))
|
||||
{
|
||||
printk("ncp_read_super: invalid ncp socket\n");
|
||||
sb->s_dev = 0;
|
||||
return NULL;
|
||||
@@ -187,7 +217,8 @@ ncp_read_super(struct super_block *sb, void *raw_data, int silent)
|
||||
|
||||
if ( (data->wdog_fd >= NR_OPEN)
|
||||
|| ((wdog_filp = current->files->fd[data->wdog_fd]) == NULL)
|
||||
|| (!S_ISSOCK(wdog_filp->f_inode->i_mode))) {
|
||||
|| (!S_ISSOCK(wdog_filp->f_inode->i_mode)))
|
||||
{
|
||||
printk("ncp_read_super: invalid wdog socket\n");
|
||||
sb->s_dev = 0;
|
||||
return NULL;
|
||||
@@ -197,7 +228,8 @@ ncp_read_super(struct super_block *sb, void *raw_data, int silent)
|
||||
server = (struct ncp_server *)ncp_kmalloc(sizeof(struct ncp_server),
|
||||
GFP_KERNEL);
|
||||
|
||||
if (server == NULL) {
|
||||
if (server == NULL)
|
||||
{
|
||||
printk("ncp_read_super: could not alloc ncp_server\n");
|
||||
return NULL;
|
||||
}
|
||||
@@ -231,7 +263,8 @@ ncp_read_super(struct super_block *sb, void *raw_data, int silent)
|
||||
server->packet_size = NCP_PACKET_SIZE;
|
||||
server->packet = ncp_kmalloc(NCP_PACKET_SIZE, GFP_KERNEL);
|
||||
|
||||
if (server->packet == NULL) {
|
||||
if (server->packet == NULL)
|
||||
{
|
||||
printk("ncpfs: could not alloc packet\n");
|
||||
error = -ENOMEM;
|
||||
unlock_super(sb);
|
||||
@@ -244,7 +277,8 @@ ncp_read_super(struct super_block *sb, void *raw_data, int silent)
|
||||
* Make the connection to the server
|
||||
*/
|
||||
|
||||
if (ncp_catch_watchdog(server) != 0) {
|
||||
if (ncp_catch_watchdog(server) != 0)
|
||||
{
|
||||
printk("ncp_read_super: Could not catch watchdog\n");
|
||||
error = -EINVAL;
|
||||
unlock_super(sb);
|
||||
@@ -256,7 +290,8 @@ ncp_read_super(struct super_block *sb, void *raw_data, int silent)
|
||||
ncp_unlock_server(server);
|
||||
unlock_super(sb);
|
||||
|
||||
if (error < 0) {
|
||||
if (error < 0)
|
||||
{
|
||||
sb->s_dev = 0;
|
||||
printk("ncp_read_super: Failed connection, bailing out "
|
||||
"(error = %d).\n", -error);
|
||||
@@ -267,14 +302,16 @@ ncp_read_super(struct super_block *sb, void *raw_data, int silent)
|
||||
|
||||
DPRINTK("ncp_read_super: NCP_SBP(sb) = %x\n", (int)NCP_SBP(sb));
|
||||
|
||||
if (!(sb->s_mounted = iget(sb, (int)&(server->root)))) {
|
||||
if (!(sb->s_mounted = iget(sb, (int)&(server->root))))
|
||||
{
|
||||
sb->s_dev = 0;
|
||||
printk("ncp_read_super: get root inode failed\n");
|
||||
goto disconnect;
|
||||
}
|
||||
|
||||
if (ncp_negotiate_buffersize(server, NCP_DEFAULT_BUFSIZE,
|
||||
&(server->buffer_size)) != 0) {
|
||||
&(server->buffer_size)) != 0)
|
||||
{
|
||||
sb->s_dev = 0;
|
||||
printk("ncp_read_super: could not get bufsize\n");
|
||||
goto disconnect;
|
||||
@@ -282,14 +319,6 @@ ncp_read_super(struct super_block *sb, void *raw_data, int silent)
|
||||
|
||||
DPRINTK("ncpfs: bufsize = %d\n", server->buffer_size);
|
||||
|
||||
/* if (ncp_login_user(server, server->m.username,
|
||||
server->m.password) != 0) {
|
||||
sb->s_dev = 0;
|
||||
printk("ncp_read_super: login failed\n");
|
||||
goto disconnect;
|
||||
}
|
||||
*/
|
||||
|
||||
MOD_INC_USE_COUNT;
|
||||
return sb;
|
||||
|
||||
@@ -336,7 +365,7 @@ ncp_put_super(struct super_block *sb)
|
||||
}
|
||||
|
||||
static void
|
||||
ncp_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
|
||||
ncp_statfs(struct super_block *sb, struct statfs *stat)
|
||||
{
|
||||
struct statfs tmp;
|
||||
|
||||
@@ -354,14 +383,15 @@ ncp_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
|
||||
tmp.f_files = -1;
|
||||
tmp.f_ffree = -1;
|
||||
tmp.f_namelen = 12;
|
||||
memcpy_tofs(buf, &tmp, bufsiz);
|
||||
memcpy_tofs(stat, &tmp, sizeof(tmp));
|
||||
}
|
||||
|
||||
/* DO MORE */
|
||||
static int
|
||||
ncp_notify_change(struct inode *inode, struct iattr *attr)
|
||||
{
|
||||
int result = 0;
|
||||
int info_mask;
|
||||
struct nw_modify_dos_info info;
|
||||
|
||||
if ((result = inode_change_ok(inode, attr)) < 0)
|
||||
return result;
|
||||
@@ -379,14 +409,62 @@ ncp_notify_change(struct inode *inode, struct iattr *attr)
|
||||
~(S_IFREG | S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO))))
|
||||
return -EPERM;
|
||||
|
||||
if ((attr->ia_valid & ATTR_SIZE) != 0) {
|
||||
info_mask = 0;
|
||||
memset(&info, 0, sizeof(info));
|
||||
|
||||
if ((attr->ia_valid & ATTR_CTIME) != 0)
|
||||
{
|
||||
info_mask |= (DM_CREATE_TIME|DM_CREATE_DATE);
|
||||
ncp_date_unix2dos(attr->ia_ctime,
|
||||
&(info.creationTime), &(info.creationDate));
|
||||
}
|
||||
|
||||
if ((attr->ia_valid & ATTR_MTIME) != 0)
|
||||
{
|
||||
info_mask |= (DM_MODIFY_TIME|DM_MODIFY_DATE);
|
||||
ncp_date_unix2dos(attr->ia_mtime,
|
||||
&(info.modifyTime), &(info.modifyDate));
|
||||
}
|
||||
|
||||
if ((attr->ia_valid & ATTR_ATIME) != 0)
|
||||
{
|
||||
__u16 dummy;
|
||||
info_mask |= (DM_LAST_ACCESS_DATE);
|
||||
ncp_date_unix2dos(attr->ia_ctime,
|
||||
&(dummy), &(info.lastAccessDate));
|
||||
}
|
||||
|
||||
if (info_mask != 0)
|
||||
{
|
||||
if ((result =
|
||||
ncp_modify_file_or_subdir_dos_info(NCP_SERVER(inode),
|
||||
NCP_ISTRUCT(inode),
|
||||
info_mask,
|
||||
&info)) != 0)
|
||||
{
|
||||
result = -EACCES;
|
||||
|
||||
if (info_mask == (DM_CREATE_TIME|DM_CREATE_DATE))
|
||||
{
|
||||
/* NetWare seems not to allow this. I
|
||||
do not know why. So, just tell the
|
||||
user everything went fine. This is
|
||||
a terrible hack, but I do not know
|
||||
how to do this correctly. */
|
||||
result = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((attr->ia_valid & ATTR_SIZE) != 0)
|
||||
{
|
||||
int written;
|
||||
|
||||
DPRINTK("ncpfs: trying to change size of %s to %ld\n",
|
||||
NCP_ISTRUCT(inode)->entryName, attr->ia_size);
|
||||
|
||||
if ((result = ncp_make_open(inode, O_RDWR)) < 0) {
|
||||
if ((result = ncp_make_open(inode, O_RDWR)) < 0)
|
||||
{
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
@@ -414,6 +492,8 @@ int ncp_current_malloced;
|
||||
|
||||
#ifdef MODULE
|
||||
|
||||
char kernel_version[] = UTS_RELEASE;
|
||||
|
||||
static struct file_system_type ncp_fs_type = {
|
||||
ncp_read_super, "ncpfs", 0, NULL
|
||||
};
|
||||
134
kernel-1.2/src/ioctl.c
Normal file
134
kernel-1.2/src/ioctl.c
Normal file
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* ioctl.c
|
||||
*
|
||||
* Copyright (C) 1995 by Volker Lendecke
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#ifdef MODULE
|
||||
#include <linux/module.h>
|
||||
#include <linux/version.h>
|
||||
#endif
|
||||
|
||||
#include <asm/segment.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/ncp_fs.h>
|
||||
#include <linux/ioctl.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/ncp.h>
|
||||
|
||||
int
|
||||
ncp_ioctl (struct inode * inode, struct file * filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
int result;
|
||||
struct ncp_ioctl_request request;
|
||||
struct ncp_fs_info info;
|
||||
struct ncp_server *server = NCP_SERVER(inode);
|
||||
|
||||
switch(cmd) {
|
||||
case NCP_IOC_NCPREQUEST:
|
||||
|
||||
if ( (permission(inode, MAY_WRITE) != 0)
|
||||
&& (current->uid != server->m.mounted_uid))
|
||||
{
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
if ((result = verify_area(VERIFY_READ, (char *)arg,
|
||||
sizeof(request))) != 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
memcpy_fromfs(&request, (struct ncp_ioctl_request *)arg,
|
||||
sizeof(request));
|
||||
|
||||
if ( (request.function > 255)
|
||||
|| (request.size >
|
||||
NCP_PACKET_SIZE - sizeof(struct ncp_request_header)))
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((result = verify_area(VERIFY_WRITE, (char *)request.data,
|
||||
NCP_PACKET_SIZE)) != 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
ncp_lock_server(server);
|
||||
|
||||
/* FIXME: We hack around in the server's structures
|
||||
here to be able to use ncp_request */
|
||||
|
||||
server->has_subfunction = 0;
|
||||
server->current_size = request.size;
|
||||
memcpy_fromfs(server->packet, request.data, request.size);
|
||||
|
||||
ncp_request(server, request.function);
|
||||
|
||||
DPRINTK("ncp_ioctl: copy %d bytes\n",
|
||||
server->reply_size);
|
||||
memcpy_tofs(request.data, server->packet, server->reply_size);
|
||||
|
||||
ncp_unlock_server(server);
|
||||
|
||||
return server->reply_size;
|
||||
|
||||
case NCP_IOC_GET_FS_INFO:
|
||||
|
||||
if ( (permission(inode, MAY_WRITE) != 0)
|
||||
&& (current->uid != server->m.mounted_uid))
|
||||
{
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
if ((result = verify_area(VERIFY_WRITE, (char *)arg,
|
||||
sizeof(info))) != 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
memcpy_fromfs(&info, (struct ncp_fs_info *)arg,
|
||||
sizeof(info));
|
||||
|
||||
if (info.version != NCP_GET_FS_INFO_VERSION)
|
||||
{
|
||||
DPRINTK("info.version invalid: %d\n", info.version);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
info.addr = server->m.serv_addr;
|
||||
info.mounted_uid = server->m.mounted_uid;
|
||||
info.connection = server->connection;
|
||||
info.buffer_size = server->buffer_size;
|
||||
|
||||
memcpy_tofs((struct ncp_fs_info *)arg, &info, sizeof(info));
|
||||
return 0;
|
||||
|
||||
case NCP_IOC_GETMOUNTUID:
|
||||
|
||||
if ( (permission(inode, MAY_READ) != 0)
|
||||
&& (current->uid != server->m.mounted_uid))
|
||||
{
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
if ((result = verify_area(VERIFY_WRITE, (uid_t*) arg,
|
||||
sizeof(uid_t))) != 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
put_fs_word(server->m.mounted_uid, (uid_t*) arg);
|
||||
return 0;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
152
kernel-1.2/src/mmap.c
Normal file
152
kernel-1.2/src/mmap.c
Normal file
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* mmap.c
|
||||
*
|
||||
* Copyright (C) 1995 by Volker Lendecke
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#ifdef MODULE
|
||||
#include <linux/module.h>
|
||||
#include <linux/version.h>
|
||||
#endif
|
||||
|
||||
#include <linux/stat.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/shm.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/mman.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/malloc.h>
|
||||
#include <linux/fcntl.h>
|
||||
#include <linux/ncp_fs.h>
|
||||
|
||||
#include "ncplib_kernel.h"
|
||||
#include <asm/segment.h>
|
||||
#include <asm/system.h>
|
||||
|
||||
static inline int min(int a, int b)
|
||||
{
|
||||
return a<b ? a : b;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill in the supplied page for mmap
|
||||
*/
|
||||
static unsigned long
|
||||
ncp_file_mmap_nopage(struct vm_area_struct * area,
|
||||
unsigned long address, unsigned long page, int no_share)
|
||||
{
|
||||
struct inode * inode = area->vm_inode;
|
||||
unsigned int clear;
|
||||
unsigned long tmp;
|
||||
int bufsize;
|
||||
int pos;
|
||||
unsigned short fs;
|
||||
|
||||
address &= PAGE_MASK;
|
||||
pos = address - area->vm_start + area->vm_offset;
|
||||
|
||||
clear = 0;
|
||||
if (address + PAGE_SIZE > area->vm_end)
|
||||
{
|
||||
clear = address + PAGE_SIZE - area->vm_end;
|
||||
}
|
||||
|
||||
/* what we can read in one go */
|
||||
bufsize = NCP_SERVER(inode)->buffer_size;
|
||||
|
||||
fs = get_fs();
|
||||
set_fs(get_ds());
|
||||
|
||||
if (ncp_make_open(inode, O_RDONLY) < 0)
|
||||
{
|
||||
clear = PAGE_SIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
int already_read = 0;
|
||||
int count = PAGE_SIZE - clear;
|
||||
int to_read;
|
||||
|
||||
while (already_read < count)
|
||||
{
|
||||
int read_this_time;
|
||||
|
||||
if ((pos % bufsize) != 0)
|
||||
{
|
||||
to_read = bufsize - (pos % bufsize);
|
||||
}
|
||||
else
|
||||
{
|
||||
to_read = bufsize;
|
||||
}
|
||||
|
||||
to_read = min(to_read, count - already_read);
|
||||
|
||||
if (ncp_read(NCP_SERVER(inode),
|
||||
NCP_FINFO(inode)->file_handle,
|
||||
pos, to_read,
|
||||
(char *)(page + already_read),
|
||||
&read_this_time) != 0)
|
||||
{
|
||||
read_this_time = 0;
|
||||
}
|
||||
|
||||
pos += read_this_time;
|
||||
already_read += read_this_time;
|
||||
|
||||
if (read_this_time < to_read)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
set_fs(fs);
|
||||
|
||||
tmp = page + PAGE_SIZE;
|
||||
while (clear--) {
|
||||
*(char *)--tmp = 0;
|
||||
}
|
||||
return page;
|
||||
}
|
||||
|
||||
struct vm_operations_struct ncp_file_mmap = {
|
||||
NULL, /* open */
|
||||
NULL, /* close */
|
||||
NULL, /* unmap */
|
||||
NULL, /* protect */
|
||||
NULL, /* sync */
|
||||
NULL, /* advise */
|
||||
ncp_file_mmap_nopage, /* nopage */
|
||||
NULL, /* wppage */
|
||||
NULL, /* swapout */
|
||||
NULL, /* swapin */
|
||||
};
|
||||
|
||||
|
||||
/* This is used for a general mmap of a ncp file */
|
||||
int
|
||||
ncp_mmap(struct inode * inode, struct file * file, struct vm_area_struct * vma)
|
||||
{
|
||||
DPRINTK("ncp_mmap: called\n");
|
||||
|
||||
/* only PAGE_COW or read-only supported now */
|
||||
if (vma->vm_flags & VM_SHARED)
|
||||
return -EINVAL;
|
||||
if (!inode->i_sb || !S_ISREG(inode->i_mode))
|
||||
return -EACCES;
|
||||
if (!IS_RDONLY(inode)) {
|
||||
inode->i_atime = CURRENT_TIME;
|
||||
inode->i_dirt = 1;
|
||||
}
|
||||
|
||||
vma->vm_inode = inode;
|
||||
inode->i_count++;
|
||||
vma->vm_ops = &ncp_file_mmap;
|
||||
return 0;
|
||||
}
|
||||
@@ -1,14 +1,25 @@
|
||||
#include "ncplib.h"
|
||||
#include "nwcrypt.h"
|
||||
#include <linux/config.h>
|
||||
#ifdef MODULE
|
||||
#include <linux/module.h>
|
||||
#include <linux/version.h>
|
||||
#endif
|
||||
|
||||
#include "ncplib_kernel.h"
|
||||
|
||||
typedef __u8 byte;
|
||||
typedef __u16 word;
|
||||
typedef __u32 dword;
|
||||
|
||||
static inline int min(int a, int b)
|
||||
{
|
||||
return a<b ? a : b;
|
||||
}
|
||||
|
||||
static void
|
||||
assert_server_locked(struct ncp_server *server)
|
||||
{
|
||||
if (server->lock == 0) {
|
||||
if (server->lock == 0)
|
||||
{
|
||||
DPRINTK("ncpfs: server not locked!\n");
|
||||
}
|
||||
}
|
||||
@@ -41,7 +52,7 @@ ncp_add_dword(struct ncp_server *server, dword x)
|
||||
}
|
||||
|
||||
static void
|
||||
ncp_add_mem(struct ncp_server *server, const char *source, int size)
|
||||
ncp_add_mem(struct ncp_server *server, const void *source, int size)
|
||||
{
|
||||
assert_server_locked(server);
|
||||
memcpy(&(server->packet[server->current_size]), source, size);
|
||||
@@ -63,7 +74,8 @@ ncp_add_pstring(struct ncp_server *server, const char *s)
|
||||
{
|
||||
int len = strlen(s);
|
||||
assert_server_locked(server);
|
||||
if (len > 255) {
|
||||
if (len > 255)
|
||||
{
|
||||
DPRINTK("ncpfs: string too long: %s\n", s);
|
||||
len = 255;
|
||||
}
|
||||
@@ -118,14 +130,15 @@ ncp_reply_dword(struct ncp_server *server, int offset)
|
||||
|
||||
int
|
||||
ncp_negotiate_buffersize(struct ncp_server *server,
|
||||
int size, int *target) {
|
||||
|
||||
int size, int *target)
|
||||
{
|
||||
int result;
|
||||
|
||||
ncp_init_request(server);
|
||||
ncp_add_word(server, htons(size));
|
||||
|
||||
if ((result = ncp_request(server, 33)) != 0) {
|
||||
if ((result = ncp_request(server, 33)) != 0)
|
||||
{
|
||||
ncp_unlock_server(server);
|
||||
return result;
|
||||
}
|
||||
@@ -146,7 +159,8 @@ ncp_get_volume_info_with_number(struct ncp_server *server, int n,
|
||||
ncp_init_request_s(server, 44);
|
||||
ncp_add_byte(server, n);
|
||||
|
||||
if ((result = ncp_request(server, 22)) != 0) {
|
||||
if ((result = ncp_request(server, 22)) != 0)
|
||||
{
|
||||
ncp_unlock_server(server);
|
||||
return result;
|
||||
}
|
||||
@@ -162,7 +176,8 @@ ncp_get_volume_info_with_number(struct ncp_server *server, int n,
|
||||
memset(&(target->volume_name), 0, sizeof(target->volume_name));
|
||||
|
||||
len = ncp_reply_byte(server, 29);
|
||||
if (len > NCP_VOLNAME_LEN) {
|
||||
if (len > NCP_VOLNAME_LEN)
|
||||
{
|
||||
DPRINTK("ncpfs: volume name too long: %d\n", len);
|
||||
ncp_unlock_server(server);
|
||||
return -EIO;
|
||||
@@ -181,7 +196,8 @@ ncp_get_volume_number(struct ncp_server *server, const char *name, int *target)
|
||||
ncp_init_request_s(server, 5);
|
||||
ncp_add_pstring(server, name);
|
||||
|
||||
if ((result = ncp_request(server, 22)) != 0) {
|
||||
if ((result = ncp_request(server, 22)) != 0)
|
||||
{
|
||||
ncp_unlock_server(server);
|
||||
return result;
|
||||
}
|
||||
@@ -200,7 +216,8 @@ ncp_close_file(struct ncp_server *server, const char *file_id)
|
||||
ncp_add_byte(server, 0);
|
||||
ncp_add_mem(server, file_id, 6);
|
||||
|
||||
if ((result = ncp_request(server, 66)) != 0) {
|
||||
if ((result = ncp_request(server, 66)) != 0)
|
||||
{
|
||||
ncp_unlock_server(server);
|
||||
return result;
|
||||
}
|
||||
@@ -217,12 +234,16 @@ ncp_add_handle_path(struct ncp_server *server,
|
||||
{
|
||||
ncp_add_byte(server, vol_num);
|
||||
ncp_add_dword(server, dir_base);
|
||||
if (have_dir_base != 0) {
|
||||
if (have_dir_base != 0)
|
||||
{
|
||||
ncp_add_byte(server, 1); /* dir_base */
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
ncp_add_byte(server, 0xff); /* no handle */
|
||||
}
|
||||
if (path != NULL) {
|
||||
if (path != NULL)
|
||||
{
|
||||
ncp_add_byte(server, 1); /* 1 component */
|
||||
ncp_add_pstring(server, path);
|
||||
}
|
||||
@@ -258,11 +279,13 @@ ncp_do_lookup(struct ncp_server *server,
|
||||
int result;
|
||||
char *volname = NULL;
|
||||
|
||||
if (target == NULL) {
|
||||
if (target == NULL)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (dir == NULL) {
|
||||
if (dir == NULL)
|
||||
{
|
||||
|
||||
DDPRINTK("ncp_do_lookup: looking up vol %s\n", path);
|
||||
|
||||
@@ -276,7 +299,8 @@ ncp_do_lookup(struct ncp_server *server,
|
||||
ncp_add_handle_path(server, 0, 0, 0, /* no handle */
|
||||
path);
|
||||
|
||||
if ((result = ncp_request(server, 87)) != 0) {
|
||||
if ((result = ncp_request(server, 87)) != 0)
|
||||
{
|
||||
ncp_unlock_server(server);
|
||||
return result;
|
||||
}
|
||||
@@ -302,14 +326,16 @@ ncp_do_lookup(struct ncp_server *server,
|
||||
ncp_add_handle_path(server, vol_num, dir_base, 1,
|
||||
path);
|
||||
|
||||
if ((result = ncp_request(server, 87)) != 0) {
|
||||
if ((result = ncp_request(server, 87)) != 0)
|
||||
{
|
||||
ncp_unlock_server(server);
|
||||
return result;
|
||||
}
|
||||
|
||||
ncp_extract_file_info(ncp_reply_data(server, 0), target);
|
||||
|
||||
if (volname != NULL) {
|
||||
if (volname != NULL)
|
||||
{
|
||||
target->nameLen = strlen(volname);
|
||||
strcpy(target->entryName, volname);
|
||||
}
|
||||
@@ -318,6 +344,35 @@ ncp_do_lookup(struct ncp_server *server,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ncp_modify_file_or_subdir_dos_info(struct ncp_server *server,
|
||||
struct nw_info_struct *file,
|
||||
__u32 info_mask,
|
||||
struct nw_modify_dos_info *info)
|
||||
{
|
||||
int result;
|
||||
|
||||
ncp_init_request(server);
|
||||
ncp_add_byte(server, 7); /* subfunction */
|
||||
ncp_add_byte(server, 0); /* dos name space */
|
||||
ncp_add_byte(server, 0); /* reserved */
|
||||
ncp_add_word(server, 0x8006); /* search attribs: all */
|
||||
|
||||
ncp_add_dword(server, info_mask);
|
||||
ncp_add_mem(server, info, sizeof(*info));
|
||||
ncp_add_handle_path(server, file->volNumber,
|
||||
file->DosDirNum, 1, NULL);
|
||||
|
||||
if ((result = ncp_request(server, 87)) != 0)
|
||||
{
|
||||
ncp_unlock_server(server);
|
||||
return result;
|
||||
}
|
||||
|
||||
ncp_unlock_server(server);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ncp_del_file_or_subdir(struct ncp_server *server,
|
||||
struct nw_info_struct *dir, char *name)
|
||||
@@ -332,7 +387,8 @@ ncp_del_file_or_subdir(struct ncp_server *server,
|
||||
ncp_add_handle_path(server, dir->volNumber,
|
||||
dir->DosDirNum, 1, name);
|
||||
|
||||
if ((result = ncp_request(server, 87)) != 0) {
|
||||
if ((result = ncp_request(server, 87)) != 0)
|
||||
{
|
||||
ncp_unlock_server(server);
|
||||
return result;
|
||||
}
|
||||
@@ -373,16 +429,20 @@ ncp_open_create_file_or_subdir(struct ncp_server *server,
|
||||
for directories */
|
||||
ncp_add_word(server, desired_acc_rights);
|
||||
|
||||
if (dir != NULL) {
|
||||
if (dir != NULL)
|
||||
{
|
||||
ncp_add_handle_path(server, dir->volNumber,
|
||||
dir->DosDirNum, 1, name);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
ncp_add_handle_path(server,
|
||||
target->i.volNumber, target->i.DosDirNum,
|
||||
1, NULL);
|
||||
}
|
||||
|
||||
if ((result = ncp_request(server, 87)) != 0) {
|
||||
if ((result = ncp_request(server, 87)) != 0)
|
||||
{
|
||||
ncp_unlock_server(server);
|
||||
return result;
|
||||
}
|
||||
@@ -391,7 +451,8 @@ ncp_open_create_file_or_subdir(struct ncp_server *server,
|
||||
target->server_file_handle = ncp_reply_dword(server, 0);
|
||||
target->open_create_action = ncp_reply_byte(server, 4);
|
||||
|
||||
if (dir != NULL) {
|
||||
if (dir != NULL)
|
||||
{
|
||||
/* in target there's a new finfo to fill */
|
||||
ncp_extract_file_info(ncp_reply_data(server, 5), &(target->i));
|
||||
}
|
||||
@@ -416,7 +477,8 @@ ncp_initialize_search(struct ncp_server *server,
|
||||
ncp_add_byte(server, 0); /* reserved */
|
||||
ncp_add_handle_path(server, dir->volNumber, dir->DosDirNum, 1, NULL);
|
||||
|
||||
if ((result = ncp_request(server, 87)) != 0) {
|
||||
if ((result = ncp_request(server, 87)) != 0)
|
||||
{
|
||||
ncp_unlock_server(server);
|
||||
return result;
|
||||
}
|
||||
@@ -441,12 +503,13 @@ ncp_search_for_file_or_subdir(struct ncp_server *server,
|
||||
ncp_add_byte(server, 0); /* data stream (???) */
|
||||
ncp_add_word(server, 0xffff); /* Search attribs */
|
||||
ncp_add_dword(server, RIM_ALL); /* return info mask */
|
||||
ncp_add_mem(server, (unsigned char *)seq, 9);
|
||||
ncp_add_mem(server, seq, 9);
|
||||
ncp_add_byte(server, 2); /* 2 byte pattern */
|
||||
ncp_add_byte(server, 0xff); /* following is a wildcard */
|
||||
ncp_add_byte(server, '*');
|
||||
|
||||
if ((result = ncp_request(server, 87)) != 0) {
|
||||
if ((result = ncp_request(server, 87)) != 0)
|
||||
{
|
||||
ncp_unlock_server(server);
|
||||
return result;
|
||||
}
|
||||
@@ -512,14 +575,15 @@ ncp_read(struct ncp_server *server, const char *file_id,
|
||||
ncp_add_dword(server, htonl(offset));
|
||||
ncp_add_word(server, htons(to_read));
|
||||
|
||||
if ((result = ncp_request(server, 72)) != 0) {
|
||||
if ((result = ncp_request(server, 72)) != 0)
|
||||
{
|
||||
ncp_unlock_server(server);
|
||||
return result;
|
||||
}
|
||||
|
||||
*bytes_read = ntohs(ncp_reply_word(server, 0));
|
||||
|
||||
memcpy_tofs(target, ncp_reply_data(server, 2), *bytes_read);
|
||||
memcpy_tofs(target, ncp_reply_data(server, 2+(offset&1)), *bytes_read);
|
||||
|
||||
ncp_unlock_server(server);
|
||||
return 0;
|
||||
@@ -539,7 +603,8 @@ ncp_write(struct ncp_server *server, const char *file_id,
|
||||
ncp_add_word(server, htons(to_write));
|
||||
ncp_add_mem_fromfs(server, source, to_write);
|
||||
|
||||
if ((result = ncp_request(server, 73)) != 0) {
|
||||
if ((result = ncp_request(server, 73)) != 0)
|
||||
{
|
||||
ncp_unlock_server(server);
|
||||
return result;
|
||||
}
|
||||
@@ -119,6 +119,12 @@ ncp_do_lookup(struct ncp_server *server,
|
||||
char *path, /* may only be one component */
|
||||
struct nw_info_struct *target);
|
||||
|
||||
int
|
||||
ncp_modify_file_or_subdir_dos_info(struct ncp_server *server,
|
||||
struct nw_info_struct *file,
|
||||
__u32 info_mask,
|
||||
struct nw_modify_dos_info *info);
|
||||
|
||||
int
|
||||
ncp_del_file_or_subdir(struct ncp_server *server,
|
||||
struct nw_info_struct *dir, char *name);
|
||||
@@ -7,7 +7,11 @@
|
||||
*
|
||||
*/
|
||||
|
||||
/* #include <linux/module.h> */
|
||||
#include <linux/config.h>
|
||||
#ifdef MODULE
|
||||
#include <linux/module.h>
|
||||
#include <linux/version.h>
|
||||
#endif
|
||||
|
||||
#include <linux/sched.h>
|
||||
#include <linux/ncp_fs.h>
|
||||
@@ -25,52 +29,10 @@
|
||||
#include <linux/ncp.h>
|
||||
#include <linux/ncp_fs.h>
|
||||
#include <linux/ncp_fs_sb.h>
|
||||
#include <net/sock.h>
|
||||
#include "/usr/src/linux/net/inet/sock.h"
|
||||
|
||||
|
||||
#define _S(nr) (1<<((nr)-1))
|
||||
static int _recvfrom(struct socket *sock, unsigned char *ubuf,
|
||||
int size, int noblock, unsigned flags,
|
||||
struct sockaddr_ipx *sa, int *addr_len)
|
||||
{
|
||||
struct iovec iov;
|
||||
struct msghdr msg;
|
||||
|
||||
iov.iov_base = ubuf;
|
||||
iov.iov_len = size;
|
||||
|
||||
msg.msg_name = (void *)sa;
|
||||
msg.msg_namelen = 0;
|
||||
if (addr_len)
|
||||
msg.msg_namelen = *addr_len;
|
||||
msg.msg_accrights = NULL;
|
||||
msg.msg_iov = &iov;
|
||||
msg.msg_iovlen = 1;
|
||||
|
||||
return sock->ops->recvmsg(sock, &msg, size, noblock, flags, addr_len);
|
||||
}
|
||||
|
||||
static int _sendto(struct socket *sock, const void *buff,
|
||||
int len, int nonblock, unsigned flags,
|
||||
struct sockaddr_ipx *sa, int addr_len)
|
||||
|
||||
{
|
||||
struct iovec iov;
|
||||
struct msghdr msg;
|
||||
|
||||
iov.iov_base = (void *)buff;
|
||||
iov.iov_len = len;
|
||||
|
||||
msg.msg_name = (void *)sa;
|
||||
msg.msg_namelen = addr_len;
|
||||
msg.msg_accrights = NULL;
|
||||
msg.msg_iov = &iov;
|
||||
msg.msg_iovlen = 1;
|
||||
|
||||
return sock->ops->sendmsg(sock, &msg, len, nonblock, flags);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ncp_wdog_data_ready(struct sock *sk, int len)
|
||||
{
|
||||
@@ -80,15 +42,16 @@ ncp_wdog_data_ready(struct sock *sk, int len)
|
||||
{
|
||||
unsigned char packet_buf[2];
|
||||
struct sockaddr_ipx sender;
|
||||
int addr_len;
|
||||
int addr_len = sizeof(struct sockaddr_ipx);
|
||||
int result;
|
||||
unsigned short fs;
|
||||
|
||||
fs = get_fs();
|
||||
set_fs(get_ds());
|
||||
|
||||
result = _recvfrom(sock, (void *)packet_buf, 2, 1, 0,
|
||||
&sender, &addr_len);
|
||||
result = sock->ops->recvfrom(sock, (void *)packet_buf, 2, 1, 0,
|
||||
(struct sockaddr *)&sender,
|
||||
&addr_len);
|
||||
|
||||
if ( (result != 2)
|
||||
|| (packet_buf[1] != '?')
|
||||
@@ -96,16 +59,19 @@ ncp_wdog_data_ready(struct sock *sk, int len)
|
||||
)
|
||||
{
|
||||
/* Error, throw away the complete packet */
|
||||
_recvfrom(sock, (void *)packet_buf, 2, 1, 0,
|
||||
&sender, &addr_len);
|
||||
sock->ops->recvfrom(sock, (void *)packet_buf, 2, 1, 0,
|
||||
(struct sockaddr *)&sender,
|
||||
&addr_len);
|
||||
|
||||
printk("ncpfs: got strange packet on watchdog "
|
||||
"socket\n");
|
||||
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
int result;
|
||||
DPRINTK("ncpfs: got watchdog from:\n");
|
||||
DPRINTK("ncpfs: %08lX:%02X%02X%02X%02X%02X%02X:%04X,"
|
||||
DDPRINTK("ncpfs: got watchdog from:\n");
|
||||
DDPRINTK("ncpfs: %08lX:%02X%02X%02X%02X%02X%02X:%04X,"
|
||||
" conn:%02X,type:%c\n",
|
||||
htonl(sender.sipx_network),
|
||||
sender.sipx_node[0], sender.sipx_node[1],
|
||||
@@ -115,9 +81,11 @@ ncp_wdog_data_ready(struct sock *sk, int len)
|
||||
packet_buf[0], packet_buf[1]);
|
||||
|
||||
packet_buf[1] = 'Y';
|
||||
result = _sendto(sock, (void *)packet_buf, 2, 1, 0,
|
||||
&sender, sizeof(sender));
|
||||
DPRINTK("send result: %d\n", result);
|
||||
result = sock->ops->sendto(sock, (void *)packet_buf,
|
||||
2, 1, 0,
|
||||
(struct sockaddr *)&sender,
|
||||
sizeof(sender));
|
||||
DDPRINTK("send result: %d\n", result);
|
||||
}
|
||||
set_fs(fs);
|
||||
}
|
||||
@@ -135,8 +103,8 @@ ncp_catch_watchdog(struct ncp_server *server)
|
||||
if ( (server == NULL)
|
||||
|| ((file = server->wdog_filp) == NULL)
|
||||
|| ((inode = file->f_inode) == NULL)
|
||||
|| (!S_ISSOCK(inode->i_mode))) {
|
||||
|
||||
|| (!S_ISSOCK(inode->i_mode)))
|
||||
{
|
||||
printk("ncp_catch_watchdog: did not get valid server!\n");
|
||||
server->data_ready = NULL;
|
||||
return -EINVAL;
|
||||
@@ -144,7 +112,8 @@ ncp_catch_watchdog(struct ncp_server *server)
|
||||
|
||||
sock = &(inode->u.socket_i);
|
||||
|
||||
if (sock->type != SOCK_DGRAM) {
|
||||
if (sock->type != SOCK_DGRAM)
|
||||
{
|
||||
printk("ncp_catch_watchdog: did not get SOCK_STREAM\n");
|
||||
server->data_ready = NULL;
|
||||
return -EINVAL;
|
||||
@@ -152,7 +121,8 @@ ncp_catch_watchdog(struct ncp_server *server)
|
||||
|
||||
sk = (struct sock *)(sock->data);
|
||||
|
||||
if (sk == NULL) {
|
||||
if (sk == NULL)
|
||||
{
|
||||
printk("ncp_catch_watchdog: sk == NULL");
|
||||
server->data_ready = NULL;
|
||||
return -EINVAL;
|
||||
@@ -162,7 +132,8 @@ ncp_catch_watchdog(struct ncp_server *server)
|
||||
(unsigned int)(sk->data_ready),
|
||||
(unsigned int)(server->data_ready));
|
||||
|
||||
if (sk->data_ready == ncp_wdog_data_ready) {
|
||||
if (sk->data_ready == ncp_wdog_data_ready)
|
||||
{
|
||||
printk("ncp_catch_watchdog: already done\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -183,8 +154,8 @@ ncp_dont_catch_watchdog(struct ncp_server *server)
|
||||
if ( (server == NULL)
|
||||
|| ((file = server->wdog_filp) == NULL)
|
||||
|| ((inode = file->f_inode) == NULL)
|
||||
|| (!S_ISSOCK(inode->i_mode))) {
|
||||
|
||||
|| (!S_ISSOCK(inode->i_mode)))
|
||||
{
|
||||
printk("ncp_dont_catch_watchdog: "
|
||||
"did not get valid server!\n");
|
||||
return -EINVAL;
|
||||
@@ -192,25 +163,29 @@ ncp_dont_catch_watchdog(struct ncp_server *server)
|
||||
|
||||
sock = &(inode->u.socket_i);
|
||||
|
||||
if (sock->type != SOCK_DGRAM) {
|
||||
if (sock->type != SOCK_DGRAM)
|
||||
{
|
||||
printk("ncp_dont_catch_watchdog: did not get SOCK_STREAM\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
sk = (struct sock *)(sock->data);
|
||||
|
||||
if (sk == NULL) {
|
||||
if (sk == NULL)
|
||||
{
|
||||
printk("ncp_dont_catch_watchdog: sk == NULL");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (server->data_ready == NULL) {
|
||||
if (server->data_ready == NULL)
|
||||
{
|
||||
printk("ncp_dont_catch_watchdog: "
|
||||
"server->data_ready == NULL\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (sk->data_ready != ncp_wdog_data_ready) {
|
||||
if (sk->data_ready != ncp_wdog_data_ready)
|
||||
{
|
||||
printk("ncp_dont_catch_watchdog: "
|
||||
"sk->data_callback != ncp_data_callback\n");
|
||||
return -EINVAL;
|
||||
@@ -247,7 +222,6 @@ do_ncp_rpc_call(struct ncp_server *server, int size)
|
||||
int timeout;
|
||||
int retrans;
|
||||
int major_timeout_seen;
|
||||
char *server_name;
|
||||
int n;
|
||||
int addrlen;
|
||||
unsigned long old_mask;
|
||||
@@ -263,7 +237,8 @@ do_ncp_rpc_call(struct ncp_server *server, int size)
|
||||
inode = file->f_inode;
|
||||
select = file->f_op->select;
|
||||
sock = &inode->u.socket_i;
|
||||
if (!sock) {
|
||||
if (!sock)
|
||||
{
|
||||
printk("ncp_rpc_call: socki_lookup failed\n");
|
||||
return -EBADF;
|
||||
}
|
||||
@@ -271,22 +246,22 @@ do_ncp_rpc_call(struct ncp_server *server, int size)
|
||||
max_timeout = NCP_MAX_RPC_TIMEOUT*HZ/10;
|
||||
retrans = server->m.retry_count;
|
||||
major_timeout_seen = 0;
|
||||
server_name = server->m.server_name;
|
||||
old_mask = current->blocked;
|
||||
current->blocked |= ~(_S(SIGKILL)
|
||||
#if 0
|
||||
| _S(SIGSTOP)
|
||||
#endif
|
||||
| ((server->m.flags & NCP_MOUNT_INTR)
|
||||
? ((current->sig->action[SIGINT - 1].sa_handler == SIG_DFL
|
||||
? ((current->sigaction[SIGINT - 1].sa_handler == SIG_DFL
|
||||
? _S(SIGINT) : 0)
|
||||
| (current->sig->action[SIGQUIT - 1].sa_handler == SIG_DFL
|
||||
| (current->sigaction[SIGQUIT - 1].sa_handler == SIG_DFL
|
||||
? _S(SIGQUIT) : 0))
|
||||
: 0));
|
||||
fs = get_fs();
|
||||
set_fs(get_ds());
|
||||
for (n = 0, timeout = init_timeout; ; n++, timeout <<= 1) {
|
||||
/* DDPRINTK("ncpfs: %08lX:%02X%02X%02X%02X%02X%02X:%04X\n",
|
||||
for (n = 0, timeout = init_timeout; ; n++, timeout <<= 1)
|
||||
{
|
||||
DDPRINTK("ncpfs: %08lX:%02X%02X%02X%02X%02X%02X:%04X\n",
|
||||
htonl(server->m.serv_addr.sipx_network),
|
||||
server->m.serv_addr.sipx_node[0],
|
||||
server->m.serv_addr.sipx_node[1],
|
||||
@@ -294,7 +269,7 @@ do_ncp_rpc_call(struct ncp_server *server, int size)
|
||||
server->m.serv_addr.sipx_node[3],
|
||||
server->m.serv_addr.sipx_node[4],
|
||||
server->m.serv_addr.sipx_node[5],
|
||||
ntohs(server->m.serv_addr.sipx_port));*/
|
||||
ntohs(server->m.serv_addr.sipx_port));
|
||||
DDPRINTK("ncpfs: req.typ: %04X, con: %d, "
|
||||
"seq: %d",
|
||||
request.type,
|
||||
@@ -303,10 +278,12 @@ do_ncp_rpc_call(struct ncp_server *server, int size)
|
||||
DDPRINTK(" func: %d\n",
|
||||
request.function);
|
||||
|
||||
result = _sendto(sock, (void *) start, size, 0, 0,
|
||||
&(server->m.serv_addr),
|
||||
sizeof(server->m.serv_addr));
|
||||
if (result < 0) {
|
||||
result = sock->ops->sendto(sock, (void *) start, size, 0, 0,
|
||||
(struct sockaddr *)
|
||||
&(server->m.serv_addr),
|
||||
sizeof(server->m.serv_addr));
|
||||
if (result < 0)
|
||||
{
|
||||
printk("ncp_rpc_call: send error = %d\n", result);
|
||||
break;
|
||||
}
|
||||
@@ -315,39 +292,42 @@ do_ncp_rpc_call(struct ncp_server *server, int size)
|
||||
wait_table.entry = &entry;
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
if ( !select(inode, file, SEL_IN, &wait_table)
|
||||
&& !select(inode, file, SEL_IN, NULL)) {
|
||||
if (timeout > max_timeout) {
|
||||
&& !select(inode, file, SEL_IN, NULL))
|
||||
{
|
||||
if (timeout > max_timeout)
|
||||
{
|
||||
/* JEJB/JSP 2/7/94
|
||||
* This is useful to see if the system is
|
||||
* hanging */
|
||||
printk("NCP max timeout reached on %s\n",
|
||||
server_name);
|
||||
printk("NCP max timeout reached\n");
|
||||
timeout = max_timeout;
|
||||
}
|
||||
current->timeout = jiffies + timeout;
|
||||
schedule();
|
||||
remove_wait_queue(entry.wait_address, &entry.wait);
|
||||
current->state = TASK_RUNNING;
|
||||
if (current->signal & ~current->blocked) {
|
||||
if (current->signal & ~current->blocked)
|
||||
{
|
||||
current->timeout = 0;
|
||||
result = -ERESTARTSYS;
|
||||
break;
|
||||
}
|
||||
if (!current->timeout) {
|
||||
if (!current->timeout)
|
||||
{
|
||||
if (n < retrans)
|
||||
continue;
|
||||
if (server->m.flags & NCP_MOUNT_SOFT) {
|
||||
printk("NCP server %s not responding, "
|
||||
"timed out\n", server_name);
|
||||
if (server->m.flags & NCP_MOUNT_SOFT)
|
||||
{
|
||||
printk("NCP server not responding\n");
|
||||
result = -EIO;
|
||||
break;
|
||||
}
|
||||
n = 0;
|
||||
timeout = init_timeout;
|
||||
init_timeout <<= 1;
|
||||
if (!major_timeout_seen) {
|
||||
printk("NCP server %s not responding, "
|
||||
"still trying\n", server_name);
|
||||
if (!major_timeout_seen)
|
||||
{
|
||||
printk("NCP server not responding\n");
|
||||
}
|
||||
major_timeout_seen = 1;
|
||||
continue;
|
||||
@@ -363,30 +343,36 @@ do_ncp_rpc_call(struct ncp_server *server, int size)
|
||||
/* Get the header from the next packet using a peek, so keep it
|
||||
* on the recv queue. If it is wrong, it will be some reply
|
||||
* we don't now need, so discard it */
|
||||
result = _recvfrom(sock, (void *)&reply,
|
||||
sizeof(reply), 1, MSG_PEEK,
|
||||
NULL, &addrlen);
|
||||
if (result < 0) {
|
||||
if (result == -EAGAIN) {
|
||||
result = sock->ops->recvfrom(sock, (void *)&reply,
|
||||
sizeof(reply), 1, MSG_PEEK,
|
||||
NULL, &addrlen);
|
||||
if (result < 0)
|
||||
{
|
||||
if (result == -EAGAIN)
|
||||
{
|
||||
DPRINTK("ncp_rpc_call: bad select ready\n");
|
||||
goto re_select;
|
||||
}
|
||||
if (result == -ECONNREFUSED) {
|
||||
if (result == -ECONNREFUSED)
|
||||
{
|
||||
DPRINTK("ncp_rpc_call: server playing coy\n");
|
||||
goto re_select;
|
||||
}
|
||||
if (result != -ERESTARTSYS) {
|
||||
if (result != -ERESTARTSYS)
|
||||
{
|
||||
printk("ncp_rpc_call: recv error = %d\n",
|
||||
-result);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if ( (result == sizeof(reply))
|
||||
&& (reply.type == NCP_POSITIVE_ACK)) {
|
||||
&& (reply.type == NCP_POSITIVE_ACK))
|
||||
{
|
||||
/* Throw away the packet */
|
||||
DPRINTK("ncp_rpc_call: got positive acknowledge\n");
|
||||
_recvfrom(sock, (void *)&reply, sizeof(reply), 1, 0,
|
||||
NULL, &addrlen);
|
||||
sock->ops->recvfrom(sock, (void *)&reply,
|
||||
sizeof(reply), 1, 0,
|
||||
NULL, &addrlen);
|
||||
goto re_select;
|
||||
}
|
||||
|
||||
@@ -403,17 +389,18 @@ do_ncp_rpc_call(struct ncp_server *server, int size)
|
||||
|| ( (reply.sequence == request.sequence)
|
||||
&& (reply.conn_low == request.conn_low)
|
||||
/* seem to get wrong task from NW311 && (reply.task == request.task)*/
|
||||
&& (reply.conn_high == request.conn_high)))) {
|
||||
&& (reply.conn_high == request.conn_high))))
|
||||
{
|
||||
if (major_timeout_seen)
|
||||
printk("NCP server %s OK\n", server_name);
|
||||
printk("NCP server OK\n");
|
||||
break;
|
||||
}
|
||||
/* JEJB/JSP 2/7/94
|
||||
* we have xid mismatch, so discard the packet and start
|
||||
* again. What a hack! but I can't call recvfrom with
|
||||
* a null buffer yet. */
|
||||
_recvfrom(sock, (void *)&reply, sizeof(reply), 1, 0, NULL,
|
||||
&addrlen);
|
||||
sock->ops->recvfrom(sock, (void *)&reply, sizeof(reply), 1, 0,
|
||||
NULL, &addrlen);
|
||||
#if 1
|
||||
printk("ncp_rpc_call: reply mismatch\n");
|
||||
#endif
|
||||
@@ -423,11 +410,14 @@ do_ncp_rpc_call(struct ncp_server *server, int size)
|
||||
* we have the correct reply, so read into the correct place and
|
||||
* return it
|
||||
*/
|
||||
result = _recvfrom(sock, (void *)start, server->packet_size, 1, 0,
|
||||
NULL, &addrlen);
|
||||
if (result < 0) {
|
||||
result = sock->ops->recvfrom(sock, (void *)start, server->packet_size,
|
||||
1, 0, NULL, &addrlen);
|
||||
if (result < 0)
|
||||
{
|
||||
printk("NCP: notice message: result=%d\n", result);
|
||||
} else if (result < sizeof(struct ncp_reply_header)) {
|
||||
}
|
||||
else if (result < sizeof(struct ncp_reply_header))
|
||||
{
|
||||
printk("NCP: just caught a too small read memory size..., "
|
||||
"email to NET channel\n");
|
||||
printk("NCP: result=%d,addrlen=%d\n", result, addrlen);
|
||||
@@ -447,7 +437,8 @@ do_ncp_rpc_call(struct ncp_server *server, int size)
|
||||
static int
|
||||
ncp_do_request(struct ncp_server *server, int size)
|
||||
{
|
||||
if (server->lock == 0) {
|
||||
if (server->lock == 0)
|
||||
{
|
||||
printk("ncpfs: Server not locked!\n");
|
||||
return -EIO;
|
||||
}
|
||||
@@ -471,7 +462,8 @@ ncp_request(struct ncp_server *server, int function)
|
||||
|
||||
int result;
|
||||
|
||||
if (server->has_subfunction != 0) {
|
||||
if (server->has_subfunction != 0)
|
||||
{
|
||||
*(__u16 *)&(h->data[0]) = request_size - 2;
|
||||
}
|
||||
|
||||
@@ -484,7 +476,8 @@ ncp_request(struct ncp_server *server, int function)
|
||||
h->task = (current->pid) & 0xff;
|
||||
h->function = function;
|
||||
|
||||
if ((result = ncp_do_request(server, request_size + sizeof(*h))) < 0) {
|
||||
if ((result = ncp_do_request(server, request_size + sizeof(*h))) < 0)
|
||||
{
|
||||
DPRINTK("ncp_request_error: %d\n", result);
|
||||
return result;
|
||||
}
|
||||
@@ -496,7 +489,8 @@ ncp_request(struct ncp_server *server, int function)
|
||||
|
||||
result = reply->completion_code;
|
||||
|
||||
if (result != 0) {
|
||||
if (result != 0)
|
||||
{
|
||||
DPRINTK("ncp_completion_code: %d\n", result);
|
||||
}
|
||||
return result;
|
||||
@@ -518,7 +512,8 @@ ncp_connect(struct ncp_server *server)
|
||||
h->task = (current->pid) & 0xff;
|
||||
h->function = 0;
|
||||
|
||||
if ((result = ncp_do_request(server, sizeof(*h))) < 0) {
|
||||
if ((result = ncp_do_request(server, sizeof(*h))) < 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -548,9 +543,10 @@ ncp_disconnect(struct ncp_server *server)
|
||||
void
|
||||
ncp_lock_server(struct ncp_server *server)
|
||||
{
|
||||
#if 1
|
||||
#if 0
|
||||
/* For testing, only 1 process */
|
||||
if (server->lock != 0) {
|
||||
if (server->lock != 0)
|
||||
{
|
||||
DPRINTK("ncpfs: server locked!!!\n");
|
||||
}
|
||||
#endif
|
||||
@@ -562,7 +558,8 @@ ncp_lock_server(struct ncp_server *server)
|
||||
void
|
||||
ncp_unlock_server(struct ncp_server *server)
|
||||
{
|
||||
if (server->lock != 1) {
|
||||
if (server->lock != 1)
|
||||
{
|
||||
printk("ncp_unlock_server: was not locked!\n");
|
||||
}
|
||||
|
||||
16
man/Makefile
Normal file
16
man/Makefile
Normal file
@@ -0,0 +1,16 @@
|
||||
MAN1= slist nprint pqlist
|
||||
MAN5= nwclient
|
||||
MAN8= ncpmount ncpumount ipx_configure ipx_interface ipx_internal_net ipx_route
|
||||
|
||||
|
||||
|
||||
all:
|
||||
|
||||
dep:
|
||||
|
||||
install:
|
||||
for i in $(MAN1); do install $$i.1 -m 755 /usr/local/man/man1; done
|
||||
for i in $(MAN5); do install $$i.5 -m 755 /usr/local/man/man5; done
|
||||
for i in $(MAN8); do install $$i.8 -m 755 /usr/local/man/man8; done
|
||||
|
||||
clean:
|
||||
47
man/ipx_configure.8
Normal file
47
man/ipx_configure.8
Normal file
@@ -0,0 +1,47 @@
|
||||
.TH IPX_CONFIGURE 8 "IPX Utilities" "Caldera, Inc."
|
||||
.SH NAME
|
||||
ipx_configure \- display/configure IPX behavior
|
||||
.SH SYNOPSIS
|
||||
.B ipx_configure
|
||||
[\-\-help]
|
||||
[\-\-auto_interface=[on|off]]
|
||||
[\-\-auto_primary=[on|off]]
|
||||
.SH DESCRIPTION
|
||||
.B ipx_configure
|
||||
displays or configures IPX behavior with respect to automatic IPX
|
||||
interface detection. IPX can be configured to automatically create
|
||||
interfaces as they are detected. It can also be configured to
|
||||
automatically select a primary interface when none is explicitly
|
||||
selected. By default, it is configured to
|
||||
.B NOT
|
||||
have this behavior.
|
||||
Without arguments,
|
||||
.B ipx_configure
|
||||
returns the current configuration state. The behavior with
|
||||
arguments is described in the section
|
||||
.B OPTIONS.
|
||||
.SS OPTIONS
|
||||
.TP
|
||||
.I "\-\-auto_interface=[on|off]"
|
||||
This argument enables or disables the feature that will automatically detect
|
||||
whether IPX is use on a network interface. If
|
||||
.B on
|
||||
and IPX packets are seen on an interface that interface will be automatically
|
||||
flagged as an IPX interface. The default setting is
|
||||
.B off.
|
||||
.TP
|
||||
.I "\-\-auto_primary=[on|off]"
|
||||
This argument enables or disables the feature that will automatically select
|
||||
which IPX interface will be the primary IPX interface. The default setting is
|
||||
.B off.
|
||||
.TP
|
||||
.I "\-\-help"
|
||||
Displays summarised usage instructions.
|
||||
.SH FILES
|
||||
.I /proc/net/ipx_interface
|
||||
.SH BUGS
|
||||
This functionality really belongs in
|
||||
.B
|
||||
ifconfig(8).
|
||||
.SH AUTHOR
|
||||
Greg Page <greg.page@caldera.com>
|
||||
60
man/ipx_interface.8
Normal file
60
man/ipx_interface.8
Normal file
@@ -0,0 +1,60 @@
|
||||
.TH IPX_INTERFACE 8 "IPX Utilities" "Caldera, Inc."
|
||||
.SH NAME
|
||||
ipx_interface \- add, delete, or display IPX interface configuration.
|
||||
.SH SYNOPSIS
|
||||
.B ipx_interface
|
||||
add [-p] device frame_type [network number]
|
||||
.LP
|
||||
.B ipx_interface
|
||||
del device frame_type
|
||||
.LP
|
||||
.B ipx_interface
|
||||
check device frame_type
|
||||
.LP
|
||||
.B ipx_interface
|
||||
help
|
||||
.SH DESCRIPTION
|
||||
.B ipx_interface
|
||||
adds, deletes, or displays the configuration of the specified IPX interface.
|
||||
.P
|
||||
An IPX interface is the item to which IPX sockets are bound.
|
||||
An IPX interface has an associated IPX Network Number, a physical device
|
||||
and frame type. A sample IPX Interface might look like:
|
||||
.LP
|
||||
Network Number: 0x00ABCDEF
|
||||
.LP
|
||||
Device: Eth0
|
||||
.LP
|
||||
Frame Type: 802.2.
|
||||
.P
|
||||
There is a special IPX interface per host known as the
|
||||
.B PRIMARY
|
||||
or default interface.
|
||||
.SS OPTIONS
|
||||
.TP
|
||||
.I add
|
||||
This option is used to create an IPX interface. If the
|
||||
.B -p
|
||||
flag is used, the interface is flagged as the
|
||||
.B PRIMARY
|
||||
interface. The IPX network number may optionally be specified. If it is not
|
||||
specified it is set to 0 which indicates it should be automatically detected
|
||||
by analysis of the existing IPX traffic on the network.
|
||||
.TP
|
||||
.I del
|
||||
This option is used to delete an IPX interface.
|
||||
.TP
|
||||
.I check
|
||||
This option is used to display the network number associated with a specified
|
||||
device and frame type combination.
|
||||
.TP
|
||||
.I help
|
||||
This option displays summarised usage instructions.
|
||||
.SH FILES
|
||||
.I /proc/net/ipx_interface /proc/net/ipx_route
|
||||
.SH BUGS
|
||||
This functionality really belongs in
|
||||
.B
|
||||
ifconfig(8).
|
||||
.SH AUTHOR
|
||||
Greg Page <greg.page@caldera.com>
|
||||
32
man/ipx_internal_net.8
Normal file
32
man/ipx_internal_net.8
Normal file
@@ -0,0 +1,32 @@
|
||||
.TH IPX_INTERNAL_NET 8 "IPX Utilities" "Caldera, Inc."
|
||||
.SH NAME
|
||||
ipx_internal_net \- add or delete the IPX internal network
|
||||
.SH SYNOPSIS
|
||||
.B ipx_internal_net
|
||||
add network_number node_number
|
||||
.LP
|
||||
.B ipx_internal_net
|
||||
del
|
||||
.SH DESCRIPTION
|
||||
.B ipx_internal_net
|
||||
adds or deletes the IPX internal network.
|
||||
An IPX internal network is a special kind of IPX interface that does
|
||||
not have a physical device or frame type. It is used to provide
|
||||
a route-independent address for service providers. Internal networks
|
||||
are optional; however, when one is present it is also the
|
||||
Primary Interface. There can only be one internal network per host.
|
||||
.SS OPTIONS
|
||||
.TP
|
||||
.I add
|
||||
This option is used to create the IPX internal network.
|
||||
.TP
|
||||
.I del
|
||||
This option is used to delete the IPX internal network.
|
||||
.SH FILES
|
||||
.I /proc/net/ipx_interface /proc/net/ipx_route
|
||||
.SH BUGS
|
||||
This functionality really belongs in
|
||||
.B
|
||||
ifconfig(8).
|
||||
.SH AUTHOR
|
||||
Greg Page <greg.page@caldera.com>
|
||||
24
man/ipx_route.8
Normal file
24
man/ipx_route.8
Normal file
@@ -0,0 +1,24 @@
|
||||
.TH IPX_ROUTE 8 "IPX Utilities" "Caldera, Inc."
|
||||
.SH NAME
|
||||
ipx_route \- add or delete an IPX route.
|
||||
.SH SYNOPSIS
|
||||
.B ipx_route
|
||||
add target_network router_network router_node
|
||||
.LP
|
||||
.B ipx_route
|
||||
del target_network
|
||||
.SH DESCRIPTION
|
||||
.B ipx_route
|
||||
adds or deletes an IPX route.
|
||||
The kernel IPX software stores only one route to any target network.
|
||||
.SS OPTIONS
|
||||
.TP
|
||||
.I add
|
||||
This option is used to configure a route to a target network.
|
||||
.TP
|
||||
.I del
|
||||
This option is used to delete the route to a target network.
|
||||
.SH FILES
|
||||
.I /proc/net/ipx_interface /proc/net/ipx_route
|
||||
.SH AUTHOR
|
||||
Greg Page <greg.page@caldera.com>
|
||||
219
man/ncpmount.8
Normal file
219
man/ncpmount.8
Normal file
@@ -0,0 +1,219 @@
|
||||
.TH NCPMOUNT 8 12/27/1995 ncpmount ncpmount
|
||||
.SH NAME
|
||||
ncpmount \- mount all volumes of a specified Novell fileserver.
|
||||
.SH SYNOPSIS
|
||||
.B ncpmount
|
||||
[
|
||||
.B -h
|
||||
] [
|
||||
.B -S
|
||||
.I server
|
||||
] [
|
||||
.B -U
|
||||
.I user name
|
||||
] [
|
||||
.B -P
|
||||
.I password
|
||||
|
|
||||
.B -n
|
||||
] [
|
||||
.B -C
|
||||
] [
|
||||
.B -c
|
||||
.I client name
|
||||
] [
|
||||
.B -u
|
||||
.I uid
|
||||
] [
|
||||
.B -g
|
||||
.I gid
|
||||
] [
|
||||
.B -f
|
||||
.I file mode
|
||||
] [
|
||||
.B -d
|
||||
.I dir mode
|
||||
]
|
||||
mount-point
|
||||
|
||||
.SH DESCRIPTION
|
||||
This program is used to mount all volumes of the specified NetWare Fileserver
|
||||
under the specified mount point.
|
||||
|
||||
.B ncpfs
|
||||
is a linux filesystem which understands the NCP protocol. This is the
|
||||
protocol Novell NetWare clients use to talk to NetWare servers. ncpfs
|
||||
was inspired by
|
||||
.B lwared,
|
||||
a free NetWare emulator for Linux written by Ales Dryak. See
|
||||
ftp://klokan.sh.cvut.cz/pub/linux for this very intersting program.
|
||||
|
||||
.B ncpmount
|
||||
when invoked with all appropriate arguments attaches, logs in and
|
||||
mounts all of the volumes associated with the specified fileserver that are
|
||||
readable by the user id under the specified mount point.
|
||||
.B ncpmount
|
||||
when invoked without any arguments specifying the fileserver, user id and
|
||||
password checks the file
|
||||
.I $HOME/.nwclient
|
||||
to find a file server, a user name and possibly a password to use for the
|
||||
specified mount point. See nwclient(5) for more information. Please note
|
||||
that the access permissions of .nwclient MUST be 600, for security reasons.
|
||||
|
||||
.SH OPTIONS
|
||||
.B mount-point
|
||||
.RS 3
|
||||
.B mount-point
|
||||
is the directory you want to mount the filesystem over. Its function is the
|
||||
the same as for a normal mount command.
|
||||
|
||||
If the real uid of the caller is not root,
|
||||
.B ncpmount
|
||||
checks whether the user is allowed to mount a filesystem on the
|
||||
mount-point. So it should be safe to make
|
||||
.B ncpmount
|
||||
setuid root. The filesystem stores the uid of the user who called
|
||||
ncpmount. So
|
||||
.B ncpumount
|
||||
can check whether the caller is allowed to unmount the filesystem.
|
||||
.RE
|
||||
|
||||
.B -S
|
||||
.I server
|
||||
.RS 3
|
||||
.B server
|
||||
is the name of the server you want to use.
|
||||
.RE
|
||||
|
||||
.B -h
|
||||
.RS 3
|
||||
.B -h
|
||||
is used to print out a short help text.
|
||||
.RE
|
||||
|
||||
.B -C
|
||||
.RS 3
|
||||
By default passwords are converted to uppercase before they are sent
|
||||
to the server because most servers require this. This option disables this
|
||||
feature ensuring that passwords are sent without any case conversion.
|
||||
.RE
|
||||
|
||||
.B -n
|
||||
.RS 3
|
||||
.B -n
|
||||
must be specified for logins that do not have a password configured.
|
||||
.RE
|
||||
|
||||
.B -P
|
||||
.I password
|
||||
.RS 3
|
||||
specifies the password to use for the Netware user id.
|
||||
|
||||
If neither
|
||||
.B -n
|
||||
nor the
|
||||
.B -P
|
||||
arguments are specified ncpmount will prompt for a password. This
|
||||
makes it difficult to use in scripts such as /etc/rc. If you want to
|
||||
have ncpmount work automatically from a script you must include the
|
||||
appropriate option and be very careful to ensure that appopriate file
|
||||
permissions are set for the script that includes your password to
|
||||
ensure that others can not read it.
|
||||
.RE
|
||||
|
||||
.B -U
|
||||
.I user name
|
||||
.RS 3
|
||||
Specifies the Netware user id to use when logging in to the fileserver. If
|
||||
this option is not specified then ncpmount will attempt to login to the
|
||||
fileserver using the Linux login id of the user invoking ncpmount.
|
||||
.RE
|
||||
|
||||
.B -u
|
||||
.I uid,
|
||||
.B -g
|
||||
.I gid
|
||||
.RS 3
|
||||
ncpmount does not yet implement a scheme for mapping NetWare users/groups
|
||||
to Linux users/groups. Linux requires that each file has an owner and group id.
|
||||
With
|
||||
.B -u
|
||||
and
|
||||
.B -g
|
||||
you can tell ncpmount which id's it should assign to the files in the
|
||||
mounted directory.
|
||||
|
||||
The defaults for these values are the current uid and gid.
|
||||
.RE
|
||||
|
||||
.B -c
|
||||
.I user name
|
||||
.RS 3
|
||||
.B -c
|
||||
names the user who is the
|
||||
.I owner
|
||||
of the connection, where owner does not refer to file ownership (that
|
||||
"owner" is set by the -u argument), but the owner of the mount, ie: who
|
||||
is allowed to call ncpumount on this mount. The default owner of the
|
||||
connection and the mount is the user who called ncpmount. This option
|
||||
allows you to specify that some other user should be set as the owner.
|
||||
|
||||
In this this way it is possible to mount a public read-only directory,
|
||||
but to allow the lp daemon to print on NetWare queues. This is
|
||||
possible because only users who have write permissions on a directory
|
||||
may issue ncp requests over a connection. The exception to this rule
|
||||
is the 'mount owner', who is also granted 'request permission'.
|
||||
.RE
|
||||
|
||||
.B -f
|
||||
.I file mode,
|
||||
.B -d
|
||||
.I dir mode
|
||||
.RS 3
|
||||
Like
|
||||
.B -u
|
||||
and
|
||||
.B -g,
|
||||
these options are used to determine what permissions should be assigned
|
||||
files and directories of the mounted volumes. The values must be specified
|
||||
as octal numbers. The default values are taken from the current umask, where
|
||||
the file mode is the current umask, and the dir mode adds execute permissions
|
||||
where the file mode gives read permissions.
|
||||
|
||||
Note that these permissions can differ from the rights the server
|
||||
gives to us. If you do not have write permissions on the server, you
|
||||
can very well choose a file mode that tells that you have. This
|
||||
certainly cannot override the restrictions imposed by the server.
|
||||
.RE
|
||||
|
||||
.SH NOTES
|
||||
You must configure the IPX subsystem before ncpmount will work.
|
||||
It is especially important that there is a route to the internal network
|
||||
of your server.
|
||||
|
||||
.SH ENVIRONMENT VARIABLES
|
||||
.B USER / LOGNAME
|
||||
.RS 3
|
||||
The variables USER or LOGNAME may contain the username of the person
|
||||
using the client. USER is tried first. If it's emtpy, LOGNAME is
|
||||
tried.
|
||||
.RE
|
||||
|
||||
.SH DIAGNOSTICS
|
||||
|
||||
Most diagnostics issued by ncpfs are logged by syslogd. Normally
|
||||
nothing is printed, only error situations are logged there.
|
||||
|
||||
.SH SEE ALSO
|
||||
.B syslogd(8), ncpumount(8)
|
||||
|
||||
.SH CREDITS
|
||||
ncpfs would not have been possible without lwared, written by Ales
|
||||
Dryak (A.Dryak@sh.cvut.cz).
|
||||
|
||||
The encryption code was taken from Dr. Dobbs's Journal 11/93. There
|
||||
Pawel Szczerbina described it in an article on NCP.
|
||||
|
||||
The ncpfs code was initially hacked from smbfs by Volker Lendecke
|
||||
(lendecke@namu01.gwdg.de). smbfs was put together by Paal-Kr. Engstad
|
||||
(pke@engstad.ingok.hitos.no) and later polished by Volker.
|
||||
29
man/ncpumount.8
Normal file
29
man/ncpumount.8
Normal file
@@ -0,0 +1,29 @@
|
||||
.TH NCPUMOUNT 8 12/27/1995 ncpumount ncpumount
|
||||
.SH NAME
|
||||
ncpumount \- unmount a NetWare filesystem mounted with ncpmount.
|
||||
.SH SYNOPSIS
|
||||
.B ncpumount
|
||||
.B mount-point
|
||||
|
||||
.SH DESCRIPTION
|
||||
This utility unmounts a NetWare filesystem that was previously mounted
|
||||
with the ncpmount utility. If the this utility is made suid root then
|
||||
non-root users will also be able to make use of it.
|
||||
|
||||
.B ncpumount
|
||||
has been written to give normal linux-users more control over their
|
||||
resources. It is safe to install this program suid root, because only
|
||||
the user who has mounted a filesystem is allowed to unmount it again.
|
||||
|
||||
For root it is not necessary to use ncpumount. The normal umount
|
||||
program works perfectly well, but it would certainly be problematic to
|
||||
make umount setuid root.
|
||||
|
||||
.SH OPTIONS
|
||||
.B mount-point
|
||||
.RS 3
|
||||
.B mount-point
|
||||
is the directory you want to unmount.
|
||||
|
||||
.SH SEE ALSO
|
||||
.B ncpmount(8)
|
||||
222
man/nprint.1
Normal file
222
man/nprint.1
Normal file
@@ -0,0 +1,222 @@
|
||||
.TH NPRINT 1 12/27/1995 nprint nprint
|
||||
.SH NAME
|
||||
nprint \- NetWare print client
|
||||
.SH SYNOPSIS
|
||||
.B nprint
|
||||
[
|
||||
.B -S
|
||||
.I server
|
||||
] [
|
||||
.B -h
|
||||
] [
|
||||
.B -U
|
||||
.I user name
|
||||
] [
|
||||
.B -P
|
||||
.I password
|
||||
|
|
||||
.B -n
|
||||
] [
|
||||
.B -C
|
||||
] [
|
||||
.B -q
|
||||
.I queue name
|
||||
] [
|
||||
.B -d
|
||||
.I job description
|
||||
] [
|
||||
.B -p
|
||||
.I path name
|
||||
] [
|
||||
.B -b
|
||||
.I banner name
|
||||
] [
|
||||
.B -f
|
||||
.I file name in banner
|
||||
] [
|
||||
.B -l
|
||||
.I lines
|
||||
] [
|
||||
.B -r
|
||||
.I rows
|
||||
] [
|
||||
.B -c
|
||||
.I copies
|
||||
] [
|
||||
.B -t
|
||||
.I tab size
|
||||
] [
|
||||
.B -T
|
||||
] [
|
||||
.B -N
|
||||
] [
|
||||
.B -F
|
||||
.I form number
|
||||
]
|
||||
.B file
|
||||
|
||||
.SH DESCRIPTION
|
||||
With
|
||||
.B nprint,
|
||||
you can print files on print queues of a NetWare file server.
|
||||
|
||||
There are a lot of options, so you should probably wrap some default
|
||||
configurations into some shell scripts.
|
||||
|
||||
.B nprint
|
||||
looks up the file
|
||||
.I $HOME/.nwclient
|
||||
to find a file server, a user name and possibly a password. See
|
||||
nwclient(5) for more information. Please note that the access
|
||||
permissions of .nwclient MUST be 600, for security reasons.
|
||||
|
||||
.SH OPTIONS
|
||||
.B file
|
||||
.RS 3
|
||||
.B file
|
||||
is the name of the file you want to print. If file is '-', or no
|
||||
filename is given, standard input is used.
|
||||
.RE
|
||||
|
||||
.B -h
|
||||
.RS 3
|
||||
.B -h
|
||||
is used to print out a short help text.
|
||||
.RE
|
||||
|
||||
.B -S
|
||||
.I server
|
||||
.RS 3
|
||||
.B server
|
||||
is the name of the server you want to use.
|
||||
.RE
|
||||
|
||||
.B -U
|
||||
.I user
|
||||
.RS 3
|
||||
.B user
|
||||
is the user name to use for the print request at the server.
|
||||
.RE
|
||||
|
||||
.B -P
|
||||
.I password
|
||||
.RS 3
|
||||
.B password
|
||||
is the password to use for the print request at the server. If neither
|
||||
.B -n
|
||||
nor
|
||||
.B -P
|
||||
are given, and the user has no open connection to the server, nprint
|
||||
prompts for a password.
|
||||
.RE
|
||||
|
||||
.B -n
|
||||
.RS 3
|
||||
.B -n
|
||||
should be given if no password is required for the print request.
|
||||
.RE
|
||||
|
||||
.B -C
|
||||
.RS 3
|
||||
By default, passwords are converted to uppercase before they are sent
|
||||
to the server, because most servers require this. You can turn off
|
||||
this conversion by
|
||||
.B -C.
|
||||
.RE
|
||||
|
||||
.B -q
|
||||
.I queue name
|
||||
.RS 3
|
||||
.B queue name
|
||||
is the name of the print queue to use at the print server. At
|
||||
present, you must specify it in upper case characters.
|
||||
.RE
|
||||
|
||||
.B -d
|
||||
.I job description
|
||||
.RS 3
|
||||
.B job description
|
||||
is the string that appears in pconsole when you list the jobs for the
|
||||
print queue. It is also printed somewhere on the top of the banner
|
||||
page.
|
||||
.RE
|
||||
|
||||
.B -p
|
||||
.I pathname
|
||||
.RS 3
|
||||
.B pathname
|
||||
is the string you want to be printed on the banner page in the field
|
||||
'path'.
|
||||
.RE
|
||||
|
||||
.B -b
|
||||
.I bannername
|
||||
.RS 3
|
||||
.B bannername
|
||||
is the string (up to 12 characters) you want to appear on the lower
|
||||
part of the banner page.
|
||||
.RE
|
||||
|
||||
.B -f
|
||||
.I filename
|
||||
.RS 3
|
||||
.B filename
|
||||
is the string (up to 12 characters) you want to appear on the upper
|
||||
part of the banner page. Default: the name of the file that is
|
||||
printed, or 'stdin'.
|
||||
.RE
|
||||
|
||||
.B -l
|
||||
.I lines
|
||||
.RS 3
|
||||
.B lines
|
||||
is the number of lines to put on one page. Default: 66
|
||||
.RE
|
||||
|
||||
.B -r
|
||||
.I rows
|
||||
.RS 3
|
||||
.B rows
|
||||
is the number of rows to put on one page. Default: 80
|
||||
.RE
|
||||
|
||||
.B -c
|
||||
.I copies
|
||||
.RS 3
|
||||
.B copies
|
||||
tells the print server to the specified number of copies. Default: 1
|
||||
.RE
|
||||
|
||||
.B -t
|
||||
.I tabs
|
||||
.RS 3
|
||||
.B tabs
|
||||
is the number of spaces to print for a Tab-Character. Default: 8
|
||||
.RE
|
||||
|
||||
.B -T
|
||||
.RS 3
|
||||
tells the print server to expand Tab-Character and use 8 spaces
|
||||
.RE
|
||||
|
||||
.B -N
|
||||
.RS 3
|
||||
tells the print server
|
||||
.B not
|
||||
to use Form Feeds
|
||||
.RE
|
||||
|
||||
.B -F
|
||||
.I form number
|
||||
.RS 3
|
||||
.B form number
|
||||
is the the number of the form to be put into the printer. If it's
|
||||
different from the one currently in the printer, your job is only
|
||||
printed if a printer operator has put in the correct form.
|
||||
.RE
|
||||
|
||||
.SH SEE ALSO
|
||||
.B nwclient(5), slist(1), pqlist(1), ncpmount(8), ncpumount(8)
|
||||
|
||||
.SH CREDITS
|
||||
nprint was written by Volker Lendecke (lendecke@namu01.gwdg.de)
|
||||
55
man/nwclient.5
Normal file
55
man/nwclient.5
Normal file
@@ -0,0 +1,55 @@
|
||||
.TH NWCLIENT 5 12/27/1995 nwmount nwmount
|
||||
.SH NAME
|
||||
nwclient \- configuration file for NWClient program suite
|
||||
.SH DESCRIPTION
|
||||
This manual page describes the rather simple format of the file
|
||||
.B $HOME/.nwclient,
|
||||
the configuration file for the NWClient program suite.
|
||||
.SH FILE FORMAT
|
||||
The file
|
||||
.B $HOME/.nwclient
|
||||
consists of several lines, each describing a NWClient
|
||||
connection. Lines beginning with # and empty lines are ignored as
|
||||
comments.
|
||||
|
||||
Because you can store passwords in .nwclient, the user programs will
|
||||
only scan .nwclient when only the file owner has access rights to
|
||||
the file. The file must be have permissions 0600.
|
||||
|
||||
To specify a NWClient connection, the name of the file server, the
|
||||
user name to be used and a password is necessary. The server name and
|
||||
the user name are specified as SERVER/USER, and the password is
|
||||
separated by a blank. The password field can be omitted. In this case
|
||||
the user programs will ask you for a password. If you specify the
|
||||
password to be just a dash, then no password is used.
|
||||
|
||||
The first valid specification has a special meaning: If the user does
|
||||
not name a server on the command line, the first specification is used
|
||||
as a 'preferred connection'.
|
||||
|
||||
An example might be the following:
|
||||
|
||||
# The preferred connection, the user is asked
|
||||
# for a password
|
||||
FS311/ME
|
||||
# And a passwordless account on another server
|
||||
CD-SERV/GUEST -
|
||||
|
||||
With these lines in $HOME/.nwclient, calling 'nwmount /mnt' will mount
|
||||
the the file server FS311 with user name ME on /mnt after asking the
|
||||
user for a password.
|
||||
|
||||
\'nwmount -S cd-serv /cd' will silently mount the server cd-serv on /cd.
|
||||
|
||||
.B nprint
|
||||
,
|
||||
.B pqlist
|
||||
and other user programs that require a valid login also look up
|
||||
.I $HOME/.nwclient
|
||||
to find a file server, a user name and possibly a password.
|
||||
|
||||
Please note that the access permissions of .nwclient MUST be 600, for
|
||||
security reasons.
|
||||
|
||||
.SH SEE ALSO
|
||||
.B ncpmount(8), ncpumount(8), slist(1), pqlist(1), nprint(1)
|
||||
105
man/pqlist.1
Normal file
105
man/pqlist.1
Normal file
@@ -0,0 +1,105 @@
|
||||
.TH PQLIST 1 01/10/1996 pqlist pqlist
|
||||
.SH NAME
|
||||
pqlist \- List available NetWare print queues
|
||||
.SH SYNOPSIS
|
||||
.B pqlist
|
||||
[
|
||||
.B -h
|
||||
] [
|
||||
.B -S
|
||||
.I server
|
||||
] [
|
||||
.B -U
|
||||
.I user name
|
||||
] [
|
||||
.B -P
|
||||
.I password
|
||||
|
|
||||
.B -n
|
||||
] [
|
||||
.B -C
|
||||
] [
|
||||
.I pattern
|
||||
]
|
||||
.SH DESCRIPTION
|
||||
.B pqlist
|
||||
lists all the NetWare print queues available to you on some server.
|
||||
If you are already connected to some server, this one is used.
|
||||
|
||||
If pqlist does not print to a tty, the decorative header line is
|
||||
not printed, so that you can count the printing queue available
|
||||
on your server by doing
|
||||
|
||||
pqlist -S server | wc -l
|
||||
|
||||
.B pqlist
|
||||
looks up the file
|
||||
.I $HOME/.nwclient
|
||||
to find a file server, a user name and possibly a password. See
|
||||
nwclient(5) for more information. Please note that the access
|
||||
permissions of .nwclient MUST be 600, for security reasons.
|
||||
|
||||
.SH OPTIONS
|
||||
|
||||
.B pattern
|
||||
.RS 3
|
||||
.B pattern
|
||||
is used to list only selected queues. You can use wildcards in the
|
||||
pattern, but you have to be careful to prevent shell interpretation of
|
||||
wildcards like '*'.
|
||||
.RE
|
||||
|
||||
.B -h
|
||||
.RS 3
|
||||
.B -h
|
||||
is used to print out a short help text.
|
||||
.RE
|
||||
|
||||
.B -S
|
||||
.I server
|
||||
.RS 3
|
||||
.B server
|
||||
is the name of the server you want to use.
|
||||
.RE
|
||||
|
||||
.B -U
|
||||
.I user name
|
||||
.RS 3
|
||||
If the user name your NetWare administrator gave to you differs
|
||||
from your unix user-id, you should use
|
||||
.B -U
|
||||
to tell the server about you NetWare user name.
|
||||
.RE
|
||||
|
||||
.B -P
|
||||
.I password
|
||||
.RS 3
|
||||
You may want to give the password required by the server on the
|
||||
command line. You should be careful to use passwords in scripts.
|
||||
.RE
|
||||
|
||||
.B -n
|
||||
.RS 3
|
||||
.B -n
|
||||
should be given to mount shares which do not require a password to log in.
|
||||
|
||||
If neither
|
||||
.B -n
|
||||
nor
|
||||
.B -P
|
||||
are given, pqlist prompts for a password.
|
||||
.RE
|
||||
|
||||
.B -C
|
||||
.RS 3
|
||||
By default, passwords are converted to uppercase before they are sent
|
||||
to the server, because most servers require this. You can turn off
|
||||
this conversion by
|
||||
.B -C.
|
||||
.RE
|
||||
|
||||
.SH SEE ALSO
|
||||
.B nwclient(5), nprint(1), slist(1), ncpmount(8), ncpumount(8)
|
||||
|
||||
.SH CREDITS
|
||||
pqlist was written by Volker Lendecke (lendecke@namu01.gwdg.de)
|
||||
142
man/pserver.1
Normal file
142
man/pserver.1
Normal file
@@ -0,0 +1,142 @@
|
||||
.TH PSERVER 1 02/10/1996 pserver pserver
|
||||
.SH NAME
|
||||
pserver \- NetWare print server
|
||||
.SH SYNOPSIS
|
||||
.B pserver
|
||||
[
|
||||
.B -S
|
||||
.I server
|
||||
] [
|
||||
.B -h
|
||||
] [
|
||||
.B -U
|
||||
.I user name
|
||||
] [
|
||||
.B -P
|
||||
.I password
|
||||
|
|
||||
.B -n
|
||||
] [
|
||||
.B -C
|
||||
] [
|
||||
.B -q
|
||||
.I queue name
|
||||
] [
|
||||
.B -c
|
||||
.I command
|
||||
] [
|
||||
.B -j
|
||||
.I job type
|
||||
] [
|
||||
.B -t
|
||||
.I timeout
|
||||
] [
|
||||
.B -d
|
||||
]
|
||||
|
||||
.SH DESCRIPTION
|
||||
.B pserver
|
||||
is a program that connects to print queues on NetWare servers and
|
||||
feeds incoming print jobs to the Linux printing system.
|
||||
|
||||
.SH OPTIONS
|
||||
.B -h
|
||||
.RS 3
|
||||
.B -h
|
||||
is used to print out a short help text.
|
||||
.RE
|
||||
|
||||
.B -S
|
||||
.I server
|
||||
.RS 3
|
||||
.B server
|
||||
is the name of the server you want to use.
|
||||
.RE
|
||||
|
||||
.B -U
|
||||
.I user
|
||||
.RS 3
|
||||
.B user
|
||||
is the print server name at the server.
|
||||
.RE
|
||||
|
||||
.B -P
|
||||
.I password
|
||||
.RS 3
|
||||
.B password
|
||||
is the password to use for the print server at the server. If neither
|
||||
.B -n
|
||||
nor
|
||||
.B -P
|
||||
are given, and the user has no open connection to the server, pserver
|
||||
prompts for a password.
|
||||
.RE
|
||||
|
||||
.B -n
|
||||
.RS 3
|
||||
.B -n
|
||||
should be given if the print server does not require a password.
|
||||
.RE
|
||||
|
||||
.B -C
|
||||
.RS 3
|
||||
By default, passwords are converted to uppercase before they are sent
|
||||
to the server, because most servers require this. You can turn off
|
||||
this conversion by
|
||||
.B -C.
|
||||
.RE
|
||||
|
||||
.B -q
|
||||
.I queue name
|
||||
.RS 3
|
||||
.B queue name
|
||||
is the name of the print queue you want to service.
|
||||
.RE
|
||||
|
||||
.B -c
|
||||
.I command
|
||||
.RS 3
|
||||
When a job is received from the print queue, pserver forks off a new
|
||||
process, and feeds the job file to stdin.
|
||||
.I command
|
||||
is the printing command that is executed for each job. The default
|
||||
command is 'lpr'.
|
||||
.RE
|
||||
|
||||
.B -j
|
||||
.I job type
|
||||
.RS 3
|
||||
Each job in a NetWare print queue has a job type. For print jobs, this
|
||||
corresponds to the number of the form the job should be printed
|
||||
on. You can tell pserver that it should only receive jobs for one
|
||||
specific form from the queue. The default is -1, which means that
|
||||
everything is received.
|
||||
.RE
|
||||
|
||||
.B -t
|
||||
.I timeout
|
||||
.RS 3
|
||||
Pserver is not informed by NetWare servers when new jobs arrive. So a
|
||||
polling scheme has to be used. When there are no jobs to service,
|
||||
.I timeout
|
||||
tells pserver how long to wait between two requests. The default is 30
|
||||
seconds. When a job is finished, pserver asks the NetWare server
|
||||
immediately for a new job, and does not wait
|
||||
.I timeout
|
||||
seconds.
|
||||
.RE
|
||||
|
||||
.B -d
|
||||
.RS 3
|
||||
Normally, pserver daemonizes itself.
|
||||
.B -d
|
||||
tells it not to do so. This is useful if you want to see the
|
||||
diagnostic messages that are printed when a error occurs.
|
||||
.RE
|
||||
|
||||
|
||||
.SH SEE ALSO
|
||||
.B nwclient(5), slist(1), pqlist(1), ncpmount(8), ncpumount(8)
|
||||
|
||||
.SH CREDITS
|
||||
pserver was written by Volker Lendecke (lendecke@namu01.gwdg.de)
|
||||
43
man/slist.1
Normal file
43
man/slist.1
Normal file
@@ -0,0 +1,43 @@
|
||||
.TH SLIST 1 01/07/1996 slist slist
|
||||
.SH NAME
|
||||
slist \- Lists available NetWare Servers
|
||||
.SH SYNOPSIS
|
||||
.B slist
|
||||
[
|
||||
.I pattern
|
||||
]
|
||||
.SH DESCRIPTION
|
||||
.B slist
|
||||
lists all NetWare Servers available in your network.
|
||||
|
||||
If slist does not print to a tty, the decorative header line is not
|
||||
printed, so that you can count the servers on your network by doing
|
||||
|
||||
slist | wc -l
|
||||
|
||||
|
||||
.SH OPTIONS
|
||||
.B pattern
|
||||
.RS 3
|
||||
.B pattern
|
||||
is used to list only servers whose names match the specified pattern. For a
|
||||
server to be listed, the pattern must match the full server name. You can use
|
||||
wildcards for the pattern, but you must protect these wildcards from any
|
||||
command line expansion by quoting. Case doesn't matter.
|
||||
.RE
|
||||
|
||||
.SH EXAMPLE
|
||||
.TP
|
||||
slist "I*"
|
||||
.TP
|
||||
or
|
||||
.TP
|
||||
slist "i*"
|
||||
List all available Netware servers on your Network, that begin with an "I".
|
||||
|
||||
|
||||
.SH SEE ALSO
|
||||
.B ncpmount(8), ncpumount(8), pqlist(1), nprint(1)
|
||||
|
||||
.SH CREDITS
|
||||
slist was written by Volker Lendecke (lendecke@namu01.gwdg.de)
|
||||
@@ -1,14 +1,17 @@
|
||||
Begin3
|
||||
Title: ncpfs
|
||||
Version: 0.5
|
||||
Entered-date: 17. November 1995
|
||||
Version: 0.15
|
||||
Entered-date: 10. February 1996
|
||||
Description: With ncpfs you can mount volumes of your novell
|
||||
server under Linux.
|
||||
server under Linux. You need kernel 1.2.x or
|
||||
1.3.54 and above. ncpfs does NOT work with any 1.3.x
|
||||
kernel below 1.3.54.
|
||||
Keywords: filesystem kernel ncp novell netware
|
||||
Author: lendecke@namu01.gwdg.de (Volker Lendecke)
|
||||
Maintained-by: lendecke@namu01.gwdg.de (Volker Lendecke)
|
||||
Primary-site: linux01.gwdg.de:/pub/ncpfs
|
||||
~50k ncpfs-0.5.tgz
|
||||
~ 1k ncpfs-0.5.lsm
|
||||
Alternate-site: sunsite.unc.edu:/pub/system/Filesystems/
|
||||
~70k ncpfs-0.15.tgz
|
||||
~ 1k ncpfs-0.15.lsm
|
||||
Copying-policy: GPL
|
||||
End
|
||||
1079
ncplib_user.c
1079
ncplib_user.c
File diff suppressed because it is too large
Load Diff
168
ncplib_user.h
168
ncplib_user.h
@@ -1,168 +0,0 @@
|
||||
#ifndef _NCPLIB_H
|
||||
#define _NCPLIB_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/ncp.h>
|
||||
#include <linux/ncp_fs.h>
|
||||
|
||||
struct ncp_server {
|
||||
int current_size;
|
||||
int has_subfunction;
|
||||
int mount_fid;
|
||||
int silent;
|
||||
int ncp_reply_size;
|
||||
char *packet;
|
||||
int lock;
|
||||
|
||||
char ncp_data[NCP_PACKET_SIZE];
|
||||
};
|
||||
|
||||
#include <linux/ncp.h>
|
||||
|
||||
int
|
||||
ncp_negotiate_buffersize(struct ncp_server *server, int size,
|
||||
int *target);
|
||||
int
|
||||
ncp_get_encryption_key(struct ncp_server *server,
|
||||
char *target);
|
||||
int
|
||||
ncp_get_bindery_object_id(struct ncp_server *server,
|
||||
int object_type, char *object_name,
|
||||
struct ncp_bindery_object *target);
|
||||
int
|
||||
ncp_read_property_value(struct ncp_server *server,
|
||||
int object_type, char *object_name,
|
||||
int segment, char *prop_name,
|
||||
struct nw_property *target);
|
||||
int
|
||||
ncp_login_encrypted(struct ncp_server *server,
|
||||
struct ncp_bindery_object *object,
|
||||
unsigned char *key,
|
||||
unsigned char *passwd);
|
||||
int
|
||||
ncp_login_user(struct ncp_server *server,
|
||||
unsigned char *username,
|
||||
unsigned char *password);
|
||||
int
|
||||
ncp_get_volume_info_with_number(struct ncp_server *server, int n,
|
||||
struct ncp_volume_info *target);
|
||||
|
||||
int
|
||||
ncp_get_volume_number(struct ncp_server *server, const char *name,
|
||||
int *target);
|
||||
|
||||
int
|
||||
ncp_file_search_init(struct ncp_server *server,
|
||||
int dir_handle, const char *path,
|
||||
struct ncp_filesearch_info *target);
|
||||
|
||||
int
|
||||
ncp_file_search_continue(struct ncp_server *server,
|
||||
struct ncp_filesearch_info *fsinfo,
|
||||
int attributes, const char *path,
|
||||
struct ncp_file_info *target);
|
||||
|
||||
int
|
||||
ncp_get_finfo(struct ncp_server *server,
|
||||
int dir_handle, const char *path, const char *name,
|
||||
struct ncp_file_info *target);
|
||||
|
||||
int
|
||||
ncp_open_file(struct ncp_server *server,
|
||||
int dir_handle, const char *path,
|
||||
int attr, int access,
|
||||
struct ncp_file_info *target);
|
||||
int
|
||||
ncp_close_file(struct ncp_server *server, const char *file_id);
|
||||
|
||||
int
|
||||
ncp_create_newfile(struct ncp_server *server,
|
||||
int dir_handle, const char *path,
|
||||
int attr,
|
||||
struct ncp_file_info *target);
|
||||
|
||||
int
|
||||
ncp_create_file(struct ncp_server *server,
|
||||
int dir_handle, const char *path,
|
||||
int attr,
|
||||
struct ncp_file_info *target);
|
||||
|
||||
int
|
||||
ncp_erase_file(struct ncp_server *server,
|
||||
int dir_handle, const char *path,
|
||||
int attr);
|
||||
|
||||
int
|
||||
ncp_rename_file(struct ncp_server *server,
|
||||
int old_handle, const char *old_path,
|
||||
int attr,
|
||||
int new_handle, const char *new_path);
|
||||
|
||||
int
|
||||
ncp_create_directory(struct ncp_server *server,
|
||||
int dir_handle, const char *path,
|
||||
int inherit_mask);
|
||||
|
||||
int
|
||||
ncp_delete_directory(struct ncp_server *server,
|
||||
int dir_handle, const char *path);
|
||||
|
||||
int
|
||||
ncp_rename_directory(struct ncp_server *server,
|
||||
int dir_handle,
|
||||
const char *old_path, const char *new_path);
|
||||
|
||||
int
|
||||
ncp_read(struct ncp_server *server, const char *file_id,
|
||||
__u32 offset, __u16 to_read,
|
||||
char *target, int *bytes_read);
|
||||
|
||||
int
|
||||
ncp_write(struct ncp_server *server, const char *file_id,
|
||||
__u32 offset, __u16 to_write,
|
||||
const char *source, int *bytes_written);
|
||||
|
||||
int
|
||||
ncp_do_lookup(struct ncp_server *server,
|
||||
struct nw_info_struct *dir,
|
||||
char *path, /* may only be one component */
|
||||
struct nw_info_struct *target);
|
||||
|
||||
int
|
||||
ncp_del_file_or_subdir(struct ncp_server *server,
|
||||
struct nw_info_struct *dir, char *name);
|
||||
|
||||
int
|
||||
ncp_open_create_file_or_subdir(struct ncp_server *server,
|
||||
struct nw_info_struct *dir, char *name,
|
||||
int open_create_mode,
|
||||
__u32 create_attributes,
|
||||
int desired_acc_rights,
|
||||
struct nw_file_info *target);
|
||||
|
||||
int
|
||||
ncp_initialize_search(struct ncp_server *server,
|
||||
struct nw_info_struct *dir,
|
||||
struct nw_search_sequence *target);
|
||||
|
||||
int
|
||||
ncp_search_for_file_or_subdir(struct ncp_server *server,
|
||||
struct nw_search_sequence *seq,
|
||||
struct nw_info_struct *target);
|
||||
|
||||
int
|
||||
ncp_ren_or_mov_file_or_subdir(struct ncp_server *server,
|
||||
struct nw_info_struct *old_dir, char *old_name,
|
||||
struct nw_info_struct *new_dir, char *new_name);
|
||||
|
||||
int
|
||||
ncp_create_queue_job_and_file(struct ncp_server *server,
|
||||
__u32 queue_id,
|
||||
struct queue_job *job);
|
||||
|
||||
int
|
||||
ncp_close_file_and_start_job(struct ncp_server *server,
|
||||
__u32 queue_id,
|
||||
struct queue_job *job);
|
||||
|
||||
#endif /* _NCPLIB_H */
|
||||
696
ncpmount.c
696
ncpmount.c
@@ -1,696 +0,0 @@
|
||||
/*
|
||||
* ncpmount.c
|
||||
*
|
||||
* Copyright (C) 1995 by Volker Lendecke
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/param.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
/* #include <sys/wait.h> */ /* generates a warning here */
|
||||
extern pid_t waitpid(pid_t, int *, int);
|
||||
#include <sys/errno.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/mount.h>
|
||||
#include <mntent.h>
|
||||
#include <linux/ipx.h>
|
||||
|
||||
#include <linux/fs.h>
|
||||
#include <linux/ncp.h>
|
||||
#include <linux/ncp_fs.h>
|
||||
#include <linux/ncp_mount.h>
|
||||
#include "ipxutil.h"
|
||||
#include "ncplib_user.h"
|
||||
|
||||
static char *progname;
|
||||
|
||||
|
||||
static void
|
||||
str_upper(char *name)
|
||||
{
|
||||
while (*name) {
|
||||
*name = toupper(*name);
|
||||
name = name + 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
printf("usage: %s server mount-point [options]\n", progname);
|
||||
printf("Try `%s -h' for more information\n", progname);
|
||||
}
|
||||
|
||||
static void
|
||||
help(void)
|
||||
{
|
||||
printf("\n");
|
||||
printf("usage: %s server mount-point [options]\n", progname);
|
||||
printf("\n"
|
||||
"-U username Username sent to server\n"
|
||||
"-u uid uid the mounted files get\n"
|
||||
"-g gid gid the mounted files get\n"
|
||||
"-f mode permission the files get (octal notation)\n"
|
||||
"-d mode permission the dirs get (octal notation)\n"
|
||||
"-C Don't convert password to uppercase\n"
|
||||
"-P password Use this password\n"
|
||||
"-n Do not use any password\n"
|
||||
" If neither -P nor -n are given, you are\n"
|
||||
" asked for a password.\n"
|
||||
"-h print this help text\n"
|
||||
"\n");
|
||||
}
|
||||
|
||||
struct sap_query {
|
||||
unsigned short query_type; /* net order */
|
||||
unsigned short server_type; /* net order */
|
||||
};
|
||||
|
||||
struct sap_server_ident {
|
||||
unsigned short server_type __attribute__ ((packed));
|
||||
char server_name[48] __attribute__ ((packed));
|
||||
IPXNet server_network __attribute__ ((packed));
|
||||
IPXNode server_node __attribute__ ((packed));
|
||||
IPXPort server_port __attribute__ ((packed));
|
||||
unsigned short intermediate_network __attribute__ ((packed));
|
||||
};
|
||||
|
||||
void
|
||||
ipx_fprint_node(FILE* file,IPXNode node)
|
||||
{
|
||||
fprintf(file,"%02X%02X%02X%02X%02X%02X",
|
||||
(unsigned char)node[0],
|
||||
(unsigned char)node[1],
|
||||
(unsigned char)node[2],
|
||||
(unsigned char)node[3],
|
||||
(unsigned char)node[4],
|
||||
(unsigned char)node[5]
|
||||
);
|
||||
}
|
||||
|
||||
void
|
||||
ipx_fprint_network(FILE* file,IPXNet net)
|
||||
{
|
||||
fprintf(file,"%08lX",ntohl(net));
|
||||
}
|
||||
|
||||
void
|
||||
ipx_fprint_port(FILE* file,IPXPort port)
|
||||
{
|
||||
fprintf(file,"%04X",ntohs(port));
|
||||
}
|
||||
|
||||
void
|
||||
ipx_fprint_saddr(FILE* file,struct sockaddr_ipx* sipx)
|
||||
{
|
||||
ipx_fprint_network(file,sipx->sipx_network);
|
||||
fprintf(file,":");
|
||||
ipx_fprint_node(file,sipx->sipx_node);
|
||||
fprintf(file,":");
|
||||
ipx_fprint_port(file,sipx->sipx_port);
|
||||
}
|
||||
|
||||
void
|
||||
ipx_print_node(IPXNode node)
|
||||
{
|
||||
ipx_fprint_node(stdout,node);
|
||||
}
|
||||
|
||||
void
|
||||
ipx_print_network(IPXNet net)
|
||||
{
|
||||
ipx_fprint_network(stdout,net);
|
||||
}
|
||||
|
||||
void
|
||||
ipx_print_port(IPXPort port)
|
||||
{
|
||||
ipx_fprint_port(stdout,port);
|
||||
}
|
||||
|
||||
void
|
||||
ipx_print_saddr(struct sockaddr_ipx* sipx)
|
||||
{
|
||||
ipx_fprint_saddr(stdout,sipx);
|
||||
}
|
||||
|
||||
int
|
||||
ipx_sap_find_server(char *name, int server_type, int timeout,
|
||||
struct sockaddr_ipx *result)
|
||||
{
|
||||
struct sockaddr_ipx ipxs;
|
||||
char data[1024];
|
||||
int sock;
|
||||
int opt;
|
||||
int res = -1;
|
||||
int name_len = strlen(name);
|
||||
fd_set rd, wr, ex;
|
||||
struct timeval tv;
|
||||
int packets;
|
||||
|
||||
if (name_len > 48) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
sock=socket(AF_IPX,SOCK_DGRAM,PF_IPX);
|
||||
if (sock==-1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
opt=1;
|
||||
/* Permit broadcast output */
|
||||
if(setsockopt(sock,SOL_SOCKET,SO_BROADCAST, &opt,sizeof(opt))==-1)
|
||||
{
|
||||
perror("setsockopt");
|
||||
goto finished;
|
||||
}
|
||||
|
||||
memset(&ipxs, 0, sizeof(ipxs));
|
||||
ipxs.sipx_family=AF_IPX;
|
||||
ipxs.sipx_network=htonl(0x0);
|
||||
ipxs.sipx_port=htons(0x0);
|
||||
ipxs.sipx_type=IPX_SAP_PTYPE;
|
||||
|
||||
if(bind(sock,(struct sockaddr*)&ipxs,sizeof(ipxs))==-1)
|
||||
{
|
||||
perror("bind");
|
||||
goto finished;
|
||||
}
|
||||
|
||||
*(unsigned short *)data = htons(0x0001);
|
||||
*(unsigned short *)&(data[2]) = htons(server_type);
|
||||
|
||||
memset(&ipxs, 0, sizeof(ipxs));
|
||||
ipxs.sipx_family=AF_IPX;
|
||||
ipxs.sipx_network=htonl(0x0);
|
||||
ipx_assign_node(ipxs.sipx_node, IPX_BROADCAST_NODE);
|
||||
ipxs.sipx_port=htons(IPX_SAP_PORT);
|
||||
ipxs.sipx_type=IPX_SAP_PTYPE;
|
||||
|
||||
if (sendto(sock, data, 4, 0,
|
||||
(struct sockaddr *)&ipxs, sizeof(ipxs)) < 0) {
|
||||
perror("sendto");
|
||||
goto finished;
|
||||
}
|
||||
|
||||
packets = 10;
|
||||
while (packets > 0) {
|
||||
|
||||
packets -= 1;
|
||||
|
||||
FD_ZERO(&rd); FD_ZERO(&wr); FD_ZERO(&ex);
|
||||
FD_SET(sock, &rd);
|
||||
|
||||
tv.tv_sec = timeout;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
if (select(sock+1, &rd, &wr, &ex, &tv) == -1) {
|
||||
perror("select");
|
||||
goto finished;
|
||||
}
|
||||
|
||||
if (FD_ISSET(sock, &rd)) {
|
||||
int len = recv(sock, data, 1024, 0);
|
||||
int i;
|
||||
struct sap_server_ident *ident;
|
||||
|
||||
for (i = 2; i < len; i += 64) {
|
||||
ident = (struct sap_server_ident *)(data+i);
|
||||
if ( (strncmp(name,ident->server_name,
|
||||
name_len)==0)
|
||||
&& (name_len < 48)
|
||||
&& (ident->server_name[name_len] == '\0'))
|
||||
{
|
||||
result->sipx_family = AF_IPX;
|
||||
result->sipx_network =
|
||||
ident->server_network;
|
||||
result->sipx_port = ident->server_port;
|
||||
ipx_assign_node(result->sipx_node,
|
||||
ident->server_node);
|
||||
res = 0;
|
||||
goto finished;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("nobody answered, server %s not found\n",
|
||||
name);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
finished:
|
||||
close(sock);
|
||||
return res;
|
||||
}
|
||||
|
||||
int
|
||||
ipx_sscanf_node(char *buf, unsigned char node[6])
|
||||
{
|
||||
int i;
|
||||
int n[6];
|
||||
|
||||
if ((i = sscanf(buf, "%2x%2x%2x%2x%2x%2x",
|
||||
&(n[0]), &(n[1]), &(n[2]),
|
||||
&(n[3]), &(n[4]), &(n[5]))) != 6) {
|
||||
return i;
|
||||
}
|
||||
|
||||
for (i=0; i<6; i++) {
|
||||
node[i] = n[i];
|
||||
}
|
||||
return 6;
|
||||
}
|
||||
|
||||
static int
|
||||
parse_args(int argc, char *argv[], struct ncp_mount_data *data,
|
||||
int *got_password, int *upcase_password)
|
||||
{
|
||||
int opt;
|
||||
struct passwd *pwd;
|
||||
struct group *grp;
|
||||
|
||||
*got_password = 0;
|
||||
*upcase_password = 1;
|
||||
|
||||
while ((opt = getopt (argc, argv, "Cp:s:c:U:u:g:f:d:m:P:n")) != EOF) {
|
||||
switch (opt) {
|
||||
case 'C':
|
||||
*upcase_password = 0;
|
||||
break;
|
||||
case 'U':
|
||||
if (strlen(optarg) > 63) {
|
||||
fprintf(stderr, "Username too long: %s\n",
|
||||
optarg);
|
||||
return 1;
|
||||
}
|
||||
strcpy(data->username, optarg);
|
||||
break;
|
||||
case 'u':
|
||||
if (isdigit(optarg[0])) {
|
||||
data->uid = atoi(optarg);
|
||||
} else {
|
||||
pwd = getpwnam(optarg);
|
||||
if (pwd == NULL) {
|
||||
fprintf(stderr, "Unknown user: %s\n",
|
||||
optarg);
|
||||
return 1;
|
||||
}
|
||||
data->uid = pwd->pw_uid;
|
||||
}
|
||||
break;
|
||||
case 'g':
|
||||
if (isdigit(optarg[0])) {
|
||||
data->gid = atoi(optarg);
|
||||
} else {
|
||||
grp = getgrnam(optarg);
|
||||
if (grp == NULL) {
|
||||
fprintf(stderr, "Unknown group: %s\n",
|
||||
optarg);
|
||||
return 1;
|
||||
}
|
||||
data->gid = grp->gr_gid;
|
||||
}
|
||||
break;
|
||||
case 'f':
|
||||
data->file_mode = strtol(optarg, NULL, 8);
|
||||
break;
|
||||
case 'd':
|
||||
data->dir_mode = strtol(optarg, NULL, 8);
|
||||
break;
|
||||
case 'P':
|
||||
strcpy(data->password, optarg);
|
||||
*got_password = 1;
|
||||
break;
|
||||
case 'n':
|
||||
data->password[0] = '\0';
|
||||
*got_password = 1;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
/* Returns 0 if the filesystem is in the kernel after this routine
|
||||
completes */
|
||||
static int
|
||||
load_ncpfs()
|
||||
{
|
||||
FILE *fver, *ffs;
|
||||
char s[1024];
|
||||
char modname[1024];
|
||||
char *p, *p1;
|
||||
pid_t pid;
|
||||
int status;
|
||||
|
||||
/* Check if ncpfs is in the kernel */
|
||||
ffs = fopen("/proc/filesystems", "r");
|
||||
if (ffs == NULL) {
|
||||
perror("Error: \"/proc/filesystems\" could not be read:");
|
||||
return -1;
|
||||
}
|
||||
p = NULL;
|
||||
while (! feof(ffs)) {
|
||||
p1 = fgets(s, sizeof(s), ffs);
|
||||
if (p1) {
|
||||
p = strstr(s, "ncpfs");
|
||||
if (p) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(ffs);
|
||||
if (p) {
|
||||
return 0;
|
||||
}
|
||||
fver = fopen("/proc/version", "r");
|
||||
if (fver == NULL) {
|
||||
perror("Error: \"/proc/version\" could not be read:");
|
||||
return -1;
|
||||
}
|
||||
fgets(s, 1024, fver);
|
||||
fclose(fver);
|
||||
p = strstr(s, "version ");
|
||||
if (p == NULL) {
|
||||
version_error:
|
||||
fprintf(stderr, "Error: Unable to determine the Linux version"
|
||||
"from \"/proc/version\n");
|
||||
return -1;
|
||||
}
|
||||
p = strchr(p, ' ') + 1;
|
||||
p1 = strchr(p, ' ');
|
||||
if (p1 == NULL) {
|
||||
goto version_error;
|
||||
}
|
||||
strcpy(modname, "/lib/modules/");
|
||||
strncat(modname, p, p1 - p);
|
||||
strcat(modname, "/ncpfs.o");
|
||||
|
||||
/* system() function without signal handling, from Stevens */
|
||||
|
||||
if ((pid = fork()) < 0) {
|
||||
return 1;
|
||||
} else if (pid == 0) {
|
||||
/* child */
|
||||
execl("/sbin/insmod", "insmod", modname, NULL);
|
||||
_exit(127); /* execl error */
|
||||
} else {
|
||||
/* parent */
|
||||
while (waitpid(pid, &status, 0) < 0) {
|
||||
if (errno != EINTR) {
|
||||
status = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Check whether user is allowed to mount on the specified mount point */
|
||||
static int
|
||||
mount_ok(struct stat *st)
|
||||
{
|
||||
if (!S_ISDIR(st->st_mode))
|
||||
{
|
||||
errno = ENOTDIR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( (getuid() != 0)
|
||||
&& ( (getuid() != st->st_uid)
|
||||
|| ((st->st_mode & S_IRWXU) != S_IRWXU)))
|
||||
{
|
||||
errno = EPERM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
struct ncp_mount_data data;
|
||||
struct sockaddr_ipx addr;
|
||||
struct stat st;
|
||||
struct ncp_server serv;
|
||||
struct ncp_server *server = &serv;
|
||||
|
||||
int fd;
|
||||
int Got_Password;
|
||||
int Upcase_Password;
|
||||
int um;
|
||||
unsigned int flags;
|
||||
char hostname[MAXHOSTNAMELEN + 1];
|
||||
|
||||
char *server_name;
|
||||
char mount_point[MAXPATHLEN];
|
||||
|
||||
struct mntent ment;
|
||||
FILE *mtab;
|
||||
|
||||
int ncp_sock, wdog_sock;
|
||||
|
||||
progname = argv[0];
|
||||
|
||||
if (geteuid() != 0) {
|
||||
fprintf(stderr, "%s must be installed suid root\n", progname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
memset(&data, 0, sizeof(struct ncp_mount_data));
|
||||
|
||||
memset(hostname, '\0', MAXHOSTNAMELEN+1);
|
||||
gethostname(hostname, MAXHOSTNAMELEN);
|
||||
|
||||
if (argc < 3) {
|
||||
if ( (argc == 2)
|
||||
&& (argv[1][0] == '-')
|
||||
&& (argv[1][1] == 'h')
|
||||
&& (argv[1][2] == '\0')) {
|
||||
|
||||
help();
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
server_name = argv[1];
|
||||
str_upper(server_name);
|
||||
|
||||
realpath(argv[2], mount_point);
|
||||
|
||||
argv += 2;
|
||||
argc -= 2;
|
||||
|
||||
if (stat(mount_point, &st) == -1) {
|
||||
fprintf(stderr, "could not find mount point %s: %s\n",
|
||||
mount_point, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (mount_ok(&st) != 0) {
|
||||
fprintf(stderr, "cannot to mount on %s: %s\n",
|
||||
mount_point, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ncp_sock = socket(AF_IPX, SOCK_DGRAM, PF_IPX);
|
||||
if (ncp_sock == -1) {
|
||||
fprintf(stderr, "could not open ncp socket: %s\n",
|
||||
strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
wdog_sock = socket(AF_IPX, SOCK_DGRAM, PF_IPX);
|
||||
if (wdog_sock == -1) {
|
||||
fprintf(stderr, "could not open wdog socket: %s\n",
|
||||
strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
addr.sipx_type = NCP_PTYPE;
|
||||
|
||||
if (bind(ncp_sock, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
|
||||
fprintf(stderr, "bind(ncp_sock, ): %s\n",
|
||||
strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (bind(wdog_sock, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
|
||||
fprintf(stderr, "bind(wdog_sock, ): %s\n",
|
||||
strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (ipx_sap_find_server(server_name, IPX_SAP_FILE_SERVER,
|
||||
3, &addr) != 0) {
|
||||
fprintf(stderr, "could not find server %s\n", server_name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Check if the ncpfs filesystem is in the kernel. If not, attempt
|
||||
* to load the ncpfs module */
|
||||
if (load_ncpfs() != 0) {
|
||||
fprintf(stderr, "Error: Unable to start ncpfs, exiting...\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
data.version = NCP_MOUNT_VERSION;
|
||||
data.ncp_fd = ncp_sock;
|
||||
data.wdog_fd = wdog_sock;
|
||||
data.mounted_uid = getuid();
|
||||
data.serv_addr = addr;
|
||||
strcpy(data.server_name, server_name);
|
||||
data.time_out = 20; /* 2 seconds */
|
||||
data.retry_count = 2;
|
||||
|
||||
/* getuid() gives us the real uid, who may umount the fs */
|
||||
data.mounted_uid = getuid();
|
||||
|
||||
if (getenv("USER")) {
|
||||
strcpy(data.username, getenv("USER"));
|
||||
str_upper(data.username);
|
||||
}
|
||||
|
||||
if (data.username[0] == 0 && getenv("LOGNAME"))
|
||||
{
|
||||
strcpy(data.username,getenv("LOGNAME"));
|
||||
str_upper(data.username);
|
||||
}
|
||||
|
||||
data.uid = getuid();
|
||||
data.gid = getgid();
|
||||
um = umask(0);
|
||||
umask(um);
|
||||
data.file_mode = (S_IRWXU|S_IRWXG|S_IRWXO) & ~um;
|
||||
data.dir_mode = 0;
|
||||
|
||||
if (parse_args(argc, argv, &data, &Got_Password,
|
||||
&Upcase_Password) != 0) {
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (data.dir_mode == 0) {
|
||||
data.dir_mode = data.file_mode;
|
||||
if ((data.dir_mode & S_IRUSR) != 0)
|
||||
data.dir_mode |= S_IXUSR;
|
||||
if ((data.dir_mode & S_IRGRP) != 0)
|
||||
data.dir_mode |= S_IXGRP;
|
||||
if ((data.dir_mode & S_IROTH) != 0)
|
||||
data.dir_mode |= S_IXOTH;
|
||||
}
|
||||
|
||||
if (Got_Password == 0) {
|
||||
strcpy(data.password, getpass("Password: "));
|
||||
}
|
||||
|
||||
if (Upcase_Password == 1) {
|
||||
str_upper(data.password);
|
||||
}
|
||||
|
||||
if (data.server_name[0] == '\0') {
|
||||
strcpy(data.server_name, server_name);
|
||||
str_upper(data.server_name);
|
||||
}
|
||||
|
||||
flags = MS_MGC_VAL;
|
||||
|
||||
if (mount(NULL, mount_point, "ncpfs",
|
||||
flags, (char *)&data) < 0) {
|
||||
printf("mount failed\n");
|
||||
close(wdog_sock);
|
||||
close(ncp_sock);
|
||||
printf("Maybe you have no route to the internal net "
|
||||
"of your server.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
close(ncp_sock);
|
||||
close(wdog_sock);
|
||||
|
||||
server->mount_fid = open(mount_point, O_RDONLY, 0);
|
||||
server->silent = 1;
|
||||
|
||||
if (server->mount_fid == -1) {
|
||||
fprintf(stderr, "Could not open %s: %s\n",
|
||||
mount_point, strerror(errno));
|
||||
umount(mount_point);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ncp_login_user(server, data.username, data.password) != 0) {
|
||||
fprintf(stderr, "login failed\n");
|
||||
fprintf(stderr,
|
||||
"should try to type the username and\n"
|
||||
"password in UPPERCASE.\n");
|
||||
close(server->mount_fid);
|
||||
umount(mount_point);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ment.mnt_fsname = server_name;
|
||||
ment.mnt_dir = mount_point;
|
||||
ment.mnt_type = "ncpfs";
|
||||
ment.mnt_opts = "rw";
|
||||
ment.mnt_freq = 0;
|
||||
ment.mnt_passno= 0;
|
||||
|
||||
if ((fd = open(MOUNTED"~", O_RDWR|O_CREAT|O_EXCL, 0600)) == -1)
|
||||
{
|
||||
fprintf(stderr, "Can't get "MOUNTED"~ lock file");
|
||||
return 1;
|
||||
}
|
||||
close(fd);
|
||||
|
||||
if ((mtab = setmntent(MOUNTED, "a+")) == NULL)
|
||||
{
|
||||
fprintf(stderr, "Can't open " MOUNTED);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (addmntent(mtab, &ment) == 1)
|
||||
{
|
||||
fprintf(stderr, "Can't write mount entry");
|
||||
return 1;
|
||||
}
|
||||
if (fchmod(fileno(mtab), 0644) == -1)
|
||||
{
|
||||
fprintf(stderr, "Can't set perms on "MOUNTED);
|
||||
return 1;
|
||||
}
|
||||
endmntent(mtab);
|
||||
|
||||
if (unlink(MOUNTED"~") == -1)
|
||||
{
|
||||
fprintf(stderr, "Can't remove "MOUNTED"~");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
407
ncptest.c
407
ncptest.c
@@ -1,407 +0,0 @@
|
||||
/*
|
||||
* ncptest.c
|
||||
*
|
||||
* Copyright (C) 1995 by Volker Lendecke
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/param.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
/* #include <sys/wait.h> */ /* generates a warning here */
|
||||
extern pid_t waitpid(pid_t, int *, int);
|
||||
#include <sys/errno.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/mount.h>
|
||||
#include <mntent.h>
|
||||
#include <linux/ipx.h>
|
||||
|
||||
#include <linux/fs.h>
|
||||
#include <linux/ncp.h>
|
||||
#include <linux/ncp_fs.h>
|
||||
#include <linux/ncp_mount.h>
|
||||
#include "ncplib_user.h"
|
||||
#include "ipxutil.h"
|
||||
|
||||
static char *progname;
|
||||
static char *mount_point;
|
||||
|
||||
void
|
||||
test_filesearch(struct ncp_server *server)
|
||||
{
|
||||
struct ncp_filesearch_info fsinfo;
|
||||
struct ncp_file_info finfo;
|
||||
|
||||
if (ncp_file_search_init(server, 0, "sys:\\public", &fsinfo) != 0) {
|
||||
printf("could not fs init\n");
|
||||
return;
|
||||
}
|
||||
|
||||
while (ncp_file_search_continue(server, &fsinfo,
|
||||
0,
|
||||
"*", &finfo) == 0) {
|
||||
printf("name: %s\n", finfo.file_name);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
test_getfinfo(struct ncp_server *server)
|
||||
{
|
||||
struct ncp_file_info finfo;
|
||||
|
||||
ncp_get_finfo(server, 0, "sys:", "public", &finfo);
|
||||
ncp_get_finfo(server, 0, "sys:login", "login.exe", &finfo);
|
||||
}
|
||||
|
||||
void
|
||||
testopen(struct ncp_server *server)
|
||||
{
|
||||
struct ncp_file_info finfo;
|
||||
char buf[1025];
|
||||
int bytes_read;
|
||||
|
||||
ncp_open_file(server, 0, "sys:\\etc\\samples\\protocol", 0,
|
||||
AR_READ|AR_WRITE,
|
||||
&finfo);
|
||||
if (ncp_read(server, finfo.file_id, 0, 1024, buf, &bytes_read) == 0) {
|
||||
printf("bytes: %d\n", bytes_read);
|
||||
buf[bytes_read]=0;
|
||||
puts(buf);
|
||||
}
|
||||
|
||||
ncp_close_file(server, finfo.file_id);
|
||||
}
|
||||
|
||||
void
|
||||
testcreate(struct ncp_server *server)
|
||||
{
|
||||
|
||||
if (ncp_rename_file(server, 0, "sys:\\me\\blub.txt", 0,
|
||||
0, "sys:\\me\\blub1.txt") != 0) {
|
||||
printf("create war nix\n");
|
||||
}
|
||||
if (ncp_create_directory(server, 0, "sys:\\me\\blubdir", 0xff) != 0) {
|
||||
printf("mkdir war nix\n");
|
||||
}
|
||||
if (ncp_rename_directory(server, 0, "sys:\\me\\blubdir",
|
||||
"\\me\\blubneu") != 0) {
|
||||
printf("mvdir war nix\n");
|
||||
return;
|
||||
}
|
||||
if (ncp_delete_directory(server, 0, "sys:\\me\\blubneu") != 0) {
|
||||
printf("rmdir war nix\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
test_lookup(struct ncp_server *server)
|
||||
{
|
||||
struct nw_info_struct sys;
|
||||
struct nw_info_struct me;
|
||||
struct nw_file_info blub;
|
||||
|
||||
if (ncp_do_lookup(server, NULL, "SYS", &sys) != 0) {
|
||||
printf("lookup error\n");
|
||||
return;
|
||||
}
|
||||
if (ncp_do_lookup(server, &sys, "ME", &me) != 0) {
|
||||
printf("lookup error\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (ncp_open_create_file_or_subdir(server, &me, "BLUB.TXT",
|
||||
OC_MODE_CREATE, 0, 0xffff,
|
||||
&blub) != 0) {
|
||||
printf("open error\n");
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
test_trunc(struct ncp_server *server)
|
||||
{
|
||||
struct nw_info_struct sys;
|
||||
struct nw_info_struct me;
|
||||
struct nw_file_info blub;
|
||||
int written;
|
||||
|
||||
if (ncp_do_lookup(server, NULL, "SYS", &sys) != 0) {
|
||||
printf("lookup error\n");
|
||||
return;
|
||||
}
|
||||
if (ncp_do_lookup(server, &sys, "ME", &me) != 0) {
|
||||
printf("lookup error\n");
|
||||
return;
|
||||
}
|
||||
if (ncp_do_lookup(server, &me, "BLUB.TXT", &(blub.i)) != 0) {
|
||||
printf("lookup error\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (ncp_open_create_file_or_subdir(server, &(blub.i), NULL,
|
||||
OC_MODE_OPEN, 0, AR_READ | AR_WRITE,
|
||||
&blub) != 0) {
|
||||
printf("open error\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (ncp_write(server, blub.file_handle, 4, 0, "", &written) != 0) {
|
||||
printf("trunc error\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (ncp_close_file(server, blub.file_handle) != 0) {
|
||||
printf("close error\n");
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
test_ls(struct ncp_server *server)
|
||||
{
|
||||
struct nw_info_struct sys;
|
||||
struct nw_search_sequence seq;
|
||||
struct nw_info_struct found;
|
||||
int res;
|
||||
|
||||
if (ncp_do_lookup(server, NULL, "SYS", &sys) != 0) {
|
||||
printf("lookup error\n");
|
||||
return;
|
||||
}
|
||||
if (ncp_initialize_search(server, &sys, &seq) != 0) {
|
||||
printf("init error\n");
|
||||
return;
|
||||
}
|
||||
while ((res=ncp_search_for_file_or_subdir(server,&seq,&found)) == 0) {
|
||||
printf("found %s: %s\n",
|
||||
(found.attributes & aDIR) ? "dir " : "file",
|
||||
found.entryName);
|
||||
}
|
||||
|
||||
if (res == 0xfe) {
|
||||
printf("result: no more files\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("other error: %x\n", res);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
test_ren(struct ncp_server *server)
|
||||
{
|
||||
struct nw_info_struct sys;
|
||||
struct nw_info_struct me;
|
||||
|
||||
if (ncp_do_lookup(server, NULL, "SYS", &sys) != 0) {
|
||||
printf("lookup error\n");
|
||||
return;
|
||||
}
|
||||
if (ncp_do_lookup(server, &sys, "ME", &me) != 0) {
|
||||
printf("lookup error\n");
|
||||
return;
|
||||
}
|
||||
if (ncp_ren_or_mov_file_or_subdir(server, &me, "BLUB.TXT",
|
||||
&me, "BLUB1.TXT") != 0) {
|
||||
printf("ren error\n");
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
test_rm(struct ncp_server *server)
|
||||
{
|
||||
struct nw_info_struct sys;
|
||||
struct nw_info_struct me;
|
||||
|
||||
if (ncp_do_lookup(server, NULL, "SYS", &sys) != 0) {
|
||||
printf("lookup error\n");
|
||||
return;
|
||||
}
|
||||
if (ncp_do_lookup(server, &sys, "ME", &me) != 0) {
|
||||
printf("lookup error\n");
|
||||
return;
|
||||
}
|
||||
if (ncp_del_file_or_subdir(server, &me, "BLUB1.TXT") != 0) {
|
||||
printf("ren error\n");
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
test_mkdir(struct ncp_server *server)
|
||||
{
|
||||
struct nw_info_struct sys;
|
||||
struct nw_info_struct me;
|
||||
struct nw_file_info dir1;
|
||||
struct nw_file_info dir2;
|
||||
|
||||
|
||||
if (ncp_do_lookup(server, NULL, "SYS", &sys) != 0) {
|
||||
printf("lookup error\n");
|
||||
return;
|
||||
}
|
||||
if (ncp_do_lookup(server, &sys, "ME", &me) != 0) {
|
||||
printf("lookup error\n");
|
||||
return;
|
||||
}
|
||||
if (ncp_open_create_file_or_subdir(server, &me, "DIR1",
|
||||
OC_MODE_CREATE, aDIR, 0xffff, &dir1)
|
||||
!= 0) {
|
||||
printf("mkdir1 error\n");
|
||||
return;
|
||||
}
|
||||
if (ncp_open_create_file_or_subdir(server, &me, "DIR2",
|
||||
OC_MODE_CREATE, aDIR, 0xffff, &dir2)
|
||||
!= 0) {
|
||||
printf("mkdir2 error\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (ncp_del_file_or_subdir(server, &me, "DIR1") != 0) {
|
||||
printf("rmdir error\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
test_print(struct ncp_server *server)
|
||||
{
|
||||
struct ncp_bindery_object q;
|
||||
struct queue_job j;
|
||||
struct print_job_record pj;
|
||||
int written;
|
||||
|
||||
if (ncp_get_bindery_object_id(server, NCP_BINDERY_PQUEUE,
|
||||
"Q_DJ500", &q) != 0) {
|
||||
printf("get oid error\n");
|
||||
return;
|
||||
}
|
||||
|
||||
memset(&j, 0, sizeof(j));
|
||||
|
||||
j.j.TargetServerID = 0xffffffff; /* any server */
|
||||
memset(&(j.j.TargetExecTime), 0xff, sizeof(j.j.TargetExecTime)); /* at once */
|
||||
j.j.JobType = 0xffff;
|
||||
strcpy(j.j.JobTextDescription, "Test Job");
|
||||
|
||||
memset(&pj, 0, sizeof(pj));
|
||||
|
||||
pj.Version = 0;
|
||||
pj.TabSize = 0;
|
||||
pj.Copies = 1;
|
||||
pj.CtrlFlags = 0;
|
||||
pj.Lines = 0;
|
||||
pj.Rows = 0;
|
||||
strcpy(pj.FormName, "");
|
||||
strcpy(pj.Banner, "");
|
||||
strcpy(pj.FnameBanner, "");
|
||||
strcpy(pj.FnameHeader, "");
|
||||
strcpy(pj.Path, "");
|
||||
|
||||
memcpy(j.j.ClientRecordArea, &pj, sizeof(pj));
|
||||
|
||||
if (ncp_create_queue_job_and_file(server, q.object_id, &j) != 0) {
|
||||
printf("create error\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (ncp_write(server, j.file_handle, 0, 5, "hallo", &written) != 0) {
|
||||
printf("write error\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (ncp_close_file_and_start_job(server, q.object_id, &j) != 0) {
|
||||
printf("close error\n");
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
struct stat st;
|
||||
struct ncp_server serv;
|
||||
struct ncp_server *server = &serv;
|
||||
|
||||
|
||||
progname = argv[0];
|
||||
|
||||
if (geteuid() != 0) {
|
||||
fprintf(stderr, "%s must be installed suid root\n", progname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (argc == 2) {
|
||||
mount_point = argv[1];
|
||||
} else {
|
||||
fprintf(stderr, "usage: %s mount-point\n", progname);
|
||||
printf("defaulting to %s mnt\n", progname);
|
||||
mount_point = "mnt";
|
||||
}
|
||||
|
||||
|
||||
if (stat(mount_point, &st) == -1) {
|
||||
fprintf(stderr, "could not find mount point %s: %s\n",
|
||||
mount_point, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
server->mount_fid = open(mount_point, O_RDONLY, 0);
|
||||
server->silent = 0;
|
||||
|
||||
if (server->mount_fid == -1) {
|
||||
fprintf(stderr, "Could not open %s: %s\n",
|
||||
mount_point, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if 0
|
||||
for (i=0; i<5; i++) {
|
||||
struct ncp_volume_info info;
|
||||
ncp_get_volume_info_with_number(server, i, &info);
|
||||
printf("vol %d: %s\n", i, info.volume_name);
|
||||
}
|
||||
|
||||
test_filesearch(server);
|
||||
test_getfinfo(server);
|
||||
test_mkdir(server);
|
||||
test_ls(server);
|
||||
|
||||
#endif
|
||||
test_trunc(server);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
void
|
||||
shuffle(unsigned char *lon, const unsigned char *buf, int buflen,
|
||||
unsigned char *target);
|
||||
void
|
||||
nw_encrypt(unsigned char *fra,unsigned char *buf,unsigned char *til);
|
||||
47
util/Makefile
Normal file
47
util/Makefile
Normal file
@@ -0,0 +1,47 @@
|
||||
#
|
||||
# Makefile for the linux ncp-filesystem routines.
|
||||
#
|
||||
|
||||
UTIL_EXECS = ncpmount ncpumount nprint slist pqlist fsinfo pserver
|
||||
UTILS = $(addprefix $(INTERM_BINDIR)/,$(UTIL_EXECS))
|
||||
UIDUTILS = ncpmount ncpumount
|
||||
|
||||
#CFLAGS = -Wall $(INCLUDES) $(KERNELD) -g
|
||||
CFLAGS = -Wall $(INCLUDES) $(KERNELD) -O2
|
||||
CC = gcc
|
||||
|
||||
all: $(UTILS) ncptest
|
||||
|
||||
install: all
|
||||
for i in $(UTIL_EXECS); \
|
||||
do install --strip $(INTERM_BINDIR)/$$i -m 755 $(BINDIR); done
|
||||
for i in $(UIDUTILS); do chmod 4755 $(BINDIR)/$$i; done
|
||||
|
||||
$(UTILS): $(addsuffix .o,$(UTIL_EXECS)) ncplib.o
|
||||
$(CC) -o $@ $(addsuffix .o,$(notdir $@)) ncplib.o
|
||||
|
||||
ncplib.o: ncplib.c ncplib.h
|
||||
$(CC) $(CFLAGS) -finline-functions -c ncplib.c
|
||||
|
||||
test: test.o ncplib.o
|
||||
$(CC) -o test test.o ncplib.o
|
||||
|
||||
ncptest: ncptest.o ncplib.o
|
||||
$(CC) -o ncptest ncptest.o ncplib.o
|
||||
|
||||
dep:
|
||||
$(CPP) -M $(INCLUDES) *.c > .depend
|
||||
|
||||
clean:
|
||||
rm -f *.o *~ slist test ncptest
|
||||
|
||||
realclean: clean
|
||||
rm -f $(UTILS) .depend $(DISTFILE)
|
||||
|
||||
#
|
||||
# include a dependency file if one exists
|
||||
#
|
||||
ifeq (.depend,$(wildcard .depend))
|
||||
include .depend
|
||||
endif
|
||||
|
||||
78
util/fsinfo.c
Normal file
78
util/fsinfo.c
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* fsinfo.c
|
||||
*
|
||||
* Print the info strings of a server, maybe sometime more.
|
||||
*
|
||||
* Copyright (C) 1996 by Volker Lendecke
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include "ncplib.h"
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
struct ncp_conn conn;
|
||||
int opt;
|
||||
|
||||
if (ncp_initialize(&conn, &argc, argv, 0) != 0)
|
||||
{
|
||||
perror("Could not open connection");
|
||||
return 1;
|
||||
}
|
||||
|
||||
while ((opt = getopt(argc, argv, "dt")) != EOF)
|
||||
{
|
||||
switch(opt)
|
||||
{
|
||||
case 'd':
|
||||
{
|
||||
char strings[512];
|
||||
char *s;
|
||||
|
||||
if (ncp_get_file_server_description_strings(&conn,
|
||||
strings)
|
||||
!= 0)
|
||||
{
|
||||
perror("could not get strings");
|
||||
ncp_close(&conn);
|
||||
return 1;
|
||||
}
|
||||
|
||||
s = strings;
|
||||
while (s < strings+512)
|
||||
{
|
||||
if (strlen(s) == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
puts(s);
|
||||
s += strlen(s)+1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 't':
|
||||
{
|
||||
time_t t;
|
||||
|
||||
if (ncp_get_file_server_time(&conn, &t) != 0)
|
||||
{
|
||||
perror("could not get server time");
|
||||
ncp_close(&conn);
|
||||
return 1;
|
||||
}
|
||||
|
||||
fputs(ctime(&t), stdout);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
printf("unknown option: %c\n", opt);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ncp_close(&conn);
|
||||
return 0;
|
||||
}
|
||||
93
util/ipxlib.h
Normal file
93
util/ipxlib.h
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* ipxlib.h
|
||||
*
|
||||
* Copyright (C) 1995 by Volker Lendecke
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _IPXLIB_H
|
||||
#define _IPXLIB_H
|
||||
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/ncp.h>
|
||||
#include <linux/ncp_fs.h>
|
||||
#include <linux/ipx.h>
|
||||
#include <stdio.h>
|
||||
|
||||
typedef unsigned long IPXNet;
|
||||
typedef unsigned short IPXPort;
|
||||
typedef unsigned char IPXNode[IPX_NODE_LEN];
|
||||
|
||||
#define IPX_USER_PTYPE (0x00)
|
||||
#define IPX_RIP_PTYPE (0x01)
|
||||
#define IPX_SAP_PTYPE (0x04)
|
||||
#define IPX_AUTO_PORT (0x0000)
|
||||
#define IPX_SAP_PORT (0x0452)
|
||||
#define IPX_RIP_PORT (0x0453)
|
||||
|
||||
#define IPX_SAP_GENERAL_QUERY (0x0001)
|
||||
#define IPX_SAP_GENERAL_RESPONSE (0x0002)
|
||||
#define IPX_SAP_NEAREST_QUERY (0x0003)
|
||||
#define IPX_SAP_NEAREST_RESPONSE (0x0004)
|
||||
|
||||
#define IPX_SAP_FILE_SERVER (0x0004)
|
||||
|
||||
struct sap_query {
|
||||
unsigned short query_type; /* net order */
|
||||
unsigned short server_type; /* net order */
|
||||
};
|
||||
|
||||
struct sap_server_ident {
|
||||
unsigned short server_type __attribute__ ((packed));
|
||||
char server_name[48] __attribute__ ((packed));
|
||||
IPXNet server_network __attribute__ ((packed));
|
||||
IPXNode server_node __attribute__ ((packed));
|
||||
IPXPort server_port __attribute__ ((packed));
|
||||
unsigned short intermediate_network __attribute__ ((packed));
|
||||
};
|
||||
|
||||
#define IPX_RIP_REQUEST (0x1)
|
||||
#define IPX_RIP_RESPONSE (0x2)
|
||||
|
||||
struct ipx_rip_packet {
|
||||
__u16 operation __attribute__ ((packed));
|
||||
struct ipx_rt_def {
|
||||
__u32 network __attribute__ ((packed));
|
||||
__u16 hops __attribute__ ((packed));
|
||||
__u16 ticks __attribute__ ((packed));
|
||||
} rt[1] __attribute__ ((packed));
|
||||
};
|
||||
|
||||
#define IPX_BROADCAST_NODE ("\xff\xff\xff\xff\xff\xff")
|
||||
#define IPX_THIS_NODE ("\0\0\0\0\0\0")
|
||||
#define IPX_THIS_NET (0)
|
||||
|
||||
#ifndef IPX_NODE_LEN
|
||||
#define IPX_NODE_LEN (6)
|
||||
#endif
|
||||
|
||||
void
|
||||
ipx_print_node(IPXNode node);
|
||||
void
|
||||
ipx_print_network(IPXNet net);
|
||||
void
|
||||
ipx_print_port(IPXPort port);
|
||||
void
|
||||
ipx_print_saddr(struct sockaddr_ipx* sipx);
|
||||
void
|
||||
ipx_fprint_node(FILE *file, IPXNode node);
|
||||
void
|
||||
ipx_fprint_network(FILE *file, IPXNet net);
|
||||
void
|
||||
ipx_fprint_port(FILE *file, IPXPort port);
|
||||
void
|
||||
ipx_fprint_saddr(FILE *file, struct sockaddr_ipx* sipx);
|
||||
int
|
||||
ipx_sscanf_node(char *buf, unsigned char node[IPX_NODE_LEN]);
|
||||
void
|
||||
ipx_assign_node(IPXNode dest, IPXNode src);
|
||||
int
|
||||
ipx_node_equal(IPXNode n1,IPXNode n2);
|
||||
|
||||
#endif /* _IPXLIB_H */
|
||||
2741
util/ncplib.c
Normal file
2741
util/ncplib.c
Normal file
File diff suppressed because it is too large
Load Diff
331
util/ncplib.h
Normal file
331
util/ncplib.h
Normal file
@@ -0,0 +1,331 @@
|
||||
/*
|
||||
* ncplib.h
|
||||
*
|
||||
* Copyright (C) 1995, 1996 by Volker Lendecke
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _NCPLIB_H
|
||||
#define _NCPLIB_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/ncp.h>
|
||||
#include <linux/ncp_fs.h>
|
||||
#include <linux/ipx.h>
|
||||
#include <sys/param.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "ipxlib.h"
|
||||
|
||||
#ifndef memzero
|
||||
#include <string.h>
|
||||
#define memzero(object) memset(&(object), 0, sizeof(object))
|
||||
#endif
|
||||
|
||||
void
|
||||
str_upper(char *name);
|
||||
|
||||
enum connect_state {
|
||||
NOT_CONNECTED = 0,
|
||||
CONN_PERMANENT,
|
||||
CONN_TEMPORARY
|
||||
};
|
||||
|
||||
struct ncp_conn {
|
||||
|
||||
enum connect_state is_connected;
|
||||
|
||||
char server[NCP_BINDERY_NAME_LEN];
|
||||
char user [NCP_BINDERY_NAME_LEN];
|
||||
|
||||
struct ncp_fs_info i;
|
||||
|
||||
/* Fields for use with permanent connections */
|
||||
int mount_fid;
|
||||
char mount_point[MAXPATHLEN];
|
||||
|
||||
/* Fields for use with temporary connections */
|
||||
int ncp_sock;
|
||||
int wdog_sock;
|
||||
int wdog_pid;
|
||||
__u8 sequence;
|
||||
int completion;
|
||||
int conn_status;
|
||||
int reply_size;
|
||||
|
||||
/* Fields used to setup ncp requests */
|
||||
int current_size;
|
||||
int has_subfunction;
|
||||
int verbose;
|
||||
int ncp_reply_size;
|
||||
|
||||
int lock;
|
||||
|
||||
char packet[NCP_PACKET_SIZE];
|
||||
};
|
||||
|
||||
struct ncp_conn_spec {
|
||||
char server[NCP_BINDERY_NAME_LEN];
|
||||
char user[NCP_BINDERY_NAME_LEN];
|
||||
uid_t uid;
|
||||
int login_type; /* NCP_BINDERY_USER / NCP_BINDERY_PSERVER */
|
||||
char password[NCP_BINDERY_NAME_LEN];
|
||||
};
|
||||
|
||||
struct ncp_search_seq {
|
||||
struct nw_search_sequence s;
|
||||
int namespace;
|
||||
};
|
||||
|
||||
/* ncp_initialize is the main entry point for user programs which want
|
||||
to connect to a NetWare Server. It looks for -S, -U, -P and -n in
|
||||
the argument list, opens the connection and removes the arguments
|
||||
from the list. It was designed after the X Windows init
|
||||
functions. */
|
||||
int
|
||||
ncp_initialize(struct ncp_conn *conn,
|
||||
int *argc, char **argv,
|
||||
int login_necessary);
|
||||
|
||||
/* You can login as another object by this procedure. As a first use
|
||||
pserver comes to mind. */
|
||||
int
|
||||
ncp_initialize_as(struct ncp_conn *conn,
|
||||
int *argc, char **argv,
|
||||
int login_necessary, int login_type);
|
||||
|
||||
|
||||
/* Open an existing permanent connection */
|
||||
int
|
||||
ncp_open(struct ncp_conn *conn,
|
||||
const struct ncp_conn_spec *spec);
|
||||
|
||||
/* Open a connection on an existing mount point */
|
||||
int
|
||||
ncp_open_mount(struct ncp_conn *conn,
|
||||
const char *mount_point);
|
||||
|
||||
/* Detach from and destroy a permanent connection */
|
||||
int
|
||||
ncp_destroy_permanent(struct ncp_conn *conn);
|
||||
|
||||
/* Create a temporary connection */
|
||||
int
|
||||
ncp_open_temporary(struct ncp_conn *conn,
|
||||
const struct ncp_conn_spec *spec);
|
||||
|
||||
/* Detach from a permanent connection or destroy a temporary
|
||||
connection */
|
||||
int
|
||||
ncp_close(struct ncp_conn *conn);
|
||||
|
||||
/* like getmntent, get_ncp_conn_ent scans /etc/mtab for usable
|
||||
connections */
|
||||
|
||||
struct ncp_conn_ent {
|
||||
char server[NCP_BINDERY_NAME_LEN];
|
||||
char user[NCP_BINDERY_NAME_LEN];
|
||||
uid_t uid;
|
||||
char mount_point[MAXPATHLEN];
|
||||
};
|
||||
|
||||
struct ncp_conn_ent *
|
||||
ncp_get_conn_ent(FILE *filep);
|
||||
|
||||
#define NWCLIENT (".nwclient")
|
||||
#define NWC_NOPASSWORD ("-")
|
||||
|
||||
/* find an appropriate connection */
|
||||
|
||||
struct ncp_conn_spec *
|
||||
ncp_find_conn_spec(const char *server, const char *user, const char *password,
|
||||
uid_t uid);
|
||||
|
||||
int
|
||||
ncp_get_file_server_description_strings(struct ncp_conn *conn,
|
||||
char target[512]);
|
||||
|
||||
int
|
||||
ncp_get_file_server_time(struct ncp_conn *conn, time_t *target);
|
||||
|
||||
int
|
||||
ncp_get_connlist(struct ncp_conn *conn, __u32 last_id,
|
||||
__u16 object_type, const char *object_name,
|
||||
int *returned_no, __u16 conn_numbers[256]);
|
||||
|
||||
int
|
||||
ncp_get_encryption_key(struct ncp_conn *conn,
|
||||
char *target);
|
||||
int
|
||||
ncp_get_bindery_object_id(struct ncp_conn *conn,
|
||||
__u16 object_type,
|
||||
const char *object_name,
|
||||
struct ncp_bindery_object *target);
|
||||
int
|
||||
ncp_scan_bindery_object(struct ncp_conn *conn,
|
||||
__u32 last_id, __u16 object_type, char *search_string,
|
||||
struct ncp_bindery_object *target);
|
||||
int
|
||||
ncp_read_property_value(struct ncp_conn *conn,
|
||||
int object_type, const char *object_name,
|
||||
int segment, const char *prop_name,
|
||||
struct nw_property *target);
|
||||
int
|
||||
ncp_login_encrypted(struct ncp_conn *conn,
|
||||
const struct ncp_bindery_object *object,
|
||||
const unsigned char *key,
|
||||
const unsigned char *passwd);
|
||||
int
|
||||
ncp_login_user(struct ncp_conn *conn,
|
||||
const unsigned char *username,
|
||||
const unsigned char *password);
|
||||
int
|
||||
ncp_get_volume_info_with_number(struct ncp_conn *conn, int n,
|
||||
struct ncp_volume_info *target);
|
||||
|
||||
int
|
||||
ncp_get_volume_number(struct ncp_conn *conn, const char *name,
|
||||
int *target);
|
||||
|
||||
int
|
||||
ncp_file_search_init(struct ncp_conn *conn,
|
||||
int dir_handle, const char *path,
|
||||
struct ncp_filesearch_info *target);
|
||||
|
||||
int
|
||||
ncp_file_search_continue(struct ncp_conn *conn,
|
||||
struct ncp_filesearch_info *fsinfo,
|
||||
int attributes, const char *path,
|
||||
struct ncp_file_info *target);
|
||||
|
||||
int
|
||||
ncp_get_finfo(struct ncp_conn *conn,
|
||||
int dir_handle, const char *path, const char *name,
|
||||
struct ncp_file_info *target);
|
||||
|
||||
int
|
||||
ncp_open_file(struct ncp_conn *conn,
|
||||
int dir_handle, const char *path,
|
||||
int attr, int access,
|
||||
struct ncp_file_info *target);
|
||||
int
|
||||
ncp_close_file(struct ncp_conn *conn, const char *file_id);
|
||||
|
||||
int
|
||||
ncp_create_newfile(struct ncp_conn *conn,
|
||||
int dir_handle, const char *path,
|
||||
int attr,
|
||||
struct ncp_file_info *target);
|
||||
|
||||
int
|
||||
ncp_create_file(struct ncp_conn *conn,
|
||||
int dir_handle, const char *path,
|
||||
int attr,
|
||||
struct ncp_file_info *target);
|
||||
|
||||
int
|
||||
ncp_erase_file(struct ncp_conn *conn,
|
||||
int dir_handle, const char *path,
|
||||
int attr);
|
||||
|
||||
int
|
||||
ncp_rename_file(struct ncp_conn *conn,
|
||||
int old_handle, const char *old_path,
|
||||
int attr,
|
||||
int new_handle, const char *new_path);
|
||||
|
||||
int
|
||||
ncp_create_directory(struct ncp_conn *conn,
|
||||
int dir_handle, const char *path,
|
||||
int inherit_mask);
|
||||
|
||||
int
|
||||
ncp_delete_directory(struct ncp_conn *conn,
|
||||
int dir_handle, const char *path);
|
||||
|
||||
int
|
||||
ncp_rename_directory(struct ncp_conn *conn,
|
||||
int dir_handle,
|
||||
const char *old_path, const char *new_path);
|
||||
|
||||
int
|
||||
ncp_read(struct ncp_conn *conn, const char *file_id,
|
||||
off_t offset, size_t count, char *target);
|
||||
|
||||
int
|
||||
ncp_write(struct ncp_conn *conn, const char *file_id,
|
||||
off_t offset, size_t count, const char *source);
|
||||
|
||||
int
|
||||
ncp_do_lookup(struct ncp_conn *conn,
|
||||
struct nw_info_struct *dir,
|
||||
char *path, /* may only be one component */
|
||||
struct nw_info_struct *target);
|
||||
|
||||
int
|
||||
ncp_modify_file_or_subdir_dos_info(struct ncp_conn *conn,
|
||||
struct nw_info_struct *file,
|
||||
__u32 info_mask,
|
||||
struct nw_modify_dos_info *info);
|
||||
|
||||
int
|
||||
ncp_del_file_or_subdir(struct ncp_conn *conn,
|
||||
struct nw_info_struct *dir, char *name);
|
||||
|
||||
|
||||
int
|
||||
ncp_open_create_file_or_subdir(struct ncp_conn *conn,
|
||||
struct nw_info_struct *dir, char *name,
|
||||
int open_create_mode,
|
||||
__u32 create_attributes,
|
||||
int desired_acc_rights,
|
||||
struct nw_file_info *target);
|
||||
|
||||
int
|
||||
ncp_initialize_search(struct ncp_conn *conn,
|
||||
const struct nw_info_struct *dir,
|
||||
int namespace,
|
||||
struct ncp_search_seq *target);
|
||||
|
||||
int
|
||||
ncp_search_for_file_or_subdir(struct ncp_conn *conn,
|
||||
struct ncp_search_seq *seq,
|
||||
struct nw_info_struct *target);
|
||||
|
||||
int
|
||||
ncp_ren_or_mov_file_or_subdir(struct ncp_conn *conn,
|
||||
struct nw_info_struct *old_dir, char *old_name,
|
||||
struct nw_info_struct *new_dir, char *new_name);
|
||||
|
||||
int
|
||||
ncp_create_queue_job_and_file(struct ncp_conn *conn,
|
||||
__u32 queue_id,
|
||||
struct queue_job *job);
|
||||
|
||||
int
|
||||
ncp_close_file_and_start_job(struct ncp_conn *conn,
|
||||
__u32 queue_id,
|
||||
struct queue_job *job);
|
||||
|
||||
int
|
||||
ncp_attach_to_queue(struct ncp_conn *conn,
|
||||
__u32 queue_id);
|
||||
|
||||
int
|
||||
ncp_detach_from_queue(struct ncp_conn *conn,
|
||||
__u32 queue_id);
|
||||
|
||||
int
|
||||
ncp_service_queue_job(struct ncp_conn *conn, __u32 queue_id, __u16 job_type,
|
||||
struct queue_job *job);
|
||||
|
||||
int
|
||||
ncp_finish_servicing_job(struct ncp_conn *conn, __u32 queue_id,
|
||||
__u32 job_number, __u32 charge_info);
|
||||
|
||||
int
|
||||
ncp_abort_servicing_job(struct ncp_conn *conn, __u32 queue_id,
|
||||
__u32 job_number);
|
||||
|
||||
#endif /* _NCPLIB_H */
|
||||
522
util/ncpmount.c
Normal file
522
util/ncpmount.c
Normal file
@@ -0,0 +1,522 @@
|
||||
/*
|
||||
* nwmount.c
|
||||
*
|
||||
* Copyright (C) 1995 by Volker Lendecke
|
||||
*
|
||||
* 1/20/96 - Steven N. Hirsch (hirsch@emba.uvm.edu)
|
||||
*
|
||||
* If the ncpfs support is not loaded and we are using kerneld to
|
||||
* autoload modules, then we don't want to do it here. I added
|
||||
* a conditional which leaves out the test and load code.
|
||||
*
|
||||
* Even if we _do_ want ncpmount to load the module, passing a
|
||||
* fully-qualified pathname to insmod causes it to bypass a
|
||||
* path search. This may lead to ncpfs.o not being found on
|
||||
* some systems.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/param.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
/* #include <sys/wait.h> */ /* generates a warning here */
|
||||
extern pid_t waitpid(pid_t, int *, int);
|
||||
#include <sys/errno.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/mount.h>
|
||||
#include <mntent.h>
|
||||
#include <linux/ipx.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <linux/fs.h>
|
||||
#include <linux/ncp.h>
|
||||
#include <linux/ncp_fs.h>
|
||||
#include <linux/ncp_mount.h>
|
||||
#include "ncplib.h"
|
||||
|
||||
static char *progname;
|
||||
static void usage(void);
|
||||
static void help(void);
|
||||
|
||||
#ifndef HAVE_KERNELD
|
||||
|
||||
/* Returns 0 if the filesystem is in the kernel after this routine
|
||||
completes */
|
||||
static int
|
||||
load_ncpfs(void)
|
||||
{
|
||||
FILE *ffs;
|
||||
char s[1024];
|
||||
char *p, *p1;
|
||||
pid_t pid;
|
||||
int status;
|
||||
|
||||
/* Check if ncpfs is in the kernel */
|
||||
ffs = fopen("/proc/filesystems", "r");
|
||||
|
||||
if (ffs == NULL)
|
||||
{
|
||||
perror("Error: \"/proc/filesystems\" could not be read:");
|
||||
return -1;
|
||||
}
|
||||
|
||||
p = NULL;
|
||||
while (! feof(ffs))
|
||||
{
|
||||
p1 = fgets(s, sizeof(s), ffs);
|
||||
if (p1)
|
||||
{
|
||||
p = strstr(s, "ncpfs");
|
||||
if (p)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(ffs);
|
||||
|
||||
if (p)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* system() function without signal handling, from Stevens */
|
||||
|
||||
if ((pid = fork()) < 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else if (pid == 0)
|
||||
{
|
||||
/* child */
|
||||
execl("/sbin/insmod", "insmod", "ncpfs", NULL);
|
||||
_exit(127); /* execl error */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* parent */
|
||||
while (waitpid(pid, &status, 0) < 0)
|
||||
{
|
||||
if (errno != EINTR)
|
||||
{
|
||||
status = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
#endif /* HAVE_KERNELD */
|
||||
|
||||
/* Check whether user is allowed to mount on the specified mount point */
|
||||
static int
|
||||
mount_ok(struct stat *st)
|
||||
{
|
||||
if (!S_ISDIR(st->st_mode))
|
||||
{
|
||||
errno = ENOTDIR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( (getuid() != 0)
|
||||
&& ( (getuid() != st->st_uid)
|
||||
|| ((st->st_mode & S_IRWXU) != S_IRWXU)))
|
||||
{
|
||||
errno = EPERM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
struct ncp_mount_data data;
|
||||
struct stat st;
|
||||
char mount_name[256];
|
||||
|
||||
int fd, result;
|
||||
struct sockaddr_ipx addr;
|
||||
int addrlen;
|
||||
|
||||
int upcase_password;
|
||||
|
||||
int um;
|
||||
unsigned int flags;
|
||||
|
||||
char mount_point[MAXPATHLEN];
|
||||
struct mntent ment;
|
||||
FILE *mtab;
|
||||
|
||||
char *server = NULL;
|
||||
char *user = NULL;
|
||||
char *password = NULL;
|
||||
struct ncp_conn_spec *spec;
|
||||
|
||||
uid_t conn_uid = getuid();
|
||||
|
||||
struct ncp_conn conn;
|
||||
|
||||
int opt;
|
||||
|
||||
progname = argv[0];
|
||||
|
||||
memzero(data); memzero(spec); memzero(conn);
|
||||
|
||||
if (geteuid() != 0)
|
||||
{
|
||||
fprintf(stderr, "%s must be installed suid root\n", progname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
data.uid = getuid();
|
||||
data.gid = getgid();
|
||||
um = umask(0);
|
||||
umask(um);
|
||||
data.file_mode = (S_IRWXU|S_IRWXG|S_IRWXO) & ~um;
|
||||
data.dir_mode = 0;
|
||||
|
||||
upcase_password = 1;
|
||||
|
||||
while ((opt = getopt (argc, argv, "CS:U:c:u:g:f:d:P:nh")) != EOF)
|
||||
{
|
||||
switch (opt)
|
||||
{
|
||||
case 'C':
|
||||
upcase_password = 0;
|
||||
break;
|
||||
case 'S':
|
||||
if (strlen(optarg) >= sizeof(spec->server))
|
||||
{
|
||||
fprintf(stderr, "Servername too long:%s\n",
|
||||
optarg);
|
||||
return 1;
|
||||
}
|
||||
server = optarg;
|
||||
break;
|
||||
case 'U':
|
||||
if (strlen(optarg) >= sizeof(spec->user))
|
||||
{
|
||||
fprintf(stderr, "Username too long: %s\n",
|
||||
optarg);
|
||||
return 1;
|
||||
}
|
||||
user = optarg;
|
||||
break;
|
||||
case 'c':
|
||||
if (isdigit(optarg[0]))
|
||||
{
|
||||
conn_uid = atoi(optarg);
|
||||
}
|
||||
else
|
||||
{
|
||||
struct passwd *pwd = getpwnam(optarg);
|
||||
if (pwd == NULL)
|
||||
{
|
||||
fprintf(stderr, "Unknown user: %s\n",
|
||||
optarg);
|
||||
return 1;
|
||||
}
|
||||
conn_uid = pwd->pw_uid;
|
||||
}
|
||||
break;
|
||||
case 'u':
|
||||
if (isdigit(optarg[0]))
|
||||
{
|
||||
data.uid = atoi(optarg);
|
||||
}
|
||||
else
|
||||
{
|
||||
struct passwd *pwd = getpwnam(optarg);
|
||||
if (pwd == NULL)
|
||||
{
|
||||
fprintf(stderr, "Unknown user: %s\n",
|
||||
optarg);
|
||||
return 1;
|
||||
}
|
||||
data.uid = pwd->pw_uid;
|
||||
}
|
||||
break;
|
||||
case 'g':
|
||||
if (isdigit(optarg[0]))
|
||||
{
|
||||
data.gid = atoi(optarg);
|
||||
}
|
||||
else
|
||||
{
|
||||
struct group *grp = getgrnam(optarg);
|
||||
if (grp == NULL)
|
||||
{
|
||||
fprintf(stderr, "Unknown group: %s\n",
|
||||
optarg);
|
||||
return 1;
|
||||
}
|
||||
data.gid = grp->gr_gid;
|
||||
}
|
||||
break;
|
||||
case 'f':
|
||||
data.file_mode = strtol(optarg, NULL, 8);
|
||||
break;
|
||||
case 'd':
|
||||
data.dir_mode = strtol(optarg, NULL, 8);
|
||||
break;
|
||||
case 'P':
|
||||
if (strlen(optarg) >= sizeof(spec->password))
|
||||
{
|
||||
printf("password too long\n");
|
||||
exit(1);
|
||||
}
|
||||
password = optarg;
|
||||
break;
|
||||
case 'n':
|
||||
password = "";
|
||||
break;
|
||||
case 'h':
|
||||
help();
|
||||
exit(1);
|
||||
default:
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if ((spec = ncp_find_conn_spec(server, user, password, data.uid))
|
||||
== NULL)
|
||||
{
|
||||
fprintf(stderr, "Could not find valid server/user\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (upcase_password != 0)
|
||||
{
|
||||
str_upper(spec->password);
|
||||
}
|
||||
|
||||
if (optind != argc-1)
|
||||
{
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
|
||||
realpath(argv[optind], mount_point);
|
||||
|
||||
if (stat(mount_point, &st) == -1)
|
||||
{
|
||||
fprintf(stderr, "could not find mount point %s: %s\n",
|
||||
mount_point, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (mount_ok(&st) != 0)
|
||||
{
|
||||
fprintf(stderr, "cannot to mount on %s: %s\n",
|
||||
mount_point, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#ifndef HAVE_KERNELD
|
||||
/* Check if the ncpfs filesystem is in the kernel. If not, attempt
|
||||
* to load the ncpfs module */
|
||||
if (load_ncpfs() != 0)
|
||||
{
|
||||
fprintf(stderr, "Error: Unable to load ncpfs, exiting...\n");
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
data.version = NCP_MOUNT_VERSION;
|
||||
data.mounted_uid = conn_uid;
|
||||
|
||||
if (data.dir_mode == 0)
|
||||
{
|
||||
data.dir_mode = data.file_mode;
|
||||
if ((data.dir_mode & S_IRUSR) != 0)
|
||||
data.dir_mode |= S_IXUSR;
|
||||
if ((data.dir_mode & S_IRGRP) != 0)
|
||||
data.dir_mode |= S_IXGRP;
|
||||
if ((data.dir_mode & S_IROTH) != 0)
|
||||
data.dir_mode |= S_IXOTH;
|
||||
}
|
||||
|
||||
if (ncp_open(&conn, spec) != 0)
|
||||
{
|
||||
fprintf(stderr, "could not connect to server %s: %s\n",
|
||||
server, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (conn.is_connected == CONN_PERMANENT)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"You already have mounted server %s\nas user "
|
||||
"%s\non mount point %s\n", spec->server, spec->user,
|
||||
conn.mount_point);
|
||||
ncp_close(&conn);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
data.serv_addr = conn.i.addr;
|
||||
|
||||
ncp_close(&conn);
|
||||
|
||||
data.ncp_fd = socket(AF_IPX, SOCK_DGRAM, PF_IPX);
|
||||
if (data.ncp_fd == -1)
|
||||
{
|
||||
fprintf(stderr, "could not open ncp socket: %s\n",
|
||||
strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
data.wdog_fd = socket(AF_IPX, SOCK_DGRAM, PF_IPX);
|
||||
if (data.wdog_fd == -1)
|
||||
{
|
||||
fprintf(stderr, "could not open wdog socket: %s\n",
|
||||
strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
memzero(addr);
|
||||
addr.sipx_type = NCP_PTYPE;
|
||||
|
||||
if (bind(data.ncp_fd, (struct sockaddr *)&addr, sizeof(addr)) == -1)
|
||||
{
|
||||
fprintf(stderr, "\nbind: %s\n",
|
||||
strerror(errno));
|
||||
fprintf(stderr,
|
||||
"\nMaybe you want to use \n"
|
||||
"ipx_configure --auto_interface=on --auto_primary=on\n"
|
||||
"and try again after waiting a minute.\n\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
addrlen = sizeof(addr);
|
||||
|
||||
if (getsockname(data.ncp_fd, (struct sockaddr *)&addr, &addrlen)==-1)
|
||||
{
|
||||
perror("getsockname ncp socket");
|
||||
close(data.ncp_fd); close(data.wdog_fd);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
addr.sipx_port = htons(ntohs(addr.sipx_port) + 1);
|
||||
|
||||
if (bind(data.wdog_fd, (struct sockaddr *)&addr, sizeof(addr)) == -1)
|
||||
{
|
||||
fprintf(stderr, "bind(wdog_sock, ): %s\n",
|
||||
strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
flags = MS_MGC_VAL;
|
||||
|
||||
data.time_out = 20;
|
||||
data.retry_count = 2;
|
||||
|
||||
result = mount(NULL, mount_point, "ncpfs", flags, (char *)&data);
|
||||
|
||||
if (result < 0)
|
||||
{
|
||||
printf("mount failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if ( (ncp_open_mount(&conn, mount_point) != 0)
|
||||
|| (ncp_login_user(&conn, spec->user, spec->password) != 0))
|
||||
{
|
||||
fprintf(stderr, "%s: login failed\n", strerror(errno));
|
||||
ncp_close(&conn);
|
||||
umount(mount_point);
|
||||
exit(1);
|
||||
}
|
||||
ncp_close(&conn);
|
||||
|
||||
strcpy(mount_name, spec->server);
|
||||
strcat(mount_name, "/");
|
||||
strcat(mount_name, spec->user);
|
||||
|
||||
ment.mnt_fsname = mount_name;
|
||||
ment.mnt_dir = mount_point;
|
||||
ment.mnt_type = "ncpfs";
|
||||
ment.mnt_opts = "rw";
|
||||
ment.mnt_freq = 0;
|
||||
ment.mnt_passno= 0;
|
||||
|
||||
if ((fd = open(MOUNTED"~", O_RDWR|O_CREAT|O_EXCL, 0600)) == -1)
|
||||
{
|
||||
fprintf(stderr, "Can't get "MOUNTED"~ lock file");
|
||||
exit(1);
|
||||
}
|
||||
close(fd);
|
||||
|
||||
if ((mtab = setmntent(MOUNTED, "a+")) == NULL)
|
||||
{
|
||||
fprintf(stderr, "Can't open " MOUNTED);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (addmntent(mtab, &ment) == 1)
|
||||
{
|
||||
fprintf(stderr, "Can't write mount entry");
|
||||
exit(1);
|
||||
}
|
||||
if (fchmod(fileno(mtab), 0644) == -1)
|
||||
{
|
||||
fprintf(stderr, "Can't set perms on "MOUNTED);
|
||||
exit(1);
|
||||
}
|
||||
endmntent(mtab);
|
||||
|
||||
if (unlink(MOUNTED"~") == -1)
|
||||
{
|
||||
fprintf(stderr, "Can't remove "MOUNTED"~");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
printf("usage: %s [options] mount-point\n", progname);
|
||||
printf("Try `%s -h' for more information\n", progname);
|
||||
}
|
||||
|
||||
static void
|
||||
help(void)
|
||||
{
|
||||
printf("\n");
|
||||
printf("usage: %s [options] mount-point\n", progname);
|
||||
printf("\n"
|
||||
"-S server Server name to be used\n"
|
||||
"-U username Username sent to server\n"
|
||||
"-u uid uid the mounted files get\n"
|
||||
"-g gid gid the mounted files get\n"
|
||||
"-f mode permission the files get (octal notation)\n"
|
||||
"-d mode permission the dirs get (octal notation)\n"
|
||||
"-c uid uid to identify the connection to mount on\n"
|
||||
" Only makes sense for root\n"
|
||||
"-C Don't convert password to uppercase\n"
|
||||
"-P password Use this password\n"
|
||||
"-n Do not use any password\n"
|
||||
" If neither -P nor -n are given, you are\n"
|
||||
" asked for a password.\n"
|
||||
"-h print this help text\n"
|
||||
"\n");
|
||||
}
|
||||
164
util/ncptest.c
Normal file
164
util/ncptest.c
Normal file
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* ncptest.c
|
||||
*
|
||||
* Copyright (C) 1995 by Volker Lendecke
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/param.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
/* #include <sys/wait.h> */ /* generates a warning here */
|
||||
extern pid_t waitpid(pid_t, int *, int);
|
||||
#include <sys/errno.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/mount.h>
|
||||
#include <mntent.h>
|
||||
#include <linux/ipx.h>
|
||||
|
||||
#include <linux/fs.h>
|
||||
#include <linux/ncp.h>
|
||||
#include <linux/ncp_fs.h>
|
||||
#include <linux/ncp_mount.h>
|
||||
#include "ncplib.h"
|
||||
|
||||
|
||||
void
|
||||
test_print(struct ncp_conn *conn)
|
||||
{
|
||||
struct ncp_bindery_object q;
|
||||
struct queue_job j;
|
||||
struct print_job_record pj;
|
||||
int written;
|
||||
|
||||
if (ncp_get_bindery_object_id(conn, NCP_BINDERY_PQUEUE,
|
||||
"Q_DJ500", &q) != 0) {
|
||||
printf("get oid error\n");
|
||||
return;
|
||||
}
|
||||
|
||||
memset(&j, 0, sizeof(j));
|
||||
|
||||
j.j.TargetServerID = 0xffffffff; /* any server */
|
||||
/* at once */
|
||||
memset(&(j.j.TargetExecTime), 0xff, sizeof(j.j.TargetExecTime));
|
||||
j.j.JobType = htons(0);
|
||||
strcpy(j.j.JobTextDescription, "Test Job");
|
||||
|
||||
memset(&pj, 0, sizeof(pj));
|
||||
|
||||
pj.Version = 0;
|
||||
pj.TabSize = 8;
|
||||
pj.Copies = htons(1);
|
||||
pj.CtrlFlags = 0;
|
||||
pj.Lines = htons(66);
|
||||
pj.Rows = htons(80);
|
||||
strcpy(pj.FormName, "test");
|
||||
strcpy(pj.BannerName, "BannerName");
|
||||
strcpy(pj.FnameBanner, "BannerFile");
|
||||
strcpy(pj.FnameHeader, "HeaderName");
|
||||
strcpy(pj.Path, "");
|
||||
|
||||
memcpy(j.j.ClientRecordArea, &pj, sizeof(pj));
|
||||
|
||||
if (ncp_create_queue_job_and_file(conn, q.object_id, &j) != 0) {
|
||||
printf("create error\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((written = ncp_write(conn, j.file_handle, 0, 15,
|
||||
"hallo, wie geht's?")) < 0) {
|
||||
printf("write error\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (ncp_close_file_and_start_job(conn, q.object_id, &j) != 0) {
|
||||
printf("close error\n");
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
test_ls(struct ncp_conn *server)
|
||||
{
|
||||
struct nw_info_struct sys;
|
||||
struct nw_info_struct public;
|
||||
struct ncp_search_seq seq;
|
||||
struct nw_info_struct found;
|
||||
int res;
|
||||
|
||||
if (ncp_do_lookup(server, NULL, "SYS", &sys) != 0)
|
||||
{
|
||||
printf("lookup error\n");
|
||||
return;
|
||||
}
|
||||
if (ncp_do_lookup(server, &sys, "PUBLIC", &public) != 0)
|
||||
{
|
||||
printf("lookup public error\n");
|
||||
return;
|
||||
}
|
||||
if (ncp_initialize_search(server, &public, 4, &seq) != 0)
|
||||
{
|
||||
printf("init error\n");
|
||||
return;
|
||||
}
|
||||
while ((res=ncp_search_for_file_or_subdir(server,&seq,&found)) == 0)
|
||||
{
|
||||
printf("found %s: %s\n",
|
||||
(found.attributes & aDIR) ? "dir " : "file",
|
||||
found.entryName);
|
||||
}
|
||||
|
||||
if (res == 0xfe)
|
||||
{
|
||||
printf("result: no more files\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("other error: %x\n", res);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
test_connlist(struct ncp_conn *conn)
|
||||
{
|
||||
__u16 conn_list[256];
|
||||
int no;
|
||||
|
||||
ncp_get_connlist(conn, 0, NCP_BINDERY_USER, "*", &no, conn_list);
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
struct ncp_conn conn;
|
||||
|
||||
if (ncp_initialize(&conn, &argc, argv, 1) != 0)
|
||||
{
|
||||
perror("ncp_initialize");
|
||||
return 1;
|
||||
}
|
||||
|
||||
test_connlist(&conn);
|
||||
ncp_close(&conn);
|
||||
return 0;
|
||||
}
|
||||
197
util/ncpumount.c
Normal file
197
util/ncpumount.c
Normal file
@@ -0,0 +1,197 @@
|
||||
/*
|
||||
* nwumount.c
|
||||
*
|
||||
* Copyright (C) 1995 by Volker Lendecke
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/param.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
/* #include <sys/wait.h> */ /* generates a warning here */
|
||||
extern pid_t waitpid(pid_t, int *, int);
|
||||
#include <sys/errno.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/mount.h>
|
||||
#include <mntent.h>
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/ncp.h>
|
||||
#include <linux/ncp_mount.h>
|
||||
#include <linux/ncp_fs.h>
|
||||
|
||||
static char *progname;
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
printf("usage: %s mount-point\n", progname);
|
||||
}
|
||||
|
||||
static int
|
||||
umount_ok(const char *mount_point)
|
||||
{
|
||||
int fid = open(mount_point, O_RDONLY, 0);
|
||||
uid_t mount_uid;
|
||||
|
||||
if (fid == -1) {
|
||||
fprintf(stderr, "Could not open %s: %s\n",
|
||||
mount_point, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ioctl(fid, NCP_IOC_GETMOUNTUID, &mount_uid) != 0) {
|
||||
fprintf(stderr, "%s probably not ncp-filesystem\n",
|
||||
mount_point);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( (getuid() != 0)
|
||||
&& (mount_uid != getuid())) {
|
||||
fprintf(stderr, "You are not allowed to umount %s\n",
|
||||
mount_point);
|
||||
return -1;
|
||||
}
|
||||
|
||||
close(fid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Make a canonical pathname from PATH. Returns a freshly malloced string.
|
||||
It is up the *caller* to ensure that the PATH is sensible. i.e.
|
||||
canonicalize ("/dev/fd0/.") returns "/dev/fd0" even though ``/dev/fd0/.''
|
||||
is not a legal pathname for ``/dev/fd0.'' Anything we cannot parse
|
||||
we return unmodified. */
|
||||
char *
|
||||
canonicalize (const char *path)
|
||||
{
|
||||
char *canonical = malloc (PATH_MAX + 1);
|
||||
|
||||
if (path == NULL)
|
||||
return NULL;
|
||||
|
||||
if (realpath (path, canonical))
|
||||
return canonical;
|
||||
|
||||
strcpy (canonical, path);
|
||||
return canonical;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int fd;
|
||||
|
||||
char* mount_point;
|
||||
|
||||
struct mntent *mnt;
|
||||
FILE* mtab;
|
||||
FILE* new_mtab;
|
||||
|
||||
progname = argv[0];
|
||||
|
||||
if (geteuid() != 0) {
|
||||
fprintf(stderr, "%s must be installed suid root\n", progname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (argc != 2) {
|
||||
usage();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
mount_point = canonicalize(argv[1]);
|
||||
|
||||
if (umount_ok(mount_point) != 0) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (umount(mount_point) != 0) {
|
||||
fprintf(stderr, "Could not umount %s: %s\n",
|
||||
mount_point, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if ((fd = open(MOUNTED"~", O_RDWR|O_CREAT|O_EXCL, 0600)) == -1)
|
||||
{
|
||||
fprintf(stderr, "Can't get "MOUNTED"~ lock file");
|
||||
return 1;
|
||||
}
|
||||
close(fd);
|
||||
|
||||
if ((mtab = setmntent(MOUNTED, "r")) == NULL) {
|
||||
fprintf(stderr, "Can't open " MOUNTED ": %s\n",
|
||||
strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define MOUNTED_TMP MOUNTED".tmp"
|
||||
|
||||
if ((new_mtab = setmntent(MOUNTED_TMP, "w")) == NULL) {
|
||||
fprintf(stderr, "Can't open " MOUNTED_TMP ": %s\n",
|
||||
strerror(errno));
|
||||
endmntent(mtab);
|
||||
return 1;
|
||||
}
|
||||
|
||||
while ((mnt = getmntent(mtab)) != NULL) {
|
||||
if (strcmp(mnt->mnt_dir, mount_point) != 0) {
|
||||
addmntent(new_mtab, mnt);
|
||||
}
|
||||
}
|
||||
|
||||
endmntent(mtab);
|
||||
|
||||
if (fchmod (fileno (new_mtab), S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0) {
|
||||
fprintf(stderr, "Error changing mode of %s: %s\n",
|
||||
MOUNTED_TMP, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
endmntent(new_mtab);
|
||||
|
||||
if (rename(MOUNTED_TMP, MOUNTED) < 0) {
|
||||
fprintf(stderr, "Cannot rename %s to %s: %s\n",
|
||||
MOUNTED, MOUNTED_TMP, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (unlink(MOUNTED"~") == -1)
|
||||
{
|
||||
fprintf(stderr, "Can't remove "MOUNTED"~");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Overrides for Emacs so that we follow Linus's tabbing style.
|
||||
* Emacs will notice this stuff at the end of the file and automatically
|
||||
* adjust the settings for this buffer only. This must remain at the end
|
||||
* of the file.
|
||||
* ---------------------------------------------------------------------------
|
||||
* Local variables:
|
||||
* c-indent-level: 8
|
||||
* c-brace-imaginary-offset: 0
|
||||
* c-brace-offset: -8
|
||||
* c-argdecl-indent: 8
|
||||
* c-label-offset: -8
|
||||
* c-continued-statement-offset: 8
|
||||
* c-continued-brace-offset: 0
|
||||
* End:
|
||||
*/
|
||||
339
util/nprint.c
Normal file
339
util/nprint.c
Normal file
@@ -0,0 +1,339 @@
|
||||
/*
|
||||
* nwprint.c
|
||||
*
|
||||
* Send data to a NetWare print queue.
|
||||
*
|
||||
* Copyright (C) 1995 by Volker Lendecke
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "ncplib.h"
|
||||
|
||||
static char *progname;
|
||||
static void
|
||||
usage(void);
|
||||
static void help(void);
|
||||
|
||||
void
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
struct ncp_conn conn;
|
||||
|
||||
char default_queue[] = "*";
|
||||
char *queue = default_queue;
|
||||
|
||||
int opt;
|
||||
|
||||
struct ncp_bindery_object q;
|
||||
struct queue_job j;
|
||||
struct print_job_record pj;
|
||||
|
||||
int written, read_this_time;
|
||||
|
||||
char buf[8192];
|
||||
|
||||
char *file_name;
|
||||
int file;
|
||||
|
||||
progname = argv[0];
|
||||
|
||||
memzero(j); memzero(pj); memzero(q); memzero(conn);
|
||||
|
||||
if ( (argc == 2)
|
||||
&& (strcmp(argv[1], "-h") == 0))
|
||||
{
|
||||
help();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (ncp_initialize(&conn, &argc, argv, 1) != 0)
|
||||
{
|
||||
perror("Could not open connection");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill in default values for print job
|
||||
*/
|
||||
j.j.TargetServerID = 0xffffffff; /* any server */
|
||||
/* at once */
|
||||
memset(&(j.j.TargetExecTime), 0xff, sizeof(j.j.TargetExecTime));
|
||||
j.j.JobType = htons(0);
|
||||
strcpy(j.j.JobTextDescription, "No Description");
|
||||
|
||||
pj.Version = 0;
|
||||
pj.TabSize = 8;
|
||||
pj.Copies = htons(1);
|
||||
pj.CtrlFlags = 0;
|
||||
pj.Lines = htons(66);
|
||||
pj.Rows = htons(80);
|
||||
strcpy(pj.FnameHeader, "stdin");
|
||||
|
||||
while ((opt = getopt(argc, argv, "hq:d:p:b:f:l:r:c:t:F:TN"))!=EOF)
|
||||
{
|
||||
switch (opt) {
|
||||
case 'h':
|
||||
help();
|
||||
ncp_close(&conn);
|
||||
exit(1);
|
||||
case 'p':
|
||||
/* Path */
|
||||
pj.CtrlFlags |= PRINT_BANNER;
|
||||
if (strlen(optarg) >= sizeof(pj.Path))
|
||||
{
|
||||
strncpy(pj.Path, optarg,
|
||||
sizeof(pj.Path));
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(pj.Path, optarg);
|
||||
}
|
||||
break;
|
||||
case 'b':
|
||||
/* Banner Name */
|
||||
pj.CtrlFlags |= PRINT_BANNER;
|
||||
if (strlen(optarg) >= sizeof(pj.BannerName))
|
||||
{
|
||||
strncpy(pj.BannerName, optarg,
|
||||
sizeof(pj.BannerName));
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(pj.BannerName, optarg);
|
||||
}
|
||||
break;
|
||||
case 'f':
|
||||
/* File Name in Banner */
|
||||
pj.CtrlFlags |= PRINT_BANNER;
|
||||
if (strlen(optarg) >= sizeof(pj.FnameBanner))
|
||||
{
|
||||
strncpy(pj.FnameBanner, optarg,
|
||||
sizeof(pj.FnameBanner));
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(pj.FnameBanner, optarg);
|
||||
}
|
||||
break;
|
||||
case 'l':
|
||||
/* lines, default: 66 */
|
||||
if ((atoi(optarg) < 0) || (atoi(optarg) > 65535))
|
||||
{
|
||||
fprintf(stderr,
|
||||
"invalid line number: %s\n", optarg);
|
||||
break;
|
||||
}
|
||||
pj.Lines = htons(atoi(optarg));
|
||||
pj.CtrlFlags |= EXPAND_TABS;
|
||||
break;
|
||||
case 'r':
|
||||
/* rows, default: 80 */
|
||||
if ((atoi(optarg) < 0) || (atoi(optarg) > 65535))
|
||||
{
|
||||
fprintf(stderr,
|
||||
"invalid row number: %s\n", optarg);
|
||||
break;
|
||||
}
|
||||
pj.Rows = htons(atoi(optarg));
|
||||
pj.CtrlFlags |= EXPAND_TABS;
|
||||
break;
|
||||
case 'c':
|
||||
/* copies, default: 1 */
|
||||
if ((atoi(optarg) < 0) || (atoi(optarg) > 65000))
|
||||
{
|
||||
fprintf(stderr,
|
||||
"invalid copies: %s\n", optarg);
|
||||
break;
|
||||
}
|
||||
pj.Copies = htons(atoi(optarg));
|
||||
pj.CtrlFlags |= EXPAND_TABS;
|
||||
break;
|
||||
case 't':
|
||||
/* tab size, default: 8 */
|
||||
if ((atoi(optarg) < 0) || (atoi(optarg) > 255))
|
||||
{
|
||||
fprintf(stderr,
|
||||
"invalid tab size: %s\n", optarg);
|
||||
break;
|
||||
}
|
||||
pj.TabSize = atoi(optarg);
|
||||
pj.CtrlFlags |= EXPAND_TABS;
|
||||
break;
|
||||
case 'T':
|
||||
/* expand tabs, default tabsize: 8 */
|
||||
pj.CtrlFlags |= EXPAND_TABS;
|
||||
break;
|
||||
case 'N':
|
||||
/* no form feed */
|
||||
pj.CtrlFlags |= NO_FORM_FEED;
|
||||
break;
|
||||
case 'F':
|
||||
/* Form number, default: 0 */
|
||||
if ((atoi(optarg) < 0) || (atoi(optarg) > 255))
|
||||
{
|
||||
fprintf(stderr,
|
||||
"invalid form number: %s\n", optarg);
|
||||
break;
|
||||
}
|
||||
j.j.JobType = htons(atoi(optarg));
|
||||
break;
|
||||
case 'q':
|
||||
/* Queue name to print on, default: '*' */
|
||||
if (strlen(optarg) >= NCP_BINDERY_NAME_LEN)
|
||||
{
|
||||
printf("queue name too long: %s\n",
|
||||
optarg);
|
||||
exit(1);
|
||||
}
|
||||
queue = optarg;
|
||||
break;
|
||||
case 'd':
|
||||
/* Job Description */
|
||||
pj.CtrlFlags |= PRINT_BANNER;
|
||||
if (strlen(optarg) >= sizeof(j.j.JobTextDescription))
|
||||
{
|
||||
strncpy(j.j.JobTextDescription, optarg,
|
||||
sizeof(j.j.JobTextDescription));
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(j.j.JobTextDescription, optarg);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
usage();
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (optind != argc-1)
|
||||
{
|
||||
usage();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
file_name = argv[optind];
|
||||
|
||||
if (strcmp(file_name, "-") == 0)
|
||||
{
|
||||
file = 0; /* stdin */
|
||||
}
|
||||
else
|
||||
{
|
||||
file = open(file_name, O_RDONLY, 0);
|
||||
if (file < 0)
|
||||
{
|
||||
perror("could not open file");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (strlen(file_name) >= sizeof(pj.FnameHeader))
|
||||
{
|
||||
strncpy(pj.FnameHeader, file_name,
|
||||
sizeof(pj.FnameHeader));
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(pj.FnameHeader, file_name);
|
||||
}
|
||||
|
||||
if (strlen(pj.FnameBanner) == 0)
|
||||
{
|
||||
if (strlen(file_name) >= sizeof(pj.FnameBanner))
|
||||
{
|
||||
strncpy(pj.FnameBanner, file_name,
|
||||
sizeof(pj.FnameBanner));
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(pj.FnameBanner, file_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(j.j.ClientRecordArea, &pj, sizeof(pj));
|
||||
|
||||
str_upper(queue);
|
||||
|
||||
if (ncp_scan_bindery_object(&conn, 0xffffffff, NCP_BINDERY_PQUEUE,
|
||||
queue, &q) != 0)
|
||||
{
|
||||
printf("could not find queue %s\n", queue);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ncp_create_queue_job_and_file(&conn, q.object_id, &j) != 0)
|
||||
{
|
||||
printf("create error\n");
|
||||
return;
|
||||
}
|
||||
|
||||
written = 0;
|
||||
do
|
||||
{
|
||||
read_this_time = read(file, buf, sizeof(buf));
|
||||
if (read_this_time < 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (ncp_write(&conn, j.file_handle,
|
||||
written, read_this_time, buf) < read_this_time)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
written += read_this_time;
|
||||
} while (read_this_time > 0);
|
||||
|
||||
close(file);
|
||||
|
||||
if (ncp_close_file_and_start_job(&conn, q.object_id, &j) != 0) {
|
||||
printf("close error\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ncp_close(&conn);
|
||||
}
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
fprintf(stderr, "usage: %s [options] file\n", progname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static void
|
||||
help(void)
|
||||
{
|
||||
printf("\n");
|
||||
printf("usage: %s [options] file\n", progname);
|
||||
printf("\n"
|
||||
"-S server Server name to be used\n"
|
||||
"-U username Username sent to server\n"
|
||||
"-P password Use this password\n"
|
||||
"-n Do not use any password\n"
|
||||
"-C Don't convert password to uppercase\n"
|
||||
"-q queue name Name of the printing queue to use\n"
|
||||
"-d job desc Job description\n"
|
||||
"-p path name Path name to appear on banner\n"
|
||||
"-b bannername Banner name (up to 12 chars)\n"
|
||||
"-f filename Filename to appear on banner\n"
|
||||
"-l lines Number of lines per page\n"
|
||||
"-r rows Number of rows per page\n"
|
||||
"-t tab Number of spaces per tab\n"
|
||||
"-T Print server tab expantion\n"
|
||||
"-N Surpress print server form feeds\n"
|
||||
"-F form # Form number to print on\n"
|
||||
"-h print this help text\n"
|
||||
"\n");
|
||||
}
|
||||
@@ -89,9 +89,8 @@ typedef unsigned char buf32[32];
|
||||
typedef unsigned char buf16[16];
|
||||
typedef unsigned char buf8[8];
|
||||
typedef unsigned char buf4[4];
|
||||
typedef unsigned char u8;
|
||||
|
||||
static u8 encrypttable[256] =
|
||||
static unsigned char encrypttable[256] =
|
||||
{0x7,0x8,0x0,0x8,0x6,0x4,0xE,0x4,0x5,0xC,0x1,0x7,0xB,0xF,0xA,0x8,
|
||||
0xF,0x8,0xC,0xC,0x9,0x4,0x1,0xE,0x4,0x6,0x2,0x4,0x0,0xA,0xB,0x9,
|
||||
0x2,0xF,0xB,0x1,0xD,0x2,0x1,0x9,0x5,0xE,0x7,0x0,0x0,0x2,0x6,0x6,
|
||||
@@ -142,8 +141,8 @@ shuffle1(buf32 temp, unsigned char *target)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
shuffle(unsigned char *lon, const unsigned char *buf, int buflen,
|
||||
static void
|
||||
shuffle(const unsigned char *lon, const unsigned char *buf, int buflen,
|
||||
unsigned char *target)
|
||||
{
|
||||
int b2, d, s;
|
||||
@@ -191,8 +190,10 @@ shuffle(unsigned char *lon, const unsigned char *buf, int buflen,
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
nw_encrypt(unsigned char *fra,unsigned char *buf,unsigned char *til)
|
||||
static void
|
||||
nw_encrypt(const unsigned char *fra,
|
||||
const unsigned char *buf,
|
||||
unsigned char *til)
|
||||
{
|
||||
buf32 k;
|
||||
int s;
|
||||
75
util/pqlist.c
Normal file
75
util/pqlist.c
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* pqlist.c
|
||||
*
|
||||
* List all print queues on a server
|
||||
*
|
||||
* Copyright (C) 1996 by Volker Lendecke
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
#include "ncplib.h"
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
struct ncp_conn conn;
|
||||
struct ncp_bindery_object q;
|
||||
int found = 0;
|
||||
|
||||
char default_pattern[] = "*";
|
||||
char *pattern = default_pattern;
|
||||
char *p;
|
||||
|
||||
if (ncp_initialize(&conn, &argc, argv, 1) != 0)
|
||||
{
|
||||
perror("Could not open connection");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (argc > 2)
|
||||
{
|
||||
fprintf(stderr, "usage: %s [options] [pattern]\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (argc == 2)
|
||||
{
|
||||
pattern = argv[1];
|
||||
}
|
||||
|
||||
for (p = pattern; *p != '\0'; p++)
|
||||
{
|
||||
*p = toupper(*p);
|
||||
}
|
||||
|
||||
if (isatty(1))
|
||||
{
|
||||
printf("\nServer: %s\n", conn.server);
|
||||
printf("%-52s%-10s\n"
|
||||
"-----------------------------------------------"
|
||||
"-------------\n",
|
||||
"Print queue name",
|
||||
"Queue ID");
|
||||
}
|
||||
|
||||
q.object_id = 0xffffffff;
|
||||
|
||||
while (ncp_scan_bindery_object(&conn, q.object_id,
|
||||
NCP_BINDERY_PQUEUE, "*", &q) == 0)
|
||||
{
|
||||
found = 1;
|
||||
printf("%-52s", q.object_name);
|
||||
printf("%08x\n", q.object_id);
|
||||
}
|
||||
|
||||
if ((found == 0) && (isatty(1)))
|
||||
{
|
||||
printf("No queues found\n");
|
||||
}
|
||||
|
||||
ncp_close(&conn);
|
||||
return 0;
|
||||
}
|
||||
338
util/pserver.c
Normal file
338
util/pserver.c
Normal file
@@ -0,0 +1,338 @@
|
||||
/*
|
||||
* pserver.c
|
||||
*
|
||||
* Copyright (C) 1996 by Volker Lendecke
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <signal.h>
|
||||
#include "ncplib.h"
|
||||
|
||||
struct nw_queue {
|
||||
struct ncp_conn *conn;
|
||||
|
||||
char queue_name[NCP_BINDERY_NAME_LEN];
|
||||
__u32 queue_id;
|
||||
__u16 job_type;
|
||||
|
||||
char *command;
|
||||
};
|
||||
|
||||
static struct nw_queue q;
|
||||
|
||||
static int term_request;
|
||||
static char *progname;
|
||||
|
||||
static int
|
||||
init_queue(struct ncp_conn *conn, char *queue_name,
|
||||
char *command, struct nw_queue *q);
|
||||
|
||||
static int
|
||||
poll_queue(struct nw_queue *q);
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
fprintf(stderr, "usage: %s [options] file\n", progname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static void
|
||||
help(void)
|
||||
{
|
||||
printf("\n");
|
||||
printf("usage: %s [options]\n", progname);
|
||||
printf("\n"
|
||||
"-S server Server name to be used\n"
|
||||
"-U username Print Server name sent to server\n"
|
||||
"-P password Use this password\n"
|
||||
"-n Do not use any password\n"
|
||||
"-C Don't convert password to uppercase\n"
|
||||
"-q queue name Name of the printing queue to use\n"
|
||||
"-c command Name of print command, default: 'lpr'\n"
|
||||
"-j job type Type of job (Form number) to service\n"
|
||||
"-t timeout Polling interval, default: 30 sec\n"
|
||||
"-d Debug: don't daemonize\n"
|
||||
"-h print this help text\n"
|
||||
"\n");
|
||||
}
|
||||
|
||||
#ifndef NCP_BINDERY_PSERVER
|
||||
#define NCP_BINDERY_PSERVER (0x0007)
|
||||
#endif
|
||||
|
||||
static void
|
||||
terminate_handler()
|
||||
{
|
||||
signal(SIGTERM,terminate_handler);
|
||||
signal(SIGINT, terminate_handler);
|
||||
term_request=1;
|
||||
}
|
||||
|
||||
static void
|
||||
daemonize()
|
||||
{
|
||||
int fd,c;
|
||||
|
||||
if ((c = fork()) > 0) exit(0);
|
||||
if (c < 0)
|
||||
{
|
||||
fprintf(stderr, "ipxripd: can't fork: %s\n",strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
close(0);
|
||||
close(1);
|
||||
close(2);
|
||||
if ((fd = open("/dev/tty", O_RDWR)) >= 0)
|
||||
{
|
||||
ioctl(fd, TIOCNOTTY, NULL);
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
struct ncp_conn conn;
|
||||
int poll_timeout = 30;
|
||||
int opt;
|
||||
int job_type = 0xffff;
|
||||
int debug = 0;
|
||||
int i;
|
||||
|
||||
char *queue_name = NULL;
|
||||
|
||||
char default_command[] = "lpr";
|
||||
char *command = default_command;
|
||||
|
||||
progname = argv[0];
|
||||
|
||||
for (i = 1; i < argc; i += 1)
|
||||
{
|
||||
if ( (strcmp(argv[i], "-h") == 0)
|
||||
|| (strcmp(argv[i], "-?") == 0))
|
||||
{
|
||||
help();
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 1; i < argc; i += 1)
|
||||
{
|
||||
if (strcmp(argv[i], "-d") == 0)
|
||||
{
|
||||
debug = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (debug == 0)
|
||||
{
|
||||
daemonize();
|
||||
}
|
||||
|
||||
if (ncp_initialize_as(&conn, &argc, argv, 1, NCP_BINDERY_PSERVER) != 0)
|
||||
{
|
||||
perror("Could not open connection");
|
||||
return 1;
|
||||
}
|
||||
|
||||
while ((opt = getopt(argc, argv, "q:c:j:t:dh")) != EOF)
|
||||
{
|
||||
switch (opt)
|
||||
{
|
||||
case 'q':
|
||||
queue_name = optarg;
|
||||
break;
|
||||
case 'c':
|
||||
command = optarg;
|
||||
break;
|
||||
case 'j':
|
||||
job_type = atoi(optarg);
|
||||
break;
|
||||
case 't':
|
||||
poll_timeout = atoi(optarg);
|
||||
break;
|
||||
case 'd':
|
||||
debug = 1;
|
||||
break;
|
||||
case 'h':
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (argc != optind)
|
||||
{
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
|
||||
memzero(q);
|
||||
|
||||
if (queue_name == NULL)
|
||||
{
|
||||
fprintf(stderr, "You must specify a queue\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (init_queue(&conn, queue_name, command, &q) != 0)
|
||||
{
|
||||
perror("Could not init queue");
|
||||
ncp_close(&conn);
|
||||
return 1;
|
||||
}
|
||||
|
||||
q.job_type = job_type;
|
||||
|
||||
term_request = 0;
|
||||
signal(SIGTERM,terminate_handler);
|
||||
signal(SIGINT, terminate_handler);
|
||||
|
||||
while (1)
|
||||
{
|
||||
if ( (poll_queue(&q) != 0)
|
||||
&& (term_request == 0))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (term_request != 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
sleep(poll_timeout);
|
||||
}
|
||||
|
||||
ncp_detach_from_queue(&conn, q.queue_id);
|
||||
|
||||
ncp_close(&conn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
init_queue(struct ncp_conn *conn, char *queue_name, char *command,
|
||||
struct nw_queue *q)
|
||||
{
|
||||
struct ncp_bindery_object obj;
|
||||
|
||||
str_upper(queue_name);
|
||||
|
||||
q->conn = conn;
|
||||
q->command = command;
|
||||
|
||||
if (ncp_get_bindery_object_id(conn, NCP_BINDERY_PQUEUE,
|
||||
queue_name, &obj) != 0)
|
||||
{
|
||||
fprintf(stderr, "Queue %s not found\n", queue_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
q->queue_id = obj.object_id;
|
||||
memcpy(q->queue_name, obj.object_name, sizeof(q->queue_name));
|
||||
|
||||
if (ncp_attach_to_queue(conn, q->queue_id) != 0)
|
||||
{
|
||||
fprintf(stderr, "Could not attach to queue %s\n",
|
||||
queue_name);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
poll_queue(struct nw_queue *q)
|
||||
{
|
||||
struct queue_job job;
|
||||
int fd[2];
|
||||
int pid;
|
||||
|
||||
if (ncp_service_queue_job(q->conn, q->queue_id, q->job_type,
|
||||
&job) != 0)
|
||||
{
|
||||
/* No job for us */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (pipe(fd) < 0)
|
||||
{
|
||||
perror("pipe");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ((pid = fork()) < 0)
|
||||
{
|
||||
perror("fork");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (pid > 0)
|
||||
{
|
||||
/* parent */
|
||||
char buf[1024];
|
||||
size_t result;
|
||||
off_t offset = 0;
|
||||
|
||||
close(fd[0]); /* close read end */
|
||||
|
||||
while ((result = ncp_read(q->conn, job.file_handle, offset,
|
||||
sizeof(buf), buf)) > 0)
|
||||
{
|
||||
offset += result;
|
||||
if (write(fd[1], buf, result) != result)
|
||||
{
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
close(fd[1]); /* and close write end */
|
||||
|
||||
if (waitpid(pid, NULL, 0) < 0)
|
||||
{
|
||||
perror("waitpid");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* child */
|
||||
|
||||
close(fd[1]); /* close write end */
|
||||
|
||||
if (fd[0] != STDIN_FILENO)
|
||||
{
|
||||
if (dup2(fd[0], STDIN_FILENO) != STDIN_FILENO)
|
||||
{
|
||||
perror("dup2");
|
||||
close(fd[0]);
|
||||
exit(1);
|
||||
}
|
||||
close(fd[0]);
|
||||
}
|
||||
|
||||
execl("/bin/sh", "sh", "-c", q->command, NULL);
|
||||
perror("exec");
|
||||
close(fd[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ncp_finish_servicing_job(q->conn, q->queue_id, job.j.JobNumber,0);
|
||||
return 1;
|
||||
|
||||
fail:
|
||||
ncp_abort_servicing_job(q->conn, q->queue_id, job.j.JobNumber);
|
||||
/* We tell that we did not have a job to avoid overloading
|
||||
when something's wrong */
|
||||
return 0;
|
||||
}
|
||||
91
util/slist.c
Normal file
91
util/slist.c
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* slist.c
|
||||
*
|
||||
* List all file server that are known in the IPX network.
|
||||
*
|
||||
* Copyright (C) 1995 by Volker Lendecke
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ncplib.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
void
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
struct ncp_conn conn;
|
||||
struct ncp_bindery_object obj;
|
||||
int found = 0;
|
||||
char default_pattern[] = "*";
|
||||
char *pattern = default_pattern;
|
||||
char *p;
|
||||
|
||||
if (argc > 2)
|
||||
{
|
||||
printf("usage: %s [pattern]\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (argc == 2)
|
||||
{
|
||||
pattern = argv[1];
|
||||
}
|
||||
|
||||
for (p = pattern; *p != '\0'; p++)
|
||||
{
|
||||
*p = toupper(*p);
|
||||
}
|
||||
|
||||
if (ncp_initialize(&conn, &argc, argv, 0) != 0)
|
||||
{
|
||||
perror("ncp_connect");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (isatty(1))
|
||||
{
|
||||
printf("\n%-52s%-10s%-12s\n"
|
||||
"-----------------------------------------------"
|
||||
"---------------------------\n",
|
||||
"Known NetWare File Servers",
|
||||
"Network",
|
||||
"Node Address");
|
||||
}
|
||||
|
||||
obj.object_id = 0xffffffff;
|
||||
|
||||
while (ncp_scan_bindery_object(&conn, obj.object_id,
|
||||
NCP_BINDERY_FSERVER, pattern,
|
||||
&obj) == 0)
|
||||
{
|
||||
struct nw_property prop;
|
||||
struct prop_net_address *naddr
|
||||
= (struct prop_net_address *)∝
|
||||
|
||||
found = 1;
|
||||
|
||||
printf("%-52s", obj.object_name);
|
||||
|
||||
if (ncp_read_property_value(&conn, NCP_BINDERY_FSERVER,
|
||||
obj.object_name, 1, "NET_ADDRESS",
|
||||
&prop) == 0)
|
||||
{
|
||||
ipx_print_network(naddr->network);
|
||||
printf(" ");
|
||||
ipx_print_node(naddr->node);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
if ((found == 0) && (isatty(1)))
|
||||
{
|
||||
printf("No servers found\n");
|
||||
}
|
||||
|
||||
ncp_close(&conn);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,5 @@
|
||||
# abcd is my ipx network number and 1234 my server's internal network number.
|
||||
# 00001b038b11 is the server's node number.
|
||||
#
|
||||
ipx_interface add -p eth0 EtherII 10
|
||||
ipx_route add 1992 10 00001b3bc0c9
|
||||
ipx_route add 1234 10 00001b038b11
|
||||
ipx_interface add -p eth0 EtherII 1234
|
||||
ipx_route add 10 1234 00001b039949
|
||||
Reference in New Issue
Block a user