Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
92f749a943 | ||
|
|
6cb56005ea | ||
|
|
0520c1d2f7 | ||
|
|
d5ac4601b1 | ||
|
|
1fa124bd7c | ||
|
|
5753870858 | ||
|
|
b8ce93c8bd | ||
|
|
7bef99df0f | ||
|
|
d31ec2ab61 | ||
|
|
1ee60bade6 | ||
|
|
20589ca203 | ||
|
|
517e207709 | ||
|
|
5d4b23a5c1 | ||
|
|
c6124785a9 | ||
|
|
f2bcb2c71e |
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.16.tgz
Normal file
BIN
.downloads/ncpfs-0.16.tgz
Normal file
Binary file not shown.
BIN
.downloads/ncpfs-0.17.tgz
Normal file
BIN
.downloads/ncpfs-0.17.tgz
Normal file
Binary file not shown.
BIN
.downloads/ncpfs-0.18.tgz
Normal file
BIN
.downloads/ncpfs-0.18.tgz
Normal file
Binary file not shown.
BIN
.downloads/ncpfs-0.19.tgz
Normal file
BIN
.downloads/ncpfs-0.19.tgz
Normal file
Binary file not shown.
BIN
.downloads/ncpfs-0.20.tgz
Normal file
BIN
.downloads/ncpfs-0.20.tgz
Normal file
Binary file not shown.
BIN
.downloads/ncpfs-0.21.tgz
Normal file
BIN
.downloads/ncpfs-0.21.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.
21
BUGS
21
BUGS
@@ -3,17 +3,20 @@ them to be bugs.
|
||||
|
||||
But there are really problems that might be fixed in the future.
|
||||
|
||||
'df' returns 0:
|
||||
Free disk space is distributed among the volumes in NetWare. df is
|
||||
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.
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
'df' returns 0: Free disk space is distributed among the volumes in
|
||||
NetWare. df is only able to report one number per mounted
|
||||
filesystem. As connections are quite expensive for NetWare (with
|
||||
mars_nwe and lwared that might change ...), I rejected the alternative
|
||||
to mount only a single volume for a unix mount point. So I simply
|
||||
return 0.
|
||||
|
||||
In your kernel log, there will appear messages like
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
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. Maybe this will be
|
||||
fixed in the future.
|
||||
These are a bit annoying, but completely harmless.
|
||||
|
||||
94
Changes
Normal file
94
Changes
Normal file
@@ -0,0 +1,94 @@
|
||||
I only began this file with ncpfs-0.12. If you're interested in older
|
||||
versions, you can find them on ftp.gwdg.de:/pub/linux/misc/ncpfs/old.
|
||||
|
||||
ncpfs-0.20 -> ncpfs-0.21
|
||||
- Included two bugfixes in ncplib.c found by Jeff Buhrt
|
||||
<buhrt@iquest.net>.
|
||||
- Included a bugfix in kernel code that could only show for servers
|
||||
that do not support namespace calls. I should have tried ncpfs
|
||||
against lwared... Thanks to Neil Turton <ndt1001@chu.cam.ac.uk> for
|
||||
this fix.
|
||||
|
||||
ncpfs-0.19 -> ncpfs-0.20
|
||||
- Changed the home site for ncpfs from linux01.gwdg.de:/pub/ncpfs
|
||||
to ftp.gwdg.de:/pub/linux/misc/ncpfs. linux01 will remain available,
|
||||
but we would like to reduce the load on that machine. Sites
|
||||
mirroring linux01 please redirect your mirror software to
|
||||
ftp.gwdg.de. Thanks.
|
||||
- Removed a bug in ncplib.c that made slist require a full
|
||||
login. Thanks to Neil Turton <ndt1001@chu.cam.ac.uk> for the hint.
|
||||
- The first real user contribution: ncopy by Brian G. Reid
|
||||
(breid@tim.com) and Tom C. Henderson (thenderson@tim.com). Many
|
||||
thanks to you! If you find bugs in ncopy, tell them, not me ;-)
|
||||
- Handle expired passwords. Thanks to "Mathew Lim" <M.Lim@sp.ac.sg>
|
||||
for the hint.
|
||||
|
||||
ncpfs-0.18 -> ncpfs-0.19
|
||||
|
||||
- hacked around in ncplib.[ch] quite heavily.
|
||||
- SAP handling in ipxparse.c. Thanks to Jeff Buhrt <buhrt@iquest.net>
|
||||
- Changed error handling to use the com_err library. This should
|
||||
eventually provide better error messages, because it's now much
|
||||
easier to define nice messages.
|
||||
- If no server is active, report this correctly
|
||||
- added nsend
|
||||
|
||||
ncpfs-0.17 -> ncpfs-0.18
|
||||
|
||||
- Another attempt at solving the problem that -n is not working.
|
||||
- Forgot nprint in 0.17 util/Makefile.
|
||||
- nprint left connections open when it fails
|
||||
- added options -r and -t to ncpmount to tune ncpfs connections.
|
||||
|
||||
ncpfs-0.16 -> ncpfs-0.17
|
||||
|
||||
- Changed the name of fsinfo to nwfsinfo, to avoid a name clash with
|
||||
the X windows utility. Thanks to Henning Brockfeld
|
||||
<Henning.Brockfeld@lrz.uni-muenchen.de> for this hint. (still
|
||||
waiting for your scripts.. :-))
|
||||
- made nwmsg available. This enables you to receive NetWare user
|
||||
broadcast messages. Please note that you need at least kernel 1.3.68
|
||||
for this feature.
|
||||
- pserver now prints debugging output via syslog().
|
||||
- Included ipxdump, a nice little utility, that has helped some
|
||||
people.
|
||||
|
||||
- And now the big one: you can re-export ncpfs-mounted directories
|
||||
with nfsd! You have to mount single volumes by specifying -V volume
|
||||
to ncpmount, and call nfsd and mountd with the option --re-export.
|
||||
See the manual page of ncpmount for more information. Please note
|
||||
that I will send Linus the required patch on 1. March 1996, so you
|
||||
will have to use kernel 1.2.13 or wait at least for 1.3.70.
|
||||
|
||||
ncpfs-0.15 -> ncpfs-0.16
|
||||
|
||||
- Included ipx-1.0, made available by Greg Page <greg@caldera.com>,
|
||||
Caldera
|
||||
- Made -n work for password-less accounts. Thanks to Alexander Jolk
|
||||
<jolk@ap-pc513b.physik.uni-karlsruhe.de>.
|
||||
- Fixed the kerneld support.
|
||||
- Fixed the NetWare 4.1 problem. Many thanks to
|
||||
Chatchai JANTARAPRIM <chat@ratree.psu.ac.th> and
|
||||
hitesh.soneji@industry.net for their patience.
|
||||
|
||||
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.
|
||||
41
FAQ
Normal file
41
FAQ
Normal file
@@ -0,0 +1,41 @@
|
||||
There is certainly not enough material to call this an FAQ, but some
|
||||
questions reach me regularly. Probably the documenation is not clear
|
||||
enough.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Q: Does ncpfs support long file names, using the OS/2 namespace?
|
||||
|
||||
No. Not yet. I still have to sort out how that really works. But it should
|
||||
certainly be possible.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Q: When I re-export ncpfs-mounted directories via nfs, I get messages like
|
||||
'pwd: cannot get current directory', and other strange things happen to
|
||||
the nfs clients. What's wrong?
|
||||
|
||||
When you want to export a directory via NFS, you have to do two things:
|
||||
|
||||
- You have to invoke mountd and nfsd with the option --re-export. On my
|
||||
computer, both are invoked at system startup from the file
|
||||
/etc/rc.d/rc.inet2.
|
||||
|
||||
- You can not export a complete NetWare server hierarchy with all volumes
|
||||
under a single mount point. You have to mount a single server volume to
|
||||
make it re-exportable. Invoke ncpmount with the option -V volume to do
|
||||
this.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Q: When I compile ncpfs, I get a message like the following:
|
||||
|
||||
make[1]: Entering directory `/home/me/netware/ncpfs/kernel-1.2/src'
|
||||
gcc -D__KERNEL__ -I. -Wall -Wstrict-prototypes -O2 -DMODULE -fomit-frame-pointer -I/home/me/netware/ncpfs/kernel-1.2 -DNCPFS_VERSION=\"0.17\" -c dir.c
|
||||
dir.c:36: warning: `struct dirent' declared inside parameter list
|
||||
dir.c:36: warning: its scope is only this definition or declaration,
|
||||
...
|
||||
|
||||
You try to compile the part of ncpfs that is meant for kernel 1.2.13 under
|
||||
kernel 1.3.x. Please look at the Makefile and comment out the
|
||||
corresponding lines.
|
||||
53
Makefile
53
Makefile
@@ -2,37 +2,48 @@
|
||||
# Makefile for the linux ncp-filesystem routines.
|
||||
#
|
||||
|
||||
KERNEL = 1.3
|
||||
VERSION = 0.21
|
||||
TOPDIR = $(shell pwd)
|
||||
|
||||
INCLUDES = -I/usr/src/linux/include -Ikernel
|
||||
BINDIR = ./bin
|
||||
BINDIR = /usr/local/bin
|
||||
SBINDIR = /sbin
|
||||
INTERM_BINDIR = $(TOPDIR)/bin
|
||||
SUBDIRS = util ipx-1.0 man
|
||||
|
||||
CFLAGS = -Wall $(INCLUDES)
|
||||
CC = gcc
|
||||
#
|
||||
# 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
|
||||
|
||||
all: kernel
|
||||
make -C util
|
||||
make -C kernel/src ncpfs.o
|
||||
cp kernel/src/ncpfs.o bin
|
||||
# If you are using kerneld to autoload ncp support,
|
||||
# uncomment this (kerneld is in linux since about 1.3.57):
|
||||
#KERNELD = -DHAVE_KERNELD
|
||||
|
||||
kernel:
|
||||
rm -f kernel
|
||||
ln -s kernel-$(KERNEL) kernel
|
||||
export INCLUDES BINDIR INTERM_BINDIR SBINDIR KERNELD VERSION
|
||||
|
||||
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 kernel
|
||||
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 -fr bin/* ncpfs.tgz util/mnt
|
||||
make -C util realclean
|
||||
mrproper: clean
|
||||
rm -fr $(INTERM_BINDIR)/* ncpfs.tgz
|
||||
make -C util mrproper
|
||||
|
||||
modules: ncpfs.o
|
||||
|
||||
@@ -40,7 +51,11 @@ SRCPATH=$(shell pwd)
|
||||
SRCDIR=$(shell basename $(SRCPATH))
|
||||
DISTFILE=$(SRCDIR).tgz
|
||||
|
||||
dist: realclean
|
||||
dist: tgz
|
||||
make dep
|
||||
make all
|
||||
|
||||
tgz: mrproper
|
||||
(cd ..; \
|
||||
tar cvf - $(SRCDIR) | \
|
||||
gzip -9 > $(DISTFILE); \
|
||||
|
||||
99
README
99
README
@@ -1,11 +1,53 @@
|
||||
This is version 0.6 of ncpfs, a free NetWare client for Linux. You
|
||||
need at least kernel 1.3.44 for this version. It does NOT work with
|
||||
any lower one, especially not with version 1.2.x.
|
||||
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. The opposite side, pserver, is also
|
||||
provided.
|
||||
|
||||
To install ncpfs, just type 'make'. After that, you find the
|
||||
neccessary kernel module and the mounting tools in ./bin. Type 'insmod
|
||||
ncpfs.o' and then 'ncpmount server mount-point'. For further
|
||||
information, please look at the manual pages in ./man.
|
||||
INSTALLATION
|
||||
|
||||
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.
|
||||
|
||||
If you use Kernel 1.3, please be sure that you use at least
|
||||
1.3.71. ncpfs does NOT work with any earlier 1.3.x kernel.
|
||||
|
||||
If you use Kernel 1.3.71 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.71 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.
|
||||
|
||||
|
||||
HELP
|
||||
|
||||
In the meantime my mail volume has grown considerably, so the response
|
||||
time might be better at the LinWare mailing list than at my personal
|
||||
email address. You can mail to and/or subscribe to the LinWare mailing
|
||||
list:
|
||||
|
||||
Topics for the list:
|
||||
- discussing LinWare server, its features, installation problems and bugs
|
||||
- using IPX protocol under Linux
|
||||
- IPX routing and router daemons under Linux
|
||||
- mars_nwe
|
||||
- ncpfs
|
||||
|
||||
You can subscribe to the list by sending the command "add linware" in
|
||||
the mail message body to address: "listserv@sh.cvut.cz". Your
|
||||
postings should be sent to: "linware@sh.cvut.cz".
|
||||
|
||||
|
||||
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
|
||||
@@ -19,8 +61,8 @@ 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 +72,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 +82,23 @@ 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.
|
||||
|
||||
Look at the file Changes for others.
|
||||
|
||||
|
||||
LIMITATIONS (compare these with smbfs :-)
|
||||
|
||||
The limitations ncpfs has are the natural limitations of the NCP
|
||||
@@ -48,16 +107,10 @@ limitation is the lack of uid, gid and permission information per
|
||||
file. You have to assign those values once for a complete mounted
|
||||
directory.
|
||||
|
||||
The second limitation is just as annoying as the first: You cannot
|
||||
re-export a ncp-mounted directory by nfs. It is not possible because
|
||||
the NFS protocol defines access to files through unique file handles,
|
||||
which can be mapped to the device and inode numbers in unix NFS
|
||||
servers. NCP does not have unique numbers per file, you only have the
|
||||
path name. I implemented a caching scheme for inode numbers, which
|
||||
gives unique inode numbers for every open file in the system. This is
|
||||
just sufficient for local use of the files, because you can tell when
|
||||
an inode number can be discarded. With NFS the situation is
|
||||
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.
|
||||
You will not be able to access servers that require packet
|
||||
signatures. This seems to be one of Novell's bigger secrets :-(.
|
||||
|
||||
Have fun with ncpfs!
|
||||
|
||||
Volker
|
||||
lendecke@namu01.gwdg.de
|
||||
|
||||
20
TODO
Normal file
20
TODO
Normal file
@@ -0,0 +1,20 @@
|
||||
Here's a list of things I want to do. Feel free to send suggestions,
|
||||
or even help me ;-).
|
||||
|
||||
- little utilities for bindery access, such as nwlsobj, nwlsprop,
|
||||
nwcreateobj and so on.
|
||||
|
||||
- Add flags to pserver's command line, so that the print command can
|
||||
find out the name of user who printed the job.
|
||||
|
||||
- do rtt estimation, like tcp does.
|
||||
|
||||
- Do better connection management. I imagine to create a ncpd.
|
||||
|
||||
- When ncp is done, one can think about mounting several volumes over
|
||||
a single NCP connection. This should make the trade-off mentioned in
|
||||
ncpmount.8 unnecessary.
|
||||
|
||||
- long file names
|
||||
|
||||
- Do some kind of mapping of NCP uid's to unix uid's
|
||||
9
ipx-1.0/COPYING
Normal file
9
ipx-1.0/COPYING
Normal file
@@ -0,0 +1,9 @@
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the original work is
|
||||
properly attributed to Greg Page and Caldera, Inc.
|
||||
Neither the name of Greg Page nor Caldera, Inc. may be used to
|
||||
endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
This software is provided by Greg Page and Caldera, Inc. "AS IS"
|
||||
and without any express or implied warranties.
|
||||
|
||||
24
ipx-1.0/Gregs.Makefile
Normal file
24
ipx-1.0/Gregs.Makefile
Normal file
@@ -0,0 +1,24 @@
|
||||
CFLAGS = -O2 -Wall
|
||||
UTILS = ipx_configure ipx_interface ipx_internal_net ipx_route
|
||||
all: $(UTILS)
|
||||
|
||||
clean:
|
||||
rm -f $(UTILS) *.o rip sap ipxrcv ipxsend
|
||||
|
||||
install: $(UTILS)
|
||||
for i in $(UTILS); \
|
||||
do \
|
||||
install --strip $$i /sbin; \
|
||||
install $$i.8 /usr/man/man8; \
|
||||
done
|
||||
install init.ipx /etc/rc.d/init.d/ipx
|
||||
install -m 0644 config.ipx /etc/sysconfig/ipx
|
||||
rm -f /etc/rc.d/rc2.d/S15ipx
|
||||
ln -sf /etc/rc.d/init.d/ipx /etc/rc.d/rc2.d/S15ipx
|
||||
rm -f /etc/rc.d/rc3.d/S15ipx
|
||||
ln -sf /etc/rc.d/init.d/ipx /etc/rc.d/rc3.d/S15ipx
|
||||
rm -f /etc/rc.d/rc5.d/S15ipx
|
||||
ln -sf /etc/rc.d/init.d/ipx /etc/rc.d/rc5.d/S15ipx
|
||||
rm -f /etc/rc.d/rc6.d/K55ipx
|
||||
ln -sf /etc/rc.d/init.d/ipx /etc/rc.d/rc6.d/K55ipx
|
||||
|
||||
30
ipx-1.0/Makefile
Normal file
30
ipx-1.0/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) -o $(INTERM_BINDIR)/ipx_configure ipx_configure.o
|
||||
|
||||
$(INTERM_BINDIR)/ipx_interface: ipx_interface.o
|
||||
$(CC) -o $(INTERM_BINDIR)/ipx_interface ipx_interface.o
|
||||
|
||||
$(INTERM_BINDIR)/ipx_internal_net: ipx_internal_net.o
|
||||
$(CC) -o $(INTERM_BINDIR)/ipx_internal_net ipx_internal_net.o
|
||||
|
||||
$(INTERM_BINDIR)/ipx_route: ipx_route.o
|
||||
$(CC) -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 $$i $(BINDIR); \
|
||||
done
|
||||
|
||||
65
ipx-1.0/README
Normal file
65
ipx-1.0/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 (found in directory Samples):
|
||||
|
||||
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.
|
||||
|
||||
52
ipx-1.0/Samples/ipxrcv.c
Normal file
52
ipx-1.0/Samples/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-1.0/Samples/ipxsend.c
Normal file
46
ipx-1.0/Samples/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-1.0/Samples/rip.c
Normal file
68
ipx-1.0/Samples/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[6], 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-1.0/Samples/sap.c
Normal file
96
ipx-1.0/Samples/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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
7
ipx-1.0/config.ipx
Normal file
7
ipx-1.0/config.ipx
Normal file
@@ -0,0 +1,7 @@
|
||||
IPX_AUTO_PRIMARY=on
|
||||
IPX_AUTO_INTERFACE=on
|
||||
IPX_CONFIGURED=no
|
||||
IPX_DEVICE=eth0
|
||||
IPX_FRAME=802.2
|
||||
IPX_INTERNAL_NET=no
|
||||
IPX_NETNUM=0
|
||||
41
ipx-1.0/init.ipx
Normal file
41
ipx-1.0/init.ipx
Normal file
@@ -0,0 +1,41 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# ipx Bring up/down IPX networking
|
||||
#
|
||||
|
||||
# Source function library.
|
||||
. /etc/rc.d/init.d/functions
|
||||
|
||||
. /etc/sysconfig/network
|
||||
. /etc/sysconfig/ipx
|
||||
|
||||
# Check that networking is up.
|
||||
[ ${NETWORKING} = "no" ] && exit 0
|
||||
|
||||
# See how we were called.
|
||||
case "$1" in
|
||||
start)
|
||||
if [ ${IPX_CONFIGURED} = "yes" ]; then
|
||||
if [ ${IPX_INTERNAL_NET} = "yes" ]; then
|
||||
/sbin/ipx_internal_net add ${IPX_NETNUM}
|
||||
else
|
||||
/sbin/ipx_interface add -p ${IPX_DEVICE} \
|
||||
${IPX_FRAME} ${IPX_NETNUM}
|
||||
fi
|
||||
fi
|
||||
ipx_configure \
|
||||
--auto_primary=${IPX_AUTO_PRIMARY} \
|
||||
--auto_interface=${IPX_AUTO_INTERFACE}
|
||||
touch /var/lock/subsys/ipx
|
||||
;;
|
||||
stop)
|
||||
ipx_configure --auto_primary=off --auto_interface=off
|
||||
ipx_interface delall
|
||||
rm -f /var/lock/subsys/ipx
|
||||
;;
|
||||
*)
|
||||
echo "Usage: network {start|stop}"
|
||||
exit 1
|
||||
esac
|
||||
|
||||
exit 0
|
||||
@@ -1,3 +1,8 @@
|
||||
/* Copyright (c) 1995-1996 Caldera, Inc. All Rights Reserved.
|
||||
*
|
||||
* See file COPYING for details.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
387
ipx-1.0/ipx_interface.c
Normal file
387
ipx-1.0/ipx_interface.c
Normal file
@@ -0,0 +1,387 @@
|
||||
/* Copyright (c) 1995-1996 Caldera, Inc. All Rights Reserved.
|
||||
*
|
||||
* See file COPYING for details.
|
||||
*/
|
||||
|
||||
#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 delall\n\
|
||||
Usage: %s check device frame_type\n", progname, progname, progname, progname);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
struct frame_type {
|
||||
char *ft_name;
|
||||
unsigned char ft_val;
|
||||
} frame_types[] = {
|
||||
{"802.2", IPX_FRAME_8022},
|
||||
#ifdef IPX_FRAME_TR_8022
|
||||
{"802.2TR", IPX_FRAME_TR_8022},
|
||||
#endif
|
||||
{"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_delall_interface(int argc, char **argv)
|
||||
{
|
||||
struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)&id.ifr_addr;
|
||||
int s;
|
||||
int result;
|
||||
char errmsg[80];
|
||||
char buffer[80];
|
||||
char device[20];
|
||||
char frame_type[20];
|
||||
int fti;
|
||||
FILE *fp;
|
||||
|
||||
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||
if (s < 0) {
|
||||
sprintf(errmsg, "%s: socket", progname);
|
||||
perror(errmsg);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
fp = fopen("/proc/net/ipx_interface", "r");
|
||||
if (fp == NULL) {
|
||||
fprintf(stderr,
|
||||
"%s: Unable to open \"/proc/net/ipx_interface.\"\n",
|
||||
progname);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
fgets(buffer, 80, fp);
|
||||
while (fscanf(fp, "%s %s %s %s %s", buffer, buffer, buffer,
|
||||
device, frame_type) == 5) {
|
||||
|
||||
sipx->sipx_network = 0L;
|
||||
if (strcasecmp(device, "Internal") == 0) {
|
||||
sipx->sipx_special = IPX_INTERNAL;
|
||||
} else {
|
||||
sipx->sipx_special = IPX_SPECIAL_NONE;
|
||||
strcpy(id.ifr_name, device);
|
||||
fti = lookup_frame_type(frame_type);
|
||||
if (fti < 0) continue;
|
||||
sipx->sipx_type = frame_types[fti].ft_val;
|
||||
}
|
||||
|
||||
sipx->sipx_action = IPX_DLTITF;
|
||||
sipx->sipx_family = AF_IPX;
|
||||
result = ioctl(s, SIOCSIFADDR, &id);
|
||||
if (result == 0) continue;
|
||||
switch (errno) {
|
||||
case EPROTONOSUPPORT:
|
||||
fprintf(stderr, "%s: Invalid frame type (%s).\n",
|
||||
progname, frame_type);
|
||||
break;
|
||||
case ENODEV:
|
||||
fprintf(stderr, "%s: No such device (%s).\n",
|
||||
progname, device);
|
||||
break;
|
||||
case EINVAL:
|
||||
fprintf(stderr, "%s: No such IPX interface %s %s.\n",
|
||||
progname, device, frame_type);
|
||||
break;
|
||||
default:
|
||||
sprintf(errmsg, "%s: ioctl", progname);
|
||||
perror(errmsg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
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;
|
||||
sipx->sipx_special = IPX_SPECIAL_NONE;
|
||||
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], "delall", 6) == 0) {
|
||||
for (i = 1; i < (argc-1); i++)
|
||||
argv[i] = argv[i+1];
|
||||
ipx_delall_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;
|
||||
}
|
||||
200
ipx-1.0/ipx_internal_net.c
Normal file
200
ipx-1.0/ipx_internal_net.c
Normal file
@@ -0,0 +1,200 @@
|
||||
/* Copyright (c) 1995-1996 Caldera, Inc. All Rights Reserved.
|
||||
*
|
||||
* See file COPYING for details.
|
||||
*/
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
220
ipx-1.0/ipx_route.c
Normal file
220
ipx-1.0/ipx_route.c
Normal file
@@ -0,0 +1,220 @@
|
||||
/* Copyright (c) 1995-1996 Caldera, Inc. All Rights Reserved.
|
||||
*
|
||||
* See file COPYING for details.
|
||||
*/
|
||||
|
||||
#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;
|
||||
}
|
||||
35
ipxdump/Makefile
Normal file
35
ipxdump/Makefile
Normal file
@@ -0,0 +1,35 @@
|
||||
EXEC= ipxdump ipxparse
|
||||
|
||||
CFLAGS= -Wall -O2
|
||||
OBJECTS= ipxutil.o
|
||||
|
||||
all: $(EXEC)
|
||||
|
||||
ipxdump: ipxdump.o $(OBJECTS)
|
||||
$(CC) -o $@ ipxdump.o $(CFLAGS) $(OBJECTS)
|
||||
|
||||
ipxparse: ipxparse.o $(OBJECTS)
|
||||
$(CC) -o $@ ipxparse.o $(CFLAGS) $(OBJECTS)
|
||||
|
||||
clean:
|
||||
rm -f *.o $(EXEC) *~
|
||||
|
||||
|
||||
modules: ncpfs.o
|
||||
|
||||
SRCPATH=$(shell pwd)
|
||||
SRCDIR=$(shell basename $(SRCPATH))
|
||||
DISTFILE=$(SRCDIR).tgz
|
||||
|
||||
mrproper: clean
|
||||
rm -f $(DISTFILE)
|
||||
|
||||
dist: tgz
|
||||
make all
|
||||
|
||||
tgz: mrproper
|
||||
(cd ..; \
|
||||
tar cvf - $(SRCDIR) | \
|
||||
gzip -9 > $(DISTFILE); \
|
||||
mv $(DISTFILE) $(SRCDIR))
|
||||
|
||||
45
ipxdump/README
Normal file
45
ipxdump/README
Normal file
@@ -0,0 +1,45 @@
|
||||
This is a VERY stupid packet sniffer for IPX ethernet packets.
|
||||
|
||||
=============================================
|
||||
! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !
|
||||
! ! ! S E C U R I T Y W A R N I N G ! ! !
|
||||
! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !
|
||||
=============================================
|
||||
|
||||
If you are using unencrypted passwords, and use this tool to send a
|
||||
dump to somebody else or store it on a computer, you might very well
|
||||
store passwords there. So, be VERY careful! This is exactly the kind
|
||||
of tools Novell designed the encrypted passwords for (or against).
|
||||
|
||||
|
||||
|
||||
I hacked it together to be able to help people with problems with
|
||||
ncpfs. The socket handling was taken from Statnet-2.0.
|
||||
|
||||
You can use it to watch commercial NetWare clients when they talk to
|
||||
servers. I divided the program into 2 parts, ipxdump and ipxparse.
|
||||
|
||||
ipxdump simply pumps all the IPX frames it receives to stdout.
|
||||
|
||||
If you use ipxdump to watch a workstation, you can use the simple
|
||||
filter function ipxdump provides. You can call ipxdump with the node
|
||||
address of the workstation you want to watch. This way only the
|
||||
packets this workstation sends and receives are monitored. As an
|
||||
example, I call ipxdump as
|
||||
|
||||
./ipxdump 00001B038B11
|
||||
|
||||
to look at my 286/10MHz test 'workstation'. ipxdump still generates
|
||||
huge amounts of data, so you should be very careful to start it just
|
||||
before you perform the operation (such as file creation for OS/2
|
||||
clients with NW4.1 as a server, or a 'dir' on a directory with long
|
||||
and short file names, or an encrypted password change ;-)) and stop it
|
||||
directly after that. And, please gzip -9 and uuencode it before you
|
||||
send it to anybody.
|
||||
|
||||
ipxparse will eventually take apart the dump that ipxdump
|
||||
generates. They can as well be used in a pipe. Currently ipxparse does
|
||||
not do anything sensible, but that will definitely change.
|
||||
|
||||
Volker Lendecke
|
||||
<lendecke@namu01.gwdg.de>
|
||||
245
ipxdump/ipxdump.c
Normal file
245
ipxdump/ipxdump.c
Normal file
@@ -0,0 +1,245 @@
|
||||
/* ipxdump.c */
|
||||
|
||||
/* Copyright 1996 Volker Lendecke, Goettingen, Germany
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <strings.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/if.h>
|
||||
#include <signal.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/tcp.h>
|
||||
#include <netinet/protocols.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <signal.h>
|
||||
#include "ipxutil.h"
|
||||
|
||||
struct ipx_address
|
||||
{
|
||||
unsigned long net;
|
||||
unsigned char node[IPX_NODE_LEN];
|
||||
unsigned short sock;
|
||||
};
|
||||
|
||||
struct ipx_packet
|
||||
{
|
||||
unsigned short ipx_checksum;
|
||||
#define IPX_NO_CHECKSUM 0xFFFF
|
||||
unsigned short ipx_pktsize;
|
||||
unsigned char ipx_tctrl;
|
||||
unsigned char ipx_type;
|
||||
#define IPX_TYPE_UNKNOWN 0x00
|
||||
#define IPX_TYPE_RIP 0x01 /* may also be 0 */
|
||||
#define IPX_TYPE_SAP 0x04 /* may also be 0 */
|
||||
#define IPX_TYPE_SPX 0x05 /* Not yet implemented */
|
||||
#define IPX_TYPE_NCP 0x11 /* $lots for docs on this (SPIT) */
|
||||
#define IPX_TYPE_PPROP 0x14 /* complicated flood fill brdcast [Not supported] */
|
||||
struct ipx_address ipx_dest __attribute__ ((packed));
|
||||
struct ipx_address ipx_source __attribute__ ((packed));
|
||||
};
|
||||
|
||||
|
||||
void handle_frame (unsigned char *buf, int length, struct sockaddr *saddr);
|
||||
void handle_ipx(char *frame, unsigned char *buf);
|
||||
|
||||
static int filter = 0;
|
||||
static IPXNode filter_node;
|
||||
|
||||
static int exit_request = 0;
|
||||
static void
|
||||
int_handler()
|
||||
{
|
||||
exit_request = 1;
|
||||
}
|
||||
|
||||
void
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
int sd;
|
||||
struct ifreq ifr, oldifr;
|
||||
char *device = "eth0";
|
||||
struct sockaddr saddr;
|
||||
int sizeaddr;
|
||||
unsigned char buf[4096];
|
||||
int length;
|
||||
|
||||
signal(SIGINT, int_handler);
|
||||
|
||||
if (argc > 1)
|
||||
{
|
||||
if (ipx_sscanf_node(argv[1], filter_node) != 0)
|
||||
{
|
||||
fprintf(stderr, "usage: %s [node]\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
filter = 1;
|
||||
}
|
||||
|
||||
if ((sd = socket (AF_INET, SOCK_PACKET, htons (ETH_P_ALL))) < 0)
|
||||
{
|
||||
perror ("Can't get socket");
|
||||
fprintf(stderr, "You must run %s as root\n", argv[0]);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* SET PROMISC */
|
||||
|
||||
strcpy (oldifr.ifr_name, device);
|
||||
if (ioctl (sd, SIOCGIFFLAGS, &oldifr) < 0)
|
||||
{
|
||||
close (sd);
|
||||
perror ("Can't get flags");
|
||||
exit (2);
|
||||
}
|
||||
|
||||
/* This should be rewritten to cooperate with other net tools */
|
||||
ifr = oldifr;
|
||||
ifr.ifr_flags |= IFF_PROMISC;
|
||||
|
||||
if (ioctl (sd, SIOCSIFFLAGS, &ifr) < 0)
|
||||
{
|
||||
close (sd);
|
||||
perror ("Can't set flags");
|
||||
exit (3);
|
||||
}
|
||||
|
||||
while ( exit_request == 0 )
|
||||
{
|
||||
/* This is the main data-gathering loop; keep it small
|
||||
and fast */
|
||||
sizeaddr = sizeof(saddr);
|
||||
length = recvfrom (sd, buf, sizeof(buf), 0,
|
||||
&saddr, &sizeaddr);
|
||||
if (length < 0 ) continue;
|
||||
handle_frame (buf, length, &saddr);
|
||||
}
|
||||
|
||||
/* This should be rewritten to cooperate with other net tools */
|
||||
if (ioctl (sd, SIOCSIFFLAGS, &oldifr) < 0)
|
||||
{
|
||||
close (sd);
|
||||
perror ("Can't set flags");
|
||||
exit (4);
|
||||
}
|
||||
|
||||
close (sd);
|
||||
exit (0);
|
||||
}
|
||||
|
||||
void
|
||||
handle_ipx (char *frame, unsigned char *buf)
|
||||
{
|
||||
int i;
|
||||
struct ipx_packet *h = (struct ipx_packet *)buf;
|
||||
struct sockaddr_ipx s_addr;
|
||||
struct sockaddr_ipx d_addr;
|
||||
int length = ntohs(h->ipx_pktsize);
|
||||
|
||||
|
||||
memset(&s_addr, 0, sizeof(s_addr));
|
||||
memset(&d_addr, 0, sizeof(d_addr));
|
||||
|
||||
memcpy(s_addr.sipx_node, h->ipx_source.node, sizeof(s_addr.sipx_node));
|
||||
s_addr.sipx_port = h->ipx_source.sock;
|
||||
s_addr.sipx_network = h->ipx_source.net;
|
||||
|
||||
memcpy(d_addr.sipx_node, h->ipx_dest.node, sizeof(d_addr.sipx_node));
|
||||
d_addr.sipx_port = h->ipx_dest.sock;
|
||||
d_addr.sipx_network = h->ipx_dest.net;
|
||||
|
||||
if (filter != 0)
|
||||
{
|
||||
if ( (memcmp(filter_node, s_addr.sipx_node,
|
||||
sizeof(filter_node)) != 0)
|
||||
&& (memcmp(filter_node, d_addr.sipx_node,
|
||||
sizeof(filter_node)) != 0))
|
||||
{
|
||||
/* Not for us */
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
printf("%s ", frame);
|
||||
|
||||
for (i = 0; i < length; i++)
|
||||
{
|
||||
printf("%2.2X", buf[i]);
|
||||
}
|
||||
printf("\n");
|
||||
if (!isatty(STDOUT_FILENO))
|
||||
{
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
handle_other (unsigned char *buf, int length, struct sockaddr *saddr)
|
||||
{
|
||||
struct ethhdr *eth = (struct ethhdr *)buf;
|
||||
unsigned char *p = &(buf[sizeof(struct ethhdr)]);
|
||||
|
||||
if (ntohs(eth->h_proto) < 1536)
|
||||
{
|
||||
/* This is a magic hack to spot IPX packets. Older
|
||||
* Novell breaks the protocol design and runs IPX over
|
||||
* 802.3 without an 802.2 LLC layer. We look for FFFF
|
||||
* which isnt a used 802.2 SSAP/DSAP. This won't work
|
||||
* for fault tolerant netware but does for the rest.
|
||||
*/
|
||||
|
||||
if (*(unsigned short *)p == 0xffff)
|
||||
{
|
||||
handle_ipx("802.3", p);
|
||||
return;
|
||||
}
|
||||
|
||||
if ( (*(unsigned short *)p == htons(0xe0e0))
|
||||
&& (p[2] == 0x03))
|
||||
{
|
||||
handle_ipx("802.2", p+3);
|
||||
return;
|
||||
}
|
||||
|
||||
if (memcmp(p, "\252\252\003\000\000\000\201\067", 8) == 0)
|
||||
{
|
||||
handle_ipx("snap", p+8);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
handle_frame (unsigned char *buf, int length, struct sockaddr *saddr)
|
||||
{
|
||||
/* Ethernet packet type ID field */
|
||||
unsigned short packet_type = ((struct ethhdr *)buf)->h_proto;
|
||||
switch( packet_type )
|
||||
{
|
||||
case __constant_ntohs(ETH_P_IPX):
|
||||
handle_ipx("EtherII ", &(buf[sizeof(struct ethhdr)]));
|
||||
break;
|
||||
default:
|
||||
handle_other(buf, length, saddr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
538
ipxdump/ipxparse.c
Normal file
538
ipxdump/ipxparse.c
Normal file
@@ -0,0 +1,538 @@
|
||||
/* ipxparse.c */
|
||||
|
||||
/* Copyright 1996 Volker Lendecke, Goettingen, Germany
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <strings.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/if.h>
|
||||
#include <signal.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/tcp.h>
|
||||
#include <netinet/protocols.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <signal.h>
|
||||
#include <ctype.h>
|
||||
#include "ipxutil.h"
|
||||
|
||||
#define DUMPALLSAPS /* #define if you want to dump all SAP's */
|
||||
|
||||
struct ipx_address
|
||||
{
|
||||
unsigned long net;
|
||||
unsigned char node[IPX_NODE_LEN];
|
||||
unsigned short sock;
|
||||
};
|
||||
|
||||
struct ipx_packet
|
||||
{
|
||||
unsigned short ipx_checksum;
|
||||
#define IPX_NO_CHECKSUM 0xFFFF
|
||||
unsigned short ipx_pktsize;
|
||||
unsigned char ipx_tctrl;
|
||||
unsigned char ipx_type;
|
||||
#define IPX_TYPE_UNKNOWN 0x00
|
||||
#define IPX_TYPE_RIP 0x01 /* may also be 0 */
|
||||
#define IPX_TYPE_SAP 0x04 /* may also be 0 */
|
||||
#define IPX_TYPE_SPX 0x05 /* Not yet implemented */
|
||||
#define IPX_TYPE_NCP 0x11 /* $lots for docs on this (SPIT) */
|
||||
#define IPX_TYPE_PPROP 0x14 /* complicated flood fill brdcast [Not supported] */
|
||||
struct ipx_address ipx_dest __attribute__ ((packed));
|
||||
struct ipx_address ipx_source __attribute__ ((packed));
|
||||
};
|
||||
|
||||
#define NCP_ALLOC_SLOT_REQUEST (0x1111)
|
||||
#define NCP_REQUEST (0x2222)
|
||||
#define NCP_DEALLOC_SLOT_REQUEST (0x5555)
|
||||
|
||||
struct ncp_request_header {
|
||||
__u16 type __attribute__ ((packed));
|
||||
__u8 sequence __attribute__ ((packed));
|
||||
__u8 conn_low __attribute__ ((packed));
|
||||
__u8 task __attribute__ ((packed));
|
||||
__u8 conn_high __attribute__ ((packed));
|
||||
__u8 function __attribute__ ((packed));
|
||||
__u8 data[0] __attribute__ ((packed));
|
||||
};
|
||||
|
||||
#define NCP_REPLY (0x3333)
|
||||
#define NCP_POSITIVE_ACK (0x9999)
|
||||
|
||||
struct ncp_reply_header {
|
||||
__u16 type __attribute__ ((packed));
|
||||
__u8 sequence __attribute__ ((packed));
|
||||
__u8 conn_low __attribute__ ((packed));
|
||||
__u8 task __attribute__ ((packed));
|
||||
__u8 conn_high __attribute__ ((packed));
|
||||
__u8 completion_code __attribute__ ((packed));
|
||||
__u8 connection_state __attribute__ ((packed));
|
||||
__u8 data[0] __attribute__ ((packed));
|
||||
};
|
||||
|
||||
void handle_ipx (unsigned char *buf, int length, char *frame, int no);
|
||||
void handle_ncp (struct sockaddr_ipx *source,
|
||||
struct sockaddr_ipx *target,
|
||||
unsigned char *buf, int length, int no);
|
||||
|
||||
#define SAP_MAX_SERVER_NAME_LENGTH 48 /* in network packets */
|
||||
#define SAP_MAX_SAPS_PER_PACKET 7
|
||||
#define SAP_SHUTDOWN 16 /* Magic "hops" value to stop SAP advertising */
|
||||
|
||||
/* SAP Query structure (returned in sap_packet as an array)
|
||||
* NBO == Network Byte Order)
|
||||
*/
|
||||
typedef struct saps {
|
||||
__u16 serverType __attribute__ ((packed)); /* NBO */
|
||||
__u8 serverName[SAP_MAX_SERVER_NAME_LENGTH] __attribute__ ((packed));
|
||||
struct ipx_address serverAddress __attribute__ ((packed));
|
||||
__u16 serverHops __attribute__ ((packed)); /* NBO */
|
||||
} SAPS;
|
||||
|
||||
/* General Service/Nearest Server Response SAP packet */
|
||||
union sap_packet {
|
||||
unsigned short sapOperation;
|
||||
struct sap_query {
|
||||
__u16 sapOperation __attribute__ ((packed));
|
||||
__u16 serverType __attribute__ ((packed));
|
||||
} query;
|
||||
struct sap_response {
|
||||
__u16 sapOperation __attribute__ ((packed));
|
||||
/* each SAP can has a max of SAP_MAX_SAPS_PER_PACKET packets */
|
||||
SAPS sap[SAP_MAX_SAPS_PER_PACKET] __attribute__ ((packed));
|
||||
} response;
|
||||
};
|
||||
|
||||
/* print out one SAP record */
|
||||
static void
|
||||
print_sap(FILE *file, SAPS *sapp)
|
||||
{
|
||||
fprintf(file, " Name:%s, serverType 0x%x, ",
|
||||
sapp->serverName,
|
||||
ntohs(sapp->serverType));
|
||||
ipx_fprint_network(file, ntohl(sapp->serverAddress.net));
|
||||
fprintf(file, ":");
|
||||
ipx_fprint_node(file, sapp->serverAddress.node);
|
||||
fprintf(file, ":");
|
||||
ipx_fprint_port(file, ntohs(sapp->serverAddress.sock));
|
||||
fprintf(file, " (Hops %d)\n", ntohs(sapp->serverHops));
|
||||
}
|
||||
|
||||
void
|
||||
handle_ipx (unsigned char *buf, int length, char *frame, int no)
|
||||
{
|
||||
struct ipx_packet *h = (struct ipx_packet *)buf;
|
||||
struct sockaddr_ipx s_addr;
|
||||
struct sockaddr_ipx d_addr;
|
||||
union sap_packet *sappacket;
|
||||
int hbo_dsock; /* Host Byte Order of Destination SOCKet */
|
||||
int hbo_sapop; /* Host Byte Order of SAP OPeration */
|
||||
|
||||
memset(&s_addr, 0, sizeof(s_addr));
|
||||
memset(&d_addr, 0, sizeof(d_addr));
|
||||
|
||||
memcpy(s_addr.sipx_node, h->ipx_source.node, sizeof(s_addr.sipx_node));
|
||||
s_addr.sipx_port = h->ipx_source.sock;
|
||||
s_addr.sipx_network = h->ipx_source.net;
|
||||
|
||||
memcpy(d_addr.sipx_node, h->ipx_dest.node, sizeof(d_addr.sipx_node));
|
||||
d_addr.sipx_port = h->ipx_dest.sock;
|
||||
d_addr.sipx_network = h->ipx_dest.net;
|
||||
|
||||
printf("%6.6d %s from ", no, frame);
|
||||
|
||||
ipx_print_saddr(&s_addr);
|
||||
printf(" to ");
|
||||
ipx_print_saddr(&d_addr);
|
||||
printf("\n");
|
||||
|
||||
if ( (ntohs(s_addr.sipx_port) == 0x451)
|
||||
|| (ntohs(d_addr.sipx_port) == 0x451))
|
||||
{
|
||||
handle_ncp(&s_addr, &d_addr, buf + sizeof(struct ipx_packet),
|
||||
length - sizeof(struct ipx_packet), no);
|
||||
}
|
||||
else /* next 3 handle IPX by type vs by socket (one or other) */
|
||||
/* Note: most things use either ipx_type OR socket, not both */
|
||||
if (h->ipx_type == 0x01)
|
||||
printf(" type 0x01 (RIP packet (router))\n");
|
||||
else
|
||||
if (h->ipx_type == 0x05)
|
||||
printf(" type 0x05 (SPX sequenced packet)\n");
|
||||
else
|
||||
if (h->ipx_type == 0x14)
|
||||
printf(" type 0x14 (propogated Client-NetBios)\n");
|
||||
else
|
||||
{
|
||||
hbo_dsock = ntohs(d_addr.sipx_port);
|
||||
if (hbo_dsock == 0x452) /* SAP */
|
||||
{
|
||||
sappacket = (union sap_packet *)
|
||||
(buf + sizeof(struct ipx_packet));
|
||||
hbo_sapop = ntohs(sappacket->sapOperation);
|
||||
if ((hbo_sapop == 0x01) || (hbo_sapop == 0x03))
|
||||
{
|
||||
printf(" type 0x%x, SAP op:0x%x %s Query, "
|
||||
"serverType 0x%x wanted\n",
|
||||
h->ipx_type, hbo_sapop,
|
||||
(hbo_sapop == 0x01)?"General Service" :
|
||||
(hbo_sapop == 0x03)?"Nearest Server" :
|
||||
"Error",
|
||||
ntohs(sappacket->query.serverType));
|
||||
}
|
||||
else
|
||||
{
|
||||
int hops;
|
||||
|
||||
hops = ntohs(sappacket->
|
||||
response.sap[0].serverHops);
|
||||
printf(" type 0x%x, SAP op:0x%x %s %s\n",
|
||||
h->ipx_type, hbo_sapop,
|
||||
(hbo_sapop == 0x02)
|
||||
? "General Service Response" :
|
||||
(hbo_sapop == 0x04)
|
||||
? "Nearest Server Response" :
|
||||
"Unknown",
|
||||
(hops >= SAP_SHUTDOWN)
|
||||
? "[Shutdown]" : "");
|
||||
|
||||
/* Service ending */
|
||||
if (hops >= SAP_SHUTDOWN)
|
||||
{
|
||||
print_sap(stdout,
|
||||
sappacket->response.sap);
|
||||
}
|
||||
#ifdef DUMPALLSAPS
|
||||
/* If you want to dump all SAP's */
|
||||
else
|
||||
{ int num_saps;
|
||||
SAPS *sapp;
|
||||
|
||||
num_saps = (length
|
||||
- sizeof(struct ipx_packet)
|
||||
- 2) / sizeof(SAPS);
|
||||
|
||||
sapp = sappacket->response.sap;
|
||||
for(; num_saps > 0; sapp++, num_saps--)
|
||||
print_sap(stdout, sapp);
|
||||
}
|
||||
#endif /* DUMPALLSAPS */
|
||||
}
|
||||
|
||||
}
|
||||
else /* Other IPX types */
|
||||
printf(" type 0x%x, Socket 0x%x (%s)\n", h->ipx_type,
|
||||
hbo_dsock,
|
||||
(hbo_dsock == 0x451) ? "NCP" :
|
||||
/* (hbo_dsock == 0x452) ? "SAP" :*/
|
||||
(hbo_dsock == 0x453) ? "RIP" :
|
||||
(hbo_dsock == 0x455) ? "Client-NetBios" :
|
||||
(hbo_dsock == 0x456) ? "Diags" :
|
||||
(hbo_dsock == 0x002) ? "Xecho" :
|
||||
(hbo_dsock == 0x8063) ? "NVT2" : "Other");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void handle_ncp (struct sockaddr_ipx *source,
|
||||
struct sockaddr_ipx *target,
|
||||
unsigned char *buf, int length, int no)
|
||||
{
|
||||
struct ncp_request_header *rq = (struct ncp_request_header *)buf;
|
||||
struct ncp_reply_header *rs = (struct ncp_reply_header *)buf;
|
||||
unsigned char *data = NULL;
|
||||
int data_length = 0;
|
||||
int i;
|
||||
|
||||
if (ntohs(rq->type) == NCP_REQUEST)
|
||||
{
|
||||
/* Request */
|
||||
printf("NCP request: conn: %-5d, seq: %-3d, task: %-3d, ",
|
||||
rq->conn_low + 256 * rq->conn_high,
|
||||
rq->sequence, rq->task);
|
||||
|
||||
data = buf + sizeof(struct ncp_request_header);
|
||||
data_length = length - sizeof(struct ncp_request_header);
|
||||
|
||||
switch(rq->function)
|
||||
{
|
||||
case 20:
|
||||
printf("fn: %-3d\n", rq->function);
|
||||
printf("Get File Server Date and Time\n");
|
||||
break;
|
||||
case 21:
|
||||
printf("fn: %-3d, subfn: %-3d\n",
|
||||
rq->function, data[2]);
|
||||
switch(data[2])
|
||||
{
|
||||
case 0:
|
||||
printf("Send Broadcast Message\n");
|
||||
break;
|
||||
case 1:
|
||||
printf("Get Broadcast Message\n");
|
||||
break;
|
||||
}
|
||||
data += 3;
|
||||
data_length -= 3;
|
||||
break;
|
||||
case 22:
|
||||
printf("fn: %-3d, subfn: %-3d\n",
|
||||
rq->function, data[2]);
|
||||
switch(data[2])
|
||||
{
|
||||
case 00:
|
||||
printf("Set Directory Handle\n");
|
||||
break;
|
||||
case 01:
|
||||
printf("Get Directory Path\n");
|
||||
break;
|
||||
case 18:
|
||||
printf("Allocate Permanent Dir Handle\n");
|
||||
break;
|
||||
case 20:
|
||||
printf("Deallocate Directory Handle\n");
|
||||
break;
|
||||
case 21:
|
||||
printf("Get Volume Info with handle\n");
|
||||
break;
|
||||
}
|
||||
data += 3;
|
||||
data_length -= 3;
|
||||
break;
|
||||
case 23:
|
||||
printf("fn: %-3d, subfn: %-3d\n", rq->function,
|
||||
data[2]);
|
||||
switch(data[2])
|
||||
{
|
||||
case 17:
|
||||
printf("Get Fileserver Information\n");
|
||||
break;
|
||||
case 23:
|
||||
printf("Get Crypt Key\n");
|
||||
break;
|
||||
case 24:
|
||||
printf("Encrypted Login\n");
|
||||
break;
|
||||
case 28:
|
||||
printf("Get Connection Information\n");
|
||||
break;
|
||||
case 53:
|
||||
printf("Get Bindery Object ID\n");
|
||||
break;
|
||||
case 55:
|
||||
printf("Scan Bindery Object\n");
|
||||
break;
|
||||
case 61:
|
||||
printf("Read Property Value\n");
|
||||
break;
|
||||
case 62:
|
||||
printf("Write Property Value\n");
|
||||
break;
|
||||
case 70:
|
||||
printf("Get Bindery Access Level\n");
|
||||
break;
|
||||
}
|
||||
|
||||
data += 3;
|
||||
data_length -= 3;
|
||||
break;
|
||||
case 24:
|
||||
printf("fn: %-3d\n", rq->function);
|
||||
printf("End of Job\n");
|
||||
break;
|
||||
case 34:
|
||||
printf("fn: %-3d, subfn: %-3d\n", rq->function,
|
||||
data[2]);
|
||||
data += 3;
|
||||
data_length -= 3;
|
||||
break;
|
||||
case 62:
|
||||
printf("fn: %-3d\n", rq->function);
|
||||
printf("File Search Initialize\n");
|
||||
break;
|
||||
case 63:
|
||||
printf("fn: %-3d\n", rq->function);
|
||||
printf("File Search Continue\n");
|
||||
break;
|
||||
case 64:
|
||||
printf("fn: %-3d\n", rq->function);
|
||||
printf("Search for a file\n");
|
||||
break;
|
||||
case 66:
|
||||
printf("fn: %-3d\n", rq->function);
|
||||
printf("Close File\n");
|
||||
break;
|
||||
case 72:
|
||||
printf("fn: %-3d\n", rq->function);
|
||||
printf("Read from File\n");
|
||||
break;
|
||||
case 73:
|
||||
printf("fn: %-3d\n", rq->function);
|
||||
printf("Write to File\n");
|
||||
break;
|
||||
case 75:
|
||||
printf("fn: %-3d\n", rq->function);
|
||||
printf("Set File Time Date Stamp\n");
|
||||
break;
|
||||
case 87:
|
||||
printf("fn: %-3d, subfn: %-3d\n",
|
||||
rq->function, data[0]);
|
||||
switch(data[0])
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
unsigned char *p = &(data[0]);
|
||||
printf("Open Create File or Subdirectory\n");
|
||||
printf("Name Space: %d\n", p[1]);
|
||||
printf("Open Create Mode: %x\n", p[2]);
|
||||
printf("Search Attributes: %x\n",
|
||||
*(__u16 *)&(p[3]));
|
||||
printf("Return Information Mask: %x\n",
|
||||
(unsigned int)(*(__u32 *)&(p[5])));
|
||||
printf("Desired Access Rights: %x\n",
|
||||
*(__u16 *)&(p[9]));
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
printf("Initialize Search\n");
|
||||
break;
|
||||
case 3:
|
||||
printf("Search for File or Subdirectory\n");
|
||||
break;
|
||||
case 6:
|
||||
printf("Obtain File Or Subdirectory "
|
||||
"Information\n");
|
||||
break;
|
||||
case 8:
|
||||
printf("Delete a File Or Subdirectory\n");
|
||||
break;
|
||||
}
|
||||
data += 1;
|
||||
data_length -= 1;
|
||||
break;
|
||||
default:
|
||||
printf("fn: %-3d\n", rq->function);
|
||||
}
|
||||
}
|
||||
|
||||
if (ntohs(rs->type) == NCP_REPLY)
|
||||
{
|
||||
printf("NCP respons: conn: %-5d, seq: %-3d, task: %-3d, ",
|
||||
rs->conn_low + 256 * rs->conn_high,
|
||||
rs->sequence, rs->task);
|
||||
printf("compl: %-3d, conn_st: %-3d\n",
|
||||
rs->completion_code, rs->connection_state);
|
||||
|
||||
data = buf + sizeof(struct ncp_reply_header);
|
||||
data_length = length - sizeof(struct ncp_reply_header);
|
||||
}
|
||||
|
||||
if (data == NULL)
|
||||
{
|
||||
data = buf;
|
||||
data_length = length;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
while (i < data_length)
|
||||
{
|
||||
int j;
|
||||
for (j = i; j < i+16; j++)
|
||||
{
|
||||
if (j >= data_length)
|
||||
{
|
||||
printf(" ");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("%-2.2X", data[j]);
|
||||
}
|
||||
}
|
||||
printf(" ");
|
||||
for (j = i; j < i+16; j++)
|
||||
{
|
||||
if (j >= data_length)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (isprint(data[j]))
|
||||
{
|
||||
printf("%c", data[j]);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf(".");
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
i += 16;
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
unsigned char buf[16384];
|
||||
unsigned char packet[8192];
|
||||
unsigned char *b;
|
||||
int len;
|
||||
int i = 1;
|
||||
|
||||
while (fgets(buf, sizeof(buf), stdin) != NULL)
|
||||
{
|
||||
if (strlen(buf) == sizeof(buf)-1)
|
||||
{
|
||||
fprintf(stderr, "line too long\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
b = strchr(buf, ' ');
|
||||
if (b == NULL)
|
||||
{
|
||||
fprintf(stderr, "illegal line format\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
*b = '\0';
|
||||
b += 1;
|
||||
len = 0;
|
||||
|
||||
while ((b[0] != '\0') && (b[1] != '\0'))
|
||||
{
|
||||
unsigned int value;
|
||||
if (sscanf(b, "%2x", &value) != 1)
|
||||
{
|
||||
fprintf(stderr, "illegal packet\n");
|
||||
exit(1);
|
||||
}
|
||||
packet[len] = value;
|
||||
b += 2;
|
||||
len += 1;
|
||||
}
|
||||
handle_ipx(packet, len, buf, i);
|
||||
i += 1;
|
||||
}
|
||||
|
||||
exit (0);
|
||||
}
|
||||
129
ipxdump/ipxutil.c
Normal file
129
ipxdump/ipxutil.c
Normal file
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
IPX support library - general functions
|
||||
|
||||
Copyright (C) 1994, 1995 Ales Dryak <e-mail: A.Dryak@sh.cvut.cz>
|
||||
Copyright (C) 1996, Volker Lendecke <lendecke@namu01.gwdg.de>
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <netinet/in.h>
|
||||
#include "ipxutil.h"
|
||||
|
||||
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",net);
|
||||
}
|
||||
|
||||
void
|
||||
ipx_fprint_port(FILE *file, IPXPort port)
|
||||
{
|
||||
fprintf(file,"%04X",port);
|
||||
}
|
||||
|
||||
void
|
||||
ipx_fprint_saddr(FILE *file, struct sockaddr_ipx *sipx)
|
||||
{
|
||||
ipx_fprint_network(file,ntohl(sipx->sipx_network));
|
||||
fprintf(file,":");
|
||||
ipx_fprint_node(file,sipx->sipx_node);
|
||||
fprintf(file,":");
|
||||
ipx_fprint_port(file,ntohs(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);
|
||||
}
|
||||
|
||||
void
|
||||
ipx_assign_node(IPXNode dest, IPXNode src)
|
||||
{
|
||||
memcpy(dest,src,sizeof(IPXNode));
|
||||
}
|
||||
|
||||
int
|
||||
ipx_node_equal(IPXNode n1, IPXNode n2)
|
||||
{
|
||||
return memcmp(n1,n2,sizeof(IPXNode))==0;
|
||||
}
|
||||
|
||||
int
|
||||
ipx_sscanf_node(char *buf, IPXNode node)
|
||||
{
|
||||
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 -1;
|
||||
}
|
||||
|
||||
for (i=0; i<6; i++)
|
||||
{
|
||||
node[i] = n[i];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ipx_sscanf_net(char *buf, IPXNet *target)
|
||||
{
|
||||
if (sscanf(buf, "%8lX", target) == 1)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
IPXNode ipx_this_node={0,0,0,0,0,0};
|
||||
IPXNode ipx_broadcast_node={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
|
||||
char ipx_err_string[IPX_MAX_ERROR+1]="no error detected";
|
||||
@@ -1,9 +1,9 @@
|
||||
|
||||
/*
|
||||
|
||||
IPX support library
|
||||
|
||||
Copyright (C) 1994, 1995 Ales Dryak <e-mail: A.Dryak@sh.cvut.cz>
|
||||
Copyright (C) 1996, Volker Lendecke <lendecke@namu01.gwdg.de>
|
||||
|
||||
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
|
||||
@@ -24,49 +24,42 @@
|
||||
|
||||
#define __IPXUTIL_H__
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <linux/ipx.h>
|
||||
|
||||
#define IPX_RIP_PTYPE (0x01)
|
||||
#define IPX_SAP_PTYPE (0x04)
|
||||
#define IPX_SAP_PORT (0x0452)
|
||||
#define IPX_RIP_PORT (0x0453)
|
||||
#define IPX_MAX_ERROR (255)
|
||||
#define IPX_THIS_NET (0)
|
||||
#define IPX_THIS_NODE (ipx_this_node)
|
||||
#define IPX_BROADCAST (ipx_broadcast_node)
|
||||
#define IPX_AUTO_PORT (0)
|
||||
#define IPX_USER_PTYPE (0)
|
||||
#define IPX_IS_INTERNAL (1)
|
||||
|
||||
#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)
|
||||
|
||||
#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"
|
||||
|
||||
|
||||
typedef unsigned long IPXNet;
|
||||
typedef unsigned short IPXPort;
|
||||
typedef unsigned char IPXNode[IPX_NODE_LEN];
|
||||
typedef unsigned char IPXNode[6];
|
||||
typedef unsigned long int IPXNet;
|
||||
typedef unsigned short int IPXPort;
|
||||
typedef unsigned short int hop_t;
|
||||
typedef unsigned short int tick_t;
|
||||
|
||||
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);
|
||||
}
|
||||
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, IPXNode node);
|
||||
int ipx_sscanf_net(char *buf, IPXNet *target);
|
||||
|
||||
void ipx_assign_node(IPXNode dest,IPXNode src);
|
||||
int ipx_node_equal(IPXNode n1,IPXNode n2);
|
||||
|
||||
extern IPXNode ipx_this_node;
|
||||
extern IPXNode ipx_broadcast_node;
|
||||
|
||||
extern char ipx_err_string[IPX_MAX_ERROR+1];
|
||||
|
||||
#endif
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* ncp_fs.h
|
||||
* ncp.h
|
||||
*
|
||||
* Copyright (C) 1995 by Volker Lendecke
|
||||
*
|
||||
@@ -9,6 +9,7 @@
|
||||
#define _LINUX_NCP_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/ipx.h>
|
||||
|
||||
#define NCP_PTYPE (0x11)
|
||||
#define NCP_PORT (0x0451)
|
||||
@@ -51,6 +52,9 @@ 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 {
|
||||
@@ -59,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)
|
||||
@@ -263,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,8 +26,24 @@ struct ncp_ioctl_request {
|
||||
char *data;
|
||||
};
|
||||
|
||||
#define NCP_IOC_NCPREQUEST _IOR('n', 1, unsigned char *)
|
||||
#define NCP_IOC_GETMOUNTUID _IOR('u', 1, uid_t)
|
||||
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! */
|
||||
|
||||
int volume_number;
|
||||
__u32 directory_id;
|
||||
};
|
||||
|
||||
#define NCP_IOC_NCPREQUEST _IOR('n', 1, struct ncp_ioctl_request)
|
||||
#define NCP_IOC_GETMOUNTUID _IOW('n', 2, uid_t)
|
||||
#define NCP_IOC_CONN_LOGGED_IN _IO('n', 3)
|
||||
|
||||
#define NCP_GET_FS_INFO_VERSION (1)
|
||||
#define NCP_IOC_GET_FS_INFO _IOWR('n', 4, struct ncp_fs_info)
|
||||
|
||||
/*
|
||||
* The packet size to allocate. One page should be enough.
|
||||
@@ -58,10 +74,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>
|
||||
@@ -113,9 +125,12 @@ extern struct inode_operations ncp_dir_inode_operations;
|
||||
void ncp_free_inode_info(struct ncp_inode_info *i);
|
||||
void ncp_free_all_inodes(struct ncp_server *server);
|
||||
void ncp_init_root(struct ncp_server *server);
|
||||
int ncp_conn_logged_in(struct ncp_server *server);
|
||||
int ncp_stat_root(struct ncp_server *server);
|
||||
void ncp_init_dir_cache(void);
|
||||
void ncp_invalid_dir_cache(unsigned long ino);
|
||||
void ncp_invalid_dir_cache(struct inode *ino);
|
||||
struct ncp_inode_info *ncp_find_inode(struct inode *inode);
|
||||
ino_t ncp_info_ino(struct ncp_server *server, struct ncp_inode_info *info);
|
||||
void ncp_invalidate_all_inodes(struct ncp_server *server);
|
||||
void ncp_free_dir_cache(void);
|
||||
int ncp_date_dos2unix(__u16 time, __u16 date);
|
||||
@@ -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
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -28,6 +28,7 @@ struct ncp_inode_info {
|
||||
number of references in memory */
|
||||
struct ncp_inode_info *dir;
|
||||
struct ncp_inode_info *next, *prev;
|
||||
struct inode *inode;
|
||||
struct nw_file_info finfo;
|
||||
};
|
||||
|
||||
@@ -22,7 +22,6 @@ struct ncp_server {
|
||||
it completely. */
|
||||
|
||||
struct file *ncp_filp; /* File pointer to ncp socket */
|
||||
|
||||
struct file *wdog_filp; /* File pointer to wdog socket */
|
||||
void *data_ready; /* The wdog socket gets a new
|
||||
data_ready callback. We store the
|
||||
@@ -35,7 +34,8 @@ struct ncp_server {
|
||||
|
||||
u8 completion; /* Status message from server */
|
||||
u8 conn_status; /* Bit 4 = 1 ==> Server going down, no
|
||||
requests allowed anymore */
|
||||
requests allowed anymore.
|
||||
Bit 0 = 1 ==> Server is down. */
|
||||
|
||||
int buffer_size; /* Negotiated bufsize */
|
||||
|
||||
@@ -56,6 +56,18 @@ struct ncp_server {
|
||||
char root_path; /* '\0' */
|
||||
};
|
||||
|
||||
static inline int
|
||||
ncp_conn_valid(struct ncp_server *server)
|
||||
{
|
||||
return ((server->conn_status & 0x11) == 0);
|
||||
}
|
||||
|
||||
static inline void
|
||||
ncp_invalidate_conn(struct ncp_server *server)
|
||||
{
|
||||
server->conn_status |= 0x01;
|
||||
}
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif
|
||||
@@ -13,7 +13,7 @@
|
||||
#include <linux/ncp.h>
|
||||
#include <linux/ncp_fs_i.h>
|
||||
|
||||
#define NCP_MOUNT_VERSION 1
|
||||
#define NCP_MOUNT_VERSION 2
|
||||
|
||||
#define NCP_USERNAME_LEN (NCP_BINDERY_NAME_LEN)
|
||||
#define NCP_PASSWORD_LEN 20
|
||||
@@ -26,14 +26,14 @@ struct ncp_mount_data {
|
||||
int version;
|
||||
unsigned int ncp_fd; /* The socket to the ncp port */
|
||||
unsigned int wdog_fd; /* Watchdog packets come here */
|
||||
unsigned int message_fd; /* Not used yet, maybe for messages */
|
||||
unsigned int message_fd; /* Message notifications come here */
|
||||
uid_t mounted_uid; /* Who may umount() this filesystem? */
|
||||
|
||||
struct sockaddr_ipx serv_addr;
|
||||
unsigned char server_name[49];
|
||||
unsigned char server_name[NCP_BINDERY_NAME_LEN];
|
||||
|
||||
unsigned char username[NCP_USERNAME_LEN+1];
|
||||
unsigned char password[NCP_PASSWORD_LEN+1];
|
||||
unsigned char mount_point[PATH_MAX+1];
|
||||
unsigned char mounted_vol[NCP_VOLNAME_LEN+1];
|
||||
|
||||
unsigned int time_out; /* How long should I wait after
|
||||
sending a NCP request? */
|
||||
@@ -2,11 +2,9 @@
|
||||
# Makefile for the linux ncp-filesystem routines.
|
||||
#
|
||||
|
||||
INCLUDES = -I/usr/src/linux/include -I..
|
||||
|
||||
CFLAGS = -Wall -Wstrict-prototypes -O2 -DMODULE -fomit-frame-pointer \
|
||||
$(INCLUDES) \
|
||||
# -DDEBUG_NCP=2 -DDEBUG_NCP_MALLOC
|
||||
$(INCLUDES) -DNCPFS_VERSION=\"$(VERSION)\"\
|
||||
# -DDEBUG_NCP=1 -DDEBUG_NCP_MALLOC
|
||||
# -DDEBUG_NCP_MALLOC
|
||||
|
||||
CC = gcc -D__KERNEL__ -I.
|
||||
@@ -20,14 +18,14 @@ ARCH = i386
|
||||
.s.o:
|
||||
$(AS) -o $*.o $<
|
||||
|
||||
OBJS= dir.o inode.o file.o sock.o ioctl.o ncplib.o
|
||||
OBJS= dir.o inode.o file.o sock.o ioctl.o ncplib_kernel.o mmap.o
|
||||
|
||||
all: ncpfs.o
|
||||
all: $(INTERM_BINDIR)/ncpfs.o
|
||||
|
||||
ncpfs.o: $(OBJS)
|
||||
$(LD) -r -o ncpfs.o $(OBJS)
|
||||
$(INTERM_BINDIR)/ncpfs.o: $(OBJS)
|
||||
$(LD) -r -o $@ $(OBJS)
|
||||
|
||||
ncplib.o: ncplib.c ncplib.h
|
||||
ncplib_kernel.o: ncplib_kernel.c ncplib_kernel.h
|
||||
$(CC) $(CFLAGS) -finline-functions -c $<
|
||||
|
||||
dep:
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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,24 @@ 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 (!ncp_conn_valid(NCP_SERVER(inode)))
|
||||
{
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
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 +114,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 +149,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 +170,25 @@ 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 (!ncp_conn_valid(NCP_SERVER(inode)))
|
||||
{
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
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 +197,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 +233,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,8 +244,10 @@ 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;
|
||||
ncp_invalid_dir_cache(NCP_INOP(inode)->dir->inode);
|
||||
}
|
||||
|
||||
DPRINTK("ncp_file_write: exit %s\n", NCP_ISTRUCT(inode)->entryName);
|
||||
@@ -225,7 +262,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
|
||||
@@ -54,48 +61,29 @@ ncp_read_inode(struct inode *inode)
|
||||
inode->i_ino. Just to make sure everything went well, we
|
||||
check it's there. */
|
||||
|
||||
struct ncp_inode_info *inode_info
|
||||
= (struct ncp_inode_info *)(inode->i_ino);
|
||||
struct ncp_inode_info *inode_info = ncp_find_inode(inode);
|
||||
|
||||
#if 1
|
||||
struct ncp_inode_info *root = &(NCP_SERVER(inode)->root);
|
||||
struct ncp_inode_info *check_info = root;
|
||||
if (inode_info == NULL)
|
||||
{
|
||||
/* Ok, now we're in trouble. The inode info is not there. What
|
||||
should we do now??? */
|
||||
printk("ncp_read_inode: inode info not found\n");
|
||||
return;
|
||||
}
|
||||
|
||||
do {
|
||||
if (inode_info == check_info) {
|
||||
if (check_info->state == INODE_LOOKED_UP) {
|
||||
DDPRINTK("ncp_read_inode: found it!\n");
|
||||
goto good;
|
||||
}
|
||||
else {
|
||||
printk("ncp_read_inode: "
|
||||
"state != INODE_LOOKED_UP\n");
|
||||
goto good;
|
||||
}
|
||||
}
|
||||
check_info = check_info->next;
|
||||
} while (check_info != root);
|
||||
|
||||
/* Ok, now we're in trouble. The inode info is not there. What
|
||||
should we do now??? */
|
||||
printk("ncp_read_inode: inode info not found\n");
|
||||
return;
|
||||
|
||||
good:
|
||||
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;
|
||||
inode_info->inode = inode;
|
||||
|
||||
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
|
||||
/* for directories 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 +96,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 +115,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,20 +133,25 @@ 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);
|
||||
ncp_invalid_dir_cache(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);
|
||||
}
|
||||
|
||||
clear_inode(inode);
|
||||
@@ -161,25 +164,29 @@ 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");
|
||||
sb->s_dev = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
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 +194,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 +205,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;
|
||||
}
|
||||
@@ -221,6 +230,7 @@ ncp_read_super(struct super_block *sb, void *raw_data, int silent)
|
||||
server->wait = NULL;
|
||||
server->packet = NULL;
|
||||
server->buffer_size = 0;
|
||||
server->conn_status = 0;
|
||||
|
||||
server->m = *data;
|
||||
server->m.file_mode = (server->m.file_mode &
|
||||
@@ -231,7 +241,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 +255,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 +268,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 +280,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, ncp_info_ino(server, &(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 +297,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 +343,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,7 +361,7 @@ 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));
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -364,6 +371,11 @@ ncp_notify_change(struct inode *inode, struct iattr *attr)
|
||||
int info_mask;
|
||||
struct nw_modify_dos_info info;
|
||||
|
||||
if (!ncp_conn_valid(NCP_SERVER(inode)))
|
||||
{
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if ((result = inode_change_ok(inode, attr)) < 0)
|
||||
return result;
|
||||
|
||||
@@ -383,43 +395,59 @@ ncp_notify_change(struct inode *inode, struct iattr *attr)
|
||||
info_mask = 0;
|
||||
memset(&info, 0, sizeof(info));
|
||||
|
||||
if ((attr->ia_valid & ATTR_CTIME) != 0) {
|
||||
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) {
|
||||
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) {
|
||||
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 (info_mask != 0)
|
||||
{
|
||||
if ((result =
|
||||
ncp_modify_file_or_subdir_dos_info(NCP_SERVER(inode),
|
||||
NCP_ISTRUCT(inode),
|
||||
info_mask,
|
||||
&info)) != 0) {
|
||||
&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) {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -435,7 +463,7 @@ ncp_notify_change(struct inode *inode, struct iattr *attr)
|
||||
result = 0;
|
||||
}
|
||||
|
||||
ncp_invalid_dir_cache((unsigned long)(NCP_INOP(inode)->dir));
|
||||
ncp_invalid_dir_cache(NCP_INOP(inode)->dir->inode);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -447,6 +475,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
|
||||
};
|
||||
@@ -463,6 +493,7 @@ init_module( void)
|
||||
|
||||
ncp_init_dir_cache();
|
||||
register_filesystem(&ncp_fs_type);
|
||||
printk("ncpfs version %s loaded\n", NCPFS_VERSION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
166
kernel-1.2/src/ioctl.c
Normal file
166
kernel-1.2/src/ioctl.c
Normal file
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
* 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);
|
||||
|
||||
/*
|
||||
* Binary compatible with 1.3.XX releases.
|
||||
* Take this out in 2.1.0 development series.
|
||||
* <mec@duracef.shout.net> 12 Mar 1996
|
||||
*/
|
||||
switch(cmd) {
|
||||
case _IOR('n', 1, unsigned char *):
|
||||
cmd = NCP_IOC_NCPREQUEST;
|
||||
break;
|
||||
case _IOR('u', 1, uid_t):
|
||||
cmd = NCP_IOC_GETMOUNTUID;
|
||||
break;
|
||||
case _IO('l', 1):
|
||||
cmd = NCP_IOC_CONN_LOGGED_IN;
|
||||
break;
|
||||
case _IOWR('i', 1, unsigned char *):
|
||||
cmd = NCP_IOC_GET_FS_INFO;
|
||||
break;
|
||||
}
|
||||
|
||||
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_CONN_LOGGED_IN:
|
||||
|
||||
if ( (permission(inode, MAY_WRITE) != 0)
|
||||
&& (current->uid != server->m.mounted_uid))
|
||||
{
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
return ncp_conn_logged_in(server);
|
||||
|
||||
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;
|
||||
info.volume_number = NCP_ISTRUCT(inode)->volNumber;
|
||||
info.directory_id = NCP_ISTRUCT(inode)->DosDirNum;
|
||||
|
||||
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;
|
||||
}
|
||||
157
kernel-1.2/src/mmap.c
Normal file
157
kernel-1.2/src/mmap.c
Normal file
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* 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");
|
||||
|
||||
if (!ncp_conn_valid(NCP_SERVER(inode)))
|
||||
{
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* 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,13 +1,25 @@
|
||||
#include "ncplib.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");
|
||||
}
|
||||
}
|
||||
@@ -62,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;
|
||||
}
|
||||
@@ -117,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;
|
||||
}
|
||||
@@ -145,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;
|
||||
}
|
||||
@@ -161,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;
|
||||
@@ -180,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;
|
||||
}
|
||||
@@ -199,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;
|
||||
}
|
||||
@@ -216,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);
|
||||
}
|
||||
@@ -244,52 +266,18 @@ ncp_extract_file_info(void *structure, struct nw_info_struct *target)
|
||||
target->entryName[*name_len] = '\0';
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
ncp_obtain_info(struct ncp_server *server,
|
||||
__u8 vol_num, __u32 dir_base,
|
||||
char *path, /* At most 1 component */
|
||||
struct nw_info_struct *target)
|
||||
{
|
||||
__u8 vol_num;
|
||||
__u32 dir_base;
|
||||
int result;
|
||||
char *volname = NULL;
|
||||
|
||||
if (target == NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (dir == NULL) {
|
||||
|
||||
DDPRINTK("ncp_do_lookup: looking up vol %s\n", path);
|
||||
|
||||
/* Access a volume's root directory */
|
||||
ncp_init_request(server);
|
||||
ncp_add_byte(server, 22); /* subfunction */
|
||||
ncp_add_byte(server, 0); /* dos name space */
|
||||
ncp_add_byte(server, 0); /* reserved */
|
||||
ncp_add_byte(server, 0); /* reserved */
|
||||
ncp_add_byte(server, 0); /* reserved */
|
||||
ncp_add_handle_path(server, 0, 0, 0, /* no handle */
|
||||
path);
|
||||
|
||||
if ((result = ncp_request(server, 87)) != 0) {
|
||||
ncp_unlock_server(server);
|
||||
return result;
|
||||
}
|
||||
|
||||
dir_base = ncp_reply_dword(server, 4);
|
||||
vol_num = ncp_reply_byte (server, 8);
|
||||
ncp_unlock_server(server);
|
||||
volname = path;
|
||||
path = NULL;
|
||||
}
|
||||
else
|
||||
if (target == NULL)
|
||||
{
|
||||
vol_num = dir->volNumber;
|
||||
dir_base = dir->DosDirNum;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ncp_init_request(server);
|
||||
@@ -298,22 +286,63 @@ ncp_do_lookup(struct ncp_server *server,
|
||||
ncp_add_byte(server, 0); /* dos name space as dest */
|
||||
ncp_add_word(server, 0xff); /* get all */
|
||||
ncp_add_dword(server, RIM_ALL);
|
||||
ncp_add_handle_path(server, vol_num, dir_base, 1,
|
||||
path);
|
||||
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);
|
||||
ncp_unlock_server(server);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (volname != NULL) {
|
||||
target->nameLen = strlen(volname);
|
||||
strcpy(target->entryName, volname);
|
||||
int
|
||||
ncp_lookup_volume(struct ncp_server *server,
|
||||
char *volname,
|
||||
struct nw_info_struct *target)
|
||||
{
|
||||
int result;
|
||||
__u8 vol_num;
|
||||
__u32 dir_base;
|
||||
|
||||
DPRINTK("ncp_lookup_volume: looking up vol %s\n", volname);
|
||||
|
||||
ncp_init_request(server);
|
||||
ncp_add_byte(server, 22); /* Subfunction: Generate dir handle */
|
||||
ncp_add_byte(server, 0); /* DOS name space */
|
||||
ncp_add_byte(server, 0); /* reserved */
|
||||
ncp_add_byte(server, 0); /* reserved */
|
||||
ncp_add_byte(server, 0); /* reserved */
|
||||
|
||||
ncp_add_byte(server, 0); /* faked volume number */
|
||||
ncp_add_dword(server, 0); /* faked dir_base */
|
||||
ncp_add_byte(server, 0xff); /* Don't have a dir_base */
|
||||
ncp_add_byte(server, 1); /* 1 path component */
|
||||
ncp_add_pstring(server, volname);
|
||||
|
||||
if ((result = ncp_request(server, 87)) != 0)
|
||||
{
|
||||
ncp_unlock_server(server);
|
||||
return result;
|
||||
}
|
||||
|
||||
dir_base = ncp_reply_dword(server, 4);
|
||||
vol_num = ncp_reply_byte(server, 8);
|
||||
ncp_unlock_server(server);
|
||||
|
||||
if ((result = ncp_obtain_info(server, vol_num, dir_base, NULL,
|
||||
target)) != 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
DPRINTK("ncp_lookup_volume: attribs = %X\n", target->attributes);
|
||||
|
||||
target->nameLen = strlen(volname);
|
||||
strcpy(target->entryName, volname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -336,7 +365,8 @@ ncp_modify_file_or_subdir_dos_info(struct ncp_server *server,
|
||||
ncp_add_handle_path(server, file->volNumber,
|
||||
file->DosDirNum, 1, NULL);
|
||||
|
||||
if ((result = ncp_request(server, 87)) != 0) {
|
||||
if ((result = ncp_request(server, 87)) != 0)
|
||||
{
|
||||
ncp_unlock_server(server);
|
||||
return result;
|
||||
}
|
||||
@@ -359,7 +389,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;
|
||||
}
|
||||
@@ -388,28 +419,38 @@ ncp_open_create_file_or_subdir(struct ncp_server *server,
|
||||
struct nw_file_info *target)
|
||||
{
|
||||
int result;
|
||||
__u16 search_attribs = 0x0006;
|
||||
|
||||
if ((create_attributes & aDIR) != 0)
|
||||
{
|
||||
search_attribs |= 0x8000;
|
||||
}
|
||||
|
||||
ncp_init_request(server);
|
||||
ncp_add_byte(server, 1); /* subfunction */
|
||||
ncp_add_byte(server, 0); /* dos name space */
|
||||
ncp_add_byte(server, open_create_mode);
|
||||
ncp_add_word(server, 0x8006);
|
||||
ncp_add_word(server, search_attribs);
|
||||
ncp_add_dword(server, RIM_ALL);
|
||||
ncp_add_dword(server, create_attributes);
|
||||
/* The desired acc rights seem to be the inherited rights mask
|
||||
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;
|
||||
}
|
||||
@@ -418,7 +459,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));
|
||||
}
|
||||
@@ -443,7 +485,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;
|
||||
}
|
||||
@@ -473,7 +516,8 @@ ncp_search_for_file_or_subdir(struct ncp_server *server,
|
||||
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;
|
||||
}
|
||||
@@ -539,14 +583,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;
|
||||
@@ -566,7 +611,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;
|
||||
}
|
||||
@@ -114,10 +114,16 @@ ncp_write(struct ncp_server *server, const char *file_id,
|
||||
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);
|
||||
ncp_obtain_info(struct ncp_server *server,
|
||||
__u8 vol_num, __u32 dir_base,
|
||||
char *path, /* At most 1 component */
|
||||
struct nw_info_struct *target);
|
||||
|
||||
int
|
||||
ncp_lookup_volume(struct ncp_server *server,
|
||||
char *volname,
|
||||
struct nw_info_struct *target);
|
||||
|
||||
|
||||
int
|
||||
ncp_modify_file_or_subdir_dos_info(struct ncp_server *server,
|
||||
@@ -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,31 +389,34 @@ 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);
|
||||
#if 1
|
||||
printk("ncp_rpc_call: reply mismatch\n");
|
||||
#endif
|
||||
sock->ops->recvfrom(sock, (void *)&reply, sizeof(reply), 1, 0,
|
||||
NULL, &addrlen);
|
||||
|
||||
DPRINTK("ncp_rpc_call: reply mismatch\n");
|
||||
goto re_select;
|
||||
}
|
||||
/*
|
||||
* 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 +436,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 +461,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 +475,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,8 +488,9 @@ ncp_request(struct ncp_server *server, int function)
|
||||
|
||||
result = reply->completion_code;
|
||||
|
||||
if (result != 0) {
|
||||
DPRINTK("ncp_completion_code: %d\n", result);
|
||||
if (result != 0)
|
||||
{
|
||||
DPRINTK("ncp_completion_code: %x\n", result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -518,7 +511,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 +542,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 +557,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");
|
||||
}
|
||||
|
||||
@@ -1,89 +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, request.data,
|
||||
request.size+sizeof(struct ncp_request_header));
|
||||
|
||||
|
||||
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_GETMOUNTUID:
|
||||
if ((result = verify_area(VERIFY_WRITE, (uid_t*) arg,
|
||||
sizeof(uid_t))) != 0) {
|
||||
return result;
|
||||
}
|
||||
put_fs_word(NCP_SERVER(inode)->m.mounted_uid, (uid_t*) arg);
|
||||
return 0;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
17
man/Makefile
Normal file
17
man/Makefile
Normal file
@@ -0,0 +1,17 @@
|
||||
MAN1= slist nprint pqlist nsend pserver ncopy
|
||||
MAN5= nwclient
|
||||
MAN8= ncpmount ncpumount ipx_configure ipx_interface ipx_internal_net \
|
||||
ipx_route nwmsg
|
||||
|
||||
|
||||
|
||||
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:
|
||||
67
man/ipx_interface.8
Normal file
67
man/ipx_interface.8
Normal file
@@ -0,0 +1,67 @@
|
||||
.TH IPX_INTERFACE 8 "IPX Utilities" "Caldera, Inc."
|
||||
.SH NAME
|
||||
ipx_interface \- add, delete, or display an IPX interface
|
||||
.SH SYNOPSIS
|
||||
.B ipx_interface
|
||||
add [-p] device frame_type [network number]
|
||||
.LP
|
||||
.B ipx_interface
|
||||
del device frame_type
|
||||
.LP
|
||||
.B ipx_interface
|
||||
delall
|
||||
.LP
|
||||
.B ipx_interface
|
||||
check device frame_type
|
||||
.LP
|
||||
.B ipx_interface
|
||||
help
|
||||
.SH DESCRIPTION
|
||||
.B ipx_interface
|
||||
adds, deletes, or displays IPX interfaces depending on the option selected.
|
||||
.P
|
||||
An IPX interface 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:
|
||||
.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 made
|
||||
.B
|
||||
PRIMARY.
|
||||
The network number can be optionally assigned. If it is not assigned, it
|
||||
is set to 0 which indicates it should be detected from the traffic on the
|
||||
network.
|
||||
.TP
|
||||
.I del
|
||||
This option is used to delete an IPX interface.
|
||||
.TP
|
||||
.I delall
|
||||
This option is used to delete all IPX interfaces.
|
||||
.TP
|
||||
.I check
|
||||
This option is used to display the device, frame type, and network number
|
||||
of an IPX interface.
|
||||
.TP
|
||||
.I help
|
||||
This option displays information about the utility.
|
||||
.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 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 stores only one route per target network at a time.
|
||||
.SS OPTIONS
|
||||
.TP
|
||||
.I add
|
||||
This option is used to set up the 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>
|
||||
96
man/ncopy.1
Normal file
96
man/ncopy.1
Normal file
@@ -0,0 +1,96 @@
|
||||
.\"
|
||||
.\" Man page for the ncopy program
|
||||
.\"
|
||||
.TH NCOPY 1 17/03/1996 ncopy ncopy
|
||||
.SH NAME
|
||||
ncopy \- NetWare file copy
|
||||
|
||||
.SH SYNOPSIS
|
||||
.B ncopy -V
|
||||
|
||||
.B ncopy
|
||||
[
|
||||
.B -vn
|
||||
]
|
||||
[
|
||||
.B -s
|
||||
.I amount
|
||||
]
|
||||
.B file destinationfile|directory
|
||||
|
||||
.B ncopy
|
||||
[
|
||||
.B -vn
|
||||
]
|
||||
[
|
||||
.B -s
|
||||
.I amount
|
||||
]
|
||||
.B file1
|
||||
[
|
||||
.B file2 ...
|
||||
]
|
||||
.B directory
|
||||
|
||||
.SH DESCRIPTION
|
||||
With
|
||||
.B ncopy
|
||||
you can copy files to different locations on a single NetWare file
|
||||
server without generating excess network traffic. The program uses
|
||||
a NetWare function to do the copy rather than transferring the file
|
||||
across the network for both the read and write.
|
||||
|
||||
If the last argument is a directory,
|
||||
.B ncopy
|
||||
will copy the source file(s) into the directory. If only two files
|
||||
are given and the last argument is not a directory, it will copy the
|
||||
source file to the destination file.
|
||||
|
||||
If the source and destination files are not on the same NetWare server
|
||||
(or are not on NetWare servers at all),
|
||||
.B ncopy
|
||||
will do a normal file copy.
|
||||
.SH OPTIONS
|
||||
.B -V
|
||||
.RS 3
|
||||
Show version number and exit
|
||||
.RE
|
||||
|
||||
.B -v
|
||||
.RS 3
|
||||
Verbose copy. Will show current file and percentage completion.
|
||||
.RE
|
||||
|
||||
.B -n
|
||||
.RS 3
|
||||
Nice NetWare copy. Will sleep for a second between copying blocks on
|
||||
the NetWare server. Gives other people a chance to do some work on
|
||||
the NetWare server when you are copying large files. This has no
|
||||
effect if you are not copying on a NetWare server.
|
||||
.RE
|
||||
|
||||
.B -s
|
||||
.I amount
|
||||
.RS 3
|
||||
Nice time slice factor. Used in conjunction with the
|
||||
.B -n
|
||||
option, this specifies the number of 100K blocks to copy before sleeping.
|
||||
Default is 10. (1 Megabyte)
|
||||
.RE
|
||||
|
||||
.SH BUGS
|
||||
.B ncopy
|
||||
cannot recurse into directories.
|
||||
Does not work on NetWare volumes mounted with the
|
||||
.I -V
|
||||
option to
|
||||
.B ncpmount.
|
||||
|
||||
.SH "SEE ALSO"
|
||||
.B ncpmount(8), ncpumount(8)
|
||||
|
||||
.SH CREDITS
|
||||
ncopy was written by Brian G. Reid (breid@tim.com) and
|
||||
Tom C. Henderson (thenderson@tim.com).
|
||||
Many thanks to Volker Lendecke (lendecke@namu01.gwdg.de) for the ncpfs
|
||||
and ncplib which made ncopy possible.
|
||||
221
man/ncpmount.8
221
man/ncpmount.8
@@ -1,29 +1,27 @@
|
||||
.TH NCPMOUNT 8 25/11/1995 ncpmount ncpmount
|
||||
.TH NCPMOUNT 8 12/27/1995 ncpmount ncpmount
|
||||
.SH NAME
|
||||
ncpmount \- mount program for ncpfs
|
||||
ncpmount \- mount all volumes of a specified Novell fileserver.
|
||||
.SH SYNOPSIS
|
||||
.B ncpmount
|
||||
.B server mount-point
|
||||
[
|
||||
.B -h
|
||||
] [
|
||||
.B -n
|
||||
.I
|
||||
] [
|
||||
.B -P
|
||||
.I password
|
||||
] [
|
||||
.B -C
|
||||
] [
|
||||
.B -s
|
||||
.I server name
|
||||
] [
|
||||
.B -c
|
||||
.I client name
|
||||
.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
|
||||
] [
|
||||
@@ -35,31 +33,50 @@ ncpmount \- mount program for ncpfs
|
||||
] [
|
||||
.B -d
|
||||
.I dir mode
|
||||
]
|
||||
] [
|
||||
.B -V
|
||||
.I volume
|
||||
] [
|
||||
.B -t
|
||||
.I time_out
|
||||
] [
|
||||
.B -r
|
||||
.I retry_count
|
||||
] [
|
||||
.B -v
|
||||
]
|
||||
mount-point
|
||||
|
||||
.SH DESCRIPTION
|
||||
This program is an interface to the NCP filesystem.
|
||||
This program is used to mount all volumes of the specified NetWare Fileserver
|
||||
under the specified mount point.
|
||||
|
||||
.B ncpfs
|
||||
is a filesystem which understands the NCP protocol. This is the
|
||||
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.
|
||||
|
||||
.SH OPTIONS
|
||||
.B server
|
||||
.RS 3
|
||||
.B server
|
||||
is the name of the server you want to use on the server.
|
||||
.RE
|
||||
.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. It's the same
|
||||
as in the normal mount command.
|
||||
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
|
||||
@@ -72,6 +89,13 @@ ncpmount. So
|
||||
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
|
||||
@@ -80,42 +104,40 @@ is used to print out a short help text.
|
||||
|
||||
.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.
|
||||
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
|
||||
should be given to mount shares which do not require a password to log in.
|
||||
must be specified for logins that do not have a password configured.
|
||||
.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.
|
||||
specifies the password to use for the Netware user id.
|
||||
|
||||
If neither
|
||||
.B -n
|
||||
nor
|
||||
nor the
|
||||
.B -P
|
||||
are given, ncpmount prompts for a password. This makes it difficult to
|
||||
use in scripts such as /etc/rc. But that's not ncpmount's fault, but a
|
||||
general problem with the fact that you need a password on every
|
||||
login. If anybody has a satisfying solution to this problem, please
|
||||
tell me.
|
||||
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
|
||||
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.
|
||||
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
|
||||
@@ -123,18 +145,37 @@ to tell the server about you NetWare user name.
|
||||
.B -g
|
||||
.I gid
|
||||
.RS 3
|
||||
Currently I did not implement a mapping from NetWare users/groups to
|
||||
unix users/groups. Unix requires that each file has an owner
|
||||
and a group it belongs to. With
|
||||
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 direcory.
|
||||
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
|
||||
@@ -144,14 +185,11 @@ Like
|
||||
.B -u
|
||||
and
|
||||
.B -g,
|
||||
these options are also used to cover deficiencies in the
|
||||
implementation of ncpfs. I did not implement a scheme to map NetWare
|
||||
permissions to unix permissions. So ncpmount has to be told which
|
||||
permissions it should assign to the mounted files and direcories. The
|
||||
values have to be given 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.
|
||||
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
|
||||
@@ -159,8 +197,75 @@ can very well choose a file mode that tells that you have. This
|
||||
certainly cannot override the restrictions imposed by the server.
|
||||
.RE
|
||||
|
||||
.B -V
|
||||
.I volume
|
||||
.RS 3
|
||||
There are 2 general ways you can mount a NetWare server's disk space:
|
||||
Either you can mount all volumes under one directory, or you can mount
|
||||
only a single volume.
|
||||
|
||||
When you choose to mount the complete disk space at once, you have the
|
||||
advantage that only one Linux mount point and only one
|
||||
NetWare connection is used for all the volumes of this server. Both of
|
||||
these are limited resources. (Although raising the number of Linux
|
||||
mount points is significantly cheaper than raising the number of
|
||||
available NetWare connections ;-))
|
||||
|
||||
When you specify to mount a single volume by using the option
|
||||
.B -V
|
||||
.I volume,
|
||||
you have the big advantage that nfsd is able to re-export this mounted
|
||||
directory. You must invoke
|
||||
.B nfsd
|
||||
and
|
||||
.B mountd
|
||||
with the option
|
||||
.I --re-export
|
||||
to make nfsd re-export ncpfs mounted directories. This uses one Linux
|
||||
mount point and one NetWare connection per mounted volume. Maybe
|
||||
sometime in the future I will make it possible to mount all volumes on
|
||||
different mount points, using only one connection.
|
||||
.RE
|
||||
|
||||
.B -t
|
||||
.I time_out
|
||||
.RS 3
|
||||
With
|
||||
.B -t
|
||||
you can adjust the time ncpfs waits for the server to answer a request
|
||||
it sent. Use the option to raise the timeout value when your ncpfs
|
||||
connections seem to be unstable although your servers are well
|
||||
up. This can happen when you have very busy servers, or servers that
|
||||
are very far away.
|
||||
|
||||
.I time_out
|
||||
is specified in 1/100s, the current default value is 60.
|
||||
.RE
|
||||
|
||||
.B -r
|
||||
.I retry_count
|
||||
.RS 3
|
||||
As
|
||||
.B -t, -r
|
||||
can be used to tune the ncpfs connection to the server. With
|
||||
retry_count you can specify how many times ncpfs will attempt to send
|
||||
a packet to the server before it decides the connection is dead. The
|
||||
current default value is 5.
|
||||
|
||||
Currently ncpfs is not too clever when trying to find out that
|
||||
connections are dead. If anybody knows how to do that correctly, as it
|
||||
is done by commercial workstations, please tell me.
|
||||
.RE
|
||||
|
||||
.B -v
|
||||
.RS 3
|
||||
Print ncpfs version number
|
||||
.RE
|
||||
|
||||
.SH NOTES
|
||||
If you have difficulties in mounting, please make sure that you have configured your ipx subsystem correctly. It is especially important that there is a route to the internal network of your server.
|
||||
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
|
||||
@@ -176,7 +281,7 @@ 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)
|
||||
.B syslogd(8), ncpumount(8), nfsd(8), mountd(8)
|
||||
|
||||
.SH CREDITS
|
||||
ncpfs would not have been possible without lwared, written by Ales
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
.TH NCPUMOUNT 8 25/11/1995 ncpumount ncpumount
|
||||
.TH NCPUMOUNT 8 12/27/1995 ncpumount ncpumount
|
||||
.SH NAME
|
||||
ncpumount \- umount for normal users
|
||||
ncpumount \- unmount a NetWare filesystem mounted with ncpmount.
|
||||
.SH SYNOPSIS
|
||||
.B ncpumount
|
||||
.B mount-point
|
||||
|
||||
.SH DESCRIPTION
|
||||
With this program, normal users can unmount ncp-filesystems, provided
|
||||
that it is suid root.
|
||||
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
|
||||
|
||||
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)
|
||||
108
man/nsend.1
Normal file
108
man/nsend.1
Normal file
@@ -0,0 +1,108 @@
|
||||
.TH NSEND 1 03/21/1996 nsend nsend
|
||||
.SH NAME
|
||||
nsend \- Send messages to users
|
||||
.SH SYNOPSIS
|
||||
.B nsend
|
||||
[
|
||||
.B -h
|
||||
] [
|
||||
.B -S
|
||||
.I server
|
||||
] [
|
||||
.B -U
|
||||
.I user name
|
||||
] [
|
||||
.B -P
|
||||
.I password
|
||||
|
|
||||
.B -n
|
||||
] [
|
||||
.B -C
|
||||
]
|
||||
.I user message
|
||||
|
||||
.SH DESCRIPTION
|
||||
With
|
||||
.B nsend,
|
||||
you can send messages to the user's workstations.
|
||||
|
||||
.B nsend
|
||||
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 user
|
||||
.RS 3
|
||||
.B user
|
||||
is the NetWare User-ID of the user to receive the message.
|
||||
.RE
|
||||
|
||||
.B message
|
||||
.RS 3
|
||||
.B message
|
||||
is the message to be sent. Please note that this has to be a single
|
||||
command line argument. If you want to send a message that contains
|
||||
spaces, you have to quote them on the command line. For example, to
|
||||
annoy your system administrator, you should try
|
||||
|
||||
nsend supervisor 'I know how this works!'
|
||||
.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, nsend 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 BUGS
|
||||
nsend only supports servers with up to 255 connections. I do not know
|
||||
the NCP functions for larger servers. If anybody knows them, please
|
||||
tell me!
|
||||
|
||||
.SH SEE ALSO
|
||||
.B nwclient(5), nprint(1), slist(1), ncpmount(8), ncpumount(8)
|
||||
|
||||
.SH CREDITS
|
||||
nsend was written by looking at mars_nwe's message handling. Thanks to
|
||||
Martin Stover <mstover@freeway.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)
|
||||
33
man/nwmsg.8
Normal file
33
man/nwmsg.8
Normal file
@@ -0,0 +1,33 @@
|
||||
.TH NWMSG 8 02/29/1996 nwmsg nwmsg
|
||||
.SH NAME
|
||||
nwmsg \- Deliver NetWare user broadcast messages
|
||||
.SH SYNOPSIS
|
||||
.B nwmsg
|
||||
.I mount-point
|
||||
.SH DESCRIPTION
|
||||
.B nwmsg
|
||||
is called by kerneld when a broadcast message arrives from a NetWare
|
||||
server.
|
||||
.B nwmsg
|
||||
fetches this message via the mount point and delivers it to
|
||||
the user using the same way write(1) uses.
|
||||
|
||||
Please note that
|
||||
.I kerneld
|
||||
must run when broadcast messages should be delivered to users.
|
||||
|
||||
NetWare servers can send asynchronous broadcast messages to users,
|
||||
either on explicit request by another user, or when the server is
|
||||
shutdown. The client workstation is informed about this event by an
|
||||
IPX packet on a special socket, the message socket.
|
||||
|
||||
This can happen at any time, so the user has to be informed about this
|
||||
event whenever it appears. I chose to use the kerneld feature of the
|
||||
Linux kernel to call the program nwmsg. For nwmsg, I used the relevant
|
||||
parts of the
|
||||
.I write
|
||||
program, so you can expect the NetWare broadcast
|
||||
messages to appear where user messages would appear.
|
||||
|
||||
.SH SEE ALSO
|
||||
ncpmount(8), kerneld(8), write(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)
|
||||
19
ncpfs-0.21.lsm
Normal file
19
ncpfs-0.21.lsm
Normal file
@@ -0,0 +1,19 @@
|
||||
Begin3
|
||||
Title: ncpfs
|
||||
Version: 0.21
|
||||
Entered-date: 26. March 1996
|
||||
Description: With ncpfs you can mount volumes of your netware
|
||||
server under Linux. You can also print to netware
|
||||
print queues and spool netware print queues to the
|
||||
Linux printing system. 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 ncp novell netware printing
|
||||
Author: lendecke@namu01.gwdg.de (Volker Lendecke)
|
||||
Maintained-by: lendecke@namu01.gwdg.de (Volker Lendecke)
|
||||
Primary-site: ftp.gwdg.de:/pub/linux/misc/ncpfs
|
||||
Alternate-site: sunsite.unc.edu:/pub/system/Filesystems/
|
||||
~111k ncpfs-0.21.tgz
|
||||
~ 1k ncpfs-0.21.lsm
|
||||
Copying-policy: GPL
|
||||
End
|
||||
@@ -1,14 +0,0 @@
|
||||
Begin3
|
||||
Title: ncpfs
|
||||
Version: 0.6
|
||||
Entered-date: 25. November 1995
|
||||
Description: With ncpfs you can mount volumes of your novell
|
||||
server under Linux.
|
||||
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
|
||||
~59k ncpfs-0.6.tgz
|
||||
~ 1k ncpfs-0.6.lsm
|
||||
Copying-policy: GPL
|
||||
End
|
||||
@@ -2,40 +2,64 @@
|
||||
# Makefile for the linux ncp-filesystem routines.
|
||||
#
|
||||
|
||||
INCLUDES = -I/usr/src/linux/include -I../kernel
|
||||
BINDIR = ../bin
|
||||
UTILS = ncpmount ncpumount ncptest ipx_configure
|
||||
USERUTILS = slist pqlist nwfsinfo pserver nprint nsend ncopy
|
||||
UIDUTILS = ncpmount ncpumount
|
||||
SBINUTILS = nwmsg
|
||||
|
||||
CFLAGS = -Wall $(INCLUDES) -g
|
||||
UTIL_EXECS = $(USERUTILS) $(UIDUTILS) $(SBINUTILS)
|
||||
UTILS = $(addprefix $(INTERM_BINDIR)/,$(UTIL_EXECS))
|
||||
|
||||
#CFLAGS = -Wall $(INCLUDES) $(KERNELD) -g -DNCPFS_VERSION=\"$(VERSION)\"
|
||||
CFLAGS = -Wall $(INCLUDES) $(KERNELD) -O2 -DNCPFS_VERSION=\"$(VERSION)\"
|
||||
CC = gcc
|
||||
|
||||
all: $(UTILS)
|
||||
all: $(UTILS) ncptest
|
||||
|
||||
ncpmount: ncpmount.o ncplib_user.o nwcrypt.o
|
||||
$(CC) -o ncpmount ncpmount.o ncplib_user.o nwcrypt.o
|
||||
cp ncpmount $(BINDIR)
|
||||
install: all
|
||||
for i in $(UTIL_EXECS); \
|
||||
do install $(INTERM_BINDIR)/$$i -m 755 $(BINDIR); done
|
||||
for i in $(UIDUTILS); \
|
||||
do install $(INTERM_BINDIR)/$$i -m 4755 $(BINDIR); done
|
||||
for i in $(SBINUTILS); \
|
||||
do install $(INTERM_BINDIR)/$$i -m 755 $(SBINDIR); done
|
||||
|
||||
ncpumount: ncpumount.o ncplib_user.o nwcrypt.o
|
||||
$(CC) -o ncpumount ncpumount.o ncplib_user.o nwcrypt.o
|
||||
cp ncpumount $(BINDIR)
|
||||
$(UTILS): $(addsuffix .o,$(UTIL_EXECS)) libncp.a
|
||||
$(CC) -o $@ $(addsuffix .o,$(notdir $@)) -L. -lncp
|
||||
|
||||
ipx_configure: ipx_configure.c
|
||||
$(CC) $(CFLAGS) ipx_configure.c -o ipx_configure
|
||||
cp ipx_configure $(BINDIR)
|
||||
ncplib.o: ncplib.c ncplib.h ncplib_err.h
|
||||
$(CC) $(CFLAGS) -finline-functions -c ncplib.c
|
||||
|
||||
ncptest: ncptest.o ncplib_user.o nwcrypt.o
|
||||
$(CC) -o ncptest ncptest.o ncplib_user.o nwcrypt.o
|
||||
COM_ERR_CFILES = com_err/com_err.c com_err/error_message.c com_err/et_name.c \
|
||||
com_err/init_et.c
|
||||
|
||||
nwcrypt.o: nwcrypt.c
|
||||
$(CC) -c -O3 -Wall nwcrypt.c
|
||||
libncp.a: ncplib.o ncplib_err.o $(COM_ERR_CFILES)
|
||||
make -C com_err
|
||||
ar r libncp.a ncplib.o ncplib_err.o \
|
||||
com_err/com_err.o com_err/error_message.o com_err/et_name.o \
|
||||
com_err/init_et.o
|
||||
|
||||
dep:
|
||||
ncplib_err.h: ncplib_err.et
|
||||
com_err/compile_et ncplib_err
|
||||
|
||||
ncplib_err.c: ncplib_err.et
|
||||
com_err/compile_et ncplib_err
|
||||
|
||||
test: test.o ncplib.o
|
||||
$(CC) -o test test.o ncplib.o
|
||||
|
||||
ncptest: ncptest.o libncp.a
|
||||
$(CC) -o ncptest ncptest.o -L. -lncp
|
||||
|
||||
dep: ncplib_err.h
|
||||
make -C com_err dep
|
||||
$(CPP) -M $(INCLUDES) *.c > .depend
|
||||
|
||||
clean:
|
||||
rm -f *.o *~
|
||||
make -C com_err clean
|
||||
rm -f *.o *~ slist test ncptest ncplib_err.[ch] libncp.a
|
||||
|
||||
realclean: clean
|
||||
mrproper: clean
|
||||
make -C com_err mrproper
|
||||
rm -f $(UTILS) .depend $(DISTFILE)
|
||||
|
||||
#
|
||||
@@ -44,3 +68,4 @@ realclean: clean
|
||||
ifeq (.depend,$(wildcard .depend))
|
||||
include .depend
|
||||
endif
|
||||
|
||||
|
||||
1
util/com_err.h
Symbolic link
1
util/com_err.h
Symbolic link
@@ -0,0 +1 @@
|
||||
com_err/com_err.h
|
||||
49
util/com_err/ChangeLog
Normal file
49
util/com_err/ChangeLog
Normal file
@@ -0,0 +1,49 @@
|
||||
Wed Jan 31 11:06:08 1996 <tytso@rsts-11.mit.edu>
|
||||
|
||||
* Release of E2fsprogs version 1.02
|
||||
|
||||
Mon Sep 4 21:44:47 1995 Remy Card <card@bbj>
|
||||
|
||||
* Makefile.in: Added support for BSD shared libraries.
|
||||
|
||||
Sat Aug 12 03:11:28 1995 Remy Card <card@bbj>
|
||||
|
||||
* Makefile.in (install): Install static libraries in $(ulibdir)
|
||||
(/usr/lib on Linux) instead of $(libdir) (/lib on Linux).
|
||||
|
||||
Sat Aug 5 11:44:17 1995 Theodore Y. Ts'o <tytso@lurch.mit.edu>
|
||||
|
||||
* Makefile.in (DLL_INSTALL_DIR, ELF_INSTALL_DIR): Set the
|
||||
installation directories correctly.
|
||||
|
||||
Thu Jun 15 23:39:51 1995 Remy Card <card@bbj>
|
||||
|
||||
* Makefile.in: Added support for ELF shared libraries.
|
||||
Fixed typos in the compilation rules.
|
||||
(distclean): Added compile_et.sh.
|
||||
|
||||
Sat Jun 10 19:56:13 1995 Theodore Y. Ts'o <tytso@lurch.mit.edu>
|
||||
|
||||
* compile_et.sh.in: Use ET_DIR instead of srcdir to determine the
|
||||
location of the et directory.
|
||||
|
||||
Thu Jun 8 12:45:41 1995 Miles Bader <miles@churchy.gnu.ai.mit.edu>
|
||||
|
||||
* vfprintf.c (vfprintf): Only compile this function if vfprintf
|
||||
doesn't already exist and _doprnt does.
|
||||
|
||||
* compile_et.sh: Moved to compile_et.sh.in.
|
||||
|
||||
* Makefile.in: Rewritten to conform to GNU coding standards and
|
||||
support separate compilation directories.
|
||||
Don't preprocess compile_et.sh, as this is now done by configure.
|
||||
|
||||
Mon Nov 7 21:17:48 1994 Remy Card <card@bbj>
|
||||
|
||||
* Makefile: Added a dummy install target in case shared libraries
|
||||
are not built.
|
||||
|
||||
Thu Sep 8 22:33:33 1994 (tytso@rsx-11)
|
||||
|
||||
* com_err.c (default_com_err_proc): Reversed order of \n\r to make
|
||||
jik happy.
|
||||
25
util/com_err/Makefile
Normal file
25
util/com_err/Makefile
Normal file
@@ -0,0 +1,25 @@
|
||||
#
|
||||
# Makefile for the com_err library
|
||||
#
|
||||
|
||||
OBJECTS = com_err.o error_message.o et_name.o init_et.o
|
||||
CFLAGS = -Wall -O2
|
||||
|
||||
all: $(OBJECTS)
|
||||
|
||||
dep:
|
||||
$(CPP) -M $(INCLUDES) *.c > .depend
|
||||
|
||||
clean:
|
||||
rm -f *.o
|
||||
|
||||
mrproper: clean
|
||||
rm -f .depend
|
||||
|
||||
#
|
||||
# include a dependency file if one exists
|
||||
#
|
||||
ifeq (.depend,$(wildcard .depend))
|
||||
include .depend
|
||||
endif
|
||||
|
||||
96
util/com_err/com_err.3
Normal file
96
util/com_err/com_err.3
Normal file
@@ -0,0 +1,96 @@
|
||||
.\" Copyright (c) 1988 Massachusetts Institute of Technology,
|
||||
.\" Student Information Processing Board. All rights reserved.
|
||||
.\"
|
||||
.\" $Header: /mit/krb5/.cvsroot/src/util/et/com_err.3,v 1.1 1993/06/03 12:29:34 tytso Exp $
|
||||
.\"
|
||||
.TH COM_ERR 3 "22 Nov 1988" SIPB
|
||||
.SH NAME
|
||||
com_err \- common error display routine
|
||||
.SH SYNOPSIS
|
||||
.nf
|
||||
#include <com_err.h>
|
||||
.PP
|
||||
void com_err (whoami, code, format, ...);
|
||||
const char *whoami;
|
||||
long code;
|
||||
const char *format;
|
||||
.PP
|
||||
proc = set_com_err_hook (proc);
|
||||
.fi
|
||||
void (*
|
||||
.I proc
|
||||
) (const char *, long, const char *, va_list);
|
||||
.nf
|
||||
.PP
|
||||
proc = reset_com_err_hook ();
|
||||
.PP
|
||||
void initialize_XXXX_error_table ();
|
||||
.fi
|
||||
.SH DESCRIPTION
|
||||
.I Com_err
|
||||
displays an error message on the standard error stream
|
||||
.I stderr
|
||||
(see
|
||||
.IR stdio (3S))
|
||||
composed of the
|
||||
.I whoami
|
||||
string, which should specify the program name or some subportion of
|
||||
a program, followed by an error message generated from the
|
||||
.I code
|
||||
value (derived from
|
||||
.IR compile_et (1)),
|
||||
and a string produced using the
|
||||
.I format
|
||||
string and any following arguments, in the same style as
|
||||
.IR fprintf (3).
|
||||
|
||||
The behavior of
|
||||
.I com_err
|
||||
can be modified using
|
||||
.I set_com_err_hook;
|
||||
this defines a procedure which is called with the arguments passed to
|
||||
.I com_err,
|
||||
instead of the default internal procedure which sends the formatted
|
||||
text to error output. Thus the error messages from a program can all
|
||||
easily be diverted to another form of diagnostic logging, such as
|
||||
.IR syslog (3).
|
||||
.I Reset_com_err_hook
|
||||
may be used to restore the behavior of
|
||||
.I com_err
|
||||
to its default form. Both procedures return the previous ``hook''
|
||||
value. These ``hook'' procedures must have the declaration given for
|
||||
.I proc
|
||||
above in the synopsis.
|
||||
|
||||
The
|
||||
.I initialize_XXXX_error_table
|
||||
routine is generated mechanically by
|
||||
.IR compile_et (1)
|
||||
from a source file containing names and associated strings. Each
|
||||
table has a name of up to four characters, which is used in place of
|
||||
the
|
||||
.B XXXX
|
||||
in the name of the routine. These routines should be called before
|
||||
any of the corresponding error codes are used, so that the
|
||||
.I com_err
|
||||
library will recognize error codes from these tables when they are
|
||||
used.
|
||||
|
||||
The
|
||||
.B com_err.h
|
||||
header file should be included in any source file that uses routines
|
||||
from the
|
||||
.I com_err
|
||||
library; executable files must be linked using
|
||||
.I ``-lcom_err''
|
||||
in order to cause the
|
||||
.I com_err
|
||||
library to be included.
|
||||
|
||||
.\" .IR for manual entries
|
||||
.\" .PP for paragraph breaks
|
||||
|
||||
.SH "SEE ALSO"
|
||||
compile_et (1), syslog (3).
|
||||
|
||||
Ken Raeburn, "A Common Error Description Library for UNIX".
|
||||
114
util/com_err/com_err.c
Normal file
114
util/com_err/com_err.c
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright 1987, 1988 by MIT Student Information Processing Board.
|
||||
*
|
||||
* For copyright info, see mit-sipb-copyright.h.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "com_err.h"
|
||||
#include "mit-sipb-copyright.h"
|
||||
#include "error_table.h"
|
||||
#include "internal.h"
|
||||
|
||||
#if !defined(__STDC__) && !defined(STDARG_PROTOTYPES)
|
||||
#include <varargs.h>
|
||||
#define VARARGS
|
||||
#endif
|
||||
|
||||
static void
|
||||
#ifdef __STDC__
|
||||
default_com_err_proc (const char *whoami, errcode_t code, const
|
||||
char *fmt, va_list args)
|
||||
#else
|
||||
default_com_err_proc (whoami, code, fmt, args)
|
||||
const char *whoami;
|
||||
errcode_t code;
|
||||
const char *fmt;
|
||||
va_list args;
|
||||
#endif
|
||||
{
|
||||
if (whoami) {
|
||||
fputs(whoami, stderr);
|
||||
fputs(": ", stderr);
|
||||
}
|
||||
if (code) {
|
||||
fputs(error_message(code), stderr);
|
||||
fputs(" ", stderr);
|
||||
}
|
||||
if (fmt) {
|
||||
vfprintf (stderr, fmt, args);
|
||||
}
|
||||
/* should do this only on a tty in raw mode */
|
||||
putc('\r', stderr);
|
||||
putc('\n', stderr);
|
||||
fflush(stderr);
|
||||
}
|
||||
|
||||
#ifdef __STDC__
|
||||
typedef void (*errf) (const char *, errcode_t, const char *, va_list);
|
||||
#else
|
||||
typedef void (*errf) ();
|
||||
#endif
|
||||
|
||||
errf com_err_hook = default_com_err_proc;
|
||||
|
||||
#ifdef __STDC__
|
||||
void com_err_va (const char *whoami, errcode_t code, const char *fmt,
|
||||
va_list args)
|
||||
#else
|
||||
void com_err_va (whoami, code, fmt, args)
|
||||
const char *whoami;
|
||||
errcode_t code;
|
||||
const char *fmt;
|
||||
va_list args;
|
||||
#endif
|
||||
{
|
||||
(*com_err_hook) (whoami, code, fmt, args);
|
||||
}
|
||||
|
||||
#ifndef VARARGS
|
||||
void com_err (const char *whoami,
|
||||
errcode_t code,
|
||||
const char *fmt, ...)
|
||||
{
|
||||
#else
|
||||
void com_err (va_alist)
|
||||
va_dcl
|
||||
{
|
||||
const char *whoami, *fmt;
|
||||
errcode_t code;
|
||||
#endif
|
||||
va_list pvar;
|
||||
|
||||
if (!com_err_hook)
|
||||
com_err_hook = default_com_err_proc;
|
||||
#ifdef VARARGS
|
||||
va_start (pvar);
|
||||
whoami = va_arg (pvar, const char *);
|
||||
code = va_arg (pvar, errcode_t);
|
||||
fmt = va_arg (pvar, const char *);
|
||||
#else
|
||||
va_start(pvar, fmt);
|
||||
#endif
|
||||
com_err_va (whoami, code, fmt, pvar);
|
||||
va_end(pvar);
|
||||
}
|
||||
|
||||
errf set_com_err_hook (new_proc)
|
||||
errf new_proc;
|
||||
{
|
||||
errf x = com_err_hook;
|
||||
|
||||
if (new_proc)
|
||||
com_err_hook = new_proc;
|
||||
else
|
||||
com_err_hook = default_com_err_proc;
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
errf reset_com_err_hook () {
|
||||
errf x = com_err_hook;
|
||||
com_err_hook = default_com_err_proc;
|
||||
return x;
|
||||
}
|
||||
40
util/com_err/com_err.h
Normal file
40
util/com_err/com_err.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Header file for common error description library.
|
||||
*
|
||||
* Copyright 1988, Student Information Processing Board of the
|
||||
* Massachusetts Institute of Technology.
|
||||
*
|
||||
* For copyright and distribution info, see the documentation supplied
|
||||
* with this package.
|
||||
*/
|
||||
|
||||
#ifndef __COM_ERR_H
|
||||
|
||||
typedef long errcode_t;
|
||||
|
||||
#ifdef __STDC__
|
||||
#include <stdarg.h>
|
||||
|
||||
/* ANSI C -- use prototypes etc */
|
||||
void com_err (const char *, long, const char *, ...);
|
||||
void com_err_va (const char *whoami, errcode_t code, const char *fmt,
|
||||
va_list args);
|
||||
char const *error_message (long);
|
||||
extern void (*com_err_hook) (const char *, long, const char *, va_list);
|
||||
void (*set_com_err_hook (void (*) (const char *, long, const char *, va_list)))
|
||||
(const char *, long, const char *, va_list);
|
||||
void (*reset_com_err_hook (void)) (const char *, long, const char *, va_list);
|
||||
int init_error_table(const char * const *msgs, int base, int count);
|
||||
#else
|
||||
/* no prototypes */
|
||||
void com_err ();
|
||||
void com_err_va ();
|
||||
char *error_message ();
|
||||
extern void (*com_err_hook) ();
|
||||
void (*set_com_err_hook ()) ();
|
||||
void (*reset_com_err_hook ()) ();
|
||||
int init_error_table();
|
||||
#endif
|
||||
|
||||
#define __COM_ERR_H
|
||||
#endif /* ! defined(__COM_ERR_H) */
|
||||
554
util/com_err/com_err.texinfo
Normal file
554
util/com_err/com_err.texinfo
Normal file
@@ -0,0 +1,554 @@
|
||||
\input texinfo @c -*-texinfo-*-
|
||||
|
||||
@c $Header: /mit/krb5/.cvsroot/src/util/et/com_err.texinfo,v 1.1 1993/06/03 12:29:38 tytso Exp $
|
||||
@c $Source: /mit/krb5/.cvsroot/src/util/et/com_err.texinfo,v $
|
||||
@c $Locker: $
|
||||
|
||||
@c Note that although this source file is in texinfo format (more
|
||||
@c or less), it is not yet suitable for turning into an ``info''
|
||||
@c file. Sorry, maybe next time.
|
||||
@c
|
||||
@c In order to produce hardcopy documentation from a texinfo file,
|
||||
@c run ``tex com_err.texinfo'' which will load in texinfo.tex,
|
||||
@c provided in this distribution. (texinfo.tex is from the Free
|
||||
@c Software Foundation, and is under different copyright restrictions
|
||||
@c from the rest of this package.)
|
||||
|
||||
@ifinfo
|
||||
@barfo
|
||||
@end ifinfo
|
||||
|
||||
@iftex
|
||||
@tolerance 10000
|
||||
|
||||
@c Mutate section headers...
|
||||
@begingroup
|
||||
@catcode#=6
|
||||
@gdef@secheading#1#2#3{@secheadingi {#3@enspace #1}}
|
||||
@endgroup
|
||||
@end iftex
|
||||
|
||||
@setfilename com_err
|
||||
@settitle A Common Error Description Library for UNIX
|
||||
|
||||
@ifinfo
|
||||
This file documents the use of the Common Error Description library.
|
||||
|
||||
Copyright (C) 1987, 1988 Student Information Processing Board of the
|
||||
Massachusetts Institute of Technology.
|
||||
|
||||
Permission to use, copy, modify, and distribute this software and its
|
||||
documentation for any purpose and without fee is hereby granted, provided
|
||||
that the above copyright notice appear in all copies and that both that
|
||||
copyright notice and this permission notice appear in supporting
|
||||
documentation, and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
|
||||
used in advertising or publicity pertaining to distribution of the software
|
||||
without specific, written prior permission. M.I.T. and the M.I.T. S.I.P.B.
|
||||
make no representations about the suitability of this software for any
|
||||
purpose. It is provided "as is" without express or implied warranty.
|
||||
|
||||
Note that the file texinfo.tex, provided with this distribution, is from
|
||||
the Free Software Foundation, and is under different copyright restrictions
|
||||
from the remainder of this package.
|
||||
|
||||
@end ifinfo
|
||||
|
||||
@ignore
|
||||
Permission is granted to process this file through Tex and print the
|
||||
results, provided the printed document carries copying permission
|
||||
notice identical to this one except for the removal of this paragraph
|
||||
(this paragraph not being relevant to the printed manual).
|
||||
|
||||
@end ignore
|
||||
|
||||
@setchapternewpage odd
|
||||
|
||||
@titlepage
|
||||
@center @titlefont{A Common Error Description}
|
||||
@center @titlefont{Library for UNIX}
|
||||
@sp 2
|
||||
@center Ken Raeburn
|
||||
@center Bill Sommerfeld
|
||||
@sp 1
|
||||
@center MIT Student Information Processing Board
|
||||
@sp 3
|
||||
@center last updated 1 January 1989
|
||||
@center for version 1.2
|
||||
@center ***DRAFT COPY ONLY***
|
||||
|
||||
@vskip 2in
|
||||
|
||||
@center @b{Abstract}
|
||||
|
||||
UNIX has always had a clean and simple system call interface, with a
|
||||
standard set of error codes passed between the kernel and user
|
||||
programs. Unfortunately, the same cannot be said of many of the
|
||||
libraries layered on top of the primitives provided by the kernel.
|
||||
Typically, each one has used a different style of indicating errors to
|
||||
their callers, leading to a total hodgepodge of error handling, and
|
||||
considerable amounts of work for the programmer. This paper describes
|
||||
a library and associated utilities which allows a more uniform way for
|
||||
libraries to return errors to their callers, and for programs to
|
||||
describe errors and exceptional conditions to their users.
|
||||
|
||||
@page
|
||||
@vskip 0pt plus 1filll
|
||||
|
||||
Copyright @copyright{} 1987, 1988 by the Student Information Processing
|
||||
Board of the Massachusetts Institute of Technology.
|
||||
|
||||
Permission to use, copy, modify, and distribute this software and its
|
||||
documentation for any purpose and without fee is hereby granted, provided
|
||||
that the above copyright notice appear in all copies and that both that
|
||||
copyright notice and this permission notice appear in supporting
|
||||
documentation, and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
|
||||
used in advertising or publicity pertaining to distribution of the software
|
||||
without specific, written prior permission. M.I.T. and the M.I.T. S.I.P.B.
|
||||
make no representations about the suitability of this software for any
|
||||
purpose. It is provided "as is" without express or implied warranty.
|
||||
|
||||
Note that the file texinfo.tex, provided with this distribution, is from
|
||||
the Free Software Foundation, and is under different copyright restrictions
|
||||
from the remainder of this package.
|
||||
|
||||
@end titlepage
|
||||
|
||||
@ifinfo
|
||||
@c should put a menu here someday....
|
||||
@end ifinfo
|
||||
|
||||
@page
|
||||
|
||||
@section Why com_err?
|
||||
|
||||
In building application software packages, a programmer often has to
|
||||
deal with a number of libraries, each of which can use a different
|
||||
error-reporting mechanism. Sometimes one of two values is returned,
|
||||
indicating simply SUCCESS or FAILURE, with no description of errors
|
||||
encountered. Sometimes it is an index into a table of text strings,
|
||||
where the name of the table used is dependent on the library being
|
||||
used when the error is generated; since each table starts numbering at
|
||||
0 or 1, additional information as to the source of the error code is
|
||||
needed to determine which table to look at. Sometimes no text messages are
|
||||
supplied at all, and the programmer must supply them at any point at which
|
||||
he may wish to report error conditions.
|
||||
Often, a global variable is assigned some value describing the error, but
|
||||
the programmer has to know in each case whether to look at @code{errno},
|
||||
@code{h_errno}, the return value from @code{hes_err()}, or whatever other
|
||||
variables or routines are specified.
|
||||
And what happens if something
|
||||
in the procedure of
|
||||
examining or reporting the error changes the same variable?
|
||||
|
||||
The package we have developed is an attempt to present a common
|
||||
error-handling mechanism to manipulate the most common form of error code
|
||||
in a fashion that does not have the problems listed above.
|
||||
|
||||
A list of up to 256 text messages is supplied to a translator we have
|
||||
written, along with the three- to four-character ``name'' of the error
|
||||
table. The library using this error table need only call a routine
|
||||
generated from this error-table source to make the table ``known'' to the
|
||||
com_err library, and any error code the library generates can be converted
|
||||
to the corresponding error message. There is also a default format for
|
||||
error codes accidentally returned before making the table known, which is
|
||||
of the form @samp{unknown code foo 32}, where @samp{foo} would be the name
|
||||
of the table.
|
||||
|
||||
@section Error codes
|
||||
|
||||
Error codes themselves are 32 bit (signed) integers, of which the high
|
||||
order 24 bits are an identifier of which error table the error code is
|
||||
from, and the low order 8 bits are a sequential error number within
|
||||
the table. An error code may thus be easily decomposed into its component
|
||||
parts. Only the lowest 32 bits of an error code are considered significant
|
||||
on systems which support wider values.
|
||||
|
||||
Error table 0 is defined to match the UNIX system call error table
|
||||
(@code{sys_errlist}); this allows @code{errno} values to be used directly
|
||||
in the library (assuming that @code{errno} is of a type with the same width
|
||||
as @t{long}). Other error table numbers are formed by compacting together
|
||||
the first four characters of the error table name. The mapping between
|
||||
characters in the name and numeric values in the error code are defined in
|
||||
a system-independent fashion, so that two systems that can pass integral
|
||||
values between them can reliably pass error codes without loss of meaning;
|
||||
this should work even if the character sets used are not the same.
|
||||
(However, if this is to be done, error table 0 should be avoided, since the
|
||||
local system call error tables may differ.)
|
||||
|
||||
Any variable which is to contain an error code should be declared @t{long}.
|
||||
The draft proposed American National Standard for C (as of May, 1988)
|
||||
requires that @t{long} variables be at least 32 bits; any system which does
|
||||
not support 32-bit @t{long} values cannot make use of this package (nor
|
||||
much other software that assumes an ANSI-C environment base) without
|
||||
significant effort.
|
||||
|
||||
@section Error table source file
|
||||
|
||||
The error table source file begins with the declaration of the table name,
|
||||
as
|
||||
|
||||
@example
|
||||
error_table @var{tablename}
|
||||
@end example
|
||||
|
||||
Individual error codes are
|
||||
specified with
|
||||
|
||||
@example
|
||||
error_code @var{ERROR_NAME}, @var{"text message"}
|
||||
@end example
|
||||
|
||||
where @samp{ec} can also be used as a short form of @samp{error_code}. To
|
||||
indicate the end of the table, use @samp{end}. Thus, a (short) sample
|
||||
error table might be:
|
||||
|
||||
@example
|
||||
|
||||
error_table dsc
|
||||
|
||||
error_code DSC_DUP_MTG_NAME,
|
||||
"Meeting already exists"
|
||||
|
||||
ec DSC_BAD_PATH,
|
||||
"A bad meeting pathname was given"
|
||||
|
||||
ec DSC_BAD_MODES,
|
||||
"Invalid mode for this access control list"
|
||||
|
||||
end
|
||||
|
||||
@end example
|
||||
|
||||
@section The error-table compiler
|
||||
|
||||
The error table compiler is named @code{compile_et}. It takes one
|
||||
argument, the pathname of a file (ending in @samp{.et}, e.g.,
|
||||
@samp{dsc_err.et}) containing an error table source file. It parses the
|
||||
error table, and generates two output files -- a C header file
|
||||
(@samp{discuss_err.h}) which contains definitions of the numerical values
|
||||
of the error codes defined in the error table, and a C source file which
|
||||
should be compiled and linked with the executable. The header file must be
|
||||
included in the source of a module which wishes to reference the error
|
||||
codes defined; the object module generated from the C code may be linked in
|
||||
to a program which wishes to use the printed forms of the error codes.
|
||||
|
||||
This translator accepts a @kbd{-language @var{lang}} argument, which
|
||||
determines for which language (or language variant) the output should be
|
||||
written. At the moment, @var{lang} is currently limited to @kbd{ANSI-C}
|
||||
and @kbd{K&R-C}, and some abbreviated forms of each. Eventually, this will
|
||||
be extended to include some support for C++. The default is currently
|
||||
@kbd{K&R-C}, though the generated sources will have ANSI-C code
|
||||
conditionalized on the symbol @t{__STDC__}.
|
||||
|
||||
@section Run-time support routines
|
||||
|
||||
Any source file which uses the routines supplied with or produced by the
|
||||
com_err package should include the header file @file{<com_err.h>}. It
|
||||
contains declarations and definitions which may be needed on some systems.
|
||||
(Some functions cannot be referenced properly without the return type
|
||||
declarations in this file. Some functions may work properly on most
|
||||
architectures even without the header file, but relying on this is not
|
||||
recommended.)
|
||||
|
||||
The run-time support routines and variables provided via this package
|
||||
include the following:
|
||||
|
||||
@example
|
||||
void initialize_@var{xxxx}_error_table (void);
|
||||
@end example
|
||||
|
||||
One of these routines is built by the error compiler for each error table.
|
||||
It makes the @var{xxxx} error table ``known'' to the error reporting
|
||||
system. By convention, this routine should be called in the initialization
|
||||
routine of the @var{xxxx} library. If the library has no initialization
|
||||
routine, some combination of routines which form the core of the library
|
||||
should ensure that this routine is called. It is not advised to leave it
|
||||
the caller to make this call.
|
||||
|
||||
There is no harm in calling this routine more than once.
|
||||
|
||||
@example
|
||||
#define ERROR_TABLE_BASE_@var{xxxx} @var{nnnnn}L
|
||||
@end example
|
||||
|
||||
This symbol contains the value of the first error code entry in the
|
||||
specified table.
|
||||
This rarely needs be used by the
|
||||
programmer.
|
||||
|
||||
@example
|
||||
const char *error_message (long code);
|
||||
@end example
|
||||
|
||||
This routine returns the character string error message associated
|
||||
with @code{code}; if this is associated with an unknown error table, or
|
||||
if the code is associated with a known error table but the code is not
|
||||
in the table, a string of the form @samp{Unknown code @var{xxxx nn}} is
|
||||
returned, where @var{xxxx} is the error table name produced by
|
||||
reversing the compaction performed on the error table number implied
|
||||
by that error code, and @var{nn} is the offset from that base value.
|
||||
|
||||
Although this routine is available for use when needed, its use should be
|
||||
left to circumstances which render @code{com_err} (below) unusable.
|
||||
|
||||
@example
|
||||
void com_err (const char *whoami, /* module reporting error */
|
||||
long code, /* error code */
|
||||
const char *format, /* format for additional detail */
|
||||
...); /* (extra parameters) */
|
||||
@end example
|
||||
|
||||
This routine provides an alternate way to print error messages to
|
||||
standard error; it allows the error message to be passed in as a
|
||||
parameter, rather than in an external variable. @emph{Provide grammatical
|
||||
context for ``message.''}
|
||||
|
||||
If @var{format} is @code{(char *)NULL}, the formatted message will not be
|
||||
printed. @var{format} may not be omitted.
|
||||
|
||||
@example
|
||||
#include <stdarg.h>
|
||||
|
||||
void com_err_va (const char *whoami,
|
||||
long code,
|
||||
const char *format,
|
||||
va_list args);
|
||||
@end example
|
||||
|
||||
This routine provides an interface, equivalent to @code{com_err} above,
|
||||
which may be used by higher-level variadic functions (functions which
|
||||
accept variable numbers of arguments).
|
||||
|
||||
@example
|
||||
#include <stdarg.h>
|
||||
|
||||
void (*set_com_err_hook (void (*proc) ())) ();
|
||||
|
||||
void (*@var{proc}) (const char *whoami, long code, va_list args);
|
||||
|
||||
void reset_com_err_hook ();
|
||||
@end example
|
||||
|
||||
These two routines allow a routine to be dynamically substituted for
|
||||
@samp{com_err}. After @samp{set_com_err_hook} has been called,
|
||||
calls to @samp{com_err} will turn into calls to the new hook routine.
|
||||
@samp{reset_com_err_hook} turns off this hook. This may intended to
|
||||
be used in daemons (to use a routine which calls @var{syslog(3)}), or
|
||||
in a window system application (which could pop up a dialogue box).
|
||||
|
||||
If a program is to be used in an environment in which simply printing
|
||||
messages to the @code{stderr} stream would be inappropriate (such as in a
|
||||
daemon program which runs without a terminal attached),
|
||||
@code{set_com_err_hook} may be used to redirect output from @code{com_err}.
|
||||
The following is an example of an error handler which uses @var{syslog(3)}
|
||||
as supplied in BSD 4.3:
|
||||
|
||||
@example
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <syslog.h>
|
||||
|
||||
/* extern openlog (const char * name, int logopt, int facility); */
|
||||
/* extern syslog (int priority, char * message, ...); */
|
||||
|
||||
void hook (const char * whoami, long code,
|
||||
const char * format, va_list args)
|
||||
@{
|
||||
char buffer[BUFSIZ];
|
||||
static int initialized = 0;
|
||||
if (!initialized) @{
|
||||
openlog (whoami,
|
||||
LOG_NOWAIT|LOG_CONS|LOG_PID|LOG_NDELAY,
|
||||
LOG_DAEMON);
|
||||
initialized = 1;
|
||||
@}
|
||||
vsprintf (buffer, format, args);
|
||||
syslog (LOG_ERR, "%s %s", error_message (code), buffer);
|
||||
@}
|
||||
@end example
|
||||
|
||||
After making the call
|
||||
@code{set_com_err_hook (hook);},
|
||||
any calls to @code{com_err} will result in messages being sent to the
|
||||
@var{syslogd} daemon for logging.
|
||||
The name of the program, @samp{whoami}, is supplied to the
|
||||
@samp{openlog()} call, and the message is formatted into a buffer and
|
||||
passed to @code{syslog}.
|
||||
|
||||
Note that since the extra arguments to @code{com_err} are passed by
|
||||
reference via the @code{va_list} value @code{args}, the hook routine may
|
||||
place any form of interpretation on them, including ignoring them. For
|
||||
consistency, @code{printf}-style interpretation is suggested, via
|
||||
@code{vsprintf} (or @code{_doprnt} on BSD systems without full support for
|
||||
the ANSI C library).
|
||||
|
||||
@section Coding Conventions
|
||||
|
||||
The following conventions are just some general stylistic conventions
|
||||
to follow when writing robust libraries and programs. Conventions
|
||||
similar to this are generally followed inside the UNIX kernel and most
|
||||
routines in the Multics operating system. In general, a routine
|
||||
either succeeds (returning a zero error code, and doing some side
|
||||
effects in the process), or it fails, doing minimal side effects; in
|
||||
any event, any invariant which the library assumes must be maintained.
|
||||
|
||||
In general, it is not in the domain of non user-interface library
|
||||
routines to write error messages to the user's terminal, or halt the
|
||||
process. Such forms of ``error handling'' should be reserved for
|
||||
failures of internal invariants and consistancy checks only, as it
|
||||
provides the user of the library no way to clean up for himself in the
|
||||
event of total failure.
|
||||
|
||||
Library routines which can fail should be set up to return an error
|
||||
code. This should usually be done as the return value of the
|
||||
function; if this is not acceptable, the routine should return a
|
||||
``null'' value, and put the error code into a parameter passed by
|
||||
reference.
|
||||
|
||||
Routines which use the first style of interface can be used from
|
||||
user-interface levels of a program as follows:
|
||||
|
||||
@example
|
||||
@{
|
||||
if ((code = initialize_world(getuid(), random())) != 0) @{
|
||||
com_err("demo", code,
|
||||
"when trying to initialize world");
|
||||
exit(1);
|
||||
@}
|
||||
if ((database = open_database("my_secrets", &code))==NULL) @{
|
||||
com_err("demo", code,
|
||||
"while opening my_secrets");
|
||||
exit(1);
|
||||
@}
|
||||
@}
|
||||
@end example
|
||||
|
||||
A caller which fails to check the return status is in error. It is
|
||||
possible to look for code which ignores error returns by using lint;
|
||||
look for error messages of the form ``foobar returns value which is
|
||||
sometimes ignored'' or ``foobar returns value which is always
|
||||
ignored.''
|
||||
|
||||
Since libraries may be built out of other libraries, it is often necessary
|
||||
for the success of one routine to depend on another. When a lower level
|
||||
routine returns an error code, the middle level routine has a few possible
|
||||
options. It can simply return the error code to its caller after doing
|
||||
some form of cleanup, it can substitute one of its own, or it can take
|
||||
corrective action of its own and continue normally. For instance, a
|
||||
library routine which makes a ``connect'' system call to make a network
|
||||
connection may reflect the system error code @code{ECONNREFUSED}
|
||||
(Connection refused) to its caller, or it may return a ``server not
|
||||
available, try again later,'' or it may try a different server.
|
||||
|
||||
Cleanup which is typically necessary may include, but not be limited
|
||||
to, freeing allocated memory which will not be needed any more,
|
||||
unlocking concurrancy locks, dropping reference counts, closing file
|
||||
descriptors, or otherwise undoing anything which the procedure did up
|
||||
to this point. When there are a lot of things which can go wrong, it
|
||||
is generally good to write one block of error-handling code which is
|
||||
branched to, using a goto, in the event of failure. A common source
|
||||
of errors in UNIX programs is failing to close file descriptors on
|
||||
error returns; this leaves a number of ``zombied'' file descriptors
|
||||
open, which eventually causes the process to run out of file
|
||||
descriptors and fall over.
|
||||
|
||||
@example
|
||||
@{
|
||||
FILE *f1=NULL, *f2=NULL, *f3=NULL;
|
||||
int status = 0;
|
||||
|
||||
if ( (f1 = fopen(FILE1, "r")) == NULL) @{
|
||||
status = errno;
|
||||
goto error;
|
||||
@}
|
||||
|
||||
/*
|
||||
* Crunch for a while
|
||||
*/
|
||||
|
||||
if ( (f2 = fopen(FILE2, "w")) == NULL) @{
|
||||
status = errno;
|
||||
goto error;
|
||||
@}
|
||||
|
||||
if ( (f3 = fopen(FILE3, "a+")) == NULL) @{
|
||||
status = errno;
|
||||
goto error;
|
||||
@}
|
||||
|
||||
/*
|
||||
* Do more processing.
|
||||
*/
|
||||
fclose(f1);
|
||||
fclose(f2);
|
||||
fclose(f3);
|
||||
return 0;
|
||||
|
||||
error:
|
||||
if (f1) fclose(f1);
|
||||
if (f2) fclose(f2);
|
||||
if (f3) fclose(f3);
|
||||
return status;
|
||||
@}
|
||||
@end example
|
||||
|
||||
@section Building and Installation
|
||||
|
||||
The distribution of this package will probably be done as a compressed
|
||||
``tar''-format file available via anonymous FTP from SIPB.MIT.EDU.
|
||||
Retrieve @samp{pub/com_err.tar.Z} and extract the contents. A subdirectory
|
||||
@t{profiled} should be created to hold objects compiled for profiling.
|
||||
Running ``make all'' should then be sufficient to build the library and
|
||||
error-table compiler. The files @samp{libcom_err.a},
|
||||
@samp{libcom_err_p.a}, @samp{com_err.h}, and @samp{compile_et} should be
|
||||
installed for use; @samp{com_err.3} and @samp{compile_et.1} can also be
|
||||
installed as manual pages.
|
||||
|
||||
Potential problems:
|
||||
|
||||
@itemize @bullet
|
||||
|
||||
@item Use of @code{strcasecmp}, a routine provided in BSD for
|
||||
case-insensitive string comparisons. If an equivalent routine is
|
||||
available, you can modify @code{CFLAGS} in the makefile to define
|
||||
@code{strcasecmp} to the name of that routine.
|
||||
|
||||
@item Compilers that defined @code{__STDC__} without providing the header
|
||||
file @code{<stdarg.h>}. One such example is Metaware's High ``C''
|
||||
compiler, as provided at Project Athena on the IBM RT/PC workstation; if
|
||||
@code{__HIGHC__} is defined, it is assumed that @code{<stdarg.h>} is not
|
||||
available, and therefore @code{<varargs.h>} must be used. If the symbol
|
||||
@code{VARARGS} is defined (e.g., in the makefile), @code{<varargs.h>} will
|
||||
be used.
|
||||
|
||||
@item If your linker rejects symbols that are simultaneously defined in two
|
||||
library files, edit @samp{Makefile} to remove @samp{perror.c} from the
|
||||
library. This file contains a version of @var{perror(3)} which calls
|
||||
@code{com_err} instead of calling @code{write} directly.
|
||||
|
||||
@end itemize
|
||||
|
||||
As I do not have access to non-BSD systems, there are probably
|
||||
bugs present that may interfere with building or using this package on
|
||||
other systems. If they are reported to me, they can probably be fixed for
|
||||
the next version.
|
||||
|
||||
@section Bug Reports
|
||||
|
||||
Please send any comments or bug reports to the principal author: Ken
|
||||
Raeburn, @t{Raeburn@@Athena.MIT.EDU}.
|
||||
|
||||
@section Acknowledgements
|
||||
|
||||
I would like to thank: Bill Sommerfeld, for his help with some of this
|
||||
documentation, and catching some of the bugs the first time around;
|
||||
Honeywell Information Systems, for not killing off the @emph{Multics}
|
||||
operating system before I had an opportunity to use it; Honeywell's
|
||||
customers, who persuaded them not to do so, for a while; Ted Anderson of
|
||||
CMU, for catching some problems before version 1.2 left the nest; Stan
|
||||
Zanarotti and several others of MIT's Student Information Processing Board,
|
||||
for getting us started with ``discuss,'' for which this package was
|
||||
originally written; and everyone I've talked into --- I mean, asked to read
|
||||
this document and the ``man'' pages.
|
||||
|
||||
@bye
|
||||
11
util/com_err/compile_et
Executable file
11
util/com_err/compile_et
Executable file
@@ -0,0 +1,11 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
#
|
||||
AWK=/usr/bin/awk
|
||||
DIR=com_err/
|
||||
|
||||
ROOT=`echo $1 | sed -e s/.et$//`
|
||||
BASE=`basename $ROOT`
|
||||
|
||||
$AWK -f ${DIR}/et_h.awk outfile=${BASE}.h $ROOT.et
|
||||
$AWK -f ${DIR}/et_c.awk outfile=${BASE}.c $ROOT.et
|
||||
79
util/com_err/compile_et.1
Normal file
79
util/com_err/compile_et.1
Normal file
@@ -0,0 +1,79 @@
|
||||
.\" Copyright (c) 1988 Massachusetts Institute of Technology,
|
||||
.\" Student Information Processing Board. All rights reserved.
|
||||
.\"
|
||||
.\" $Header: /mit/krb5/.cvsroot/src/util/et/compile_et.1,v 1.1 1993/06/03 12:29:46 tytso Exp $
|
||||
.\"
|
||||
.TH COMPILE_ET 1 "22 Nov 1988" SIPB
|
||||
.SH NAME
|
||||
compile_et \- error table compiler
|
||||
.SH SYNOPSIS
|
||||
.B compile_et
|
||||
file
|
||||
.SH DESCRIPTION
|
||||
.B Compile_et
|
||||
converts a table listing error-code names and associated messages into
|
||||
a C source file suitable for use with the
|
||||
.IR com_err (3)
|
||||
library.
|
||||
|
||||
The source file name must end with a suffix of ``.et''; the file
|
||||
consists of a declaration supplying the name (up to four characters
|
||||
long) of the error-code table:
|
||||
|
||||
.B error_table
|
||||
.I name
|
||||
|
||||
followed by up to 256 entries of the form:
|
||||
|
||||
.B error_code
|
||||
.I name,
|
||||
"
|
||||
.I string
|
||||
"
|
||||
|
||||
and a final
|
||||
|
||||
.B end
|
||||
|
||||
to indicate the end of the table.
|
||||
|
||||
The name of the table is used to construct the name of a subroutine
|
||||
.I initialize_XXXX_error_table
|
||||
which must be called in order for the
|
||||
.I com_err
|
||||
library to recognize the error table.
|
||||
|
||||
The various error codes defined are assigned sequentially increasing
|
||||
numbers (starting with a large number computed as a hash function of
|
||||
the name of the table); thus for compatibility it is suggested that
|
||||
new codes be added only to the end of an existing table, and that no
|
||||
codes be removed from tables.
|
||||
|
||||
The names defined in the table are placed into a C header file with
|
||||
preprocessor directives defining them as integer constants of up to
|
||||
32 bits in magnitude.
|
||||
|
||||
A C source file is also generated which should be compiled and linked
|
||||
with the object files which reference these error codes; it contains
|
||||
the text of the messages and the initialization subroutine. Both C
|
||||
files have names derived from that of the original source file, with
|
||||
the ``.et'' suffix replaced by ``.c'' and ``.h''.
|
||||
|
||||
A ``#'' in the source file is treated as a comment character, and all
|
||||
remaining text to the end of the source line will be ignored.
|
||||
|
||||
.SH BUGS
|
||||
|
||||
Since
|
||||
.B compile_et
|
||||
uses a very simple parser based on
|
||||
.IR yacc (1),
|
||||
its error recovery leaves much to be desired.
|
||||
|
||||
.\" .IR for manual entries
|
||||
.\" .PP for paragraph breaks
|
||||
|
||||
.SH "SEE ALSO"
|
||||
com_err (3).
|
||||
|
||||
Ken Raeburn, "A Common Error Description Library for UNIX".
|
||||
82
util/com_err/error_message.c
Normal file
82
util/com_err/error_message.c
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* $Header: /mit/krb5/.cvsroot/src/util/et/error_message.c,v 5.0 1993/04/13 19:56:17 tytso Exp $
|
||||
* $Source: /mit/krb5/.cvsroot/src/util/et/error_message.c,v $
|
||||
* $Locker: $
|
||||
*
|
||||
* Copyright 1987 by the Student Information Processing Board
|
||||
* of the Massachusetts Institute of Technology
|
||||
*
|
||||
* For copyright info, see "mit-sipb-copyright.h".
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include "com_err.h"
|
||||
#include "error_table.h"
|
||||
#include "mit-sipb-copyright.h"
|
||||
#include "internal.h"
|
||||
|
||||
static char buffer[25];
|
||||
|
||||
struct et_list * _et_list = (struct et_list *) NULL;
|
||||
|
||||
|
||||
#ifdef __STDC__
|
||||
const char * error_message (errcode_t code)
|
||||
#else
|
||||
const char * error_message (code)
|
||||
errcode_t code;
|
||||
#endif
|
||||
{
|
||||
int offset;
|
||||
struct et_list *et;
|
||||
int table_num;
|
||||
int started = 0;
|
||||
char *cp;
|
||||
|
||||
offset = code & ((1<<ERRCODE_RANGE)-1);
|
||||
table_num = code - offset;
|
||||
if (!table_num) {
|
||||
#ifdef HAS_SYS_ERRLIST
|
||||
if (offset < sys_nerr)
|
||||
return(sys_errlist[offset]);
|
||||
else
|
||||
goto oops;
|
||||
#else
|
||||
cp = strerror(offset);
|
||||
if (cp)
|
||||
return(cp);
|
||||
else
|
||||
goto oops;
|
||||
#endif
|
||||
}
|
||||
for (et = _et_list; et; et = et->next) {
|
||||
if (et->table->base == table_num) {
|
||||
/* This is the right table */
|
||||
if (et->table->n_msgs <= offset)
|
||||
goto oops;
|
||||
return(et->table->msgs[offset]);
|
||||
}
|
||||
}
|
||||
oops:
|
||||
strcpy (buffer, "Unknown code ");
|
||||
if (table_num) {
|
||||
strcat (buffer, error_table_name (table_num));
|
||||
strcat (buffer, " ");
|
||||
}
|
||||
for (cp = buffer; *cp; cp++)
|
||||
;
|
||||
if (offset >= 100) {
|
||||
*cp++ = '0' + offset / 100;
|
||||
offset %= 100;
|
||||
started++;
|
||||
}
|
||||
if (started || offset >= 10) {
|
||||
*cp++ = '0' + offset / 10;
|
||||
offset %= 10;
|
||||
}
|
||||
*cp++ = '0' + offset;
|
||||
*cp = '\0';
|
||||
return(buffer);
|
||||
}
|
||||
35
util/com_err/error_table.h
Normal file
35
util/com_err/error_table.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 1988 by the Student Information Processing Board of the
|
||||
* Massachusetts Institute of Technology.
|
||||
*
|
||||
* For copyright info, see mit-sipb-copyright.h.
|
||||
*/
|
||||
|
||||
#ifndef _ET_H
|
||||
/* Are we using ANSI C? */
|
||||
#ifndef __STDC__
|
||||
#define const
|
||||
#endif
|
||||
|
||||
struct error_table {
|
||||
char const * const * msgs;
|
||||
long base;
|
||||
int n_msgs;
|
||||
};
|
||||
struct et_list {
|
||||
struct et_list *next;
|
||||
const struct error_table *table;
|
||||
};
|
||||
extern struct et_list * _et_list;
|
||||
|
||||
#define ERRCODE_RANGE 8 /* # of bits to shift table number */
|
||||
#define BITS_PER_CHAR 6 /* # bits to shift per character in name */
|
||||
|
||||
#ifdef __STDC__
|
||||
extern const char *error_table_name(int num);
|
||||
#else
|
||||
extern const char *error_table_name();
|
||||
#endif
|
||||
|
||||
#define _ET_H
|
||||
#endif
|
||||
185
util/com_err/et_c.awk
Normal file
185
util/com_err/et_c.awk
Normal file
@@ -0,0 +1,185 @@
|
||||
BEGIN {
|
||||
char_shift=64
|
||||
## "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
|
||||
c2n["A"]=1
|
||||
c2n["B"]=2
|
||||
c2n["C"]=3
|
||||
c2n["D"]=4
|
||||
c2n["E"]=5
|
||||
c2n["F"]=6
|
||||
c2n["G"]=7
|
||||
c2n["H"]=8
|
||||
c2n["I"]=9
|
||||
c2n["J"]=10
|
||||
c2n["K"]=11
|
||||
c2n["L"]=12
|
||||
c2n["M"]=13
|
||||
c2n["N"]=14
|
||||
c2n["O"]=15
|
||||
c2n["P"]=16
|
||||
c2n["Q"]=17
|
||||
c2n["R"]=18
|
||||
c2n["S"]=19
|
||||
c2n["T"]=20
|
||||
c2n["U"]=21
|
||||
c2n["V"]=22
|
||||
c2n["W"]=23
|
||||
c2n["X"]=24
|
||||
c2n["Y"]=25
|
||||
c2n["Z"]=26
|
||||
c2n["a"]=27
|
||||
c2n["b"]=28
|
||||
c2n["c"]=29
|
||||
c2n["d"]=30
|
||||
c2n["e"]=31
|
||||
c2n["f"]=32
|
||||
c2n["g"]=33
|
||||
c2n["h"]=34
|
||||
c2n["i"]=35
|
||||
c2n["j"]=36
|
||||
c2n["k"]=37
|
||||
c2n["l"]=38
|
||||
c2n["m"]=39
|
||||
c2n["n"]=40
|
||||
c2n["o"]=41
|
||||
c2n["p"]=42
|
||||
c2n["q"]=43
|
||||
c2n["r"]=44
|
||||
c2n["s"]=45
|
||||
c2n["t"]=46
|
||||
c2n["u"]=47
|
||||
c2n["v"]=48
|
||||
c2n["w"]=49
|
||||
c2n["x"]=50
|
||||
c2n["y"]=51
|
||||
c2n["z"]=52
|
||||
c2n["0"]=53
|
||||
c2n["1"]=54
|
||||
c2n["2"]=55
|
||||
c2n["3"]=56
|
||||
c2n["4"]=57
|
||||
c2n["5"]=58
|
||||
c2n["6"]=59
|
||||
c2n["7"]=60
|
||||
c2n["8"]=61
|
||||
c2n["9"]=62
|
||||
c2n["_"]=63
|
||||
}
|
||||
/^#/ { next }
|
||||
/^[ \t]*(error_table|et)[ \t]+[a-zA-Z][a-zA-Z0-9_]+/ {
|
||||
table_number = 0
|
||||
table_name = $2
|
||||
mod_base = 1000000
|
||||
for(i=1; i<=length(table_name); i++) {
|
||||
table_number=(table_number*char_shift)+c2n[substr(table_name,i,1)]
|
||||
}
|
||||
|
||||
# We start playing *_high, *low games here because the some
|
||||
# awk programs do not have the necessary precision (sigh)
|
||||
tab_base_low = table_number % mod_base
|
||||
tab_base_high = int(table_number / mod_base)
|
||||
tab_base_sign = 1;
|
||||
|
||||
# figure out: table_number_base=table_number*256
|
||||
tab_base_low = tab_base_low * 256
|
||||
tab_base_high = (tab_base_high * 256) + \
|
||||
int(tab_base_low / mod_base)
|
||||
tab_base_low = tab_base_low % mod_base
|
||||
|
||||
if (table_number > 128*256*256) {
|
||||
# figure out: table_number_base -= 256*256*256*256
|
||||
# sub_high, sub_low is 256*256*256*256
|
||||
sub_low = 256*256*256 % mod_base
|
||||
sub_high = int(256*256*256 / mod_base)
|
||||
|
||||
sub_low = sub_low * 256
|
||||
sub_high = (sub_high * 256) + int(sub_low / mod_base)
|
||||
sub_low = sub_low % mod_base
|
||||
|
||||
tab_base_low = sub_low - tab_base_low;
|
||||
tab_base_high = sub_high - tab_base_high;
|
||||
tab_base_sign = -1;
|
||||
if (tab_base_low < 0) {
|
||||
tab_base_low = tab_base_low + mod_base
|
||||
tab_base_high--
|
||||
}
|
||||
}
|
||||
print "/*" > outfile
|
||||
print " * " outfile ":" > outfile
|
||||
print " * This file is automatically generated; please do not edit it." > outfile
|
||||
print " */" > outfile
|
||||
|
||||
print "#ifdef __STDC__" > outfile
|
||||
print "#define NOARGS void" > outfile
|
||||
print "#else" > outfile
|
||||
print "#define NOARGS" > outfile
|
||||
print "#define const" > outfile
|
||||
print "#endif" > outfile
|
||||
print "" > outfile
|
||||
print "static const char * const text[] = {" > outfile
|
||||
table_item_count = 0
|
||||
}
|
||||
|
||||
/^[ \t]*(error_code|ec)[ \t]+[A-Z_0-9]+,[ \t]*$/ {
|
||||
skipone=1
|
||||
next
|
||||
}
|
||||
|
||||
/^[ \t]*(error_code|ec)[ \t]+[A-Z_0-9]+,[ \t]*".*"[ \t]*$/ {
|
||||
text=""
|
||||
for (i=3; i<=NF; i++) {
|
||||
text = text FS $i
|
||||
}
|
||||
text=substr(text,2,length(text)-1);
|
||||
printf "\t%s,\n", text > outfile
|
||||
table_item_count++
|
||||
}
|
||||
|
||||
{
|
||||
if (skipone) {
|
||||
printf "\t%s,\n", $0 > outfile
|
||||
table_item_count++
|
||||
}
|
||||
skipone=0
|
||||
}
|
||||
END {
|
||||
|
||||
|
||||
print " 0" > outfile
|
||||
print "};" > outfile
|
||||
print "" > outfile
|
||||
print "struct error_table {" > outfile
|
||||
print " char const * const * msgs;" > outfile
|
||||
print " long base;" > outfile
|
||||
print " int n_msgs;" > outfile
|
||||
print "};" > outfile
|
||||
print "struct et_list {" > outfile
|
||||
print " struct et_list *next;" > outfile
|
||||
print " const struct error_table * table;" > outfile
|
||||
print "};" > outfile
|
||||
print "extern struct et_list *_et_list;" > outfile
|
||||
print "" > outfile
|
||||
if (tab_base_high == 0) {
|
||||
print "static const struct error_table et = { text, " \
|
||||
sprintf("%dL, %d };", tab_base_sign*tab_base_low, \
|
||||
table_item_count) > outfile
|
||||
} else {
|
||||
print "static const struct error_table et = { text, " \
|
||||
sprintf("%d%06dL, %d };", tab_base_sign*tab_base_high, \
|
||||
tab_base_low, table_item_count) > outfile
|
||||
}
|
||||
print "" > outfile
|
||||
print "static struct et_list link = { 0, 0 };" > outfile
|
||||
print "" > outfile
|
||||
print "void initialize_" table_name "_error_table (NOARGS);" > outfile
|
||||
print "" > outfile
|
||||
print "void initialize_" table_name "_error_table (NOARGS) {" > outfile
|
||||
print " if (!link.table) {" > outfile
|
||||
print " link.next = _et_list;" > outfile
|
||||
print " link.table = &et;" > outfile
|
||||
print " _et_list = &link;" > outfile
|
||||
print " }" > outfile
|
||||
print "}" > outfile
|
||||
|
||||
|
||||
}
|
||||
157
util/com_err/et_h.awk
Normal file
157
util/com_err/et_h.awk
Normal file
@@ -0,0 +1,157 @@
|
||||
BEGIN {
|
||||
char_shift=64
|
||||
## "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
|
||||
c2n["A"]=1
|
||||
c2n["B"]=2
|
||||
c2n["C"]=3
|
||||
c2n["D"]=4
|
||||
c2n["E"]=5
|
||||
c2n["F"]=6
|
||||
c2n["G"]=7
|
||||
c2n["H"]=8
|
||||
c2n["I"]=9
|
||||
c2n["J"]=10
|
||||
c2n["K"]=11
|
||||
c2n["L"]=12
|
||||
c2n["M"]=13
|
||||
c2n["N"]=14
|
||||
c2n["O"]=15
|
||||
c2n["P"]=16
|
||||
c2n["Q"]=17
|
||||
c2n["R"]=18
|
||||
c2n["S"]=19
|
||||
c2n["T"]=20
|
||||
c2n["U"]=21
|
||||
c2n["V"]=22
|
||||
c2n["W"]=23
|
||||
c2n["X"]=24
|
||||
c2n["Y"]=25
|
||||
c2n["Z"]=26
|
||||
c2n["a"]=27
|
||||
c2n["b"]=28
|
||||
c2n["c"]=29
|
||||
c2n["d"]=30
|
||||
c2n["e"]=31
|
||||
c2n["f"]=32
|
||||
c2n["g"]=33
|
||||
c2n["h"]=34
|
||||
c2n["i"]=35
|
||||
c2n["j"]=36
|
||||
c2n["k"]=37
|
||||
c2n["l"]=38
|
||||
c2n["m"]=39
|
||||
c2n["n"]=40
|
||||
c2n["o"]=41
|
||||
c2n["p"]=42
|
||||
c2n["q"]=43
|
||||
c2n["r"]=44
|
||||
c2n["s"]=45
|
||||
c2n["t"]=46
|
||||
c2n["u"]=47
|
||||
c2n["v"]=48
|
||||
c2n["w"]=49
|
||||
c2n["x"]=50
|
||||
c2n["y"]=51
|
||||
c2n["z"]=52
|
||||
c2n["0"]=53
|
||||
c2n["1"]=54
|
||||
c2n["2"]=55
|
||||
c2n["3"]=56
|
||||
c2n["4"]=57
|
||||
c2n["5"]=58
|
||||
c2n["6"]=59
|
||||
c2n["7"]=60
|
||||
c2n["8"]=61
|
||||
c2n["9"]=62
|
||||
c2n["_"]=63
|
||||
}
|
||||
/^#/ { next }
|
||||
/^[ \t]*(error_table|et)[ \t]+[a-zA-Z][a-zA-Z0-9_]+/ {
|
||||
table_number = 0
|
||||
table_name = $2
|
||||
mod_base = 1000000
|
||||
for(i=1; i<=length(table_name); i++) {
|
||||
table_number=(table_number*char_shift)+c2n[substr(table_name,i,1)]
|
||||
}
|
||||
# We start playing *_high, *low games here because the some
|
||||
# awk programs do not have the necessary precision (sigh)
|
||||
tab_base_low = table_number % mod_base
|
||||
tab_base_high = int(table_number / mod_base)
|
||||
tab_base_sign = 1;
|
||||
|
||||
# figure out: table_number_base=table_number*256
|
||||
tab_base_low = tab_base_low * 256
|
||||
tab_base_high = (tab_base_high * 256) + \
|
||||
int(tab_base_low / mod_base)
|
||||
tab_base_low = tab_base_low % mod_base
|
||||
|
||||
if (table_number > 128*256*256) {
|
||||
# figure out: table_number_base -= 256*256*256*256
|
||||
# sub_high, sub_low is 256*256*256*256
|
||||
sub_low = 256*256*256 % mod_base
|
||||
sub_high = int(256*256*256 / mod_base)
|
||||
|
||||
sub_low = sub_low * 256
|
||||
sub_high = (sub_high * 256) + int(sub_low / mod_base)
|
||||
sub_low = sub_low % mod_base
|
||||
|
||||
tab_base_low = sub_low - tab_base_low;
|
||||
tab_base_high = sub_high - tab_base_high;
|
||||
tab_base_sign = -1;
|
||||
if (tab_base_low < 0) {
|
||||
tab_base_low = tab_base_low + mod_base
|
||||
tab_base_high--
|
||||
}
|
||||
}
|
||||
curr_low = tab_base_low
|
||||
curr_high = tab_base_high
|
||||
curr_sign = tab_base_sign
|
||||
print "/*" > outfile
|
||||
print " * " outfile ":" > outfile
|
||||
print " * This file is automatically generated; please do not edit it." > outfile
|
||||
print " */" > outfile
|
||||
print "#ifdef __STDC__" > outfile
|
||||
print "#define NOARGS void" > outfile
|
||||
print "#else" > outfile
|
||||
print "#define NOARGS" > outfile
|
||||
print "#define const" > outfile
|
||||
print "#endif" > outfile
|
||||
print "" > outfile
|
||||
}
|
||||
|
||||
/^[ \t]*(error_code|ec)[ \t]+[A-Z_0-9]+,/ {
|
||||
tag=substr($2,1,length($2)-1)
|
||||
if (curr_high == 0) {
|
||||
printf "#define %-40s (%dL)\n", tag, \
|
||||
curr_sign*curr_low > outfile
|
||||
} else {
|
||||
printf "#define %-40s (%d%06dL)\n", tag, curr_high*curr_sign, \
|
||||
curr_low > outfile
|
||||
}
|
||||
curr_low += curr_sign;
|
||||
if (curr_low >= mod_base) {
|
||||
curr_low -= mod_base;
|
||||
curr_high++
|
||||
}
|
||||
if (curr_low < 0) {
|
||||
cur_low += mod_base
|
||||
cur_high--
|
||||
}
|
||||
}
|
||||
|
||||
END {
|
||||
print "extern void initialize_" table_name "_error_table (NOARGS);" > outfile
|
||||
if (tab_base_high == 0) {
|
||||
print "#define ERROR_TABLE_BASE_" table_name " (" \
|
||||
sprintf("%d", tab_base_sign*tab_base_low) \
|
||||
"L)" > outfile
|
||||
} else {
|
||||
print "#define ERROR_TABLE_BASE_" table_name " (" \
|
||||
sprintf("%d%06d", tab_base_sign*tab_base_high, \
|
||||
tab_base_low) "L)" > outfile
|
||||
}
|
||||
print "" > outfile
|
||||
print "/* for compatibility with older versions... */" > outfile
|
||||
print "#define init_" table_name "_err_tbl initialize_" table_name "_error_table" > outfile
|
||||
print "#define " table_name "_err_base ERROR_TABLE_BASE_" table_name > outfile
|
||||
}
|
||||
36
util/com_err/et_name.c
Normal file
36
util/com_err/et_name.c
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 1987 by MIT Student Information Processing Board
|
||||
*
|
||||
* For copyright info, see mit-sipb-copyright.h.
|
||||
*/
|
||||
|
||||
#include "error_table.h"
|
||||
#include "mit-sipb-copyright.h"
|
||||
#include "internal.h"
|
||||
|
||||
static const char char_set[] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
|
||||
|
||||
static char buf[6];
|
||||
|
||||
const char * error_table_name(num)
|
||||
int num;
|
||||
{
|
||||
int ch;
|
||||
int i;
|
||||
char *p;
|
||||
|
||||
/* num = aa aaa abb bbb bcc ccc cdd ddd d?? ??? ??? */
|
||||
p = buf;
|
||||
num >>= ERRCODE_RANGE;
|
||||
/* num = ?? ??? ??? aaa aaa bbb bbb ccc ccc ddd ddd */
|
||||
num &= 077777777;
|
||||
/* num = 00 000 000 aaa aaa bbb bbb ccc ccc ddd ddd */
|
||||
for (i = 4; i >= 0; i--) {
|
||||
ch = (num >> BITS_PER_CHAR * i) & ((1 << BITS_PER_CHAR) - 1);
|
||||
if (ch != 0)
|
||||
*p++ = char_set[ch-1];
|
||||
}
|
||||
*p = '\0';
|
||||
return(buf);
|
||||
}
|
||||
58
util/com_err/init_et.c
Normal file
58
util/com_err/init_et.c
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* $Header: /mit/krb5/.cvsroot/src/util/et/init_et.c,v 5.0 1993/04/13 19:56:25 tytso Exp $
|
||||
* $Source: /mit/krb5/.cvsroot/src/util/et/init_et.c,v $
|
||||
* $Locker: $
|
||||
*
|
||||
* Copyright 1986, 1987, 1988 by MIT Information Systems and
|
||||
* the MIT Student Information Processing Board.
|
||||
*
|
||||
* For copyright info, see mit-sipb-copyright.h.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <malloc.h>
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#include "com_err.h"
|
||||
#include "error_table.h"
|
||||
#include "mit-sipb-copyright.h"
|
||||
|
||||
#ifndef __STDC__
|
||||
#define const
|
||||
#endif
|
||||
|
||||
struct foobar {
|
||||
struct et_list etl;
|
||||
struct error_table et;
|
||||
};
|
||||
|
||||
extern struct et_list * _et_list;
|
||||
|
||||
#ifdef __STDC__
|
||||
int init_error_table(const char * const *msgs, int base, int count)
|
||||
#else
|
||||
int init_error_table(msgs, base, count)
|
||||
const char * const * msgs;
|
||||
int base;
|
||||
int count;
|
||||
#endif
|
||||
{
|
||||
struct foobar * new_et;
|
||||
|
||||
if (!base || !count || !msgs)
|
||||
return 0;
|
||||
|
||||
new_et = (struct foobar *) malloc(sizeof(struct foobar));
|
||||
if (!new_et)
|
||||
return ENOMEM; /* oops */
|
||||
new_et->etl.table = &new_et->et;
|
||||
new_et->et.msgs = msgs;
|
||||
new_et->et.base = base;
|
||||
new_et->et.n_msgs= count;
|
||||
|
||||
new_et->etl.next = _et_list;
|
||||
_et_list = &new_et->etl;
|
||||
return 0;
|
||||
}
|
||||
22
util/com_err/internal.h
Normal file
22
util/com_err/internal.h
Normal file
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* internal include file for com_err package
|
||||
*/
|
||||
#include "mit-sipb-copyright.h"
|
||||
#ifndef __STDC__
|
||||
#undef const
|
||||
#define const
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef NEED_SYS_ERRLIST
|
||||
extern char const * const sys_errlist[];
|
||||
extern const int sys_nerr;
|
||||
#endif
|
||||
|
||||
/* AIX and Ultrix have standard conforming header files. */
|
||||
#if !defined(ultrix) && !defined(_AIX)
|
||||
#ifdef __STDC__
|
||||
void perror (const char *);
|
||||
#endif
|
||||
#endif
|
||||
19
util/com_err/mit-sipb-copyright.h
Normal file
19
util/com_err/mit-sipb-copyright.h
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
|
||||
Copyright 1987, 1988 by the Student Information Processing Board
|
||||
of the Massachusetts Institute of Technology
|
||||
|
||||
Permission to use, copy, modify, and distribute this software
|
||||
and its documentation for any purpose and without fee is
|
||||
hereby granted, provided that the above copyright notice
|
||||
appear in all copies and that both that copyright notice and
|
||||
this permission notice appear in supporting documentation,
|
||||
and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
|
||||
used in advertising or publicity pertaining to distribution
|
||||
of the software without specific, written prior permission.
|
||||
M.I.T. and the M.I.T. S.I.P.B. make no representations about
|
||||
the suitability of this software for any purpose. It is
|
||||
provided "as is" without express or implied warranty.
|
||||
|
||||
*/
|
||||
|
||||
BIN
util/ipx.tar
BIN
util/ipx.tar
Binary file not shown.
32
util/ipx_sap_types
Normal file
32
util/ipx_sap_types
Normal file
@@ -0,0 +1,32 @@
|
||||
0001 User
|
||||
0002 User Group
|
||||
0003 Print Queue
|
||||
0004 File Server
|
||||
0005 Job Server
|
||||
0006 Gateway
|
||||
0007 Print Server
|
||||
0008 Archive Server
|
||||
0009 Archive Server
|
||||
000A Job Queue
|
||||
000B Administration
|
||||
0021 NAS SNA Gateway
|
||||
0024 Remote Bridge
|
||||
0026 Bridge Server
|
||||
0027 TCP/IP Gateway
|
||||
002D Time Synchronization VAP
|
||||
002E Archive Server Dynamic SAP
|
||||
0047 Advertising Print Server
|
||||
004B Btrieve VAP 5.0
|
||||
0050 Btrieve VAP
|
||||
0053 Print Queue User
|
||||
007A TES NetWare for VMS
|
||||
0098 NetWare Access Server
|
||||
009A Named Pipe Server
|
||||
009E Portable NetWare Unix
|
||||
0107 NetWare 386
|
||||
0111 Test Server
|
||||
0133 NetWare Name Service
|
||||
0166 NetWare Management
|
||||
026A NetWare Management
|
||||
026B Time Server (NetWare 4.0)
|
||||
0278 NetWare Directory Server (NetWare 4.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 */
|
||||
849
util/ncopy.c
Normal file
849
util/ncopy.c
Normal file
@@ -0,0 +1,849 @@
|
||||
/****************************************************************************
|
||||
* ncopy.c
|
||||
*
|
||||
* Copy file on a Netware server without Network Traffic
|
||||
*
|
||||
* Copyright (C) 1996 by Brian Reid and Tom Henderson.
|
||||
*
|
||||
* Send bug reports for ncopy to "breid@tim.com"
|
||||
*
|
||||
* Still to do: support recursive copy with two arguments
|
||||
* Both must be directories. (similar to rcp -r)
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/param.h>
|
||||
#include <ctype.h>
|
||||
#include <mntent.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include "ncplib.h"
|
||||
|
||||
|
||||
struct NCPMountRec
|
||||
{
|
||||
char *mountDir;
|
||||
char *server;
|
||||
struct ncp_conn *conn;
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Globals:
|
||||
*
|
||||
*/
|
||||
const char *VersionStr = "0.1";
|
||||
char * ProgramName;
|
||||
|
||||
struct NCPMountRec *NcpMountTable = NULL;
|
||||
int ncpCount = 0;
|
||||
|
||||
/* (initialized) command options */
|
||||
|
||||
int optVersion=0; /* -V TRUE if just want version */
|
||||
int optVerbose=0; /* -v TRUE if want verbose output */
|
||||
int optNice=0; /* -n TRUE if we are cooperative (nice) */
|
||||
int optNiceFactorSel=0; /* -s TRUE if we selected a nice factor */
|
||||
int optNiceFactor=10; /* -s arg, number of 100K blocks to copy
|
||||
before sleeping for a second */
|
||||
__u32 CopyBlockSize = 100000; /* Size of the default block copy size */
|
||||
unsigned int NiceSleepTime=1; /* Number of seconds to sleep in Nice Mode */
|
||||
|
||||
int BlocksCopied=0; /* Number of blocks copied */
|
||||
int MaxNcopyRetries=25; /* Maximum number of times to retry a failed
|
||||
copy before giving up */
|
||||
|
||||
/* Globals needed for signal handlers */
|
||||
int OutputOpen=0; /* True if the ncp output file is open */
|
||||
struct ncp_conn *CurrentConn = NULL; /* Connection of output file */
|
||||
struct ncp_file_info *CurrentFile = NULL; /* File info of output file */
|
||||
|
||||
/* Signal control structures */
|
||||
static struct sigaction sHangupSig;
|
||||
static struct sigaction sInterruptSig;
|
||||
static struct sigaction sQuitSig;
|
||||
static struct sigaction sTermSig;
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
*/
|
||||
static void usage()
|
||||
{
|
||||
fprintf(stderr,"usage: %s [-V]\n", ProgramName);
|
||||
fprintf(stderr," %s [-vn] [-s amt] sourcefile destinationfile|directory\n", ProgramName);
|
||||
fprintf(stderr," %s [-vn] [-s amt] sourcefile [...] directory\n", ProgramName);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Return pointer to last component of the path.
|
||||
* Returned string may have one or more "/" left on the end.
|
||||
* ("/" returns pointer to "/", null returns pointer to null)
|
||||
* Return pointer to original string if no "/" in string. (except at end)
|
||||
*/
|
||||
static const char *myBaseName(const char *path)
|
||||
{
|
||||
const char *p;
|
||||
|
||||
for(p = &path[strlen(path)]; p != path; p--) { /* skip ENDING "/" chars */
|
||||
if(*p && *p != '/') break;
|
||||
}
|
||||
if(p==path) return p;
|
||||
for( ; p != path || *p == '/'; p--) {
|
||||
if(*p == '/') return ++p;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
*/
|
||||
static const char *notDir(const char *path)
|
||||
{
|
||||
struct stat buf;
|
||||
static const char *notDirectory="not a directory";
|
||||
|
||||
if(stat(path, &buf)) return strerror(errno); /* no permission? not exist? */
|
||||
if(!S_ISDIR(buf.st_mode)) return notDirectory; /* not a directory */
|
||||
return (char *) 0; /* OK */
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
*/
|
||||
static int handleOptions(const int argc, char * const argv[])
|
||||
{
|
||||
int opt;
|
||||
|
||||
while ((opt = getopt(argc, argv, "vVns:")) != EOF)
|
||||
{
|
||||
switch (opt) {
|
||||
|
||||
case 'V': /* Version */
|
||||
optVersion=1;
|
||||
break;
|
||||
|
||||
case 'v': /* Verbose output */
|
||||
optVerbose=1;
|
||||
break;
|
||||
|
||||
case 'n': /* Nice, cooperative copy */
|
||||
optNice=1;
|
||||
break;
|
||||
|
||||
case 's': /* Nice Factor */
|
||||
optNiceFactorSel=1;
|
||||
optNiceFactor=atoi(optarg);
|
||||
if (optNiceFactor < 1) {
|
||||
fprintf(stderr,"%s: -s option requires positive numeric argument > 0\n",
|
||||
ProgramName);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
default: /* invalid options or options without required arguments */
|
||||
return 1;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* TODO: if recursive flag last MUST be a directory, even if only 2 args.
|
||||
*/
|
||||
static int validateFileArgs(const int argc, char * const argv[])
|
||||
{
|
||||
const char *p;
|
||||
if (argc == 0) {
|
||||
fprintf(stderr,"%s: No arguments specified.\n", ProgramName);
|
||||
return 1;
|
||||
}
|
||||
if(argc == 1) {
|
||||
fprintf(stderr,"%s: No destination specified.\n", ProgramName);
|
||||
return 1;
|
||||
}
|
||||
if((argc > 2) && (p=notDir(argv[argc-1]))) { /* last arg MUST be dir */
|
||||
fprintf(stderr,"%s: %s: %s\n", ProgramName, argv[argc-1], p);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Duplicate a string.
|
||||
*/
|
||||
char *duplicateStr(const char *InStr)
|
||||
{
|
||||
char *dup;
|
||||
if (!InStr) return NULL;
|
||||
dup = (char*)malloc(strlen(InStr)+1);
|
||||
if (dup)
|
||||
strcpy(dup,InStr);
|
||||
return dup;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* load a table of ncpfs mount points.
|
||||
*/
|
||||
int loadMountTable()
|
||||
{
|
||||
FILE *mountedFile;
|
||||
struct mntent *mountEntry = NULL;
|
||||
ncpCount = 0;
|
||||
if ( (mountedFile = fopen(MOUNTED,"r")) == NULL) {
|
||||
fprintf(stderr,"ncopy: cannot open %s, %s\n",MOUNTED,strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
while ( (mountEntry = getmntent(mountedFile)) != NULL) {
|
||||
if (!strcmp(mountEntry->mnt_type,"ncpfs"))
|
||||
ncpCount++;
|
||||
}
|
||||
if (ncpCount) {
|
||||
NcpMountTable = (struct NCPMountRec*)
|
||||
malloc(ncpCount * sizeof(struct NCPMountRec));
|
||||
if (!NcpMountTable) {
|
||||
fprintf(stderr,"Out of memory\n");
|
||||
fclose(mountedFile);
|
||||
return 1;
|
||||
}
|
||||
fseek(mountedFile,0,SEEK_SET);
|
||||
ncpCount = 0;
|
||||
while ( (mountEntry = getmntent(mountedFile)) != NULL) {
|
||||
if (!strcmp(mountEntry->mnt_type,"ncpfs")) {
|
||||
NcpMountTable[ncpCount].mountDir = duplicateStr(mountEntry->mnt_dir);
|
||||
NcpMountTable[ncpCount].server =
|
||||
duplicateStr(mountEntry->mnt_fsname);
|
||||
NcpMountTable[ncpCount].conn = NULL;
|
||||
ncpCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(mountedFile);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Releases the table of ncpfs mount points.
|
||||
*/
|
||||
void releaseMountTable()
|
||||
{
|
||||
int loop;
|
||||
if (!ncpCount) return;
|
||||
for (loop = ncpCount; loop; loop--,ncpCount--) {
|
||||
if (NcpMountTable[loop-1].conn) {
|
||||
ncp_close(NcpMountTable[loop-1].conn);
|
||||
NcpMountTable[loop-1].conn = NULL;
|
||||
}
|
||||
free(NcpMountTable[loop-1].server);
|
||||
free(NcpMountTable[loop-1].mountDir);
|
||||
}
|
||||
free(NcpMountTable);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Finds the index into the mount point table that enables ncp copy for
|
||||
* the file.
|
||||
* Returns -1 if the files do not reference the same server.
|
||||
*/
|
||||
int ncpIndex(const char *InputFile, const char *OutputFile)
|
||||
{
|
||||
int loop;
|
||||
char *mountDir;
|
||||
if (!ncpCount) return -1;
|
||||
|
||||
for (loop = 0; loop < ncpCount; loop++) {
|
||||
mountDir = NcpMountTable[loop].mountDir;
|
||||
if (!strncmp(mountDir,InputFile,strlen(mountDir)) &&
|
||||
!strncmp(mountDir,OutputFile,strlen(mountDir))) return loop;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* Does a regular buffered file copy.
|
||||
* This is used if we cannot use the Netware file copy.
|
||||
*/
|
||||
int normalFileCopy(const char *InputFile, const char *OutputFile,
|
||||
char *Buffer,int BufferSize,
|
||||
const char *paramInputFile,
|
||||
const char *paramOutputFile)
|
||||
{
|
||||
int fdIn, fdOut;
|
||||
long fileSize,totalSize;
|
||||
struct stat statBuf;
|
||||
fdIn = open(InputFile,O_RDONLY);
|
||||
if (fdIn == -1) {
|
||||
fprintf(stderr,"%s: Cannot open %s, %s\n",ProgramName,paramInputFile,
|
||||
strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
if (fstat(fdIn,&statBuf)) {
|
||||
fprintf(stderr,"%s: Cannot stat %s, %s\n",ProgramName,paramInputFile,
|
||||
strerror(errno));
|
||||
close(fdIn);
|
||||
return 1;
|
||||
}
|
||||
if(S_ISDIR(statBuf.st_mode)) {
|
||||
close(fdIn);
|
||||
fprintf(stderr,"%s: %s: omitting directory\n",ProgramName,paramInputFile);
|
||||
return 0; /* At this point, don't consider this a fatal error */
|
||||
}
|
||||
|
||||
fdOut = open(OutputFile,O_CREAT | O_TRUNC | O_WRONLY,statBuf.st_mode);
|
||||
if (fdOut == -1) {
|
||||
fprintf(stderr,"%s: Cannot create %s, %s\n",ProgramName,paramOutputFile,
|
||||
strerror(errno));
|
||||
close(fdIn);
|
||||
return 1;
|
||||
}
|
||||
fileSize = lseek(fdIn,0,SEEK_END);
|
||||
if (fileSize < 0) {
|
||||
fprintf(stderr,"%s: lseek error on %s, %s\n",ProgramName,paramInputFile,
|
||||
strerror(errno));
|
||||
close(fdOut);
|
||||
close(fdIn);
|
||||
return 1;
|
||||
}
|
||||
lseek(fdIn,0,SEEK_SET);
|
||||
if (optVerbose) {
|
||||
printf("Normal copy: %s -> %s 0%%",paramInputFile,paramOutputFile);
|
||||
fflush(stdout);
|
||||
}
|
||||
totalSize = fileSize;
|
||||
while (fileSize) {
|
||||
int currentMove;
|
||||
int writeAmt;
|
||||
currentMove = (fileSize > BufferSize) ? BufferSize : fileSize;
|
||||
if (read(fdIn,Buffer,currentMove) != currentMove) {
|
||||
fprintf(stderr,"%s: Error reading %s, %s\n",ProgramName,paramInputFile,
|
||||
strerror(errno));
|
||||
close(fdIn);
|
||||
close(fdOut);
|
||||
return 1;
|
||||
}
|
||||
writeAmt = write(fdOut,Buffer,currentMove);
|
||||
if (writeAmt < 0) {
|
||||
fprintf(stderr,"%s: Error writing %s, %s\n",ProgramName,paramOutputFile,
|
||||
strerror(errno));
|
||||
close(fdIn);
|
||||
close(fdOut);
|
||||
return 1;
|
||||
} else if (writeAmt == 0) {
|
||||
fprintf(stderr,"%s: Out of space on destination device writing %s\n",
|
||||
ProgramName,OutputFile);
|
||||
close(fdIn);
|
||||
close(fdOut);
|
||||
return 1;
|
||||
}
|
||||
fileSize -= currentMove;
|
||||
if (optVerbose) {
|
||||
printf("\rNormal copy: %s -> %s %ld%%",paramInputFile,paramOutputFile,(100 - (fileSize * 100/totalSize)));
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
close(fdOut);
|
||||
close(fdIn);
|
||||
if (optVerbose)
|
||||
printf("\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Converts a string to upper case.
|
||||
* Netware file names need to be all upper case.
|
||||
*/
|
||||
char *upString(char *str)
|
||||
{
|
||||
char *alias = str;
|
||||
while (*alias) {
|
||||
*alias = toupper(*alias);
|
||||
++alias;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Locates the first occurrance of a single character in the input string.
|
||||
* returns -1 if the character is not found.
|
||||
*/
|
||||
int stringPosition(const char *str,char token)
|
||||
{
|
||||
const char *alias = str;
|
||||
while (*alias) {
|
||||
if (*alias == token) return alias - str;
|
||||
alias++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Walks up the directory path building info structures along the way
|
||||
* in order to get a dir_handle.
|
||||
* This will mangle the input "FileString", leaving just the file name
|
||||
* component in it when it is finished.
|
||||
*/
|
||||
int getDirHandle(struct ncp_conn *conn, char *FileString, __u8 *NewDirHandle)
|
||||
{
|
||||
struct nw_info_struct info1,info2;
|
||||
int currentLevel = 0;
|
||||
int k;
|
||||
struct nw_info_struct *parentInfo = NULL;
|
||||
struct nw_info_struct *currentInfo = NULL;
|
||||
|
||||
while ( (k = stringPosition(FileString,'/')) >= 0) {
|
||||
FileString[k] = 0;
|
||||
if (!currentLevel) {
|
||||
parentInfo = NULL;
|
||||
currentInfo = &info1;
|
||||
} else if (currentLevel % 2) {
|
||||
parentInfo = &info1;
|
||||
currentInfo = &info2;
|
||||
} else {
|
||||
parentInfo = &info2;
|
||||
currentInfo = &info1;
|
||||
}
|
||||
if (ncp_do_lookup(conn, parentInfo, FileString,
|
||||
currentInfo) != 0) {
|
||||
fprintf(stderr,"%s: Ncp lookup failed on directory %s--%s\n",
|
||||
ProgramName,FileString,strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
++currentLevel;
|
||||
memmove(FileString,FileString+k+1,strlen(FileString+k+1)+1);
|
||||
}
|
||||
|
||||
if (ncp_alloc_short_dir_handle(conn, currentInfo, NCP_ALLOC_TEMPORARY,
|
||||
NewDirHandle) != 0) {
|
||||
fprintf(stderr,"%s: Ncp alloc dir handle failed--%s\n",
|
||||
ProgramName,strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* Interfaces with the ncplib to do the netware copy of the file.
|
||||
*/
|
||||
int netwareCopyFile(int ncpMountIndex, const char *sourcefile,
|
||||
const char *destfile,
|
||||
const char *paramInputFile,
|
||||
const char *paramOutputFile)
|
||||
{
|
||||
__u8 source_dir_handle;
|
||||
__u8 dest_dir_handle;
|
||||
struct ncp_file_info source_file;
|
||||
struct ncp_file_info dest_file;
|
||||
__u32 amountCopied;
|
||||
__u32 amtLeft;
|
||||
__u32 totalSize;
|
||||
__u32 sourceOff;
|
||||
__u32 thisMove;
|
||||
int stroffset;
|
||||
int retValue;
|
||||
char *sourceDup;
|
||||
char *destDup;
|
||||
struct ncp_conn *sourceconn;
|
||||
int retryCount;
|
||||
long err = 0;
|
||||
|
||||
/* Establish a connection to a Netware mount point if
|
||||
one is not already established. */
|
||||
if (!NcpMountTable[ncpMountIndex].conn) {
|
||||
NcpMountTable[ncpMountIndex].conn =
|
||||
ncp_open_mount(NcpMountTable[ncpMountIndex].mountDir,&err);
|
||||
if (err) {
|
||||
com_err(ProgramName,err,"opening ncp connection on mount point %s",
|
||||
NcpMountTable[ncpMountIndex].mountDir);
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
sourceconn = NcpMountTable[ncpMountIndex].conn;
|
||||
|
||||
/* Duplicate and upper case the file names so we do not trample
|
||||
on the input strings */
|
||||
stroffset = strlen(NcpMountTable[ncpMountIndex].mountDir) + 1;
|
||||
sourceDup = duplicateStr(sourcefile+stroffset);
|
||||
destDup = duplicateStr(destfile+stroffset);
|
||||
if (!sourceDup || !destDup) {
|
||||
fprintf(stderr,"%s: Malloc failed duplicating file names\n",
|
||||
ProgramName);
|
||||
return 2;
|
||||
}
|
||||
|
||||
upString(sourceDup);
|
||||
upString(destDup);
|
||||
|
||||
/* Get Handles to the input and output directories */
|
||||
if (getDirHandle(sourceconn,sourceDup,&source_dir_handle) ||
|
||||
getDirHandle(sourceconn,destDup,&dest_dir_handle)) {
|
||||
free(sourceDup);
|
||||
free(destDup);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Open the input and output files. */
|
||||
if (ncp_open_file(sourceconn, source_dir_handle, sourceDup,0,AR_READ,
|
||||
&source_file) != 0) {
|
||||
fprintf(stderr,"%s: Cannot open %s--%s\n",
|
||||
ProgramName,paramInputFile,strerror(errno));
|
||||
free(sourceDup);
|
||||
free(destDup);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (ncp_create_file(sourceconn, dest_dir_handle, destDup,
|
||||
source_file.file_attributes, &dest_file) != 0) {
|
||||
fprintf(stderr,"%s: Cannot create %s--%s\n",ProgramName, paramOutputFile,
|
||||
strerror(errno));
|
||||
ncp_close_file(sourceconn,source_file.file_id);
|
||||
free(sourceDup);
|
||||
free(destDup);
|
||||
return 1;
|
||||
}
|
||||
/* Set globals in case a signal happens while copying */
|
||||
CurrentConn = sourceconn;
|
||||
CurrentFile = &dest_file;
|
||||
OutputOpen = 1;
|
||||
|
||||
free(sourceDup);
|
||||
free(destDup);
|
||||
|
||||
retValue = 0;
|
||||
if (optVerbose) {
|
||||
printf("NetWare copy: %s -> %s 0%%",paramInputFile,paramOutputFile);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
/* The main copy loop. */
|
||||
|
||||
amtLeft = totalSize = source_file.file_length;
|
||||
sourceOff = 0;
|
||||
retryCount = 0;
|
||||
|
||||
while (amtLeft && retryCount < MaxNcopyRetries) {
|
||||
int ncopyRetValue;
|
||||
if (amtLeft > CopyBlockSize)
|
||||
thisMove = CopyBlockSize;
|
||||
else
|
||||
thisMove = amtLeft;
|
||||
/* If we are being nice and we've copied enough blocks, go to sleep */
|
||||
if (optNice) {
|
||||
if (BlocksCopied == optNiceFactor) {
|
||||
sleep(NiceSleepTime);
|
||||
BlocksCopied=0;
|
||||
} else
|
||||
++BlocksCopied;
|
||||
}
|
||||
ncopyRetValue = ncp_copy_file(sourceconn, source_file.file_id,
|
||||
dest_file.file_id, sourceOff,sourceOff,
|
||||
thisMove,&amountCopied);
|
||||
if (ncopyRetValue != 0) {
|
||||
/* In my testing this only happens when you run out of space
|
||||
on the server.
|
||||
Netware seems to wait a bit before reporting space recently
|
||||
free'd. I will just wait a bit before bombin */
|
||||
sleep(1); /* Sleep for a second and try again */
|
||||
retryCount++;
|
||||
amountCopied = thisMove = 0;
|
||||
}
|
||||
if (amountCopied != thisMove) {
|
||||
fprintf(stderr,"%s: Warning, amountCopied (%u) != thisMove (%u)\n",
|
||||
ProgramName,(unsigned int)amountCopied,(unsigned int)thisMove);
|
||||
}
|
||||
#ifdef NCOPY_DEBUG
|
||||
fprintf(stderr,"Copied %u (actual %u)\n",(unsigned int)thisMove,
|
||||
(unsigned int)amountCopied);
|
||||
#endif
|
||||
amtLeft -= amountCopied;
|
||||
sourceOff += amountCopied;
|
||||
if (optVerbose) {
|
||||
printf("\rNetWare copy: %s -> %s %ld%%",paramInputFile,paramOutputFile,
|
||||
(100 - (long)((float)amtLeft /(float)totalSize * 100.0)));
|
||||
if (retryCount)
|
||||
printf(" %d retries",retryCount);
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
if (retryCount >= MaxNcopyRetries)
|
||||
retValue = 1;
|
||||
if (optVerbose)
|
||||
printf("\n");
|
||||
if (ncp_close_file(sourceconn,dest_file.file_id) != 0) {
|
||||
fprintf(stderr,"%s: Close failed for %s\n",ProgramName,paramOutputFile);
|
||||
retValue = 1;
|
||||
}
|
||||
|
||||
/* Clear signal handling globals */
|
||||
OutputOpen = 0;
|
||||
CurrentConn = NULL;
|
||||
CurrentFile = NULL;
|
||||
|
||||
if (ncp_close_file(sourceconn,source_file.file_id) != 0) {
|
||||
fprintf(stderr,"%s: Close failed for %s\n",ProgramName,paramInputFile);
|
||||
retValue = 1;
|
||||
}
|
||||
|
||||
if (ncp_dealloc_dir_handle(sourceconn, dest_dir_handle) != 0)
|
||||
{
|
||||
fprintf(stderr,"%s: Dealloc dir handle error for %s\n",ProgramName,
|
||||
paramOutputFile);
|
||||
retValue = 1;
|
||||
}
|
||||
if (ncp_dealloc_dir_handle(sourceconn, source_dir_handle) != 0)
|
||||
{
|
||||
fprintf(stderr,"%s: Dealloc dir handle error for %s\n",ProgramName,
|
||||
paramInputFile);
|
||||
retValue = 1;
|
||||
}
|
||||
return retValue;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* Decides whether to use the traditional file copy or the netware remote
|
||||
* file copy.
|
||||
*/
|
||||
int copyFiles(const char *realsource, const char *realdestination,
|
||||
const char *paraminputfile, const char *paramoutputfile)
|
||||
{
|
||||
int oldUMask;
|
||||
char fileBuffer[24000];
|
||||
int retVal = 0;
|
||||
int ncpMountIndex = ncpIndex(realsource,realdestination);
|
||||
#ifdef NCOPY_DEBUG
|
||||
printf("Real Source '%s'\n"
|
||||
"Real Dest '%s'\n"
|
||||
"Param Src '%s'\n"
|
||||
"Param Dest '%s'\n",realsource,realdestination,paraminputfile,
|
||||
paramoutputfile);
|
||||
#endif
|
||||
|
||||
oldUMask = umask(0);
|
||||
if (ncpMountIndex < 0)
|
||||
retVal = normalFileCopy(realsource,realdestination,fileBuffer,
|
||||
sizeof(fileBuffer),
|
||||
paraminputfile,paramoutputfile);
|
||||
else
|
||||
retVal = netwareCopyFile(ncpMountIndex,realsource,realdestination,
|
||||
paraminputfile,paramoutputfile);
|
||||
umask(oldUMask);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* HERE
|
||||
*
|
||||
* Brian may NEED "fake" path if he prints error messages?
|
||||
* or I may need a way to get his error messages so I can
|
||||
* print them with the "fake" path.
|
||||
* My current error messages are on the REAL path, which would be confusing...
|
||||
*
|
||||
* (1-source problem, 2-destination problem, 3-other fatal)
|
||||
* We need to decide when to exit or continue the loop,
|
||||
* and what to return when we do exit the loop.
|
||||
* Is it failure if 3 files are to be copied, and 1 fails?
|
||||
* If one copy fails, we stay in the loop, right?
|
||||
* Is it failure if destination fails?
|
||||
* Do we Stay in the loop?
|
||||
*/
|
||||
static int copyRealPaths(const char *source, const char *destination)
|
||||
{
|
||||
char realsource[MAXPATHLEN*2];
|
||||
char realdestination[MAXPATHLEN*2];
|
||||
char dirPart[MAXPATHLEN+1];
|
||||
char filePart[MAXPATHLEN+1];
|
||||
const char *p;
|
||||
|
||||
if(realpath(source, realsource) == 0) { /* the source must at least exist */
|
||||
fprintf(stderr,"%s: %s: %s\n",
|
||||
ProgramName, source, strerror(errno));
|
||||
return 1; /* indicate a "source" problem */
|
||||
}
|
||||
if(realpath(destination, realdestination) == 0) {/* dest file missing? OK */
|
||||
strncpy(dirPart, destination, MAXPATHLEN); /* but "dirpart" must work */
|
||||
dirPart[MAXPATHLEN] = 0;
|
||||
p=myBaseName(dirPart);
|
||||
strcpy(filePart, p);
|
||||
dirPart[p - dirPart] = 0; /* isolates "directory" part from "file part" */
|
||||
if(realpath(dirPart, realdestination) == 0) {
|
||||
fprintf(stderr,"%s: %s: %s\n",
|
||||
ProgramName, dirPart, strerror(errno));
|
||||
return 2; /* indicate a "destination" problem */
|
||||
}
|
||||
if(*realdestination != '/' || *(realdestination+1)) strcat(realdestination, "/");
|
||||
strcat(realdestination, filePart);
|
||||
}
|
||||
/* becomes prog exit code */
|
||||
|
||||
/* Test Cases: (Where file/dir may or may not exist)
|
||||
* "", file, file/, dir, dir/
|
||||
* /, //, /dir, /dir/, /file, /file/,
|
||||
* /tmp/file, /tmp/file/, tmp/file, tmp/file/,
|
||||
* /tmp/dir, /tmp/dir/, tmp/dir, tmp/dir/
|
||||
*/
|
||||
return copyFiles(realsource, realdestination,source,destination);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* guaranteed argc is at least 2 and
|
||||
* if argc > 2 last parameter is a directory
|
||||
* by validateFileArgs()
|
||||
*/
|
||||
static int handleFileArgs(int argc, char * const argv[])
|
||||
{
|
||||
int loop;
|
||||
const char *destination;
|
||||
int copyStatus;
|
||||
int returnCode=0; /* default program exit code */
|
||||
const char *baseNamePtr;
|
||||
char destinationfile[MAXPATHLEN*2];
|
||||
|
||||
destination=argv[argc-1]; /* get LAST argument */
|
||||
for (loop = 0; loop < (argc-1); loop++) { /* all file arguments, but last */
|
||||
strncpy(destinationfile, destination, MAXPATHLEN);
|
||||
destinationfile[MAXPATHLEN]=0;
|
||||
if((argc > 2) || (!notDir(argv[argc-1]))) { /* destination is a dir */
|
||||
if(*destinationfile != '/' || *(destinationfile+1)) strcat(destinationfile,"/");
|
||||
baseNamePtr=myBaseName(argv[loop]); /* get the file name */
|
||||
strcat(destinationfile,baseNamePtr); /* add it on end of directory */
|
||||
}
|
||||
copyStatus=copyRealPaths(argv[loop], destinationfile); /* do the copy */
|
||||
if(copyStatus > 1) return copyStatus; /* fatal failure? bye */
|
||||
if(copyStatus == 1) returnCode=1; /* a partial failure? we can continue */
|
||||
}
|
||||
return returnCode; /* return what will be the program exit code */
|
||||
}
|
||||
/****************************************************************************
|
||||
*
|
||||
*/
|
||||
static void handleSignals(int sigNumber)
|
||||
{
|
||||
/* Ignore Signal Handling while cleaning up */
|
||||
|
||||
/* SIGHUP */
|
||||
sHangupSig.sa_handler=SIG_IGN;
|
||||
if(sigaction(SIGHUP, &sHangupSig, NULL) == -1) {
|
||||
fprintf(stderr,"%s: Reset to ignore SIGHUP signal failed: %s",
|
||||
ProgramName, strerror(errno));
|
||||
}
|
||||
/* SIGINT */
|
||||
sInterruptSig.sa_handler=SIG_IGN;
|
||||
if(sigaction(SIGINT, &sInterruptSig, NULL) == -1) {
|
||||
fprintf(stderr,"%s: Reset to ignore SIGINT signal failed: %s",
|
||||
ProgramName, strerror(errno));
|
||||
}
|
||||
/* SIGQUIT */
|
||||
sQuitSig.sa_handler=SIG_IGN;
|
||||
if(sigaction(SIGQUIT, &sQuitSig, NULL) == -1) {
|
||||
fprintf(stderr,"%s: Reset to ignore SIGQUIT signal failed: %s",
|
||||
ProgramName, strerror(errno));
|
||||
}
|
||||
/* SIGTERM */
|
||||
sTermSig.sa_handler=SIG_IGN;
|
||||
if(sigaction(SIGTERM, &sTermSig, NULL) == -1) {
|
||||
fprintf(stderr,"%s: Reset to ignore SIGTERM signal failed: %s",
|
||||
ProgramName, strerror(errno));
|
||||
}
|
||||
|
||||
/* If we don't close the ncp output file, we have to ncpumount and
|
||||
ncpmount before we can get rid of it. */
|
||||
if (OutputOpen) {
|
||||
/* Issue a warning if we cannot close the file */
|
||||
/* If an error occurs we probably have to umount/mount to
|
||||
remove the file */
|
||||
if (ncp_close_file(CurrentConn,CurrentFile->file_id) != 0) {
|
||||
fprintf(stderr,"%s: unclean close of output file",ProgramName);
|
||||
}
|
||||
OutputOpen = 0;
|
||||
}
|
||||
|
||||
exit(128 + sigNumber);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* We'll trap Hangup, Interrupt, Quit or Terminate
|
||||
*/
|
||||
static int trapSignals()
|
||||
{
|
||||
if(sigaction(SIGHUP, NULL, &sHangupSig)) { /* init structure fields */
|
||||
fprintf(stderr,"%s: Get HANGUP signal action failed: %s",
|
||||
ProgramName, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
sHangupSig.sa_handler = handleSignals;
|
||||
if(sigaction(SIGHUP, &sHangupSig, NULL) == -1) {
|
||||
fprintf(stderr,"%s: Reset HANGUP signal action failed: %s",
|
||||
ProgramName, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
if(sigaction(SIGINT, NULL, &sInterruptSig)) { /* init structure fields */
|
||||
fprintf(stderr,"%s: Get INTERRUPT signal action failed: %s",
|
||||
ProgramName, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
sInterruptSig.sa_handler = handleSignals;
|
||||
if(sigaction(SIGINT, &sInterruptSig, NULL) == -1) {
|
||||
fprintf(stderr,"%s: Reset INTERRUPT signal action failed: %s",
|
||||
ProgramName, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
if(sigaction(SIGQUIT, NULL, &sQuitSig)) { /* init structure fields */
|
||||
fprintf(stderr,"%s: Get QUIT signal action failed: %s",
|
||||
ProgramName, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
sQuitSig.sa_handler = handleSignals;
|
||||
if(sigaction(SIGQUIT, &sQuitSig, NULL) == -1) {
|
||||
fprintf(stderr,"%s: Reset QUIT signal action failed: %s",
|
||||
ProgramName, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
if(sigaction(SIGTERM, NULL, &sTermSig)) { /* init structure fields */
|
||||
fprintf(stderr,"%s: Get TERMINATE signal action failed: %s",
|
||||
ProgramName, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
sTermSig.sa_handler = handleSignals;
|
||||
if(sigaction(SIGTERM, &sTermSig, NULL) == -1) {
|
||||
fprintf(stderr,"%s: Reset TERMINATE signal action failed: %s",
|
||||
ProgramName, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
*/
|
||||
int main(int argc, char * const argv[])
|
||||
{
|
||||
int returnCode;
|
||||
ProgramName=argv[0];
|
||||
|
||||
if(handleOptions(argc, argv)) { /* bad option, missing option parameter */
|
||||
usage();
|
||||
return 1;
|
||||
}
|
||||
if(optVersion) { /* only option not requiring any arguments */
|
||||
printf("%s version %s\n", ProgramName, VersionStr);
|
||||
return 0;
|
||||
}
|
||||
if(validateFileArgs(argc - optind, argv + optind)) {
|
||||
usage();
|
||||
return 1;
|
||||
}
|
||||
if(trapSignals()) return 1;
|
||||
loadMountTable();
|
||||
returnCode = handleFileArgs(argc - optind, argv + optind);
|
||||
releaseMountTable();
|
||||
return returnCode;
|
||||
}
|
||||
2986
util/ncplib.c
Normal file
2986
util/ncplib.c
Normal file
File diff suppressed because it is too large
Load Diff
381
util/ncplib.h
Normal file
381
util/ncplib.h
Normal file
@@ -0,0 +1,381 @@
|
||||
/*
|
||||
* 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"
|
||||
#include "com_err.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. */
|
||||
struct ncp_conn *
|
||||
ncp_initialize(int *argc, char **argv,
|
||||
int login_necessary, long *err);
|
||||
|
||||
/* You can login as another object by this procedure. As a first use
|
||||
pserver comes to mind. */
|
||||
struct ncp_conn *
|
||||
ncp_initialize_as(int *argc, char **argv,
|
||||
int login_necessary, int login_type, long *err);
|
||||
|
||||
|
||||
/* Open an existing permanent connection */
|
||||
struct ncp_conn *
|
||||
ncp_open(const struct ncp_conn_spec *spec, long *err);
|
||||
|
||||
/* Open a connection on an existing mount point */
|
||||
struct ncp_conn *
|
||||
ncp_open_mount(const char *mount_point, long *err);
|
||||
|
||||
/* Find a permanent connection that fits the spec, return NULL if
|
||||
* there is none. */
|
||||
char *
|
||||
ncp_find_permanent(const struct ncp_conn_spec *spec);
|
||||
|
||||
/* Find the address of a file server */
|
||||
struct sockaddr_ipx *
|
||||
ncp_find_fileserver(const char *server_name, long *err);
|
||||
|
||||
/* Detach from a permanent connection or destroy a temporary
|
||||
connection */
|
||||
long
|
||||
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, long *err);
|
||||
|
||||
long
|
||||
ncp_get_file_server_description_strings(struct ncp_conn *conn,
|
||||
char target[512]);
|
||||
|
||||
long
|
||||
ncp_get_file_server_time(struct ncp_conn *conn, time_t *target);
|
||||
|
||||
long
|
||||
ncp_get_connlist(struct ncp_conn *conn,
|
||||
__u16 object_type, const char *object_name,
|
||||
int *returned_no, __u8 conn_numbers[256]);
|
||||
|
||||
long
|
||||
ncp_send_broadcast(struct ncp_conn *conn,
|
||||
__u8 no_conn, const __u8 *connections,
|
||||
const char *message);
|
||||
|
||||
long
|
||||
ncp_get_encryption_key(struct ncp_conn *conn,
|
||||
char *target);
|
||||
long
|
||||
ncp_get_bindery_object_id(struct ncp_conn *conn,
|
||||
__u16 object_type,
|
||||
const char *object_name,
|
||||
struct ncp_bindery_object *target);
|
||||
long
|
||||
ncp_scan_bindery_object(struct ncp_conn *conn,
|
||||
__u32 last_id, __u16 object_type, char *search_string,
|
||||
struct ncp_bindery_object *target);
|
||||
|
||||
struct ncp_prop_login_control {
|
||||
__u8 AccountExpireDate[3] __attribute__ ((packed));
|
||||
__u8 Disabled __attribute__ ((packed));
|
||||
__u8 PasswordExpireDate[3] __attribute__ ((packed));
|
||||
__u8 GraceLogins __attribute__ ((packed));
|
||||
__u16 PasswordExpireInterval __attribute__ ((packed));
|
||||
__u8 MaxGraceLogins __attribute__ ((packed));
|
||||
__u8 MinPasswordLength __attribute__ ((packed));
|
||||
__u16 MaxConnections __attribute__ ((packed));
|
||||
__u8 ConnectionTimeMask[42] __attribute__ ((packed));
|
||||
__u8 LastLogin[6] __attribute__ ((packed));
|
||||
__u8 RestrictionMask __attribute__ ((packed));
|
||||
__u8 reserved __attribute__ ((packed));
|
||||
__u32 MaxDiskUsage __attribute__ ((packed));
|
||||
__u16 BadLoginCount __attribute__ ((packed));
|
||||
__u32 BadLoginCountDown __attribute__ ((packed));
|
||||
__u8 LastIntruder[8] __attribute__ ((packed));
|
||||
};
|
||||
|
||||
long
|
||||
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);
|
||||
long
|
||||
ncp_login_encrypted(struct ncp_conn *conn,
|
||||
const struct ncp_bindery_object *object,
|
||||
const unsigned char *key,
|
||||
const unsigned char *passwd);
|
||||
|
||||
#define NCP_GRACE_PERIOD (0xdf)
|
||||
|
||||
long
|
||||
ncp_login_user(struct ncp_conn *conn,
|
||||
const unsigned char *username,
|
||||
const unsigned char *password);
|
||||
long
|
||||
ncp_get_volume_info_with_number(struct ncp_conn *conn, int n,
|
||||
struct ncp_volume_info *target);
|
||||
|
||||
long
|
||||
ncp_get_volume_number(struct ncp_conn *conn, const char *name,
|
||||
int *target);
|
||||
|
||||
long
|
||||
ncp_file_search_init(struct ncp_conn *conn,
|
||||
int dir_handle, const char *path,
|
||||
struct ncp_filesearch_info *target);
|
||||
|
||||
long
|
||||
ncp_file_search_continue(struct ncp_conn *conn,
|
||||
struct ncp_filesearch_info *fsinfo,
|
||||
int attributes, const char *path,
|
||||
struct ncp_file_info *target);
|
||||
|
||||
long
|
||||
ncp_get_finfo(struct ncp_conn *conn,
|
||||
int dir_handle, const char *path, const char *name,
|
||||
struct ncp_file_info *target);
|
||||
|
||||
long
|
||||
ncp_open_file(struct ncp_conn *conn,
|
||||
int dir_handle, const char *path,
|
||||
int attr, int access,
|
||||
struct ncp_file_info *target);
|
||||
long
|
||||
ncp_close_file(struct ncp_conn *conn, const char *file_id);
|
||||
|
||||
long
|
||||
ncp_create_newfile(struct ncp_conn *conn,
|
||||
int dir_handle, const char *path,
|
||||
int attr,
|
||||
struct ncp_file_info *target);
|
||||
|
||||
long
|
||||
ncp_create_file(struct ncp_conn *conn,
|
||||
int dir_handle, const char *path,
|
||||
int attr,
|
||||
struct ncp_file_info *target);
|
||||
|
||||
long
|
||||
ncp_erase_file(struct ncp_conn *conn,
|
||||
int dir_handle, const char *path,
|
||||
int attr);
|
||||
|
||||
long
|
||||
ncp_rename_file(struct ncp_conn *conn,
|
||||
int old_handle, const char *old_path,
|
||||
int attr,
|
||||
int new_handle, const char *new_path);
|
||||
|
||||
long
|
||||
ncp_create_directory(struct ncp_conn *conn,
|
||||
int dir_handle, const char *path,
|
||||
int inherit_mask);
|
||||
|
||||
long
|
||||
ncp_delete_directory(struct ncp_conn *conn,
|
||||
int dir_handle, const char *path);
|
||||
|
||||
long
|
||||
ncp_rename_directory(struct ncp_conn *conn,
|
||||
int dir_handle,
|
||||
const char *old_path, const char *new_path);
|
||||
|
||||
long
|
||||
ncp_read(struct ncp_conn *conn, const char *file_id,
|
||||
off_t offset, size_t count, char *target);
|
||||
|
||||
long
|
||||
ncp_write(struct ncp_conn *conn, const char *file_id,
|
||||
off_t offset, size_t count, const char *source);
|
||||
|
||||
long
|
||||
ncp_copy_file(struct ncp_conn *conn,
|
||||
const char source_file[6],
|
||||
const char target_file[6],
|
||||
__u32 source_offset,
|
||||
__u32 target_offset,
|
||||
__u32 count,
|
||||
__u32 *copied_count);
|
||||
|
||||
long
|
||||
ncp_do_lookup(struct ncp_conn *conn,
|
||||
struct nw_info_struct *dir,
|
||||
char *path, /* may only be one component */
|
||||
struct nw_info_struct *target);
|
||||
|
||||
long
|
||||
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);
|
||||
|
||||
long
|
||||
ncp_del_file_or_subdir(struct ncp_conn *conn,
|
||||
struct nw_info_struct *dir, char *name);
|
||||
|
||||
|
||||
long
|
||||
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);
|
||||
|
||||
long
|
||||
ncp_initialize_search(struct ncp_conn *conn,
|
||||
const struct nw_info_struct *dir,
|
||||
int namespace,
|
||||
struct ncp_search_seq *target);
|
||||
|
||||
long
|
||||
ncp_search_for_file_or_subdir(struct ncp_conn *conn,
|
||||
struct ncp_search_seq *seq,
|
||||
struct nw_info_struct *target);
|
||||
|
||||
long
|
||||
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);
|
||||
|
||||
long
|
||||
ncp_create_queue_job_and_file(struct ncp_conn *conn,
|
||||
__u32 queue_id,
|
||||
struct queue_job *job);
|
||||
|
||||
long
|
||||
ncp_close_file_and_start_job(struct ncp_conn *conn,
|
||||
__u32 queue_id,
|
||||
struct queue_job *job);
|
||||
|
||||
long
|
||||
ncp_attach_to_queue(struct ncp_conn *conn,
|
||||
__u32 queue_id);
|
||||
|
||||
long
|
||||
ncp_detach_from_queue(struct ncp_conn *conn,
|
||||
__u32 queue_id);
|
||||
|
||||
long
|
||||
ncp_service_queue_job(struct ncp_conn *conn, __u32 queue_id, __u16 job_type,
|
||||
struct queue_job *job);
|
||||
|
||||
long
|
||||
ncp_finish_servicing_job(struct ncp_conn *conn, __u32 queue_id,
|
||||
__u32 job_number, __u32 charge_info);
|
||||
|
||||
long
|
||||
ncp_abort_servicing_job(struct ncp_conn *conn, __u32 queue_id,
|
||||
__u32 job_number);
|
||||
|
||||
long
|
||||
ncp_get_broadcast_message(struct ncp_conn *conn, char message[256]);
|
||||
|
||||
long
|
||||
ncp_dealloc_dir_handle(struct ncp_conn *conn, __u8 dir_handle);
|
||||
|
||||
#define NCP_ALLOC_PERMANENT (0x0000)
|
||||
#define NCP_ALLOC_TEMPORARY (0x0001)
|
||||
#define NCP_ALLOC_SPECIAL (0x0002)
|
||||
|
||||
long
|
||||
ncp_alloc_short_dir_handle(struct ncp_conn *conn,
|
||||
struct nw_info_struct *dir,
|
||||
__u16 alloc_mode,
|
||||
__u8 *target);
|
||||
|
||||
#endif /* _NCPLIB_H */
|
||||
21
util/ncplib_err.et
Normal file
21
util/ncplib_err.et
Normal file
@@ -0,0 +1,21 @@
|
||||
error_table NCPL
|
||||
|
||||
ec NCPL_ET_NO_SERVER,
|
||||
"No server found"
|
||||
|
||||
ec NCPL_ET_HOST_UNKNOWN,
|
||||
"Server Unknown"
|
||||
|
||||
ec NCPL_ET_REQUEST_ERROR,
|
||||
"NCP Request returned error code"
|
||||
|
||||
ec NCPL_ET_NAMETOOLONG,
|
||||
"Name too long"
|
||||
|
||||
ec NCPL_ET_MSG_TOO_LONG,
|
||||
"Message too long"
|
||||
|
||||
ec NCPL_ET_NO_SPEC,
|
||||
"Could not find valid connection spec"
|
||||
|
||||
end
|
||||
1459
util/ncplib_user.c
1459
util/ncplib_user.c
File diff suppressed because it is too large
Load Diff
@@ -1,204 +0,0 @@
|
||||
#ifndef _NCPLIB_H
|
||||
#define _NCPLIB_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/ncp.h>
|
||||
#include <linux/ncp_fs.h>
|
||||
#include <linux/ipx.h>
|
||||
|
||||
enum connect_state {
|
||||
NOT_CONNECTED = 0,
|
||||
CONN_MOUNTED,
|
||||
CONN_SOCKET
|
||||
};
|
||||
|
||||
struct ncp_server {
|
||||
int current_size;
|
||||
int has_subfunction;
|
||||
int silent;
|
||||
int ncp_reply_size;
|
||||
char *packet;
|
||||
int lock;
|
||||
|
||||
enum connect_state is_connected;
|
||||
|
||||
int mount_fid;
|
||||
|
||||
struct sockaddr_ipx addr;
|
||||
int ncp_sock;
|
||||
int wdog_sock;
|
||||
int wdog_pid;
|
||||
__u8 sequence;
|
||||
__u16 connection;
|
||||
int completion;
|
||||
int conn_status;
|
||||
int reply_size;
|
||||
|
||||
char ncp_data[NCP_PACKET_SIZE];
|
||||
};
|
||||
|
||||
#include <linux/ncp.h>
|
||||
|
||||
int
|
||||
ncp_connect_mount(struct ncp_server *server, const char *mount_point);
|
||||
|
||||
int
|
||||
ncp_connect(struct ncp_server *server);
|
||||
|
||||
int
|
||||
ncp_disconnect(struct ncp_server *server);
|
||||
|
||||
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_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);
|
||||
|
||||
|
||||
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 */
|
||||
1105
util/ncpmount.c
1105
util/ncpmount.c
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user