Compare commits

..

19 Commits

Author SHA1 Message Date
ncpfs archive import
915f560f85 Import ncpfs 2.0.11 2026-04-28 20:39:59 +02:00
ncpfs archive import
1a5653d403 Import ncpfs 2.0.10 2026-04-28 20:39:58 +02:00
ncpfs archive import
f88460b2e6 Import ncpfs 2.0.9 2026-04-28 20:39:58 +02:00
ncpfs archive import
fff159f2db Import ncpfs 2.0.8 2026-04-28 20:39:58 +02:00
ncpfs archive import
c4d2144d0d Import ncpfs 2.0.7 2026-04-28 20:39:58 +02:00
ncpfs archive import
134b5d6ebf Import ncpfs 2.0.6 2026-04-28 20:39:58 +02:00
ncpfs archive import
ab78307868 Import ncpfs 2.0.5 2026-04-28 20:39:58 +02:00
ncpfs archive import
3019bba627 Import ncpfs 2.0.4 2026-04-28 20:39:58 +02:00
ncpfs archive import
011a5107c5 Import ncpfs 2.0.3 2026-04-28 20:39:58 +02:00
ncpfs archive import
7179281575 Import ncpfs 2.0.2 2026-04-28 20:39:58 +02:00
ncpfs archive import
b8d830f9a3 Import ncpfs 2.0.1 2026-04-28 20:39:58 +02:00
ncpfs archive import
b36a27bedb Import ncpfs 2.0.0 2026-04-28 20:39:58 +02:00
ncpfs archive import
7d0e3d011b Import ncpfs 0.24 2026-04-28 20:39:58 +02:00
ncpfs archive import
84cb1f167d Import ncpfs 0.23 2026-04-28 20:39:58 +02:00
ncpfs archive import
64f006632a Import ncpfs 0.22 2026-04-28 20:39:58 +02:00
ncpfs archive import
92f749a943 Import ncpfs 0.21 2026-04-28 20:39:58 +02:00
ncpfs archive import
6cb56005ea Import ncpfs 0.20 2026-04-28 20:39:58 +02:00
ncpfs archive import
0520c1d2f7 Import ncpfs 0.19 2026-04-28 20:39:57 +02:00
ncpfs archive import
d5ac4601b1 Import ncpfs 0.18 2026-04-28 20:39:57 +02:00
157 changed files with 19899 additions and 6516 deletions

BIN
.downloads/ncpfs-0.18.tgz Normal file

Binary file not shown.

BIN
.downloads/ncpfs-0.19.tgz Normal file

Binary file not shown.

BIN
.downloads/ncpfs-0.20.tgz Normal file

Binary file not shown.

BIN
.downloads/ncpfs-0.21.tgz Normal file

Binary file not shown.

BIN
.downloads/ncpfs-0.22.tgz Normal file

Binary file not shown.

BIN
.downloads/ncpfs-0.23.tgz Normal file

Binary file not shown.

BIN
.downloads/ncpfs-0.24.tgz Normal file

Binary file not shown.

BIN
.downloads/ncpfs-2.0.0.tgz Normal file

Binary file not shown.

BIN
.downloads/ncpfs-2.0.1.tgz Normal file

Binary file not shown.

BIN
.downloads/ncpfs-2.0.10.tgz Normal file

Binary file not shown.

BIN
.downloads/ncpfs-2.0.11.tgz Normal file

Binary file not shown.

BIN
.downloads/ncpfs-2.0.2.tgz Normal file

Binary file not shown.

BIN
.downloads/ncpfs-2.0.3.tgz Normal file

Binary file not shown.

BIN
.downloads/ncpfs-2.0.4.tgz Normal file

Binary file not shown.

BIN
.downloads/ncpfs-2.0.5.tgz Normal file

Binary file not shown.

BIN
.downloads/ncpfs-2.0.6.tgz Normal file

Binary file not shown.

BIN
.downloads/ncpfs-2.0.7.tgz Normal file

Binary file not shown.

BIN
.downloads/ncpfs-2.0.8.tgz Normal file

Binary file not shown.

BIN
.downloads/ncpfs-2.0.9.tgz Normal file

Binary file not shown.

13
BUGS
View File

@@ -5,6 +5,19 @@ But there are really problems that might be fixed in the future.
-------------------------------------------------------------------------------
You might experience lockups of ncpfs volumes. It happens especially
under high network traffic, not necessarily only IPX traffic. I am not
able to reproduce this problem on my machine, so I'm sorry I can not
do anything about that. When such a lockup happens, you have to shut
down the complete ipx subsystem by deleting all ipx interfaces,
unmounting all ncpfs volumes (in this order!) and restarting all
again.
This problem has been solved by Martin Stover (THANKS!!)
See patches/lockup-2.0.30.diff for the fix.
-------------------------------------------------------------------------------
'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

157
Changes
View File

@@ -1,5 +1,158 @@
I only began this file with ncpfs-0.12. If you're interested in older
versions, you can find them on linux01.gwdg.de:/pub/ncpfs/old.
versions, you can find them on ftp.gwdg.de:/pub/linux/misc/ncpfs/old.
ncpfs-2.0.10 -> ncpfs-2.0.11
- Added Martin's patch to Linux 2.0.30 to get rid of the lockups.
MANY thanks to Martin Stover!
ncpfs-2.0.9 -> ncpfs-2.0.10
- Made nwtrustee hopefully work ;-)
- Made the manpages a little bit prettier
ncpfs-2.0.8 -> ncpfs-2.0.9
- Added patches directory
- Added nwvolinfo and nwtrustee. Thanks to Jacek Stepniewski <cunio@gazeta.pl>
- nwpasswd can change other's passwords. Thanks to Martin Stover.
ncpfs-2.0.7 -> ncpfs-2.0.8
- Fixed util/Makefile for easier optimization handling. Thanks to Rik
Faith <faith@cs.unc.edu> for this one
- added nwfstime. You can now set the file server date and time from Linux.
- added the contrib directory. Feel free to add more!
ncpfs-2.0.6 -> ncpfs-2.0.7
- Hopefully removed one security problem in ncpumount.
- Added command line flag to pserver.c
- Heavily reconstructed ncpfs utils. Created the lib/ dir.
- Separated the uid utils in sutil
- Add nwsfind to enable users to use ncpfs safely without setting
the utils setuid root.
ncpfs-2.0.5 -> ncpfs-2.0.6
- Added a short description of a problem that I need help with to the
file BUGS. If you know a bit of the linux networking code, please
take a look at it. Thanks a lot.
- Added canonic output format to nwpbvalues and the command nwbpset. I
would like to invite you to help building capable bindery management
utilities. For little examples, look at the manual page of nwbpset.
- Added some values to ipxparse. Those interested in NDS should take a
look at it. It's really not much, but maybe it's a beginning.
ncpfs-2.0.4 -> ncpfs-2.0.5
- Removed another bug in nwbpvalues.
- Cleaned up man/Makefile
- Some manpage typos fixed. Thanks to Jim Van Zandt
<jrv@mbunix.mitre.org>
- added nwrights
ncpfs-2.0.3 -> ncpfs-2.0.4
- Changed name of npasswd to nwpasswd, as npasswd collides with
RedHat. Thanks to Mike Slater <mslater@nfinity.com> for pointing me
at this one.
- Put '\r\n' into nwmsg, because sometimes it did not print
correctly. Thanks to Petr Vandrovec Ing. VTEI
<VANDROVE@vcnet.vc.cvut.cz> for this one.
- Improved the ELF Makefile for ELF support. Thanks to Uwe Bonnes
<bon@elektron.ikp.physik.th-darmstadt.de>.
- Removed a very embarassing bug in nwpvalues :-(.
- Added a some routines to nwbpvalues.
ncpfs-2.0.2 -> ncpfs-2.0.3
- Removed the kernel-2.0 directory. Linus took the patch into 2.0.8.
So, if you want to use long file name support, upgrade to Linux
kernel version 2.0.8.
- Applied the lfn patch to the kernel-1.2 module with some light
testing. If you experience problems, tell it to me, and use the
ncpfs-2.0.2 kernel module, or upgrade to Linux 2.0.8.
- Added unencrypted login when no crypt key is returned.
- Hopefully improved error messages a bit
- Added some values to ipxparse
- For ELF systems, moved ncplib to /lib/libncp.so.1.x. This saves
about 1MB of disk space. As ncpfs grows, the saving will
increase. Please look at the Makefile to enable this.
- Enhanced nwfsinfo a bit. (Even with a manpage!)
- Added nwuserlist.
ncpfs-2.0.1 -> ncpfs-2.0.2
- Added some values to ipxparse.
- Added a patch against 2.0.7 for long file names support. I did not
apply this change to the 1.2-module. Please upgrade to 2.0.7 if you
want to use long file names.
- nwbpvalues can print ITEM properties
ncpfs-2.0.0 -> ncpfs-2.0.1
- Added some values to ipxparse.
- Added the little bindery utilities. Maybe someone has the time to
write a shellscript named 'nwadduser' ?
- Fixed a bug that made the __255 message reappear. Many thanks to
Guntram Blom for his detailed bug report.
- Fixed a bug that made ncpfs incompatible with W95's server
capabilities. Thanks to Tomasz Babczynski
<faster@dino.ict.pwr.wroc.pl> for this one.
ncpfs-0.24 -> ncpfs-2.0.0
- Changed the numbering scheme :-).
- Added npasswd. Many thanks to Guntram Blom for his work!
- Hopefully improved error messages a bit
- Hopefully made slist a bit more robust
ncpfs-0.23 -> ncpfs-0.24
- Fixed a bug that made it impossible to umount a filesystem after you
tried 'mkdir .' or 'mkdir ..'.
- Fixed a bad race condition when opening files.
- Made the default timeout values more robust.
ncpfs-0.22 -> ncpfs-0.23
- Fixed a memory allocation problem in nwmsg.c. Thanks to
Andrew Ross <anr1001@hermes.cam.ac.uk>
- slist hopefully does not ask for a password anymore.
- cleaned up error messages a bit.
- ncpmount now calls modprobe instead of insmod.
ncpfs-0.21 -> ncpfs-0.22
- removed a bad race condition in kernel-1.2/src/dir.c.
- handle 0x9999-responses from the ncp server correctly.
- Bindery functions in ncplib.c by Brian G. Reid (breid@tim.com)
- set blocksize to 512 to satisfy 'du -k'
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
@@ -52,4 +205,4 @@ 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.
<bon@elektron.ikp.physik.th-darmstadt.de>. Thanks a lot.

67
FAQ Normal file
View File

@@ -0,0 +1,67 @@
There is certainly not enough material to call this an FAQ, but some
questions reach me regularly. Probably the documentation is not clear
enough.
-------------------------------------------------------------------------------
Q: The ncpfs utilities like slist or ncpmount tell me that they can
not find a server, although I'm sure there are servers on my
net. What's wrong?
You probably used
ipx_configure --auto_interface=on --auto_primary=on
and you have Windows (95?) workstations on your network. Windows 95
makes Linux configure IPX interfaces for non-existent frame types. To
solve this problem, you have to configure your IPX interface manually
with the command
ipx_interface add -p <device> <frame>
For <device> use eth0, eth1 or whatever you network adapter is
called. The value for <frame> must match the frame type used on your
network. Possible values are 802.2, 802.3, SNAP and EtherII.
-------------------------------------------------------------------------------
Q: I have difficulties with NetWare 4.1. What can I do?
To be honest, I do not really know. Currently my only test equipment
is a NetWare 3.11 server. You should make your 4.1 Server as
3.x-compatible as it can be. As I do not know 4.1, you are on your own
doing this.
A promising hint that has already helped some people is to switch off
packet signatures on the 4.1 server, as ncpfs does not support them.
-------------------------------------------------------------------------------
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.

View File

@@ -2,31 +2,51 @@
# Makefile for the linux ncp-filesystem routines.
#
VERSION = 0.17
TOPDIR = $(shell pwd)
BINDIR = /usr/local/bin
SBINDIR = /sbin
INTERM_BINDIR = $(TOPDIR)/bin
SUBDIRS = util ipx-1.0 man
#
# 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
VERSION = 2.0.11
# If you are using kerneld to autoload ncp support,
# uncomment this (kerneld is in linux since about 1.3.57):
#KERNELD = -DHAVE_KERNELD
KERNELD = -DHAVE_KERNELD
export INCLUDES BINDIR INTERM_BINDIR SBINDIR KERNELD VERSION
# If your system is ELF, either also do a 'make install', or append the util/
# directory where the dynamic library resides to the environment
# variable LD_LIBRARY_PATH
HAVE_ELF=$(shell file `whereis gcc|cut -d ' ' -f 2`| \
grep ELF >/dev/null && echo -n yes )
TOPDIR = $(shell pwd)
BINDIR = /usr/bin
SBINDIR = /sbin
SUBDIRS = lib sutil util ipx-1.0 man
KVERSION=$(shell uname -r | cut -b1-3)
INCLUDES=-I$(TOPDIR)/include
ifeq ($(KVERSION),1.2)
SUBDIRS += kernel-1.2/src
INCLUDES += -I$(TOPDIR)/kernel-1.2
endif
COPT = -O2
COPT += -g
CFLAGS = $(COPT) -Wall $(INCLUDES) $(KERNELD) -DNCPFS_VERSION=\"$(VERSION)\"
export INCLUDES BINDIR SBINDIR KERNELD VERSION HAVE_ELF CFLAGS
all:
for i in $(SUBDIRS); do make -C $$i; done
for i in $(SUBDIRS); do make -C $$i all; done
@if [ "$(HAVE_ELF)" = yes ] ;\
then \
echo ; echo ; echo ;\
echo Please add \'`pwd`/lib\' to the environment ; \
echo variable LD_LIBRARY_PATH by executing ; \
echo ;\
echo export LD_LIBRARY_PATH=\"\$$LD_LIBRARY_PATH:`pwd`/lib\" ; \
echo ;\
echo or do a \'make install\'. ;\
echo ;\
fi
dep:
for i in $(SUBDIRS); do make -C $$i dep; done
@@ -34,16 +54,16 @@ dep:
install:
for i in $(SUBDIRS); do make -C $$i install; done
clean:
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`
clean_me:
rm -f `find -name '*.out'`
rm -f `find -name '*~'`
rm -f *.tgz
clean: clean_me
for i in $(SUBDIRS); do make -C $$i clean; done
mrproper: clean
rm -fr $(INTERM_BINDIR)/* ncpfs.tgz
make -C util realclean
mrproper: clean_me
for i in $(SUBDIRS) ipxdump; do make -C $$i mrproper; done
modules: ncpfs.o
@@ -55,7 +75,9 @@ dist: tgz
make dep
make all
tgz: mrproper
tgz:
indent -kr -i8 `find . -name '*.[ch]'`
make mrproper
(cd ..; \
tar cvf - $(SRCDIR) | \
gzip -9 > $(DISTFILE); \

65
README
View File

@@ -3,8 +3,35 @@ some little utilities it also contains nprint, which enables you to
print on NetWare print queues. The opposite side, pserver, is also
provided.
ncpfs works with NetWare versions 3.x and following. It does NOT work
with NetWare version 2.x. Some of the NetWare look-alikes, such as
CD-ROM servers WinNT 3.51 Server are also NOT supported. This
restriction comes from the fact that ncpfs relies heavily on the name
space facilities NetWare supports since version 3. When you want to
mount volumes that have been exported by mars_nwe, you have to
activate the name space calls in mars_nwe's config.h file, although
probably it's more clever to use nfs between two Linux machines.
The user-space utilities such as nprint and the bindery utils should
work with all versions of NetWare.
ncpfs does NOT support access to the NDS, so if you want to mount
volumes exported by a NetWare 4.x server, you will have to install the
bindery emulation on that server. If you need access to the NDS, ask
Caldera for their CND. See http://www.caldera.com for more
information.
INSTALLATION
Before you start the installation, make sure that your kernel has IPX
support compiled in. When 'make config' asks you for
The IPX protocol (CONFIG_IPX) [N/y/m/?]
simply answer 'y'. Probably you do not need the full internal net that
you are asked for next.
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
@@ -12,10 +39,9 @@ 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.54. ncpfs does NOT work with any earlier 1.3.x kernel, especially
not with 1.3.53, although this one has a fs/ncpfs/ subdirectory.
1.3.71. ncpfs does NOT work with any earlier 1.3.x kernel.
If you use Kernel 1.3.54 or later, you might have to recompile your
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
@@ -23,10 +49,32 @@ asks for ncpfs. After you have rebooted with the new kernel, 'cat
/proc/filesystems' should show you a line saying that the kernel knows
ncpfs.
With Kernel 1.3.54 or later you also have to modify the Makefile in the
directory you found this README in. Please see the Makefile for the
necessary modifications. Then typing 'make' should work with no
problem.
If you are running kerneld, please uncomment the corresponding line in
the Makefile to reflect this.
If your system is ELF, please enable the use of the shared ncp-library
in the Makefile. This will save at least 1MB of disk space.
After you adapted your Makefile, type 'make' and, as root, 'make install'.
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
@@ -93,3 +141,6 @@ 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

24
bin/nwbpsecurity Executable file
View File

@@ -0,0 +1,24 @@
#!/bin/sh
SECURITY=`nwbpvalues $* -c | head -3 | tail -1`
WRITE=`echo $SECURITY | cut -b1`
READ=`echo $SECURITY | cut -b2`
function print_sec () {
case "$1" in
0 ) echo "Everyone"
;;
1 ) echo "Logged in"
;;
2 ) echo "Object"
;;
3 ) echo "Supervisor"
;;
* ) echo "Bindery"
;;
esac
}
echo -n "Write security: "
print_sec $WRITE
echo -n "Read security : "
print_sec $READ

232
contrib/tknwmsg/nwmsg.c Normal file
View File

@@ -0,0 +1,232 @@
/*
* nwmsg.c
*
* Fetch NetWare broadcast messages and write to the user
*
* Copyright (C) 1996 by Volker Lendecke
*
*/
#include <pwd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <sys/wait.h>
#include <unistd.h>
#include <syslog.h>
#include <signal.h>
#include <paths.h>
#include <utmp.h>
#include <mntent.h>
#include "ncplib.h"
static int search_utmp(char *user, char *tty);
static char *progname;
void
main(int argc, char *argv[])
{
struct ncp_conn *conn;
char message[256];
char *mount_point;
struct ncp_fs_info info;
struct passwd *pwd;
char tty[256];
char tty_path[256];
FILE *tty_file;
FILE *mtab;
struct mntent *mnt;
long err;
char tknwmsg_command[256];
int error_level;
progname = argv[0];
openlog("nwmsg", LOG_PID, LOG_LPR);
if (argc != 2)
{
fprintf(stderr, "usage: %s mount-point\n",
progname);
exit(1);
}
mount_point = argv[1];
if ((conn = ncp_open_mount(mount_point, &err)) == NULL)
{
com_err(progname, err, "in ncp_open_mount");
exit(1);
}
if (ncp_get_broadcast_message(conn, message) != 0)
{
fprintf(stderr, "%s: could not get broadcast message\n",
progname);
ncp_close(conn);
exit(1);
}
if (strlen(message) == 0)
{
syslog(LOG_DEBUG, "no message");
exit(0);
}
#if 0
syslog(LOG_DEBUG, "message: %s", message);
#endif
info.version = NCP_GET_FS_INFO_VERSION;
if (ioctl(conn->mount_fid, NCP_IOC_GET_FS_INFO, &info) < 0)
{
fprintf(stderr, "%s: could not ioctl on connection: %s\n",
progname, strerror(errno));
ncp_close(conn);
exit(1);
}
ncp_close(conn);
if ((pwd = getpwuid(info.mounted_uid)) == NULL)
{
fprintf(stderr, "%s: user %d not known\n",
progname, info.mounted_uid);
exit(1);
}
if ((mtab = fopen(MOUNTED, "r")) == NULL)
{
fprintf(stderr, "%s: can't open %s\n",
progname, MOUNTED);
exit(1);
}
while ((mnt = getmntent(mtab)) != NULL)
{
if (strcmp(mnt->mnt_dir, mount_point) == 0)
{
break;
}
}
if (mnt == NULL)
{
syslog(LOG_DEBUG, "cannot find mtab entry\n");
}
if (search_utmp(pwd->pw_name, tty) != 0)
{
exit(1);
}
sprintf(tty_path, "/dev/%s", tty);
if ((tty_file = fopen(tty_path, "w")) == NULL)
{
fprintf(stderr, "%s: cannot open %s: %s\n",
progname, tty_path, strerror(errno));
exit(1);
}
fprintf(tty_file, "\r\n\007\007\007Message from NetWare Server: %s\r\n",
mnt->mnt_fsname);
fprintf(tty_file, "%s\r\n", message);
//formulate the full system command for the X notice...
strcat(tknwmsg_command, "/usr/bin/tknwmsg -display :0 ");
strcat(tknwmsg_command, "Message from NetWare Server: ");
strcat(tknwmsg_command, mnt->mnt_fsname);
strcat(tknwmsg_command, " ");
strcat(tknwmsg_command, message);
strcat(tknwmsg_command, " &");
//execute this system command...
error_level = system(tknwmsg_command);
fclose(tty_file);
fclose(mtab);
return;
}
/* The following routines have been taken from util-linux-2.5's write.c */
/*
* term_chk - check that a terminal exists, and get the message bit
* and the access time
*/
static int
term_chk(char *tty, int *msgsokP, time_t * atimeP, int *showerror)
{
struct stat s;
char path[MAXPATHLEN];
(void) sprintf(path, "/dev/%s", tty);
if (stat(path, &s) < 0)
{
if (showerror)
(void) fprintf(stderr,
"write: %s: %s\n", path, strerror(errno));
return (1);
}
*msgsokP = (s.st_mode & (S_IWRITE >> 3)) != 0; /* group write bit */
*atimeP = s.st_atime;
return (0);
}
/*
* search_utmp - search utmp for the "best" terminal to write to
*
* Ignores terminals with messages disabled, and of the rest, returns
* the one with the most recent access time. Returns as value the number
* of the user's terminals with messages enabled, or -1 if the user is
* not logged in at all.
*
* Special case for writing to yourself - ignore the terminal you're
* writing from, unless that's the only terminal with messages enabled.
*/
static int
search_utmp(char *user, char *tty)
{
struct utmp u;
time_t bestatime, atime;
int ufd, nloggedttys, nttys, msgsok, user_is_me;
char atty[sizeof(u.ut_line) + 1];
if ((ufd = open(_PATH_UTMP, O_RDONLY)) < 0)
{
perror("utmp");
return -1;
}
nloggedttys = nttys = 0;
bestatime = 0;
user_is_me = 0;
while (read(ufd, (char *) &u, sizeof(u)) == sizeof(u))
if (strncmp(user, u.ut_name, sizeof(u.ut_name)) == 0)
{
++nloggedttys;
(void) strncpy(atty, u.ut_line, sizeof(u.ut_line));
atty[sizeof(u.ut_line)] = '\0';
if (term_chk(atty, &msgsok, &atime, 0))
continue; /* bad term? skip */
if (!msgsok)
continue; /* skip ttys with msgs off */
if (u.ut_type != USER_PROCESS)
continue; /* it's not a valid entry */
++nttys;
if (atime > bestatime)
{
bestatime = atime;
(void) strcpy(tty, atty);
}
}
(void) close(ufd);
if (nloggedttys == 0)
{
(void) fprintf(stderr, "write: %s is not logged in\n", user);
return -1;
}
return 0;
}

57
contrib/tknwmsg/tknwmsg Executable file
View File

@@ -0,0 +1,57 @@
#!/usr/bin/wish
#This is a procedure for centering windows...
#
#
proc center {window_to_center} {
update idletasks
set width [expr [winfo reqwidth $window_to_center]]
set height [expr [winfo reqheight $window_to_center]]
if {$width < 400} {set width 400}
set x [expr [winfo screenwidth $window_to_center]/2 - $width/2]
set y [expr [winfo screenheight $window_to_center]/2 - $height/2]
wm geometry $window_to_center $width\x$height+$x+$y
#update idletasks
wm deiconify $window_to_center
}
#
#
#
#
#This is the main() proc...
set argv_exist [string length $argv]
if {$argv_exist <= 0} {puts "syntax: tkmesg string\a";exit}
wm withdraw .
wm title . "Netware Client for Linux"
wm resizable . 0 0
puts "\a"
label .mesg -text $argv
pack .mesg -padx 5 -pady 5
button .ok -text "Ok" -command exit -width 5
pack .ok -padx 5 -pady 5
focus .ok
bind .ok <Return> exit
center .
#beep the users console after the window appears...
set ofd [open /dev/console w]
puts $ofd "\a"
close $ofd

BIN
contrib/tknwmsg/tknwmsg.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

@@ -0,0 +1,29 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<TITLE></TITLE>
<META NAME="GENERATOR" CONTENT="Mozilla/3.01Gold (X11; I; Linux 2.0.25 i586) [Netscape]">
</HEAD>
<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#0000EF" VLINK="#51188E" ALINK="#FF0000">
<CENTER><P><FONT SIZE=+3>Tknwmsg</FONT></P></CENTER>
<P>Recieve NetWare broadcasts in a dialog under Linux.</P>
<P>The original source was included in the ncpfs package distributed on
sunsite.unc.edu. The modified source to nwmsg.c and a tcl/tk script can
be downloaded here. The <A HREF="tknwmsg_README">tknwmsg_README</A> is
also available for download.</P>
<P>The only requirements for installation are a system with tcl/tk installed
and X running. The system()&nbsp;command will fail if X is not running.</P>
<P>
<HR WIDTH="100%"></P>
<P><A HREF="mailto:kburto1@umbc.edu">Kevin Burton</A></P>
<P><A HREF="http://www.gl.umbc.edu/~kburto1/kburto1.html">http://www.gl.umbc.edu/~kburto1/kburto1.html</A></P>
</BODY>
</HTML>

View File

@@ -0,0 +1,40 @@
Tknwmsg 1.0 for NCPFS.
Kevin Burton (kburto1@umbc.edu), Copyright 1996
Distributed under GPL (GNU Public License)
-- INTRO --
Tknwmesg is a extension for ncpfs for linux that allows users to recived messages
while under an X console.
Essentially it is an extension for nwmsg that comes with ncpfs. The only
changes are a system() call to a tk script that will run a dialog with an "ok"
button under X.
-- INSTALLATION --
TCL/TK must be installed on your system. If they are not then you will have to
get the source for their installation if you want to run tkmesg.
- Download ncpfs from sunsite.unc.edu
- Run "su" to become root if you are not already root.
- Unpack ncpfs in a temporary directory.
- copy the Tknwmsg nwmsg.c to util/nwmsg.c in your ncpfs directory.
- copy tknwmsg to /usr/bin
- change to your nwmsg directory.
- run "make all;make install" and the new version of tknwmsg will be
installed.
-- USE --
- At least 1 terminal on the local system must be have "mesg y". Else
no GUI dialog will be displayed.
Using mesg y in a .bashrc will not work. The only way that I have
found to do this is to have chmod a+w /dev/ttyp? in Xsession or
$HOME/.xsession. Also it may be necessary to have .bashrc do the
same thing if users are starting and stopping xterms.

40
include/com_err.h Normal file
View 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) */

98
include/ipxlib.h Normal file
View File

@@ -0,0 +1,98 @@
/*
* 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 */

676
include/ncplib.h Normal file
View File

@@ -0,0 +1,676 @@
/*
* 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"
typedef __u8 byte;
typedef __u16 word;
typedef __u32 dword;
#ifndef memzero
#include <string.h>
#define memzero(object) memset(&(object), 0, sizeof(object))
#endif
#define BVAL(buf,pos) (((__u8 *)(buf))[pos])
#define PVAL(buf,pos) ((unsigned)BVAL(buf,pos))
#define BSET(buf,pos,val) (BVAL(buf,pos) = (val))
static inline word
WVAL_HL(__u8 * buf, int pos)
{
return PVAL(buf, pos) << 8 | PVAL(buf, pos + 1);
}
static inline dword
DVAL_HL(__u8 * buf, int pos)
{
return WVAL_HL(buf, pos) << 16 | WVAL_HL(buf, pos + 2);
}
static inline void
WSET_HL(__u8 * buf, int pos, word val)
{
BSET(buf, pos, val >> 8);
BSET(buf, pos + 1, val & 0xff);
}
static inline void
DSET_HL(__u8 * buf, int pos, dword val)
{
WSET_HL(buf, pos, val >> 16);
WSET_HL(buf, pos + 2, val & 0xffff);
}
/* we know that the 386 can handle misalignment and has the "right"
byteorder */
#if defined(__i386__)
static inline word
WVAL_LH(__u8 * buf, int pos)
{
return *((word *) (buf + pos));
}
static inline dword
DVAL_LH(__u8 * buf, int pos)
{
return *((dword *) (buf + pos));
}
static inline void
WSET_LH(__u8 * buf, int pos, word val)
{
*((word *) (buf + pos)) = val;
}
static inline void
DSET_LH(__u8 * buf, int pos, dword val)
{
*((dword *) (buf + pos)) = val;
}
#else
static inline word
WVAL_LH(__u8 * buf, int pos)
{
return PVAL(buf, pos) | PVAL(buf, pos + 1) << 8;
}
static inline dword
DVAL_LH(__u8 * buf, int pos)
{
return WVAL_LH(buf, pos) | WVAL_LH(buf, pos + 2) << 16;
}
static inline void
WSET_LH(__u8 * buf, int pos, word val)
{
BSET(buf, pos, val & 0xff);
BSET(buf, pos + 1, val >> 8);
}
static inline void
DSET_LH(__u8 * buf, int pos, dword val)
{
WSET_LH(buf, pos, val & 0xffff);
WSET_LH(buf, pos + 2, val >> 16);
}
#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;
};
struct ncp_property_info
{
__u8 property_name[16];
__u8 property_flags;
__u8 property_security;
__u32 search_instance;
__u8 value_available_flag;
__u8 more_properties_flag;
};
/* 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 a 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);
/* Find the address of a server */
struct sockaddr_ipx *
ncp_find_server(const char **server_name, int type, 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,
int login_necessary, 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_set_file_server_time(struct ncp_conn *conn, time_t * source);
struct ncp_file_server_info
{
__u8 ServerName[48] __attribute__((packed));
__u8 FileServiceVersion __attribute__((packed));
__u8 FileServiceSubVersion __attribute__((packed));
__u16 MaximumServiceConnections __attribute__((packed));
__u16 ConnectionsInUse __attribute__((packed));
__u16 NumberMountedVolumes __attribute__((packed));
__u8 Revision __attribute__((packed));
__u8 SFTLevel __attribute__((packed));
__u8 TTSLevel __attribute__((packed));
__u16 MaxConnectionsEverUsed __attribute__((packed));
__u8 AccountVersion __attribute__((packed));
__u8 VAPVersion __attribute__((packed));
__u8 QueueVersion __attribute__((packed));
__u8 PrintVersion __attribute__((packed));
__u8 VirtualConsoleVersion __attribute__((packed));
__u8 RestrictionLevel __attribute__((packed));
__u8 InternetBridge __attribute__((packed));
__u8 Reserved[60] __attribute__((packed));
};
long
ncp_get_file_server_information(struct ncp_conn *conn,
struct ncp_file_server_info *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_get_stations_logged_info(struct ncp_conn *conn,
__u32 connection,
struct ncp_bindery_object *target,
time_t * login_time);
long
ncp_get_internet_address(struct ncp_conn *conn,
__u32 connection,
struct sockaddr_ipx *target,
__u8 * conn_type);
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_get_bindery_object_name(struct ncp_conn *conn,
__u32 object_id,
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);
long
ncp_create_bindery_object(struct ncp_conn *conn,
__u16 object_type,
const char *object_name,
__u8 object_security,
__u8 object_status);
long
ncp_delete_bindery_object(struct ncp_conn *conn,
__u16 object_type,
const char *object_name);
long
ncp_change_object_security(struct ncp_conn *conn,
__u16 object_type,
const char *object_name,
__u8 security);
struct ncp_station_addr
{
__u32 NetWork __attribute__((packed));
__u8 Node[6] __attribute__((packed));
__u16 Socket __attribute__((packed));
};
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));
struct ncp_station_addr LastIntruder __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_scan_property(struct ncp_conn *conn,
__u16 object_type, const char *object_name,
__u32 last_id, char *search_string,
struct ncp_property_info *property_info);
long
ncp_add_object_to_set(struct ncp_conn *conn,
__u16 object_type, const char *object_name,
const char *property_name,
__u16 member_type,
const char *member_name);
long
ncp_change_property_security(struct ncp_conn *conn,
__u16 object_type, const char *object_name,
const char *property_name,
__u8 property_security);
long
ncp_create_property(struct ncp_conn *conn,
__u16 object_type, const char *object_name,
const char *property_name,
__u8 property_flags, __u8 property_security);
long
ncp_delete_object_from_set(struct ncp_conn *conn,
__u16 object_type, const char *object_name,
const char *property_name,
__u16 member_type,
const char *member_name);
long
ncp_delete_property(struct ncp_conn *conn,
__u16 object_type, const char *object_name,
const char *property_name);
long
ncp_write_property_value(struct ncp_conn *conn,
__u16 object_type, const char *object_name,
const char *property_name,
__u8 segment,
struct nw_property *property_value);
/* Bit masks for security flag */
#define NCP_SEC_CHECKSUMMING_REQUESTED (1)
#define NCP_SEC_SIGNATURE_REQUESTED (2)
#define NCP_SEC_COMPLETE_SIGNATURES_REQUESTED (4)
#define NCP_SEC_ENCRYPTION_REQUESTED (8)
#define NCP_SEC_LIP_DISABLED (128)
long
ncp_get_big_ncp_max_packet_size(struct ncp_conn *conn,
__u16 proposed_max_size,
__u8 proposed_security_flag,
__u16 * accepted_max_size,
__u16 * echo_socket,
__u8 * accepted_security_flag);
long
ncp_login_encrypted(struct ncp_conn *conn,
const struct ncp_bindery_object *object,
const unsigned char *key,
const unsigned char *passwd);
long
ncp_login_unencrypted(struct ncp_conn *conn,
__u16 object_type, const char *object_name,
const unsigned char *passwd);
long
ncp_change_login_passwd(struct ncp_conn *conn,
const struct ncp_bindery_object *object,
const unsigned char *key,
const unsigned char *oldpasswd,
const unsigned char *newpasswd);
#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_get_trustee(struct ncp_conn *conn, __u32 object_id,
__u8 vol, char *path,
__u16 * trustee, __u16 * contin);
long
ncp_add_trustee(struct ncp_conn *conn,
int dir_handle, const char *path,
__u32 object_id, __u8 rights);
long
ncp_delete_trustee(struct ncp_conn *conn,
int dir_handle, const char *path, __u32 object_id);
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_obtain_file_or_subdir_info(struct ncp_conn *conn,
__u8 source_ns, __u8 target_ns,
__u16 search_attribs, __u32 rim,
__u8 vol, __u32 dirent, const char *path,
struct nw_info_struct *target);
#define NCP_PERM_READ (0x001)
#define NCP_PERM_WRITE (0x002)
#define NCP_PERM_OPEN (0x004)
#define NCP_PERM_CREATE (0x008)
#define NCP_PERM_DELETE (0x010)
#define NCP_PERM_OWNER (0x020)
#define NCP_PERM_SEARCH (0x040)
#define NCP_PERM_MODIFY (0x080)
#define NCP_PERM_SUPER (0x100)
long
ncp_get_eff_directory_rights(struct ncp_conn *conn,
__u8 source_ns, __u8 target_ns,
__u16 search_attribs,
__u8 vol, __u32 dirent, const char *path,
__u16 * my_effective_rights);
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);
long
ncp_get_effective_dir_rights(struct ncp_conn *conn,
struct nw_info_struct *file,
__u16 * target);
struct ncp_trustee_struct
{
__u32 object_id;
__u16 rights;
};
long
ncp_add_trustee_set(struct ncp_conn *conn,
__u8 volume_number, __u32 dir_entry,
__u16 rights_mask,
int object_count, struct ncp_trustee_struct *rights);
#endif /* _NCPLIB_H */

View File

@@ -1,24 +0,0 @@
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

View File

@@ -1,30 +1,19 @@
CFLAGS = -O2 -Wall
UTILS = $(INTERM_BINDIR)/ipx_configure $(INTERM_BINDIR)/ipx_interface \
$(INTERM_BINDIR)/ipx_internal_net $(INTERM_BINDIR)/ipx_route
UTILS = ipx_configure ipx_interface ipx_internal_net 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
mrproper: clean
rm -f .depend
install: $(UTILS)
for i in $(UTILS); \
do \
install $$i $(BINDIR); \
done

View File

@@ -8,14 +8,15 @@
int
main(int argc, char **argv)
{
struct sockaddr_ipx sipx;
int s;
int result;
char msg[100];
int len;
struct sockaddr_ipx sipx;
int s;
int result;
char msg[100];
int len;
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
if (s < 0) {
if (s < 0)
{
perror("IPX: socket: ");
exit(-1);
}
@@ -24,29 +25,25 @@ main(int argc, char **argv)
sipx.sipx_port = htons(0x5000);
sipx.sipx_type = 17;
len = sizeof(sipx);
result = bind(s, (struct sockaddr *)&sipx, sizeof(sipx));
if (result < 0) {
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) {
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("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;
}

View File

@@ -1,3 +1,7 @@
#include <stdio.h>
#include <sys/types.h>
#include <linux/ipx.h>
@@ -8,14 +12,15 @@
int
main(int argc, char **argv)
{
struct sockaddr_ipx sipx;
int s;
int result;
char msg[100] = "Hi Mom";
int len = sizeof(sipx);
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) {
if (s < 0)
{
perror("IPX: socket: ");
exit(-1);
}
@@ -24,23 +29,20 @@ main(int argc, char **argv)
sipx.sipx_port = 0;
sipx.sipx_type = 17;
result = bind(s, (struct sockaddr *)&sipx, sizeof(sipx));
if (result < 0) {
result = bind(s, (struct sockaddr *) &sipx, sizeof(sipx));
if (result < 0)
{
perror("IPX: bind: ");
exit(-1);
}
result = getsockname(s, (struct sockaddr *)&sipx, &len);
result = getsockname(s, (struct sockaddr *) &sipx, &len);
sipx.sipx_port = htons(0x5000);
result = sendto(s, msg, sizeof(msg), 0, (struct sockaddr *)&sipx,
result = sendto(s, msg, sizeof(msg), 0, (struct sockaddr *) &sipx,
sizeof(sipx));
if (result < 0) {
if (result < 0)
{
perror("IPX: send: ");
exit(-1);
}
return 0;
}

View File

@@ -1,3 +1,7 @@
#include <stdio.h>
#include <sys/types.h>
#include <linux/ipx.h>
@@ -5,25 +9,27 @@
#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));
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;
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) {
if (s < 0)
{
perror("IPX: socket: ");
exit(-1);
}
@@ -31,38 +37,37 @@ main(int argc, char **argv)
sipx.sipx_network = 0;
sipx.sipx_port = htons(0x453);
sipx.sipx_type = 17;
result = bind(s, (struct sockaddr *)&sipx, sizeof(sipx));
if (result < 0) {
result = bind(s, (struct sockaddr *) &sipx, sizeof(sipx));
if (result < 0)
{
perror("IPX: bind: ");
exit(-1);
}
while (1) {
while (1)
{
len = sizeof(sipx);
result = recvfrom(s, msg, sizeof(msg), 0,
(struct sockaddr *)&sipx, &len);
if (result < 0) {
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]);
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)) {
while (result >= sizeof(struct rip_data))
{
printf("\tNET: %08lX HOPS: %d\n", ntohl(rp->rip_net),
ntohs(rp->rip_hops));
ntohs(rp->rip_hops));
result -= sizeof(struct rip_data);
rp++;
}
}
}

View File

@@ -1,3 +1,7 @@
#include <stdio.h>
#include <sys/types.h>
#include <linux/ipx.h>
@@ -6,55 +10,58 @@
#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));
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;
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) {
if (s < 0)
{
perror("IPX: socket: ");
exit(-1);
}
result = setsockopt(s, SOL_SOCKET, SO_DEBUG, &val, 4);
if (result < 0) {
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) {
result = bind(s, (struct sockaddr *) &sipx, sizeof(sipx));
if (result < 0)
{
perror("IPX: bind: ");
exit(-1);
}
while (1) {
while (1)
{
len = 1024;
result = recvfrom(s, msg, sizeof(msg), 0,
(struct sockaddr *)&sipx, &len);
if (result < 0) {
result = recvfrom(s, msg, sizeof(msg), 0,
(struct sockaddr *) &sipx, &len);
if (result < 0)
{
perror("IPX: recvfrom: ");
exit(-1);
}
@@ -67,30 +74,27 @@ main(int argc, char **argv)
bptr += 2;
sp = (struct sap_data *) bptr;
while (result >= sizeof(struct sap_data)) {
int i;
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));
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++;
}
}
}

View File

@@ -1,5 +1,5 @@
/* Copyright (c) 1995-1996 Caldera, Inc. All Rights Reserved.
*
* See file COPYING for details.
*/
@@ -12,21 +12,23 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <errno.h>
struct option options[] = {
{ "auto_primary", required_argument, NULL, 1 },
{ "auto_interface", required_argument, NULL, 2 },
{ "help", no_argument, NULL, 3},
{ NULL, 0, NULL, 0 }
struct option options[] =
{
{"auto_primary", required_argument, NULL, 1},
{"auto_interface", required_argument, NULL, 2},
{"help", no_argument, NULL, 3},
{NULL, 0, NULL, 0}
};
char *progname;
char *progname;
void
usage(void)
{
fprintf(stderr,
"Usage: %s --auto_primary=[on|off]\n\
fprintf(stderr,
"Usage: %s --auto_primary=[on|off]\n\
Usage: %s --auto_interface=[on|off]\n\
Usage: %s --help\n\
Usage: %s\n", progname, progname, progname, progname);
@@ -36,75 +38,86 @@ int
map_string_to_bool(char *optarg)
{
if ((strcasecmp(optarg, "ON") == 0) ||
(strcasecmp(optarg, "TRUE") == 0) ||
(strcasecmp(optarg, "SET") == 0) ||
(strcasecmp(optarg, "YES") == 0)) {
(strcasecmp(optarg, "TRUE") == 0) ||
(strcasecmp(optarg, "SET") == 0) ||
(strcasecmp(optarg, "YES") == 0))
{
return 1;
} else if ((strcasecmp(optarg, "OFF") == 0) ||
(strcasecmp(optarg, "FALSE") == 0) ||
(strcasecmp(optarg, "CLEAR") == 0) ||
(strcasecmp(optarg, "NO") == 0)) {
(strcasecmp(optarg, "FALSE") == 0) ||
(strcasecmp(optarg, "CLEAR") == 0) ||
(strcasecmp(optarg, "NO") == 0))
{
return 0;
}
}
return -1;
}
int
main(int argc, char **argv)
{
int s;
int result;
char errmsg[80];
char val;
int option_index = 0;
int got_auto_pri = 0;
int got_auto_itf = 0;
ipx_config_data data;
int s;
int result;
char errmsg[80];
char val;
int option_index = 0;
int got_auto_pri = 0;
int got_auto_itf = 0;
ipx_config_data data;
progname = argv[0];
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
if (s < 0) {
if (s < 0)
{
int old_errno = errno;
sprintf(errmsg, "%s: socket", progname);
perror(errmsg);
if (old_errno == -EINVAL)
{
fprintf(stderr, "Probably you have no IPX support in "
"your kernel\n");
}
exit(-1);
}
sprintf(errmsg, "%s: ioctl", progname);
while ((result = getopt_long(argc, argv, "", options,
&option_index)) != -1) {
switch (result) {
case 1:
while ((result = getopt_long(argc, argv, "", options,
&option_index)) != -1)
{
switch (result)
{
case 1:
if (got_auto_pri)
break;
got_auto_pri++;
val = map_string_to_bool(optarg);
if (val < 0) {
if (val < 0)
{
usage();
exit(-1);
}
result = ioctl(s, SIOCAIPXPRISLT, &val);
if (result < 0) {
if (result < 0)
{
perror(errmsg);
exit(-1);
}
break;
case 2:
if (got_auto_itf)
if (got_auto_itf)
break;
got_auto_itf++;
val = map_string_to_bool(optarg);
if (val < 0) {
if (val < 0)
{
usage();
exit(-1);
}
result = ioctl(s, SIOCAIPXITFCRT, &val);
if (result < 0) {
if (result < 0)
{
perror(errmsg);
exit(-1);
}
@@ -115,16 +128,17 @@ main(int argc, char **argv)
}
}
result = ioctl(s, SIOCIPXCFGDATA, &data);
if (result < 0) {
if (result < 0)
{
perror(errmsg);
exit(-1);
}
if (argc == 1) {
if (argc == 1)
{
fprintf(stdout, "Auto Primary Select is %s\n\
Auto Interface Create is %s\n",
Auto Interface Create is %s\n",
(data.ipxcfg_auto_select_primary) ? "ON" : "OFF",
(data.ipxcfg_auto_create_interfaces) ? "ON" : "OFF");
}
exit(0);
}

View File

@@ -1,5 +1,6 @@
/* Copyright (c) 1995-1996 Caldera, Inc. All Rights Reserved.
*
* See file COPYING for details.
*/
@@ -15,9 +16,10 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <errno.h>
static struct ifreq id;
static char *progname;
static struct ifreq id;
static char *progname;
void
usage(void)
@@ -29,17 +31,34 @@ 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},
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},
{
"802.2TR", IPX_FRAME_TR_8022
}
,
#endif
{"802.3", IPX_FRAME_8023},
{"SNAP", IPX_FRAME_SNAP},
{"EtherII", IPX_FRAME_ETHERII}
{
"802.3", IPX_FRAME_8023
}
,
{
"SNAP", IPX_FRAME_SNAP
}
,
{
"EtherII", IPX_FRAME_ETHERII
}
};
#define NFTYPES (sizeof(frame_types)/sizeof(struct frame_type))
@@ -47,20 +66,21 @@ struct frame_type {
int
lookup_frame_type(char *frame)
{
int j;
int j;
for (j = 0; (j < NFTYPES) &&
(strcasecmp(frame_types[j].ft_name, frame));
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 " : " ",
for (j = 0; j < NFTYPES; j++)
{
fprintf(stderr, "%s%s",
(j == NFTYPES - 1) ? " or " : " ",
frame_types[j].ft_name);
}
fprintf(stderr, ".\n");
@@ -70,44 +90,51 @@ lookup_frame_type(char *frame)
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;
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;
while ((c = getopt(argc, argv, "p")) > 0)
{
switch (c)
{
case 'p':
sipx->sipx_special = IPX_PRIMARY;
break;
}
}
if (((i = (argc - optind)) < 2) || (i > 3)) {
if (((i = (argc - optind)) < 2) || (i > 3))
{
usage();
}
for (i = optind; i < argc; i++) {
switch (i-optind) {
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 */
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",
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);
}
@@ -115,25 +142,35 @@ ipx_add_interface(int argc, char **argv)
break;
}
}
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
if (s < 0) {
if (s < 0)
{
int old_errno = errno;
sprintf(errmsg, "%s: socket", progname);
perror(errmsg);
if (old_errno == -EINVAL)
{
fprintf(stderr, "Probably you have no IPX support in "
"your kernel\n");
}
exit(-1);
}
i = 0;
sipx->sipx_family = AF_IPX;
sipx->sipx_action = IPX_CRTITF;
do {
do
{
result = ioctl(s, SIOCSIFADDR, &id);
i++;
} while ((i < 5) && (result < 0) && (errno == EAGAIN));
}
while ((i < 5) && (result < 0) && (errno == EAGAIN));
if (result == 0) exit(0);
switch (errno) {
if (result == 0)
exit(0);
switch (errno)
{
case EEXIST:
fprintf(stderr, "%s: Primary network already selected.\n",
progname);
@@ -159,7 +196,7 @@ ipx_add_interface(int argc, char **argv)
id.ifr_name);
break;
case EAGAIN:
fprintf(stderr,
fprintf(stderr,
"%s: Insufficient memory to create interface.\n",
progname);
break;
@@ -174,61 +211,67 @@ ipx_add_interface(int argc, char **argv)
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;
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) {
if (s < 0)
{
sprintf(errmsg, "%s: socket", progname);
perror(errmsg);
exit(-1);
}
fp = fopen("/proc/net/ipx_interface", "r");
if (fp == NULL) {
fprintf(stderr,
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) {
device, frame_type) == 5)
{
sipx->sipx_network = 0L;
if (strcasecmp(device, "Internal") == 0) {
if (strcasecmp(device, "Internal") == 0)
{
sipx->sipx_special = IPX_INTERNAL;
} else {
} else
{
sipx->sipx_special = IPX_SPECIAL_NONE;
strcpy(id.ifr_name, device);
fti = lookup_frame_type(frame_type);
if (fti < 0) continue;
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) {
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",
fprintf(stderr, "%s: No such device (%s).\n",
progname, device);
break;
case EINVAL:
fprintf(stderr, "%s: No such IPX interface %s %s.\n",
fprintf(stderr, "%s: No such IPX interface %s %s.\n",
progname, device, frame_type);
break;
default:
@@ -244,16 +287,16 @@ ipx_delall_interface(int argc, char **argv)
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) {
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]);
@@ -263,7 +306,8 @@ ipx_del_interface(int argc, char **argv)
sipx->sipx_type = frame_types[fti].ft_val;
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
if (s < 0) {
if (s < 0)
{
sprintf(errmsg, "%s: socket", progname);
perror(errmsg);
exit(-1);
@@ -271,9 +315,11 @@ ipx_del_interface(int argc, char **argv)
sipx->sipx_action = IPX_DLTITF;
sipx->sipx_family = AF_IPX;
result = ioctl(s, SIOCSIFADDR, &id);
if (result == 0) exit(0);
if (result == 0)
exit(0);
switch (errno) {
switch (errno)
{
case EPROTONOSUPPORT:
fprintf(stderr, "%s: Invalid frame type (%s).\n",
progname, frame_types[fti].ft_name);
@@ -297,16 +343,16 @@ ipx_del_interface(int argc, char **argv)
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) {
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]);
@@ -315,25 +361,27 @@ ipx_check_interface(int argc, char **argv)
sipx->sipx_type = frame_types[fti].ft_val;
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
if (s < 0) {
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) {
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]);
"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) {
switch (errno)
{
case EPROTONOSUPPORT:
fprintf(stderr, "%s: Invalid frame type (%s).\n",
progname, frame_types[fti].ft_name);
@@ -357,31 +405,35 @@ ipx_check_interface(int argc, char **argv)
int
main(int argc, char **argv)
{
int i;
int i;
progname = argv[0];
if (argc < 2) {
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);
}
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;
}

View File

@@ -1,5 +1,5 @@
/* Copyright (c) 1995-1996 Caldera, Inc. All Rights Reserved.
*
* See file COPYING for details.
*/
@@ -15,8 +15,8 @@
#include <sys/socket.h>
#include <sys/ioctl.h>
static struct ifreq id;
static char *progname;
static struct ifreq id;
static char *progname;
void
usage(void)
@@ -29,12 +29,15 @@ Usage: %s del\n", progname, progname);
int
map_char_to_val(char dig)
{
char digit = tolower(dig);
if ((digit >= '0') && (digit <= '9')) {
char digit = tolower(dig);
if ((digit >= '0') && (digit <= '9'))
{
return digit - '0';
} else if ((digit >= 'a') && (digit <= 'f')) {
} else if ((digit >= 'a') && (digit <= 'f'))
{
return (10 + (digit - 'a'));
} else {
} else
{
return 0;
}
}
@@ -42,80 +45,85 @@ map_char_to_val(char dig)
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) {
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",
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) {
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++)
for (i = 0; (i < nodelen) && isxdigit(node[i]); i++)
;
if (i < nodelen) {
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++) {
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));
*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)){
(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) {
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 {
do
{
result = ioctl(s, SIOCSIFADDR, &id);
i++;
} while ((i < 5) && (result < 0) && (errno == EAGAIN));
}
while ((i < 5) && (result < 0) && (errno == EAGAIN));
if (result == 0) exit(0);
switch (errno) {
if (result == 0)
exit(0);
switch (errno)
{
case EEXIST:
fprintf(stderr, "%s: Primary network already selected.\n",
progname);
@@ -125,7 +133,7 @@ ipx_add_internal_net(int argc, char **argv)
progname, htonl(sipx->sipx_network));
break;
case EAGAIN:
fprintf(stderr,
fprintf(stderr,
"%s: Insufficient memory to create internal net.\n",
progname);
break;
@@ -140,19 +148,20 @@ ipx_add_internal_net(int argc, char **argv)
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) {
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) {
if (s < 0)
{
sprintf(errmsg, "%s: socket", progname);
perror(errmsg);
exit(-1);
@@ -160,9 +169,11 @@ ipx_del_internal_net(int argc, char **argv)
sipx->sipx_family = AF_IPX;
sipx->sipx_action = IPX_DLTITF;
result = ioctl(s, SIOCSIFADDR, &id);
if (result == 0) exit(0);
if (result == 0)
exit(0);
switch (errno) {
switch (errno)
{
case ENOENT:
fprintf(stderr, "%s: No internal network configured.\n", progname);
break;
@@ -177,24 +188,25 @@ ipx_del_internal_net(int argc, char **argv)
int
main(int argc, char **argv)
{
int i;
int i;
progname = argv[0];
if (argc < 2) {
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);
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;
}

View File

@@ -1,5 +1,6 @@
/* Copyright (c) 1995-1996 Caldera, Inc. All Rights Reserved.
*
* See file COPYING for details.
*/
@@ -16,18 +17,21 @@
#include <sys/ioctl.h>
#include <linux/route.h>
static struct rtentry rd;
static char *progname;
static struct rtentry rd;
static char *progname;
int
map_char_to_val(char dig)
{
char digit = tolower(dig);
if ((digit >= '0') && (digit <= '9')) {
char digit = tolower(dig);
if ((digit >= '0') && (digit <= '9'))
{
return digit - '0';
} else if ((digit >= 'a') && (digit <= 'f')) {
} else if ((digit >= 'a') && (digit <= 'f'))
{
return (10 + (digit - 'a'));
} else {
} else
{
return 0;
}
}
@@ -35,8 +39,8 @@ map_char_to_val(char dig)
void
usage(void)
{
fprintf(stderr,
"Usage: %s add network(hex) router_network(hex) router_node(hex)\n\
fprintf(stderr,
"Usage: %s add network(hex) router_network(hex) router_node(hex)\n\
Usage: %s del network(hex)\n", progname, progname);
exit(-1);
}
@@ -45,27 +49,28 @@ int
ipx_add_route(int argc, char **argv)
{
/* Router */
struct sockaddr_ipx *sr = (struct sockaddr_ipx *)&rd.rt_gateway;
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;
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",
netnum = strtoul(argv[1], (char **) NULL, 16);
if ((netnum == 0xffffffffL) || (netnum == 0L))
{
fprintf(stderr, "%s: Inappropriate network number %08lX\n",
progname, netnum);
exit(-1);
}
@@ -73,63 +78,69 @@ ipx_add_route(int argc, char **argv)
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",
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",
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++)
for (i = 0; (i < nodelen) && isxdigit(node[i]); i++)
;
if (i < nodelen) {
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++) {
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));
*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)){
(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) {
if (s < 0)
{
sprintf(errmsg, "%s: socket", progname);
perror(errmsg);
exit(-1);
}
sr->sipx_family = st->sipx_family = AF_IPX;
i = 0;
do {
do
{
result = ioctl(s, SIOCADDRT, &rd);
i++;
} while ((i < 5) && (result < 0) && (errno == EAGAIN));
}
while ((i < 5) && (result < 0) && (errno == EAGAIN));
if (result == 0) exit(0);
if (result == 0)
exit(0);
switch (errno) {
switch (errno)
{
case ENETUNREACH:
fprintf(stderr, "%s: Router network (%08lX) not reachable.\n",
progname, htonl(sr->sipx_network));
@@ -146,23 +157,24 @@ int
ipx_del_route(int argc, char **argv)
{
/* Router */
struct sockaddr_ipx *sr = (struct sockaddr_ipx *)&rd.rt_gateway;
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) {
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",
netnum = strtoul(argv[1], (char **) NULL, 16);
if ((netnum == 0xffffffffL) || (netnum == 0L))
{
fprintf(stderr, "%s: Inappropriate network number %08lX.\n",
progname, netnum);
exit(-1);
}
@@ -170,15 +182,18 @@ ipx_del_route(int argc, char **argv)
st->sipx_family = sr->sipx_family = AF_IPX;
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
if (s < 0) {
if (s < 0)
{
sprintf(errmsg, "%s: socket", progname);
perror(errmsg);
exit(-1);
}
result = ioctl(s, SIOCDELRT, &rd);
if (result == 0) exit(0);
if (result == 0)
exit(0);
switch (errno) {
switch (errno)
{
case ENOENT:
fprintf(stderr, "%s: Route not found for network %08lX.\n",
progname, netnum);
@@ -198,22 +213,24 @@ ipx_del_route(int argc, char **argv)
int
main(int argc, char **argv)
{
int i;
int i;
progname = argv[0];
if (argc < 2) {
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);
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;

View File

@@ -1,7 +1,7 @@
/* ipxdump.c */
/* 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
@@ -37,30 +37,30 @@
struct ipx_address
{
unsigned long net;
unsigned char node[IPX_NODE_LEN];
unsigned char node[IPX_NODE_LEN];
unsigned short sock;
};
struct ipx_packet
{
unsigned short ipx_checksum;
unsigned short ipx_checksum;
#define IPX_NO_CHECKSUM 0xFFFF
unsigned short ipx_pktsize;
unsigned char ipx_tctrl;
unsigned char ipx_type;
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));
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 (unsigned char *buf);
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;
@@ -73,7 +73,7 @@ int_handler()
}
void
main (int argc, char *argv[])
main(int argc, char *argv[])
{
int sd;
struct ifreq ifr, oldifr;
@@ -94,63 +94,59 @@ main (int argc, char *argv[])
}
filter = 1;
}
if ((sd = socket (AF_INET, SOCK_PACKET, htons (ETH_P_ALL))) < 0)
if ((sd = socket(AF_INET, SOCK_PACKET, htons(ETH_P_ALL))) < 0)
{
perror ("Can't get socket");
perror("Can't get socket");
fprintf(stderr, "You must run %s as root\n", argv[0]);
exit (1);
exit(1);
}
/* SET PROMISC */
strcpy (oldifr.ifr_name, device);
if (ioctl (sd, SIOCGIFFLAGS, &oldifr) < 0)
strcpy(oldifr.ifr_name, device);
if (ioctl(sd, SIOCGIFFLAGS, &oldifr) < 0)
{
close (sd);
perror ("Can't get flags");
exit (2);
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)
if (ioctl(sd, SIOCSIFFLAGS, &ifr) < 0)
{
close (sd);
perror ("Can't set flags");
exit (3);
close(sd);
perror("Can't set flags");
exit(3);
}
while ( exit_request == 0 )
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);
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)
if (ioctl(sd, SIOCSIFFLAGS, &oldifr) < 0)
{
close (sd);
perror ("Can't set flags");
exit (4);
close(sd);
perror("Can't set flags");
exit(4);
}
close (sd);
exit (0);
close(sd);
exit(0);
}
void
handle_ipx (unsigned char *buf)
handle_ipx(char *frame, unsigned char *buf)
{
int i;
struct ipx_packet *h = (struct ipx_packet *)buf;
struct ipx_packet *h = (struct ipx_packet *) buf;
struct sockaddr_ipx s_addr;
struct sockaddr_ipx d_addr;
int length = ntohs(h->ipx_pktsize);
@@ -161,16 +157,16 @@ handle_ipx (unsigned char *buf)
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;
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;
d_addr.sipx_network = h->ipx_dest.net;
if (filter != 0)
{
if ( (memcmp(filter_node, s_addr.sipx_node,
sizeof(filter_node)) != 0)
if ((memcmp(filter_node, s_addr.sipx_node,
sizeof(filter_node)) != 0)
&& (memcmp(filter_node, d_addr.sipx_node,
sizeof(filter_node)) != 0))
{
@@ -178,6 +174,7 @@ handle_ipx (unsigned char *buf)
return;
}
}
printf("%s ", frame);
for (i = 0; i < length; i++)
{
@@ -191,9 +188,9 @@ handle_ipx (unsigned char *buf)
}
void
handle_other (unsigned char *buf, int length, struct sockaddr *saddr)
handle_other(unsigned char *buf, int length, struct sockaddr *saddr)
{
struct ethhdr *eth = (struct ethhdr *)buf;
struct ethhdr *eth = (struct ethhdr *) buf;
unsigned char *p = &(buf[sizeof(struct ethhdr)]);
if (ntohs(eth->h_proto) < 1536)
@@ -204,41 +201,35 @@ handle_other (unsigned char *buf, int length, struct sockaddr *saddr)
* 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)
if (*(unsigned short *) p == 0xffff)
{
printf("802.3 ");
handle_ipx(p);
handle_ipx("802.3", p);
return;
}
if ( (*(unsigned short *)p == htons(0xe0e0))
if ((*(unsigned short *) p == htons(0xe0e0))
&& (p[2] == 0x03))
{
printf("802.2 ");
handle_ipx(p+3);
handle_ipx("802.2", p + 3);
return;
}
if (memcmp(p, "\252\252\003\000\000\000\201\067", 8) == 0)
{
printf("snap ");
handle_ipx(p+8);
handle_ipx("snap", p + 8);
return;
}
}
}
void
handle_frame (unsigned char *buf, int length, struct sockaddr *saddr)
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 )
unsigned short packet_type = ((struct ethhdr *) buf)->h_proto;
switch (packet_type)
{
case __constant_ntohs(ETH_P_IPX):
printf("EtherII ");
handle_ipx(&(buf[sizeof(struct ethhdr)]));
handle_ipx("EtherII", &(buf[sizeof(struct ethhdr)]));
break;
default:
handle_other(buf, length, saddr);

File diff suppressed because it is too large Load Diff

View File

@@ -1,97 +1,101 @@
/*
IPX support library - general functions
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>
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 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.
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.
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)
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]
);
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)
ipx_fprint_network(FILE * file, IPXNet net)
{
fprintf(file,"%08lX",net);
fprintf(file, "%08lX", net);
}
void
ipx_fprint_port(FILE *file, IPXPort port)
ipx_fprint_port(FILE * file, IPXPort port)
{
fprintf(file,"%04X",port);
fprintf(file, "%04X", port);
}
void
ipx_fprint_saddr(FILE *file, struct sockaddr_ipx *sipx)
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));
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);
ipx_fprint_node(stdout, node);
}
void
ipx_print_network(IPXNet net)
{
ipx_fprint_network(stdout,net);
ipx_fprint_network(stdout, net);
}
void
ipx_print_port(IPXPort port)
{
ipx_fprint_port(stdout,port);
ipx_fprint_port(stdout, port);
}
void
ipx_print_saddr(struct sockaddr_ipx *sipx)
{
ipx_fprint_saddr(stdout,sipx);
ipx_fprint_saddr(stdout, sipx);
}
void
ipx_assign_node(IPXNode dest, IPXNode src)
{
memcpy(dest,src,sizeof(IPXNode));
memcpy(dest, src, sizeof(IPXNode));
}
int
ipx_node_equal(IPXNode n1, IPXNode n2)
{
return memcmp(n1,n2,sizeof(n1))==0;
return memcmp(n1, n2, sizeof(IPXNode)) == 0;
}
int
@@ -106,8 +110,7 @@ ipx_sscanf_node(char *buf, IPXNode node)
{
return -1;
}
for (i=0; i<6; i++)
for (i = 0; i < 6; i++)
{
node[i] = n[i];
}
@@ -115,7 +118,7 @@ ipx_sscanf_node(char *buf, IPXNode node)
}
int
ipx_sscanf_net(char *buf, IPXNet *target)
ipx_sscanf_net(char *buf, IPXNet * target)
{
if (sscanf(buf, "%8lX", target) == 1)
{
@@ -124,6 +127,8 @@ ipx_sscanf_net(char *buf, IPXNet *target)
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";
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";

View File

@@ -1,25 +1,25 @@
/*
IPX support library
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>
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 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.
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.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
*/
#ifndef __IPXUTIL_H__
#define __IPXUTIL_H__
@@ -44,22 +44,22 @@ 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);
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);
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);
int ipx_sscanf_net(char *buf, IPXNet * target);
void ipx_assign_node(IPXNode dest,IPXNode src);
int ipx_node_equal(IPXNode n1,IPXNode n2);
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];
extern char ipx_err_string[IPX_MAX_ERROR + 1];
#endif

View File

@@ -18,28 +18,30 @@
#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));
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));
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));
};
@@ -48,45 +50,50 @@ struct ncp_reply_header {
#define NCP_BINDERY_PQUEUE (0x0003)
#define NCP_BINDERY_FSERVER (0x0004)
#define NCP_BINDERY_NAME_LEN (48)
struct ncp_bindery_object {
__u32 object_id;
__u16 object_type;
__u8 object_name[NCP_BINDERY_NAME_LEN];
__u8 object_flags;
__u8 object_security;
__u8 object_has_prop;
struct 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 {
__u8 value[128];
__u8 more_flag;
__u8 property_flag;
struct nw_property
{
__u8 value[128];
__u8 more_flag;
__u8 property_flag;
};
struct prop_net_address {
__u32 network __attribute__ ((packed));
__u8 node[IPX_NODE_LEN] __attribute__ ((packed));
__u16 port __attribute__ ((packed));
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)
struct ncp_volume_info {
__u32 total_blocks;
__u32 free_blocks;
__u32 purgeable_blocks;
__u32 not_yet_purgeable_blocks;
__u32 total_dir_entries;
__u32 available_dir_entries;
__u8 sectors_per_block;
char volume_name[NCP_VOLNAME_LEN+1];
struct ncp_volume_info
{
__u32 total_blocks;
__u32 free_blocks;
__u32 purgeable_blocks;
__u32 not_yet_purgeable_blocks;
__u32 total_dir_entries;
__u32 available_dir_entries;
__u8 sectors_per_block;
char volume_name[NCP_VOLNAME_LEN + 1];
};
struct ncp_filesearch_info {
__u8 volume_number;
__u16 directory_id;
__u16 sequence_no;
__u8 access_rights;
struct ncp_filesearch_info
{
__u8 volume_number;
__u16 directory_id;
__u16 sequence_no;
__u8 access_rights;
};
#define NCP_MAX_FILENAME 14
@@ -104,18 +111,25 @@ struct ncp_filesearch_info {
#define AR_EXCLUSIVE (0x20)
#define NCP_FILE_ID_LEN 6
struct ncp_file_info {
__u8 file_id[NCP_FILE_ID_LEN];
char file_name[NCP_MAX_FILENAME+1];
__u8 file_attributes;
__u8 file_mode;
__u32 file_length;
__u16 creation_date;
__u16 access_date;
__u16 update_date;
__u16 update_time;
struct ncp_file_info
{
__u8 file_id[NCP_FILE_ID_LEN];
char file_name[NCP_MAX_FILENAME + 1];
__u8 file_attributes;
__u8 file_mode;
__u32 file_length;
__u16 creation_date;
__u16 access_date;
__u16 update_date;
__u16 update_time;
};
/* Defines for Name Spaces */
#define NW_NS_DOS 0
#define NW_NS_MAC 1
#define NW_NS_NFS 2
#define NW_NS_FTAM 3
#define NW_NS_OS2 4
/* Defines for ReturnInformationMask */
#define RIM_NAME (0x0001L)
@@ -159,32 +173,32 @@ struct ncp_file_info {
struct nw_info_struct
{
__u32 spaceAlloc __attribute__ ((packed));
__u32 attributes __attribute__ ((packed));
__u16 flags __attribute__ ((packed));
__u32 dataStreamSize __attribute__ ((packed));
__u32 totalStreamSize __attribute__ ((packed));
__u16 numberOfStreams __attribute__ ((packed));
__u16 creationTime __attribute__ ((packed));
__u16 creationDate __attribute__ ((packed));
__u32 creatorID __attribute__ ((packed));
__u16 modifyTime __attribute__ ((packed));
__u16 modifyDate __attribute__ ((packed));
__u32 modifierID __attribute__ ((packed));
__u16 lastAccessDate __attribute__ ((packed));
__u16 archiveTime __attribute__ ((packed));
__u16 archiveDate __attribute__ ((packed));
__u32 archiverID __attribute__ ((packed));
__u16 inheritedRightsMask __attribute__ ((packed));
__u32 dirEntNum __attribute__ ((packed));
__u32 DosDirNum __attribute__ ((packed));
__u32 volNumber __attribute__ ((packed));
__u32 EADataSize __attribute__ ((packed));
__u32 EAKeyCount __attribute__ ((packed));
__u32 EAKeySize __attribute__ ((packed));
__u32 NSCreator __attribute__ ((packed));
__u8 nameLen __attribute__ ((packed));
__u8 entryName[256] __attribute__ ((packed));
__u32 spaceAlloc __attribute__((packed));
__u32 attributes __attribute__((packed));
__u16 flags __attribute__((packed));
__u32 dataStreamSize __attribute__((packed));
__u32 totalStreamSize __attribute__((packed));
__u16 numberOfStreams __attribute__((packed));
__u16 creationTime __attribute__((packed));
__u16 creationDate __attribute__((packed));
__u32 creatorID __attribute__((packed));
__u16 modifyTime __attribute__((packed));
__u16 modifyDate __attribute__((packed));
__u32 modifierID __attribute__((packed));
__u16 lastAccessDate __attribute__((packed));
__u16 archiveTime __attribute__((packed));
__u16 archiveDate __attribute__((packed));
__u32 archiverID __attribute__((packed));
__u16 inheritedRightsMask __attribute__((packed));
__u32 dirEntNum __attribute__((packed));
__u32 DosDirNum __attribute__((packed));
__u32 volNumber __attribute__((packed));
__u32 EADataSize __attribute__((packed));
__u32 EAKeyCount __attribute__((packed));
__u32 EAKeySize __attribute__((packed));
__u32 NSCreator __attribute__((packed));
__u8 nameLen __attribute__((packed));
__u8 entryName[256] __attribute__((packed));
};
/* modify mask - use with MODIFY_DOS_INFO structure */
@@ -204,62 +218,66 @@ struct nw_info_struct
struct nw_modify_dos_info
{
__u32 attributes __attribute__ ((packed));
__u16 creationDate __attribute__ ((packed));
__u16 creationTime __attribute__ ((packed));
__u32 creatorID __attribute__ ((packed));
__u16 modifyDate __attribute__ ((packed));
__u16 modifyTime __attribute__ ((packed));
__u32 modifierID __attribute__ ((packed));
__u16 archiveDate __attribute__ ((packed));
__u16 archiveTime __attribute__ ((packed));
__u32 archiverID __attribute__ ((packed));
__u16 lastAccessDate __attribute__ ((packed));
__u16 inheritanceGrantMask __attribute__ ((packed));
__u16 inheritanceRevokeMask __attribute__ ((packed));
__u32 maximumSpace __attribute__ ((packed));
__u32 attributes __attribute__((packed));
__u16 creationDate __attribute__((packed));
__u16 creationTime __attribute__((packed));
__u32 creatorID __attribute__((packed));
__u16 modifyDate __attribute__((packed));
__u16 modifyTime __attribute__((packed));
__u32 modifierID __attribute__((packed));
__u16 archiveDate __attribute__((packed));
__u16 archiveTime __attribute__((packed));
__u32 archiverID __attribute__((packed));
__u16 lastAccessDate __attribute__((packed));
__u16 inheritanceGrantMask __attribute__((packed));
__u16 inheritanceRevokeMask __attribute__((packed));
__u32 maximumSpace __attribute__((packed));
};
struct nw_file_info {
struct nw_file_info
{
struct nw_info_struct i;
int opened;
int access;
__u32 server_file_handle __attribute__ ((packed));
__u8 open_create_action __attribute__ ((packed));
__u8 file_handle[6] __attribute__ ((packed));
int opened;
int access;
__u32 server_file_handle __attribute__((packed));
__u8 open_create_action __attribute__((packed));
__u8 file_handle[6] __attribute__((packed));
};
struct nw_search_sequence {
__u8 volNumber __attribute__ ((packed));
__u32 dirBase __attribute__ ((packed));
__u32 sequence __attribute__ ((packed));
struct nw_search_sequence
{
__u8 volNumber __attribute__((packed));
__u32 dirBase __attribute__((packed));
__u32 sequence __attribute__((packed));
};
struct nw_queue_job_entry {
__u16 InUse __attribute__ ((packed));
__u32 prev __attribute__ ((packed));
__u32 next __attribute__ ((packed));
__u32 ClientStation __attribute__ ((packed));
__u32 ClientTask __attribute__ ((packed));
__u32 ClientObjectID __attribute__ ((packed));
__u32 TargetServerID __attribute__ ((packed));
__u8 TargetExecTime[6] __attribute__ ((packed));
__u8 JobEntryTime[6] __attribute__ ((packed));
__u32 JobNumber __attribute__ ((packed));
__u16 JobType __attribute__ ((packed));
__u16 JobPosition __attribute__ ((packed));
__u16 JobControlFlags __attribute__ ((packed));
__u8 FileNameLen __attribute__ ((packed));
char JobFileName[13] __attribute__ ((packed));
__u32 JobFileHandle __attribute__ ((packed));
__u32 ServerStation __attribute__ ((packed));
__u32 ServerTaskNumber __attribute__ ((packed));
__u32 ServerObjectID __attribute__ ((packed));
char JobTextDescription[50] __attribute__ ((packed));
char ClientRecordArea[152] __attribute__ ((packed));
struct nw_queue_job_entry
{
__u16 InUse __attribute__((packed));
__u32 prev __attribute__((packed));
__u32 next __attribute__((packed));
__u32 ClientStation __attribute__((packed));
__u32 ClientTask __attribute__((packed));
__u32 ClientObjectID __attribute__((packed));
__u32 TargetServerID __attribute__((packed));
__u8 TargetExecTime[6] __attribute__((packed));
__u8 JobEntryTime[6] __attribute__((packed));
__u32 JobNumber __attribute__((packed));
__u16 JobType __attribute__((packed));
__u16 JobPosition __attribute__((packed));
__u16 JobControlFlags __attribute__((packed));
__u8 FileNameLen __attribute__((packed));
char JobFileName[13] __attribute__((packed));
__u32 JobFileHandle __attribute__((packed));
__u32 ServerStation __attribute__((packed));
__u32 ServerTaskNumber __attribute__((packed));
__u32 ServerObjectID __attribute__((packed));
char JobTextDescription[50] __attribute__((packed));
char ClientRecordArea[152] __attribute__((packed));
};
struct queue_job {
struct queue_job
{
struct nw_queue_job_entry j;
__u8 file_handle[6];
};
@@ -279,20 +297,21 @@ struct queue_job {
#define EXPAND_TABS 0x4000
#define PRINT_BANNER 0x8000
struct print_job_record {
__u8 Version __attribute__ ((packed));
__u8 TabSize __attribute__ ((packed));
__u16 Copies __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 BannerName[13] __attribute__ ((packed));
char FnameBanner[13] __attribute__ ((packed));
char FnameHeader[14] __attribute__ ((packed));
char Path[80] __attribute__ ((packed));
struct print_job_record
{
__u8 Version __attribute__((packed));
__u8 TabSize __attribute__((packed));
__u16 Copies __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 BannerName[13] __attribute__((packed));
char FnameBanner[13] __attribute__((packed));
char FnameHeader[14] __attribute__((packed));
char Path[80] __attribute__((packed));
};
#endif /* _LINUX_NCP_H */
#endif /* _LINUX_NCP_H */

View File

@@ -20,32 +20,32 @@
* ioctl commands
*/
struct ncp_ioctl_request {
unsigned int function;
unsigned int size;
char *data;
struct ncp_ioctl_request
{
unsigned int function;
unsigned int size;
char *data;
};
struct ncp_fs_info {
int version;
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
uid_t mounted_uid;
int connection; /* Connection number the server assigned us */
int buffer_size; /* The negotiated buffer size, to be
used for read/write requests! */
/* Not used yet, but here some day the namespace numbers will be
stored. */
int volume_number;
__u32 directory_id;
};
int volume_number;
__u32 directory_id;
};
#define NCP_IOC_NCPREQUEST _IOR('n', 1, unsigned char *)
#define NCP_IOC_GETMOUNTUID _IOR('u', 1, uid_t)
#define NCP_IOC_CONN_LOGGED_IN _IO('l', 1)
#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('i', 1, unsigned char *)
#define NCP_IOC_GET_FS_INFO _IOWR('n', 4, struct ncp_fs_info)
/*
* The packet size to allocate. One page should be enough.
@@ -63,7 +63,7 @@ struct ncp_fs_info {
#define NCP_READDIR_CACHE_SIZE 64
#define NCP_MAX_RPC_TIMEOUT (60) /* 6 seconds */
#define NCP_MAX_RPC_TIMEOUT (6*HZ)
/* Guess, what 0x564c is :-) */
#define NCP_SUPER_MAGIC 0x564c
@@ -86,24 +86,24 @@ extern int ncp_current_malloced;
static inline void *
ncp_kmalloc(unsigned int size, int priority)
{
ncp_malloced += 1;
ncp_current_malloced += 1;
return kmalloc(size, priority);
ncp_malloced += 1;
ncp_current_malloced += 1;
return kmalloc(size, priority);
}
static inline void
ncp_kfree_s(void *obj, int size)
{
ncp_current_malloced -= 1;
kfree_s(obj, size);
ncp_current_malloced -= 1;
kfree_s(obj, size);
}
#else /* DEBUG_NCP_MALLOC */
#else /* DEBUG_NCP_MALLOC */
#define ncp_kmalloc(s,p) kmalloc(s,p)
#define ncp_kfree_s(o,s) kfree_s(o,s)
#endif /* DEBUG_NCP_MALLOC */
#endif /* DEBUG_NCP_MALLOC */
#if DEBUG_NCP > 0
#define DPRINTK(format, args...) printk(format , ## args)
@@ -127,25 +127,25 @@ 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);
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(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);
void ncp_date_unix2dos(int unix_date, __u16 *time, __u16 *date);
int ncp_date_dos2unix(__u16 time, __u16 date);
void ncp_date_unix2dos(int unix_date, __u16 * time, __u16 * date);
/* linux/fs/ncpfs/ioctl.c */
int ncp_ioctl (struct inode * inode, struct file * filp,
unsigned int cmd, unsigned long arg);
int ncp_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
/* linux/fs/ncpfs/inode.c */
struct super_block *ncp_read_super(struct super_block *sb,
void *raw_data, int silent);
void *raw_data, int silent);
void ncp_invalidate_connection(struct ncp_server *server);
int ncp_conn_is_valid(struct ncp_server *server);
@@ -159,8 +159,8 @@ void ncp_lock_server(struct ncp_server *server);
void ncp_unlock_server(struct ncp_server *server);
/* linux/fs/ncpfs/mmap.c */
int ncp_mmap(struct inode * inode, struct file * file, struct vm_area_struct * vma);
int ncp_mmap(struct inode *inode, struct file *file, struct vm_area_struct *vma);
#endif /* __KERNEL__ */
#endif /* __KERNEL__ */
#endif /* _LINUX_NCP_FS_H */
#endif /* _LINUX_NCP_FS_H */

View File

@@ -12,22 +12,24 @@
#ifdef __KERNEL__
enum ncp_inode_state {
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
enum ncp_inode_state
{
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
};
/*
* ncp fs inode data (in memory only)
*/
struct ncp_inode_info {
enum ncp_inode_state state;
int nused; /* for directories:
number of references in memory */
struct ncp_inode_info *dir;
struct ncp_inode_info *next, *prev;
struct ncp_inode_info
{
enum ncp_inode_state state;
int nused; /* for directories:
number of references in memory */
struct ncp_inode_info *dir;
struct ncp_inode_info *next, *prev;
struct inode *inode;
struct nw_file_info finfo;
};

View File

@@ -15,11 +15,14 @@
#define NCP_DEFAULT_BUFSIZE 1024
struct ncp_server {
struct ncp_server
{
struct ncp_mount_data m; /* Nearly all of the mount data is of
interest for us later, so we store
it completely. */
struct ncp_mount_data m; /* Nearly all of the mount data is of
interest for us later, so we store
it completely. */
__u8 name_space[NCP_NUMBER_OF_VOLUMES];
struct file *ncp_filp; /* File pointer to ncp socket */
struct file *wdog_filp; /* File pointer to wdog socket */
@@ -28,32 +31,32 @@ struct ncp_server {
old one for checking purposes and
to reset it on unmounting. */
u8 sequence;
u8 task;
u16 connection; /* Remote connection number */
u8 sequence;
u8 task;
u16 connection; /* Remote connection number */
u8 completion; /* Status message from server */
u8 conn_status; /* Bit 4 = 1 ==> Server going down, no
u8 completion; /* Status message from server */
u8 conn_status; /* Bit 4 = 1 ==> Server going down, no
requests allowed anymore.
Bit 0 = 1 ==> Server is down. */
int buffer_size; /* Negotiated bufsize */
int buffer_size; /* Negotiated bufsize */
int reply_size; /* Size of last reply */
int reply_size; /* Size of last reply */
int packet_size;
int packet_size;
unsigned char *packet; /* Here we prepare requests and
receive replies */
int lock; /* To prevent mismatch in protocols. */
int lock; /* To prevent mismatch in protocols. */
struct wait_queue *wait;
int current_size; /* for packet preparation */
int has_subfunction;
int ncp_reply_size;
int current_size; /* for packet preparation */
int has_subfunction;
int ncp_reply_size;
struct ncp_inode_info root;
char root_path; /* '\0' */
struct ncp_inode_info root;
char root_path; /* '\0' */
};
static inline int
@@ -68,6 +71,6 @@ ncp_invalidate_conn(struct ncp_server *server)
server->conn_status |= 0x01;
}
#endif /* __KERNEL__ */
#endif /* __KERNEL__ */
#endif

View File

@@ -22,28 +22,29 @@
#define NCP_MOUNT_SOFT 0x0001
#define NCP_MOUNT_INTR 0x0002
struct ncp_mount_data {
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; /* Message notifications come here */
uid_t mounted_uid; /* Who may umount() this filesystem? */
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[NCP_BINDERY_NAME_LEN];
unsigned char mount_point[PATH_MAX+1];
unsigned char mounted_vol[NCP_VOLNAME_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? */
unsigned int retry_count; /* And how often should I retry? */
unsigned int retry_count; /* And how often should I retry? */
unsigned int flags;
uid_t uid;
gid_t gid;
mode_t file_mode;
mode_t dir_mode;
uid_t uid;
gid_t gid;
mode_t file_mode;
mode_t dir_mode;
};
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -21,15 +21,17 @@
#include <linux/stat.h>
#include <linux/mm.h>
#include <linux/ncp_fs.h>
#include <linux/locks.h>
#include "ncplib_kernel.h"
#include <linux/malloc.h>
static inline int min(int a, int b)
static inline int
min(int a, int b)
{
return a<b ? a : b;
return a < b ? a : b;
}
static int
static int
ncp_fsync(struct inode *inode, struct file *file)
{
return 0;
@@ -38,21 +40,22 @@ ncp_fsync(struct inode *inode, struct file *file)
int
ncp_make_open(struct inode *i, int right)
{
struct nw_file_info *finfo;
struct nw_file_info *finfo;
if (i == NULL)
if (i == NULL)
{
printk("ncp_make_open: got NULL inode\n");
return -EINVAL;
}
printk("ncp_make_open: got NULL inode\n");
return -EINVAL;
}
finfo = NCP_FINFO(i);
finfo = NCP_FINFO(i);
DPRINTK("ncp_make_open: dirent->opened = %d\n", finfo->opened);
DPRINTK("ncp_make_open: dirent->opened = %d\n", finfo->opened);
if (finfo->opened == 0)
lock_super(i->i_sb);
if (finfo->opened == 0)
{
/* tries max. rights */
finfo->access = -1;
/* tries max. rights */
if (ncp_open_create_file_or_subdir(NCP_SERVER(i),
NULL, NULL,
OC_MODE_OPEN, 0,
@@ -60,40 +63,36 @@ ncp_make_open(struct inode *i, int right)
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)
} else if (ncp_open_create_file_or_subdir(NCP_SERVER(i),
NULL, NULL,
OC_MODE_OPEN, 0,
AR_READ,
finfo) == 0)
{
finfo->access = O_RDONLY;
}
else
{
return -EACCES;
}
}
}
unlock_super(i->i_sb);
if ( ((right == O_RDONLY) && ( (finfo->access == O_RDONLY)
|| (finfo->access == O_RDWR)))
|| ((right == O_WRONLY) && ( (finfo->access == O_WRONLY)
|| (finfo->access == O_RDWR)))
|| ((right == O_RDWR) && (finfo->access == O_RDWR)))
return 0;
if (((right == O_RDONLY) && ((finfo->access == O_RDONLY)
|| (finfo->access == O_RDWR)))
|| ((right == O_WRONLY) && ((finfo->access == O_WRONLY)
|| (finfo->access == O_RDWR)))
|| ((right == O_RDWR) && (finfo->access == O_RDWR)))
return 0;
return -EACCES;
return -EACCES;
}
static int
static int
ncp_file_read(struct inode *inode, struct file *file, char *buf, int count)
{
int bufsize, already_read;
off_t pos;
int errno;
int errno;
DPRINTK("ncp_file_read: enter %s\n", NCP_ISTRUCT(inode)->entryName);
DPRINTK("ncp_file_read: enter %s\n", NCP_ISTRUCT(inode)->entryName);
if (inode == NULL)
{
DPRINTK("ncp_file_read: inode = NULL\n");
@@ -103,37 +102,32 @@ ncp_file_read(struct inode *inode, struct file *file, char *buf, int count)
{
return -EIO;
}
if (!S_ISREG(inode->i_mode))
{
DPRINTK("ncp_file_read: read from non-file, mode %07o\n",
inode->i_mode);
inode->i_mode);
return -EINVAL;
}
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)
if ((errno = ncp_make_open(inode, O_RDONLY)) != 0)
{
return errno;
return errno;
}
bufsize = NCP_SERVER(inode)->buffer_size;
already_read = 0;
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;
int to_read = min(bufsize - (pos % bufsize),
@@ -142,41 +136,39 @@ ncp_file_read(struct inode *inode, struct file *file, char *buf, int count)
if (ncp_read(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle,
pos, to_read, buf, &read_this_time) != 0)
{
return -EIO; /* This is not exact, i know.. */
return -EIO; /* This is not exact, i know.. */
}
pos += read_this_time;
buf += read_this_time;
already_read += read_this_time;
already_read += read_this_time;
if (read_this_time < to_read)
{
break;
break;
}
}
file->f_pos = pos;
file->f_pos = pos;
if (!IS_RDONLY(inode))
{
inode->i_atime = CURRENT_TIME;
}
inode->i_dirt = 1;
DPRINTK("ncp_file_read: exit %s\n", NCP_ISTRUCT(inode)->entryName);
DPRINTK("ncp_file_read: exit %s\n", NCP_ISTRUCT(inode)->entryName);
return already_read;
return already_read;
}
static int
static int
ncp_file_write(struct inode *inode, struct file *file, char *buf,
int count)
{
int bufsize, already_written;
off_t pos;
int errno;
off_t pos;
int errno;
if (inode == NULL)
{
DPRINTK("ncp_file_write: inode = NULL\n");
@@ -186,38 +178,33 @@ ncp_file_write(struct inode *inode, struct file *file, char *buf,
{
return -EIO;
}
if (!S_ISREG(inode->i_mode))
{
DPRINTK("ncp_file_write: write to non-file, mode %07o\n",
inode->i_mode);
inode->i_mode);
return -EINVAL;
}
DPRINTK("ncp_file_write: enter %s\n", NCP_ISTRUCT(inode)->entryName);
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)
if ((errno = ncp_make_open(inode, O_RDWR)) != 0)
{
return errno;
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;
already_written = 0;
while (already_written < count)
while (already_written < count)
{
int written_this_time;
int to_write = min(bufsize - (pos % bufsize),
@@ -227,8 +214,7 @@ ncp_file_write(struct inode *inode, struct file *file, char *buf,
pos, to_write, buf, &written_this_time) != 0)
{
return -EIO;
}
}
pos += written_this_time;
buf += written_this_time;
already_written += written_this_time;
@@ -244,18 +230,18 @@ ncp_file_write(struct inode *inode, struct file *file, char *buf,
file->f_pos = pos;
if (pos > inode->i_size)
if (pos > inode->i_size)
{
inode->i_size = pos;
inode->i_size = pos;
ncp_invalid_dir_cache(NCP_INOP(inode)->dir->inode);
}
DPRINTK("ncp_file_write: exit %s\n", NCP_ISTRUCT(inode)->entryName);
}
DPRINTK("ncp_file_write: exit %s\n", NCP_ISTRUCT(inode)->entryName);
return already_written;
}
static struct file_operations ncp_file_operations = {
static struct file_operations ncp_file_operations =
{
NULL, /* lseek - default */
ncp_file_read, /* read */
ncp_file_write, /* write */
@@ -263,12 +249,13 @@ static struct file_operations ncp_file_operations = {
NULL, /* select - default */
ncp_ioctl, /* ioctl */
ncp_mmap, /* mmap */
NULL, /* open */
NULL, /* release */
NULL, /* open */
NULL, /* release */
ncp_fsync, /* fsync */
};
struct inode_operations ncp_file_inode_operations = {
struct inode_operations ncp_file_inode_operations =
{
&ncp_file_operations, /* default file operations */
NULL, /* create */
NULL, /* lookup */

View File

@@ -37,8 +37,9 @@ static void ncp_put_super(struct super_block *);
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 = {
ncp_read_inode, /* read inode */
static struct super_operations ncp_sops =
{
ncp_read_inode, /* read inode */
ncp_notify_change, /* notify change */
NULL, /* write inode */
ncp_put_inode, /* put inode */
@@ -55,13 +56,13 @@ static struct super_operations ncp_sops = {
static void
ncp_read_inode(struct inode *inode)
{
/* Our task should be extremely simple here. We only have to
look up the infomation somebody else (ncp_iget) put into
the inode tree. The address of this information is the
inode->i_ino. Just to make sure everything went well, we
check it's there. */
/* Our task should be extremely simple here. We only have to
look up the infomation somebody else (ncp_iget) put into
the inode tree. The address of this information is the
inode->i_ino. Just to make sure everything went well, we
check it's there. */
struct ncp_inode_info *inode_info = ncp_find_inode(inode);
struct ncp_inode_info *inode_info = ncp_find_inode(inode);
if (inode_info == NULL)
{
@@ -70,41 +71,38 @@ ncp_read_inode(struct inode *inode)
printk("ncp_read_inode: inode info not found\n");
return;
}
inode_info->state = NCP_INODE_VALID;
inode_info->state = NCP_INODE_VALID;
NCP_INOP(inode) = inode_info;
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;
inode->i_mode = NCP_SERVER(inode)->m.dir_mode;
/* for directories dataStreamSize seems to be some
Object ID ??? */
inode->i_size = 512;
}
else
} else
{
inode->i_mode = NCP_SERVER(inode)->m.file_mode;
inode->i_mode = NCP_SERVER(inode)->m.file_mode;
inode->i_size = NCP_ISTRUCT(inode)->dataStreamSize;
}
DDPRINTK("ncp_read_inode: inode->i_mode = %u\n", inode->i_mode);
DDPRINTK("ncp_read_inode: inode->i_mode = %u\n", inode->i_mode);
inode->i_nlink = 1;
inode->i_uid = NCP_SERVER(inode)->m.uid;
inode->i_gid = NCP_SERVER(inode)->m.gid;
inode->i_blksize = 1024;
inode->i_rdev = 0;
inode->i_nlink = 1;
inode->i_uid = NCP_SERVER(inode)->m.uid;
inode->i_gid = NCP_SERVER(inode)->m.gid;
inode->i_blksize = 512;
inode->i_rdev = 0;
if ((inode->i_blksize != 0) && (inode->i_size != 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 =
(inode->i_size - 1) / inode->i_blksize + 1;
} else
{
inode->i_blocks = 0;
inode->i_blocks = 0;
}
inode->i_mtime = ncp_date_dos2unix(NCP_ISTRUCT(inode)->modifyTime,
@@ -114,54 +112,53 @@ ncp_read_inode(struct inode *inode)
inode->i_atime = ncp_date_dos2unix(0,
NCP_ISTRUCT(inode)->lastAccessDate);
if (S_ISREG(inode->i_mode))
if (S_ISREG(inode->i_mode))
{
inode->i_op = &ncp_file_inode_operations;
}
else if (S_ISDIR(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 = &ncp_dir_inode_operations;
} else
{
inode->i_op = NULL;
inode->i_op = NULL;
}
}
static void
ncp_put_inode(struct inode *inode)
{
struct nw_file_info *finfo = NCP_FINFO(inode);
struct nw_file_info *finfo = NCP_FINFO(inode);
struct super_block *sb = inode->i_sb;
if (finfo->opened != 0)
lock_super(sb);
if (finfo->opened != 0)
{
if (ncp_close_file(NCP_SERVER(inode), finfo->file_handle)!=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");
}
}
/* 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);
finfo->i.entryName);
ncp_free_inode_info(NCP_INOP(inode));
ncp_free_inode_info(NCP_INOP(inode));
if (S_ISDIR(inode->i_mode))
if (S_ISDIR(inode->i_mode))
{
DDPRINTK("ncp_put_inode: put directory %ld\n",
DDPRINTK("ncp_put_inode: put directory %ld\n",
inode->i_ino);
ncp_invalid_dir_cache(inode);
}
ncp_invalid_dir_cache(inode);
}
clear_inode(inode);
unlock_super(sb);
}
struct super_block *
ncp_read_super(struct super_block *sb, void *raw_data, int silent)
{
struct ncp_mount_data *data = (struct ncp_mount_data *) raw_data;
struct ncp_server *server;
struct ncp_server *server;
struct file *ncp_filp;
struct file *wdog_filp;
dev_t dev = sb->s_dev;
@@ -173,17 +170,15 @@ ncp_read_super(struct super_block *sb, void *raw_data, int silent)
sb->s_dev = 0;
return NULL;
}
if (data->version != NCP_MOUNT_VERSION)
{
printk("ncp warning: mount version %s than kernel\n",
(data->version < NCP_MOUNT_VERSION) ?
"older" : "newer");
"older" : "newer");
sb->s_dev = 0;
return NULL;
}
if ( (data->ncp_fd >= NR_OPEN)
if ((data->ncp_fd >= NR_OPEN)
|| ((ncp_filp = current->files->fd[data->ncp_fd]) == NULL)
|| (!S_ISSOCK(ncp_filp->f_inode->i_mode)))
{
@@ -191,8 +186,7 @@ ncp_read_super(struct super_block *sb, void *raw_data, int silent)
sb->s_dev = 0;
return NULL;
}
if ( (data->wdog_fd >= NR_OPEN)
if ((data->wdog_fd >= NR_OPEN)
|| ((wdog_filp = current->files->fd[data->wdog_fd]) == NULL)
|| (!S_ISSOCK(wdog_filp->f_inode->i_mode)))
{
@@ -200,46 +194,44 @@ ncp_read_super(struct super_block *sb, void *raw_data, int silent)
sb->s_dev = 0;
return NULL;
}
/* We must malloc our own super-block info */
server = (struct ncp_server *) ncp_kmalloc(sizeof(struct ncp_server),
GFP_KERNEL);
/* We must malloc our own super-block info */
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;
}
printk("ncp_read_super: could not alloc ncp_server\n");
return NULL;
}
ncp_filp->f_count += 1;
wdog_filp->f_count += 1;
lock_super(sb);
NCP_SBP(sb) = server;
sb->s_blocksize = 1024; /* Eh... Is this correct? */
NCP_SBP(sb) = server;
sb->s_blocksize = 1024; /* Eh... Is this correct? */
sb->s_blocksize_bits = 10;
sb->s_magic = NCP_SUPER_MAGIC;
sb->s_dev = dev;
sb->s_op = &ncp_sops;
server->ncp_filp = ncp_filp;
server->wdog_filp = wdog_filp;
server->lock = 0;
server->wait = NULL;
server->packet = NULL;
server->ncp_filp = ncp_filp;
server->wdog_filp = wdog_filp;
server->lock = 0;
server->wait = NULL;
server->packet = NULL;
server->buffer_size = 0;
server->conn_status = 0;
server->m = *data;
server->m = *data;
server->m.file_mode = (server->m.file_mode &
(S_IRWXU|S_IRWXG|S_IRWXO)) | S_IFREG;
server->m.dir_mode = (server->m.dir_mode &
(S_IRWXU|S_IRWXG|S_IRWXO)) | S_IFDIR;
(S_IRWXU | S_IRWXG | S_IRWXO)) | S_IFREG;
server->m.dir_mode = (server->m.dir_mode &
(S_IRWXU | S_IRWXG | S_IRWXO)) | S_IFDIR;
server->packet_size = NCP_PACKET_SIZE;
server->packet = ncp_kmalloc(NCP_PACKET_SIZE, GFP_KERNEL);
server->packet = ncp_kmalloc(NCP_PACKET_SIZE, GFP_KERNEL);
if (server->packet == NULL)
{
@@ -248,12 +240,11 @@ ncp_read_super(struct super_block *sb, void *raw_data, int silent)
unlock_super(sb);
goto fail;
}
ncp_init_root(server);
ncp_init_root(server);
/*
* Make the connection to the server
*/
/*
* Make the connection to the server
*/
if (ncp_catch_watchdog(server) != 0)
{
@@ -262,7 +253,6 @@ ncp_read_super(struct super_block *sb, void *raw_data, int silent)
unlock_super(sb);
goto fail;
}
ncp_lock_server(server);
error = ncp_connect(server);
ncp_unlock_server(server);
@@ -272,21 +262,19 @@ ncp_read_super(struct super_block *sb, void *raw_data, int silent)
{
sb->s_dev = 0;
printk("ncp_read_super: Failed connection, bailing out "
"(error = %d).\n", -error);
ncp_kfree_s(server->packet, server->packet_size);
"(error = %d).\n", -error);
ncp_kfree_s(server->packet, server->packet_size);
ncp_dont_catch_watchdog(server);
goto fail;
goto fail;
}
DPRINTK("ncp_read_super: NCP_SBP(sb) = %x\n", (int)NCP_SBP(sb));
DPRINTK("ncp_read_super: NCP_SBP(sb) = %x\n", (int) NCP_SBP(sb));
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;
goto disconnect;
}
if (ncp_negotiate_buffersize(server, NCP_DEFAULT_BUFSIZE,
&(server->buffer_size)) != 0)
{
@@ -294,34 +282,33 @@ ncp_read_super(struct super_block *sb, void *raw_data, int silent)
printk("ncp_read_super: could not get bufsize\n");
goto disconnect;
}
DPRINTK("ncpfs: bufsize = %d\n", server->buffer_size);
MOD_INC_USE_COUNT;
MOD_INC_USE_COUNT;
return sb;
disconnect:
disconnect:
ncp_lock_server(server);
ncp_disconnect(server);
ncp_unlock_server(server);
ncp_kfree_s(server->packet, server->packet_size);
ncp_dont_catch_watchdog(server);
fail:
fail:
ncp_filp->f_count -= 1;
wdog_filp->f_count -= 1;
ncp_kfree_s(NCP_SBP(sb), sizeof(struct ncp_server));
return NULL;
ncp_kfree_s(NCP_SBP(sb), sizeof(struct ncp_server));
return NULL;
}
static void
ncp_put_super(struct super_block *sb)
{
struct ncp_server *server = NCP_SBP(sb);
struct ncp_server *server = NCP_SBP(sb);
lock_super(sb);
ncp_lock_server(server);
ncp_disconnect(server);
ncp_disconnect(server);
ncp_unlock_server(server);
close_fp(server->ncp_filp);
@@ -329,29 +316,29 @@ ncp_put_super(struct super_block *sb)
ncp_dont_catch_watchdog(server);
close_fp(server->wdog_filp);
ncp_free_all_inodes(server);
ncp_free_all_inodes(server);
ncp_kfree_s(server->packet, server->packet_size);
ncp_kfree_s(server->packet, server->packet_size);
sb->s_dev = 0;
ncp_kfree_s(NCP_SBP(sb), sizeof(struct ncp_server));
ncp_kfree_s(NCP_SBP(sb), sizeof(struct ncp_server));
NCP_SBP(sb) = NULL;
unlock_super(sb);
MOD_DEC_USE_COUNT;
MOD_DEC_USE_COUNT;
}
static void
static void
ncp_statfs(struct super_block *sb, struct statfs *stat)
{
struct statfs tmp;
/* We cannot say how much disk space is left on a mounted
NetWare Server, because free space is distributed over
volumes, and the current user might have disk quotas. So
free space is not that simple to determine. Our decision
here is to err conservatively. */
NetWare Server, because free space is distributed over
volumes, and the current user might have disk quotas. So
free space is not that simple to determine. Our decision
here is to err conservatively. */
tmp.f_type = NCP_SUPER_MAGIC;
tmp.f_bsize = 512;
@@ -375,17 +362,16 @@ ncp_notify_change(struct inode *inode, struct iattr *attr)
{
return -EIO;
}
if ((result = inode_change_ok(inode, attr)) < 0)
return result;
if (((attr->ia_valid & ATTR_UID) &&
if (((attr->ia_valid & ATTR_UID) &&
(attr->ia_uid != NCP_SERVER(inode)->m.uid)))
return -EPERM;
if (((attr->ia_valid & ATTR_GID) &&
if (((attr->ia_valid & ATTR_GID) &&
(attr->ia_uid != NCP_SERVER(inode)->m.gid)))
return -EPERM;
return -EPERM;
if (((attr->ia_valid & ATTR_MODE) &&
(attr->ia_mode &
@@ -397,18 +383,16 @@ ncp_notify_change(struct inode *inode, struct iattr *attr)
if ((attr->ia_valid & ATTR_CTIME) != 0)
{
info_mask |= (DM_CREATE_TIME|DM_CREATE_DATE);
info_mask |= (DM_CREATE_TIME | DM_CREATE_DATE);
ncp_date_unix2dos(attr->ia_ctime,
&(info.creationTime), &(info.creationDate));
}
if ((attr->ia_valid & ATTR_MTIME) != 0)
{
info_mask |= (DM_MODIFY_TIME|DM_MODIFY_DATE);
info_mask |= (DM_MODIFY_TIME | DM_MODIFY_DATE);
ncp_date_unix2dos(attr->ia_mtime,
&(info.modifyTime), &(info.modifyDate));
}
if ((attr->ia_valid & ATTR_ATIME) != 0)
{
__u16 dummy;
@@ -416,7 +400,6 @@ ncp_notify_change(struct inode *inode, struct iattr *attr)
ncp_date_unix2dos(attr->ia_ctime,
&(dummy), &(info.lastAccessDate));
}
if (info_mask != 0)
{
if ((result =
@@ -427,19 +410,18 @@ ncp_notify_change(struct inode *inode, struct iattr *attr)
{
result = -EACCES;
if (info_mask == (DM_CREATE_TIME|DM_CREATE_DATE))
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. */
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;
@@ -450,7 +432,6 @@ ncp_notify_change(struct inode *inode, struct iattr *attr)
{
return -EACCES;
}
ncp_write(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle,
attr->ia_size, 0, "", &written);
@@ -462,12 +443,11 @@ ncp_notify_change(struct inode *inode, struct iattr *attr)
result = 0;
}
ncp_invalid_dir_cache(NCP_INOP(inode)->dir->inode);
ncp_invalid_dir_cache(NCP_INOP(inode)->dir->inode);
return result;
}
#ifdef DEBUG_NCP_MALLOC
int ncp_malloced;
int ncp_current_malloced;
@@ -477,35 +457,36 @@ int ncp_current_malloced;
char kernel_version[] = UTS_RELEASE;
static struct file_system_type ncp_fs_type = {
ncp_read_super, "ncpfs", 0, NULL
};
static struct file_system_type ncp_fs_type =
{
ncp_read_super, "ncpfs", 0, NULL
};
int
init_module( void)
init_module(void)
{
DPRINTK("ncpfs: init_module called\n");
DPRINTK("ncpfs: init_module called\n");
#ifdef DEBUG_NCP_MALLOC
ncp_malloced = 0;
ncp_current_malloced = 0;
ncp_malloced = 0;
ncp_current_malloced = 0;
#endif
ncp_init_dir_cache();
register_filesystem(&ncp_fs_type);
ncp_init_dir_cache();
register_filesystem(&ncp_fs_type);
printk("ncpfs version %s loaded\n", NCPFS_VERSION);
return 0;
return 0;
}
void
cleanup_module(void)
{
DPRINTK("ncpfs: cleanup_module called\n");
ncp_free_dir_cache();
unregister_filesystem(&ncp_fs_type);
DPRINTK("ncpfs: cleanup_module called\n");
ncp_free_dir_cache();
unregister_filesystem(&ncp_fs_type);
#ifdef DEBUG_NCP_MALLOC
printk("ncp_malloced: %d\n", ncp_malloced);
printk("ncp_current_malloced: %d\n", ncp_current_malloced);
printk("ncp_malloced: %d\n", ncp_malloced);
printk("ncp_current_malloced: %d\n", ncp_current_malloced);
#endif
}

View File

@@ -21,49 +21,67 @@
#include <linux/ncp.h>
int
ncp_ioctl (struct inode * inode, struct file * filp,
unsigned int cmd, unsigned long arg)
ncp_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
int result;
struct ncp_ioctl_request request;
struct ncp_fs_info info;
struct ncp_server *server = NCP_SERVER(inode);
switch(cmd) {
/*
* 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)
if ((permission(inode, MAY_WRITE) != 0)
&& (current->uid != server->m.mounted_uid))
{
return -EACCES;
}
if ((result = verify_area(VERIFY_READ, (char *)arg,
if ((result = verify_area(VERIFY_READ, (char *) arg,
sizeof(request))) != 0)
{
return result;
}
memcpy_fromfs(&request, (struct ncp_ioctl_request *)arg,
memcpy_fromfs(&request, (struct ncp_ioctl_request *) arg,
sizeof(request));
if ( (request.function > 255)
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,
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 */
here to be able to use ncp_request */
server->has_subfunction = 0;
server->current_size = request.size;
@@ -81,29 +99,26 @@ ncp_ioctl (struct inode * inode, struct file * filp,
case NCP_IOC_CONN_LOGGED_IN:
if ( (permission(inode, MAY_WRITE) != 0)
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)
if ((permission(inode, MAY_WRITE) != 0)
&& (current->uid != server->m.mounted_uid))
{
return -EACCES;
}
if ((result = verify_area(VERIFY_WRITE, (char *)arg,
if ((result = verify_area(VERIFY_WRITE, (char *) arg,
sizeof(info))) != 0)
{
return result;
}
memcpy_fromfs(&info, (struct ncp_fs_info *)arg,
memcpy_fromfs(&info, (struct ncp_fs_info *) arg,
sizeof(info));
if (info.version != NCP_GET_FS_INFO_VERSION)
@@ -111,34 +126,34 @@ ncp_ioctl (struct inode * inode, struct file * filp,
DPRINTK("info.version invalid: %d\n", info.version);
return -EINVAL;
}
info.addr = server->m.serv_addr;
info.addr = server->m.serv_addr;
info.mounted_uid = server->m.mounted_uid;
info.connection = server->connection;
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;
memcpy_tofs((struct ncp_fs_info *) arg, &info, sizeof(info));
return 0;
case NCP_IOC_GETMOUNTUID:
case NCP_IOC_GETMOUNTUID:
if ( (permission(inode, MAY_READ) != 0)
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)
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;
return result;
}
put_fs_word(server->m.mounted_uid, (uid_t *) arg);
return 0;
default:
return -EINVAL;
}
return -EINVAL;
}

View File

@@ -27,19 +27,20 @@
#include <asm/segment.h>
#include <asm/system.h>
static inline int min(int a, int b)
static inline int
min(int a, int b)
{
return a<b ? a : 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,
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;
struct inode *inode = area->vm_inode;
unsigned int clear;
unsigned long tmp;
int bufsize;
@@ -54,19 +55,17 @@ ncp_file_mmap_nopage(struct vm_area_struct * area,
{
clear = address + PAGE_SIZE - area->vm_end;
}
/* what we can read in one go */
/* 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)
if (ncp_make_open(inode, O_RDONLY) < 0)
{
clear = PAGE_SIZE;
} else
{
clear = PAGE_SIZE;
}
else
{
int already_read = 0;
int count = PAGE_SIZE - clear;
int to_read;
@@ -78,8 +77,7 @@ ncp_file_mmap_nopage(struct vm_area_struct * area,
if ((pos % bufsize) != 0)
{
to_read = bufsize - (pos % bufsize);
}
else
} else
{
to_read = bufsize;
}
@@ -89,12 +87,11 @@ ncp_file_mmap_nopage(struct vm_area_struct * area,
if (ncp_read(NCP_SERVER(inode),
NCP_FINFO(inode)->file_handle,
pos, to_read,
(char *)(page + already_read),
(char *) (page + already_read),
&read_this_time) != 0)
{
read_this_time = 0;
read_this_time = 0;
}
pos += read_this_time;
already_read += read_this_time;
@@ -104,18 +101,20 @@ ncp_file_mmap_nopage(struct vm_area_struct * area,
}
}
}
}
set_fs(fs);
tmp = page + PAGE_SIZE;
while (clear--) {
*(char *)--tmp = 0;
while (clear--)
{
*(char *) --tmp = 0;
}
return page;
}
struct vm_operations_struct ncp_file_mmap = {
struct vm_operations_struct ncp_file_mmap =
{
NULL, /* open */
NULL, /* close */
NULL, /* unmap */
@@ -131,25 +130,24 @@ struct vm_operations_struct ncp_file_mmap = {
/* 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)
ncp_mmap(struct inode *inode, struct file *file, struct vm_area_struct *vma)
{
DPRINTK("ncp_mmap: called\n");
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)
/* 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)) {
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;

View File

@@ -1,3 +1,4 @@
#include <linux/config.h>
#ifdef MODULE
#include <linux/module.h>
@@ -6,13 +7,14 @@
#include "ncplib_kernel.h"
typedef __u8 byte;
typedef __u8 byte;
typedef __u16 word;
typedef __u32 dword;
static inline int min(int a, int b)
static inline int
min(int a, int b)
{
return a<b ? a : b;
return a < b ? a : b;
}
static void
@@ -28,7 +30,7 @@ static void
ncp_add_byte(struct ncp_server *server, byte x)
{
assert_server_locked(server);
*(byte *)(&(server->packet[server->current_size])) = x;
*(byte *) (&(server->packet[server->current_size])) = x;
server->current_size += 1;
return;
}
@@ -37,7 +39,7 @@ static void
ncp_add_word(struct ncp_server *server, word x)
{
assert_server_locked(server);
*(word *)(&(server->packet[server->current_size])) = x;
*(word *) (&(server->packet[server->current_size])) = x;
server->current_size += 2;
return;
}
@@ -46,7 +48,7 @@ static void
ncp_add_dword(struct ncp_server *server, dword x)
{
assert_server_locked(server);
*(dword *)(&(server->packet[server->current_size])) = x;
*(dword *) (&(server->packet[server->current_size])) = x;
server->current_size += 4;
return;
}
@@ -97,7 +99,7 @@ static void
ncp_init_request_s(struct ncp_server *server, int subfunction)
{
ncp_init_request(server);
ncp_add_word(server, 0); /* preliminary size */
ncp_add_word(server, 0); /* preliminary size */
ncp_add_byte(server, subfunction);
@@ -113,19 +115,19 @@ ncp_reply_data(struct ncp_server *server, int offset)
static byte
ncp_reply_byte(struct ncp_server *server, int offset)
{
return *(byte *)(ncp_reply_data(server, offset));
return *(byte *) (ncp_reply_data(server, offset));
}
static word
ncp_reply_word(struct ncp_server *server, int offset)
{
return *(word *)(ncp_reply_data(server, offset));
return *(word *) (ncp_reply_data(server, offset));
}
static dword
ncp_reply_dword(struct ncp_server *server, int offset)
{
return *(dword *)(ncp_reply_data(server, offset));
return *(dword *) (ncp_reply_data(server, offset));
}
int
@@ -136,14 +138,13 @@ ncp_negotiate_buffersize(struct ncp_server *server,
ncp_init_request(server);
ncp_add_word(server, htons(size));
if ((result = ncp_request(server, 33)) != 0)
{
ncp_unlock_server(server);
return result;
}
*target =min(ntohs(ncp_reply_word(server, 0)), size);
*target = min(ntohs(ncp_reply_word(server, 0)), size);
ncp_unlock_server(server);
return 0;
@@ -164,9 +165,8 @@ ncp_get_volume_info_with_number(struct ncp_server *server, int n,
ncp_unlock_server(server);
return result;
}
target->total_blocks = ncp_reply_dword(server, 0);
target->free_blocks = ncp_reply_dword(server, 4);
target->free_blocks = ncp_reply_dword(server, 4);
target->purgeable_blocks = ncp_reply_dword(server, 8);
target->not_yet_purgeable_blocks = ncp_reply_dword(server, 12);
target->total_dir_entries = ncp_reply_dword(server, 16);
@@ -182,31 +182,11 @@ ncp_get_volume_info_with_number(struct ncp_server *server, int n,
ncp_unlock_server(server);
return -EIO;
}
memcpy(&(target->volume_name), ncp_reply_data(server, 30), len);
ncp_unlock_server(server);
return 0;
}
int
ncp_get_volume_number(struct ncp_server *server, const char *name, int *target)
{
int result;
ncp_init_request_s(server, 5);
ncp_add_pstring(server, name);
if ((result = ncp_request(server, 22)) != 0)
{
ncp_unlock_server(server);
return result;
}
*target = ncp_reply_byte(server, 0);
ncp_unlock_server(server);
return 0;
}
int
ncp_close_file(struct ncp_server *server, const char *file_id)
{
@@ -221,7 +201,6 @@ ncp_close_file(struct ncp_server *server, const char *file_id)
ncp_unlock_server(server);
return result;
}
ncp_unlock_server(server);
return 0;
}
@@ -236,18 +215,16 @@ ncp_add_handle_path(struct ncp_server *server,
ncp_add_dword(server, dir_base);
if (have_dir_base != 0)
{
ncp_add_byte(server, 1); /* dir_base */
}
else
ncp_add_byte(server, 1); /* dir_base */
} else
{
ncp_add_byte(server, 0xff); /* no handle */
ncp_add_byte(server, 0xff); /* no handle */
}
if (path != NULL)
{
ncp_add_byte(server, 1); /* 1 component */
ncp_add_byte(server, 1); /* 1 component */
ncp_add_pstring(server, path);
}
else
} else
{
ncp_add_byte(server, 0);
}
@@ -262,7 +239,7 @@ ncp_extract_file_info(void *structure, struct nw_info_struct *target)
memcpy(target, structure, info_struct_size);
name_len = structure + info_struct_size;
target->nameLen = *name_len;
strncpy(target->entryName, name_len+1, *name_len);
strncpy(target->entryName, name_len + 1, *name_len);
target->entryName[*name_len] = '\0';
return;
}
@@ -270,7 +247,7 @@ ncp_extract_file_info(void *structure, struct nw_info_struct *target)
int
ncp_obtain_info(struct ncp_server *server,
__u8 vol_num, __u32 dir_base,
char *path, /* At most 1 component */
char *path, /* At most 1 component */
struct nw_info_struct *target)
{
int result;
@@ -279,12 +256,11 @@ ncp_obtain_info(struct ncp_server *server,
{
return -EINVAL;
}
ncp_init_request(server);
ncp_add_byte(server, 6); /* subfunction */
ncp_add_byte(server, 0); /* dos name space */
ncp_add_byte(server, 0); /* dos name space as dest */
ncp_add_word(server, 0xff); /* get all */
ncp_add_byte(server, 6); /* subfunction */
ncp_add_byte(server, server->name_space[vol_num]);
ncp_add_byte(server, server->name_space[vol_num]);
ncp_add_word(server, 0xff); /* get all */
ncp_add_dword(server, RIM_ALL);
ncp_add_handle_path(server, vol_num, dir_base, 1, path);
@@ -293,34 +269,69 @@ ncp_obtain_info(struct ncp_server *server,
ncp_unlock_server(server);
return result;
}
ncp_extract_file_info(ncp_reply_data(server, 0), target);
ncp_unlock_server(server);
return 0;
}
static inline int
ncp_has_os2_namespace(struct ncp_server *server, __u8 volume)
{
int result;
__u8 *namespace;
__u16 no_namespaces;
ncp_init_request(server);
ncp_add_byte(server, 24); /* Subfunction: Get Name Spaces Loaded */
ncp_add_word(server, 0);
ncp_add_byte(server, volume);
if ((result = ncp_request(server, 87)) != 0)
{
ncp_unlock_server(server);
return 0;
}
no_namespaces = ncp_reply_word(server, 0);
namespace = ncp_reply_data(server, 2);
while (no_namespaces > 0)
{
DPRINTK("get_namespaces: found %d on %d\n", *namespace, volume);
if (*namespace == 4)
{
DPRINTK("get_namespaces: found OS2\n");
ncp_unlock_server(server);
return 1;
}
namespace += 1;
no_namespaces -= 1;
}
ncp_unlock_server(server);
return 0;
}
int
ncp_lookup_volume(struct ncp_server *server,
char *volname,
struct nw_info_struct *target)
{
int result;
__u8 vol_num;
__u32 dir_base;
int volnum;
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, 22); /* Subfunction: Generate dir handle */
ncp_add_byte(server, 0); /* DOS namespace */
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_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)
@@ -328,21 +339,19 @@ ncp_lookup_volume(struct ncp_server *server,
ncp_unlock_server(server);
return result;
}
dir_base = ncp_reply_dword(server, 4);
vol_num = ncp_reply_byte(server, 8);
memset(target, 0, sizeof(*target));
target->DosDirNum = target->dirEntNum = ncp_reply_dword(server, 4);
target->volNumber = volnum = ncp_reply_byte(server, 8);
ncp_unlock_server(server);
if ((result = ncp_obtain_info(server, vol_num, dir_base, NULL,
target)) != 0)
{
return result;
}
server->name_space[volnum] = ncp_has_os2_namespace(server, volnum) ? 4 : 0;
DPRINTK("ncp_lookup_volume: attribs = %X\n", target->attributes);
DPRINTK("lookup_vol: namespace[%d] = %d\n",
volnum, server->name_space[volnum]);
target->nameLen = strlen(volname);
strcpy(target->entryName, volname);
target->attributes = aDIR;
return 0;
}
@@ -355,22 +364,21 @@ ncp_modify_file_or_subdir_dos_info(struct ncp_server *server,
int result;
ncp_init_request(server);
ncp_add_byte(server, 7); /* subfunction */
ncp_add_byte(server, 0); /* dos name space */
ncp_add_byte(server, 0); /* reserved */
ncp_add_word(server, 0x8006); /* search attribs: all */
ncp_add_byte(server, 7); /* subfunction */
ncp_add_byte(server, server->name_space[file->volNumber]);
ncp_add_byte(server, 0); /* reserved */
ncp_add_word(server, 0x8006); /* search attribs: all */
ncp_add_dword(server, info_mask);
ncp_add_mem(server, info, sizeof(*info));
ncp_add_handle_path(server, file->volNumber,
file->DosDirNum, 1, NULL);
file->dirEntNum, 1, NULL);
if ((result = ncp_request(server, 87)) != 0)
{
ncp_unlock_server(server);
return result;
}
ncp_unlock_server(server);
return 0;
}
@@ -382,30 +390,29 @@ ncp_del_file_or_subdir(struct ncp_server *server,
int result;
ncp_init_request(server);
ncp_add_byte(server, 8); /* subfunction */
ncp_add_byte(server, 0); /* dos name space */
ncp_add_byte(server, 0); /* reserved */
ncp_add_word(server, 0x8006); /* search attribs: all */
ncp_add_byte(server, 8); /* subfunction */
ncp_add_byte(server, server->name_space[dir->volNumber]);
ncp_add_byte(server, 0); /* reserved */
ncp_add_word(server, 0x8006); /* search attribs: all */
ncp_add_handle_path(server, dir->volNumber,
dir->DosDirNum, 1, name);
dir->dirEntNum, 1, name);
if ((result = ncp_request(server, 87)) != 0)
{
ncp_unlock_server(server);
return result;
}
ncp_unlock_server(server);
return 0;
}
static inline void
ConvertToNWfromDWORD ( __u32 sfd , __u8 ret[6] )
ConvertToNWfromDWORD(__u32 sfd, __u8 ret[6])
{
__u16 *dest = (__u16 *) ret;
memcpy(&(dest[1]), &sfd, 4);
dest[0] = dest[1] + 1;
return;
__u16 *dest = (__u16 *) ret;
memcpy(&(dest[1]), &sfd, 4);
dest[0] = dest[1] + 1;
return;
}
/* If both dir and name are NULL, then in target there's already a
@@ -420,15 +427,15 @@ ncp_open_create_file_or_subdir(struct ncp_server *server,
{
int result;
__u16 search_attribs = 0x0006;
__u8 volume = (dir != NULL) ? dir->volNumber : target->i.volNumber;
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, 1); /* subfunction */
ncp_add_byte(server, server->name_space[volume]);
ncp_add_byte(server, open_create_mode);
ncp_add_word(server, search_attribs);
ncp_add_dword(server, RIM_ALL);
@@ -439,22 +446,18 @@ ncp_open_create_file_or_subdir(struct ncp_server *server,
if (dir != NULL)
{
ncp_add_handle_path(server, dir->volNumber,
dir->DosDirNum, 1, name);
}
else
ncp_add_handle_path(server, volume, dir->dirEntNum, 1, name);
} else
{
ncp_add_handle_path(server,
target->i.volNumber, target->i.DosDirNum,
ncp_add_handle_path(server, volume, target->i.dirEntNum,
1, NULL);
}
}
if ((result = ncp_request(server, 87)) != 0)
{
ncp_unlock_server(server);
return result;
}
target->opened = 1;
target->server_file_handle = ncp_reply_dword(server, 0);
target->open_create_action = ncp_reply_byte(server, 4);
@@ -464,13 +467,12 @@ ncp_open_create_file_or_subdir(struct ncp_server *server,
/* in target there's a new finfo to fill */
ncp_extract_file_info(ncp_reply_data(server, 5), &(target->i));
}
ConvertToNWfromDWORD(target->server_file_handle, target->file_handle);
ncp_unlock_server(server);
return 0;
}
int
ncp_initialize_search(struct ncp_server *server,
@@ -480,23 +482,22 @@ ncp_initialize_search(struct ncp_server *server,
int result;
ncp_init_request(server);
ncp_add_byte(server, 2); /* subfunction */
ncp_add_byte(server, 0); /* dos name space */
ncp_add_byte(server, 0); /* reserved */
ncp_add_handle_path(server, dir->volNumber, dir->DosDirNum, 1, NULL);
ncp_add_byte(server, 2); /* subfunction */
ncp_add_byte(server, server->name_space[dir->volNumber]);
ncp_add_byte(server, 0); /* reserved */
ncp_add_handle_path(server, dir->volNumber, dir->dirEntNum, 1, NULL);
if ((result = ncp_request(server, 87)) != 0)
{
ncp_unlock_server(server);
return result;
}
memcpy(target, ncp_reply_data(server, 0), sizeof(*target));
ncp_unlock_server(server);
return 0;
}
/* Search for everything */
int
ncp_search_for_file_or_subdir(struct ncp_server *server,
@@ -506,22 +507,21 @@ ncp_search_for_file_or_subdir(struct ncp_server *server,
int result;
ncp_init_request(server);
ncp_add_byte(server, 3); /* subfunction */
ncp_add_byte(server, 0); /* dos name space */
ncp_add_byte(server, 0); /* data stream (???) */
ncp_add_word(server, 0xffff); /* Search attribs */
ncp_add_dword(server, RIM_ALL); /* return info mask */
ncp_add_byte(server, 3); /* subfunction */
ncp_add_byte(server, server->name_space[seq->volNumber]);
ncp_add_byte(server, 0); /* data stream (???) */
ncp_add_word(server, 0xffff); /* Search attribs */
ncp_add_dword(server, RIM_ALL); /* return info mask */
ncp_add_mem(server, seq, 9);
ncp_add_byte(server, 2); /* 2 byte pattern */
ncp_add_byte(server, 0xff); /* following is a wildcard */
ncp_add_byte(server, 2); /* 2 byte pattern */
ncp_add_byte(server, 0xff); /* following is a wildcard */
ncp_add_byte(server, '*');
if ((result = ncp_request(server, 87)) != 0)
{
ncp_unlock_server(server);
return result;
}
memcpy(seq, ncp_reply_data(server, 0), sizeof(*seq));
ncp_extract_file_info(ncp_reply_data(server, 10), target);
@@ -536,27 +536,27 @@ ncp_ren_or_mov_file_or_subdir(struct ncp_server *server,
{
int result;
if ( (old_dir == NULL) || (old_name == NULL)
if ((old_dir == NULL) || (old_name == NULL)
|| (new_dir == NULL) || (new_name == NULL))
return -EINVAL;
ncp_init_request(server);
ncp_add_byte(server, 4); /* subfunction */
ncp_add_byte(server, 0); /* dos name space */
ncp_add_byte(server, 1); /* rename flag */
ncp_add_word(server, 0x8006); /* search attributes */
ncp_add_byte(server, 4); /* subfunction */
ncp_add_byte(server, server->name_space[old_dir->volNumber]);
ncp_add_byte(server, 1); /* rename flag */
ncp_add_word(server, 0x8006); /* search attributes */
/* source Handle Path */
ncp_add_byte(server, old_dir->volNumber);
ncp_add_dword(server, old_dir->DosDirNum);
ncp_add_dword(server, old_dir->dirEntNum);
ncp_add_byte(server, 1);
ncp_add_byte(server, 1); /* 1 source component */
ncp_add_byte(server, 1); /* 1 source component */
/* dest Handle Path */
ncp_add_byte(server, new_dir->volNumber);
ncp_add_dword(server, new_dir->DosDirNum);
ncp_add_dword(server, new_dir->dirEntNum);
ncp_add_byte(server, 1);
ncp_add_byte(server, 1); /* 1 destination component */
ncp_add_byte(server, 1); /* 1 destination component */
/* source path string */
ncp_add_pstring(server, old_name);
@@ -567,7 +567,7 @@ ncp_ren_or_mov_file_or_subdir(struct ncp_server *server,
ncp_unlock_server(server);
return result;
}
/* We have to transfer to/from user space */
int
@@ -588,10 +588,9 @@ ncp_read(struct ncp_server *server, const char *file_id,
ncp_unlock_server(server);
return result;
}
*bytes_read = ntohs(ncp_reply_word(server, 0));
memcpy_tofs(target, ncp_reply_data(server, 2+(offset&1)), *bytes_read);
memcpy_tofs(target, ncp_reply_data(server, 2 + (offset & 1)), *bytes_read);
ncp_unlock_server(server);
return 0;
@@ -616,10 +615,8 @@ ncp_write(struct ncp_server *server, const char *file_id,
ncp_unlock_server(server);
return result;
}
*bytes_written = to_write;
ncp_unlock_server(server);
return 0;
}

View File

@@ -1,3 +1,4 @@
#ifndef _NCPLIB_H
#define _NCPLIB_H
@@ -16,147 +17,147 @@
#include <linux/ncp.h>
int
ncp_negotiate_buffersize(struct ncp_server *server, int size,
int *target);
ncp_negotiate_buffersize(struct ncp_server *server, int size,
int *target);
int
ncp_get_encryption_key(struct ncp_server *server,
char *target);
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);
ncp_get_bindery_object_id(struct ncp_server *server,
int object_type, char *object_name,
struct ncp_bindery_object *target);
int
ncp_login_encrypted(struct ncp_server *server,
struct ncp_bindery_object *object,
unsigned char *key,
unsigned char *passwd);
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);
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);
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);
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);
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);
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);
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,
ncp_open_file(struct ncp_server *server,
int dir_handle, const char *path,
int attr);
int attr, int access,
struct ncp_file_info *target);
int
ncp_close_file(struct ncp_server *server, const char *file_id);
int
ncp_rename_file(struct ncp_server *server,
int old_handle, const char *old_path,
int attr,
int new_handle, const char *new_path);
ncp_create_newfile(struct ncp_server *server,
int dir_handle, const char *path,
int attr,
struct ncp_file_info *target);
int
ncp_create_directory(struct ncp_server *server,
int dir_handle, const char *path,
int inherit_mask);
ncp_create_file(struct ncp_server *server,
int dir_handle, const char *path,
int attr,
struct ncp_file_info *target);
int
ncp_delete_directory(struct ncp_server *server,
int dir_handle, const char *path);
ncp_erase_file(struct ncp_server *server,
int dir_handle, const char *path,
int attr);
int
ncp_rename_directory(struct ncp_server *server,
int dir_handle,
const char *old_path, const char *new_path);
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_read(struct ncp_server *server, const char *file_id,
__u32 offset, __u16 to_read,
char *target, int *bytes_read);
ncp_create_directory(struct ncp_server *server,
int dir_handle, const char *path,
int inherit_mask);
int
ncp_write(struct ncp_server *server, const char *file_id,
__u32 offset, __u16 to_write,
const char *source, int *bytes_written);
ncp_delete_directory(struct ncp_server *server,
int dir_handle, const char *path);
int
ncp_obtain_info(struct ncp_server *server,
__u8 vol_num, __u32 dir_base,
char *path, /* At most 1 component */
struct nw_info_struct *target);
ncp_rename_directory(struct ncp_server *server,
int dir_handle,
const char *old_path, const char *new_path);
int
ncp_lookup_volume(struct ncp_server *server,
char *volname,
struct nw_info_struct *target);
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_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,
struct nw_info_struct *file,
__u32 info_mask,
struct nw_modify_dos_info *info);
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);
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);
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);
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);
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);
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);
#endif /* _NCPLIB_H */
#endif /* _NCPLIB_H */

View File

@@ -49,41 +49,40 @@ ncp_wdog_data_ready(struct sock *sk, int len)
fs = get_fs();
set_fs(get_ds());
result = sock->ops->recvfrom(sock, (void *)packet_buf, 2, 1, 0,
(struct sockaddr *)&sender,
result = sock->ops->recvfrom(sock, (void *) packet_buf, 2, 1, 0,
(struct sockaddr *) &sender,
&addr_len);
if ( (result != 2)
if ((result != 2)
|| (packet_buf[1] != '?')
/* How to check connection number here? */
/* How to check connection number here? */
)
{
/* Error, throw away the complete packet */
sock->ops->recvfrom(sock, (void *)packet_buf, 2, 1, 0,
(struct sockaddr *)&sender,
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;
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],
sender.sipx_node[2], sender.sipx_node[3],
sender.sipx_node[4], sender.sipx_node[5],
ntohs(sender.sipx_port),
packet_buf[0], packet_buf[1]);
" conn:%02X,type:%c\n",
htonl(sender.sipx_network),
sender.sipx_node[0], sender.sipx_node[1],
sender.sipx_node[2], sender.sipx_node[3],
sender.sipx_node[4], sender.sipx_node[5],
ntohs(sender.sipx_port),
packet_buf[0], packet_buf[1]);
packet_buf[1] = 'Y';
result = sock->ops->sendto(sock, (void *)packet_buf,
result = sock->ops->sendto(sock, (void *) packet_buf,
2, 1, 0,
(struct sockaddr *)&sender,
(struct sockaddr *) &sender,
sizeof(sender));
DDPRINTK("send result: %d\n", result);
}
@@ -95,109 +94,100 @@ ncp_wdog_data_ready(struct sock *sk, int len)
int
ncp_catch_watchdog(struct ncp_server *server)
{
struct file *file;
struct inode *inode;
struct socket *sock;
struct sock *sk;
struct file *file;
struct inode *inode;
struct socket *sock;
struct sock *sk;
if ( (server == NULL)
|| ((file = server->wdog_filp) == NULL)
|| ((inode = file->f_inode) == NULL)
|| (!S_ISSOCK(inode->i_mode)))
if ((server == NULL)
|| ((file = server->wdog_filp) == NULL)
|| ((inode = file->f_inode) == NULL)
|| (!S_ISSOCK(inode->i_mode)))
{
printk("ncp_catch_watchdog: did not get valid server!\n");
server->data_ready = NULL;
return -EINVAL;
}
printk("ncp_catch_watchdog: did not get valid server!\n");
server->data_ready = NULL;
return -EINVAL;
}
sock = &(inode->u.socket_i);
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;
}
printk("ncp_catch_watchdog: did not get SOCK_STREAM\n");
server->data_ready = NULL;
return -EINVAL;
}
sk = (struct sock *) (sock->data);
sk = (struct sock *)(sock->data);
if (sk == NULL)
if (sk == NULL)
{
printk("ncp_catch_watchdog: sk == NULL");
server->data_ready = NULL;
return -EINVAL;
}
printk("ncp_catch_watchdog: sk == NULL");
server->data_ready = NULL;
return -EINVAL;
}
DDPRINTK("ncp_catch_watchdog.: sk->d_r = %x, server->d_r = %x\n",
(unsigned int) (sk->data_ready),
(unsigned int) (server->data_ready));
DDPRINTK("ncp_catch_watchdog.: sk->d_r = %x, server->d_r = %x\n",
(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;
}
server->data_ready = sk->data_ready;
sk->data_ready = ncp_wdog_data_ready;
return 0;
printk("ncp_catch_watchdog: already done\n");
return -EINVAL;
}
server->data_ready = sk->data_ready;
sk->data_ready = ncp_wdog_data_ready;
return 0;
}
int
ncp_dont_catch_watchdog(struct ncp_server *server)
{
struct file *file;
struct inode *inode;
struct socket *sock;
struct sock *sk;
struct file *file;
struct inode *inode;
struct socket *sock;
struct sock *sk;
if ( (server == NULL)
|| ((file = server->wdog_filp) == NULL)
|| ((inode = file->f_inode) == NULL)
|| (!S_ISSOCK(inode->i_mode)))
if ((server == NULL)
|| ((file = server->wdog_filp) == NULL)
|| ((inode = file->f_inode) == NULL)
|| (!S_ISSOCK(inode->i_mode)))
{
printk("ncp_dont_catch_watchdog: "
"did not get valid server!\n");
return -EINVAL;
}
printk("ncp_dont_catch_watchdog: "
"did not get valid server!\n");
return -EINVAL;
}
sock = &(inode->u.socket_i);
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;
}
printk("ncp_dont_catch_watchdog: did not get SOCK_STREAM\n");
return -EINVAL;
}
sk = (struct sock *) (sock->data);
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)
printk("ncp_dont_catch_watchdog: sk == NULL");
return -EINVAL;
}
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)
printk("ncp_dont_catch_watchdog: "
"server->data_ready == NULL\n");
return -EINVAL;
}
if (sk->data_ready != ncp_wdog_data_ready)
{
printk("ncp_dont_catch_watchdog: "
"sk->data_callback != ncp_data_callback\n");
return -EINVAL;
}
printk("ncp_dont_catch_watchdog: "
"sk->data_callback != ncp_data_callback\n");
return -EINVAL;
}
DDPRINTK("ncp_dont_catch_watchdog: sk->d_r = %x, server->d_r = %x\n",
(unsigned int) (sk->data_ready),
(unsigned int) (server->data_ready));
DDPRINTK("ncp_dont_catch_watchdog: sk->d_r = %x, server->d_r = %x\n",
(unsigned int)(sk->data_ready),
(unsigned int)(server->data_ready));
sk->data_ready = server->data_ready;
server->data_ready = NULL;
return 0;
sk->data_ready = server->data_ready;
server->data_ready = NULL;
return 0;
}
@@ -222,15 +212,16 @@ do_ncp_rpc_call(struct ncp_server *server, int size)
int timeout;
int retrans;
int major_timeout_seen;
int acknowledge_seen;
int n;
int addrlen;
unsigned long old_mask;
/* We have to check the result, so store the complete header */
struct ncp_request_header request =
*((struct ncp_request_header *)(server->packet));
*((struct ncp_request_header *) (server->packet));
struct ncp_reply_header reply;
struct ncp_reply_header reply;
file = server->ncp_filp;
@@ -243,38 +234,39 @@ do_ncp_rpc_call(struct ncp_server *server, int size)
return -EBADF;
}
init_timeout = server->m.time_out;
max_timeout = NCP_MAX_RPC_TIMEOUT*HZ/10;
max_timeout = NCP_MAX_RPC_TIMEOUT;
acknowledge_seen = 0;
retrans = server->m.retry_count;
major_timeout_seen = 0;
old_mask = current->blocked;
current->blocked |= ~(_S(SIGKILL)
#if 0
| _S(SIGSTOP)
| _S(SIGSTOP)
#endif
| ((server->m.flags & NCP_MOUNT_INTR)
? ((current->sigaction[SIGINT - 1].sa_handler == SIG_DFL
? _S(SIGINT) : 0)
| (current->sigaction[SIGQUIT - 1].sa_handler == SIG_DFL
? _S(SIGQUIT) : 0))
: 0));
| ((server->m.flags & NCP_MOUNT_INTR)
? ((current->sigaction[SIGINT - 1].sa_handler == SIG_DFL
? _S(SIGINT) : 0)
| (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)
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],
server->m.serv_addr.sipx_node[2],
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));
htonl(server->m.serv_addr.sipx_network),
server->m.serv_addr.sipx_node[0],
server->m.serv_addr.sipx_node[1],
server->m.serv_addr.sipx_node[2],
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));
DDPRINTK("ncpfs: req.typ: %04X, con: %d, "
"seq: %d",
request.type,
(request.conn_high << 8) + request.conn_low,
request.sequence);
"seq: %d",
request.type,
(request.conn_high << 8) + request.conn_low,
request.sequence);
DDPRINTK(" func: %d\n",
request.function);
@@ -287,20 +279,23 @@ do_ncp_rpc_call(struct ncp_server *server, int size)
printk("ncp_rpc_call: send error = %d\n", result);
break;
}
re_select:
re_select:
wait_table.nr = 0;
wait_table.entry = &entry;
current->state = TASK_INTERRUPTIBLE;
if ( !select(inode, file, SEL_IN, &wait_table)
if (!select(inode, file, SEL_IN, &wait_table)
&& !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\n");
timeout = max_timeout;
/* JEJB/JSP 2/7/94
* This is useful to see if the system is
* hanging */
if (acknowledge_seen == 0)
{
printk("NCP max timeout reached\n");
}
timeout = max_timeout;
}
current->timeout = jiffies + timeout;
schedule();
@@ -331,11 +326,9 @@ do_ncp_rpc_call(struct ncp_server *server, int size)
}
major_timeout_seen = 1;
continue;
}
else
} else
current->timeout = 0;
}
else if (wait_table.nr)
} else if (wait_table.nr)
remove_wait_queue(entry.wait_address, &entry.wait);
current->state = TASK_RUNNING;
addrlen = 0;
@@ -343,7 +336,7 @@ 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 = sock->ops->recvfrom(sock, (void *)&reply,
result = sock->ops->recvfrom(sock, (void *) &reply,
sizeof(reply), 1, MSG_PEEK,
NULL, &addrlen);
if (result < 0)
@@ -361,34 +354,36 @@ do_ncp_rpc_call(struct ncp_server *server, int size)
if (result != -ERESTARTSYS)
{
printk("ncp_rpc_call: recv error = %d\n",
-result);
-result);
}
break;
}
if ( (result == sizeof(reply))
if ((result == sizeof(reply))
&& (reply.type == NCP_POSITIVE_ACK))
{
/* Throw away the packet */
DPRINTK("ncp_rpc_call: got positive acknowledge\n");
sock->ops->recvfrom(sock, (void *)&reply,
sock->ops->recvfrom(sock, (void *) &reply,
sizeof(reply), 1, 0,
NULL, &addrlen);
n = 0;
timeout = max_timeout;
acknowledge_seen = 1;
goto re_select;
}
DDPRINTK("ncpfs: rep.typ: %04X, con: %d, tsk: %d,"
"seq: %d\n",
reply.type,
(reply.conn_high << 8) + reply.conn_low,
reply.task,
reply.sequence);
if ( (result >= sizeof(reply))
&& (reply.type == NCP_REPLY)
&& ( (request.type == NCP_ALLOC_SLOT_REQUEST)
|| ( (reply.sequence == request.sequence)
&& (reply.conn_low == request.conn_low)
/* seem to get wrong task from NW311 && (reply.task == request.task)*/
"seq: %d\n",
reply.type,
(reply.conn_high << 8) + reply.conn_low,
reply.task,
reply.sequence);
if ((result >= sizeof(reply))
&& (reply.type == NCP_REPLY)
&& ((request.type == NCP_ALLOC_SLOT_REQUEST)
|| ((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))))
{
if (major_timeout_seen)
@@ -399,31 +394,28 @@ do_ncp_rpc_call(struct ncp_server *server, int size)
* 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. */
sock->ops->recvfrom(sock, (void *)&reply, sizeof(reply), 1, 0,
sock->ops->recvfrom(sock, (void *) &reply, sizeof(reply), 1, 0,
NULL, &addrlen);
#if 1
printk("ncp_rpc_call: reply mismatch\n");
#endif
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 = sock->ops->recvfrom(sock, (void *)start, server->packet_size,
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);
result = -EIO;
}
current->blocked = old_mask;
set_fs(fs);
return result;
@@ -442,7 +434,6 @@ ncp_do_request(struct ncp_server *server, int size)
printk("ncpfs: Server not locked!\n");
return -EIO;
}
return do_ncp_rpc_call(server, size);
}
@@ -453,38 +444,36 @@ int
ncp_request(struct ncp_server *server, int function)
{
struct ncp_request_header *h
= (struct ncp_request_header *)(server->packet);
= (struct ncp_request_header *) (server->packet);
struct ncp_reply_header *reply
= (struct ncp_reply_header *)(server->packet);
= (struct ncp_reply_header *) (server->packet);
int request_size = server->current_size
- sizeof(struct ncp_request_header);
- sizeof(struct ncp_request_header);
int result;
if (server->has_subfunction != 0)
{
*(__u16 *)&(h->data[0]) = request_size - 2;
*(__u16 *) & (h->data[0]) = request_size - 2;
}
h->type = NCP_REQUEST;
server->sequence += 1;
h->sequence = server->sequence;
h->conn_low = (server->connection) & 0xff;
h->sequence = server->sequence;
h->conn_low = (server->connection) & 0xff;
h->conn_high = ((server->connection) & 0xff00) >> 8;
h->task = (current->pid) & 0xff;
h->function = function;
h->task = (current->pid) & 0xff;
h->function = function;
if ((result = ncp_do_request(server, request_size + sizeof(*h))) < 0)
{
DPRINTK("ncp_request_error: %d\n", result);
return result;
}
server->completion = reply->completion_code;
server->completion = reply->completion_code;
server->conn_status = reply->connection_state;
server->reply_size = result;
server->reply_size = result;
server->ncp_reply_size = result - sizeof(struct ncp_reply_header);
result = reply->completion_code;
@@ -493,49 +482,48 @@ ncp_request(struct ncp_server *server, int function)
{
DPRINTK("ncp_completion_code: %x\n", result);
}
return result;
return result;
}
int
ncp_connect(struct ncp_server *server)
{
struct ncp_request_header *h
= (struct ncp_request_header *)(server->packet);
= (struct ncp_request_header *) (server->packet);
int result;
h->type = NCP_ALLOC_SLOT_REQUEST;
server->sequence = 0;
h->sequence = server->sequence;
h->conn_low = 0xff;
h->sequence = server->sequence;
h->conn_low = 0xff;
h->conn_high = 0xff;
h->task = (current->pid) & 0xff;
h->function = 0;
h->task = (current->pid) & 0xff;
h->function = 0;
if ((result = ncp_do_request(server, sizeof(*h))) < 0)
{
return result;
}
server->sequence = 0;
server->connection = h->conn_low + (h->conn_high * 256);
return 0;
}
int
ncp_disconnect(struct ncp_server *server)
{
struct ncp_request_header *h
= (struct ncp_request_header *)(server->packet);
= (struct ncp_request_header *) (server->packet);
h->type = NCP_DEALLOC_SLOT_REQUEST;
server->sequence += 1;
h->sequence = server->sequence;
h->conn_low = (server->connection) & 0xff;
h->sequence = server->sequence;
h->conn_low = (server->connection) & 0xff;
h->conn_high = ((server->connection) & 0xff00) >> 8;
h->task = (current->pid) & 0xff;
h->function = 0;
h->task = (current->pid) & 0xff;
h->function = 0;
return ncp_do_request(server, sizeof(*h));
}
@@ -550,7 +538,7 @@ ncp_lock_server(struct ncp_server *server)
DPRINTK("ncpfs: server locked!!!\n");
}
#endif
while (server->lock)
while (server->lock)
sleep_on(&server->wait);
server->lock = 1;
}
@@ -558,12 +546,10 @@ 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");
}
server->lock = 0;
wake_up(&server->wait);
printk("ncp_unlock_server: was not locked!\n");
}
server->lock = 0;
wake_up(&server->wait);
}

76
lib/Makefile Normal file
View File

@@ -0,0 +1,76 @@
#
# Makefile for the linux ncp-filesystem routines.
#
CC = gcc
ifeq ($(HAVE_ELF),yes)
PIC_FLAG = -fPIC
NCP_LIB = libncp.so.1.0
LIB_LINK_COMMAND = gcc -shared -Wl,-soname,libncp.so.1 -o $(NCP_LIB)
INSTALL_LIB = install $(NCP_LIB) -m 755 /lib; \
ln -sf $(NCP_LIB) /lib/libncp.so.1; \
ldconfig
export PIC_FLAG
else
NCP_LIB = libncp.a
LIB_LINK_COMMAND = ar r libncp.a
endif
CFLAGS += $(PIC_FLAG)
default:
make -C ..
all: libcom_err.a ncplib_err.o $(NCP_LIB)
install:
$(INSTALL_LIB)
ncplib.o: ncplib.c ncplib_err.h
$(CC) $(CFLAGS) -c ncplib.c
COM_ERR_CFILES = com_err/com_err.c com_err/error_message.c com_err/et_name.c \
com_err/init_et.c
COM_ERR_OFILES = com_err/com_err.o com_err/error_message.o com_err/et_name.o \
com_err/init_et.o
libcom_err.a: $(COM_ERR_CFILES)
make -C com_err
$(NCP_LIB): ncplib.o ncplib_err.o libcom_err.a
$(LIB_LINK_COMMAND) ncplib.o ncplib_err.o $(COM_ERR_OFILES)
ln -sf libncp.so.1.0 libncp.so.1
ln -sf libncp.so.1 libncp.so
export LD_LIBRARY_PATH=`pwd`:LD_LIBRARY_PATH
ncplib_err.o: ncplib_err.h ncplib_err.c
$(CC) $(CFLAGS) -c ncplib_err.c
ncplib_err.h: ncplib_err.et
com_err/compile_et ncplib_err
ln -sf ../lib/ncplib_err.h ../include/ncplib_err.h
ncplib_err.c: ncplib_err.et
com_err/compile_et ncplib_err
dep: ncplib_err.h
make -C com_err dep
$(CPP) -M $(INCLUDES) *.c > .depend
clean:
make -C com_err clean
rm -f *.o *~ ncplib_err.[ch] ../include/ncplib_err.h
rm -f libncp.*
mrproper: clean
make -C com_err mrproper
rm -f $(UTILS) .depend $(DISTFILE)
#
# include a dependency file if one exists
#
ifeq (.depend,$(wildcard .depend))
include .depend
endif

49
lib/com_err/ChangeLog Normal file
View 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.

28
lib/com_err/Makefile Normal file
View File

@@ -0,0 +1,28 @@
#
# Makefile for the com_err library
#
OBJECTS = com_err.o error_message.o et_name.o init_et.o
CFLAGS = -Wall -O2 $(PIC_FLAG)
all: ../libcom_err.a
../libcom_err.a: $(OBJECTS)
ar r ../libcom_err.a $(OBJECTS)
dep:
$(CPP) -M $(INCLUDES) *.c > .depend
clean:
rm -f *.o ../libcom_err.a
mrproper: clean
rm -f .depend
#
# include a dependency file if one exists
#
ifeq (.depend,$(wildcard .depend))
include .depend
endif

96
lib/com_err/com_err.3 Normal file
View 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".

124
lib/com_err/com_err.c Normal file
View File

@@ -0,0 +1,124 @@
/*
* 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
lib/com_err/com_err.h Normal file
View 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
lib/com_err/com_err.texinfo Normal file
View 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
lib/com_err/compile_et Executable file
View 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
lib/com_err/compile_et.1 Normal file
View 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".

View File

@@ -0,0 +1,90 @@
/*
* $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);
}

37
lib/com_err/error_table.h Normal file
View File

@@ -0,0 +1,37 @@
/*
* 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
lib/com_err/et_c.awk Normal file
View 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
lib/com_err/et_h.awk Normal file
View 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
}

38
lib/com_err/et_name.c Normal file
View File

@@ -0,0 +1,38 @@
/*
* 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);
}

61
lib/com_err/init_et.c Normal file
View File

@@ -0,0 +1,61 @@
/*
* $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
lib/com_err/internal.h Normal file
View 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

View File

@@ -0,0 +1,18 @@
/*
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.
*/

32
lib/ipx_sap_types Normal file
View 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)

3327
lib/ncplib.c Normal file

File diff suppressed because it is too large Load Diff

45
lib/ncplib_err.et Normal file
View File

@@ -0,0 +1,45 @@
error_table NCPL
ec NCPL_ET_NO_SERVER,
"No server found"
ec NCPL_ET_NO_USER,
"No username 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"
ec NCPL_ET_INVALID_MODE,
"$HOME/.nwclient has invalid mode, must be 600"
ec NCPL_ET_LOGIN_DENIED,
"Login denied"
ec NCPL_ET_NO_INTERFACE,
"No primary IPX interface found"
ec NCPL_ET_NO_PASSWORD,
"Could not get password"
ec NCPL_ET_PWD_TOO_LONG,
"Password too long"
ec NCPL_ET_NO_IPX,
"Could not alloc IPX socket. Probably no IPX support in kernel"
ec NCPL_ET_NO_NCPFS_FILE,
"The file is probably not on a ncpfs mounted directory"
end

343
lib/nwcrypt.c Normal file
View File

@@ -0,0 +1,343 @@
/*$*********************************************************
$*
$* This code has been taken from DDJ 11/93, from an
$* article by Pawel Szczerbina.
$*
$* Password encryption routines follow.
$* Converted to C from Barry Nance's Pascal
$* prog published in the March -93 issue of Byte.
$*
$* Adapted to be useable for ncpfs by
$* Volker Lendecke <lendecke@namu01.gwdg.de> in
$* October 1995.
$*
$********************************************************* */
/****************************************************************************
I read that Novell is not very open when it comes to technical details
of the Netware Core Protocol. This might be especially true for the
encryption stuff. I took the necessary code from Dr. Dobb's Journal
11/93, Undocumented Corner. I asked Jon Erickson <jon@ddj.com> about
the legal status of this piece of code:
---
Date: Thu, 12 Oct 1995 13:44:18 +0100
From: Volker Lendecke <lendecke>
To: jon@ddj.com
Subject: legal status of your source code?
Hello!
I hope that you're the right one to write to, you are the first on your WWW
server. If you are not, could you please forward this message to the right
person? Thanks.
I'm currently exploring the possibility to write a free (in the GNU GPL
sense) NCP filesystem, which would allow me to access a novell server
transparently. For that I would like to use the encryption functions you
published in DDJ 11/93, Undocumented Corner. I would make some cosmetic
changes, such as other indentations, minor code changes and so on. But I do
not know if that allows me to publish this code under GPL. One alternative
would be to publish a diff against your listing, but that would probably
contain much of your code as well, and it would be very inconvenient for
the average user.
I think that you have some kind of standard procedure for such a
case. Please tell me what I should do.
Many thanks in advance,
Volker
+=================================================================+
! Volker Lendecke Internet: lendecke@namu01.gwdg.de !
! D-37081 Goettingen, Germany !
+=================================================================+
--
I got the following answer:
---
From: Jon Erickson <jon@ddj.com>
X-Mailer: SCO System V Mail (version 3.2)
To: lendecke@namu01.gwdg.de
Subject: Re: legal status of your source code?
Date: Thu, 12 Oct 95 5:42:56 PDT
Volker,
Code from Dr. Dobb's Journal related articles is provided for
anyone to use. Clearly, the author of the article should be
given credit.
Jon Erickson
---
With this answer in mind, I took the code and made it a bit more
C-like. The original seemed to be translated by a mechanical pascal->c
translator. Jon's answer encouraged me to publish nwcrypt.c under the
GPL. If anybody who knows more about copyright and sees any problems
with this, please tell me.
****************************************************************************/
/******************* Data types ***************************/
typedef unsigned char buf32[32];
typedef unsigned char buf16[16];
typedef unsigned char buf8[8];
typedef unsigned char buf4[4];
static unsigned char encrypttable[256] =
{0x7, 0x8, 0x0, 0x8, 0x6, 0x4, 0xE, 0x4, 0x5, 0xC, 0x1, 0x7, 0xB, 0xF, 0xA, 0x8,
0xF, 0x8, 0xC, 0xC, 0x9, 0x4, 0x1, 0xE, 0x4, 0x6, 0x2, 0x4, 0x0, 0xA, 0xB, 0x9,
0x2, 0xF, 0xB, 0x1, 0xD, 0x2, 0x1, 0x9, 0x5, 0xE, 0x7, 0x0, 0x0, 0x2, 0x6, 0x6,
0x0, 0x7, 0x3, 0x8, 0x2, 0x9, 0x3, 0xF, 0x7, 0xF, 0xC, 0xF, 0x6, 0x4, 0xA, 0x0,
0x2, 0x3, 0xA, 0xB, 0xD, 0x8, 0x3, 0xA, 0x1, 0x7, 0xC, 0xF, 0x1, 0x8, 0x9, 0xD,
0x9, 0x1, 0x9, 0x4, 0xE, 0x4, 0xC, 0x5, 0x5, 0xC, 0x8, 0xB, 0x2, 0x3, 0x9, 0xE,
0x7, 0x7, 0x6, 0x9, 0xE, 0xF, 0xC, 0x8, 0xD, 0x1, 0xA, 0x6, 0xE, 0xD, 0x0, 0x7,
0x7, 0xA, 0x0, 0x1, 0xF, 0x5, 0x4, 0xB, 0x7, 0xB, 0xE, 0xC, 0x9, 0x5, 0xD, 0x1,
0xB, 0xD, 0x1, 0x3, 0x5, 0xD, 0xE, 0x6, 0x3, 0x0, 0xB, 0xB, 0xF, 0x3, 0x6, 0x4,
0x9, 0xD, 0xA, 0x3, 0x1, 0x4, 0x9, 0x4, 0x8, 0x3, 0xB, 0xE, 0x5, 0x0, 0x5, 0x2,
0xC, 0xB, 0xD, 0x5, 0xD, 0x5, 0xD, 0x2, 0xD, 0x9, 0xA, 0xC, 0xA, 0x0, 0xB, 0x3,
0x5, 0x3, 0x6, 0x9, 0x5, 0x1, 0xE, 0xE, 0x0, 0xE, 0x8, 0x2, 0xD, 0x2, 0x2, 0x0,
0x4, 0xF, 0x8, 0x5, 0x9, 0x6, 0x8, 0x6, 0xB, 0xA, 0xB, 0xF, 0x0, 0x7, 0x2, 0x8,
0xC, 0x7, 0x3, 0xA, 0x1, 0x4, 0x2, 0x5, 0xF, 0x7, 0xA, 0xC, 0xE, 0x5, 0x9, 0x3,
0xE, 0x7, 0x1, 0x2, 0xE, 0x1, 0xF, 0x4, 0xA, 0x6, 0xC, 0x6, 0xF, 0x4, 0x3, 0x0,
0xC, 0x0, 0x3, 0x6, 0xF, 0x8, 0x7, 0xB, 0x2, 0xD, 0xC, 0x6, 0xA, 0xA, 0x8, 0xD};
static buf32 encryptkeys =
{0x48, 0x93, 0x46, 0x67, 0x98, 0x3D, 0xE6, 0x8D,
0xB7, 0x10, 0x7A, 0x26, 0x5A, 0xB9, 0xB1, 0x35,
0x6B, 0x0F, 0xD5, 0x70, 0xAE, 0xFB, 0xAD, 0x11,
0xF4, 0x47, 0xDC, 0xA7, 0xEC, 0xCF, 0x50, 0xC0};
static void
shuffle1(buf32 temp, unsigned char *target)
{
short b4;
unsigned char b3;
int s, b2, i;
b4 = 0;
for (b2 = 0; b2 <= 1; ++b2)
{
for (s = 0; s <= 31; ++s)
{
b3 = (temp[s] + b4) ^ (temp[(s + b4) & 31] - encryptkeys[s]);
b4 = b4 + b3;
temp[s] = b3;
}
}
for (i = 0; i <= 15; ++i)
{
target[i] = encrypttable[temp[2 * i]]
| (encrypttable[temp[2 * i + 1]] << 4);
}
}
static void
shuffle(const unsigned char *lon, const unsigned char *buf, int buflen,
unsigned char *target)
{
int b2, d, s;
buf32 temp;
while ((buflen > 0)
&& (buf[buflen - 1] == 0))
{
buflen = buflen - 1;
}
for (s = 0; s < 32; s++)
{
temp[s] = 0;
}
d = 0;
while (buflen >= 32)
{
for (s = 0; s <= 31; ++s)
{
temp[s] = temp[s] ^ buf[d];
d = d + 1;
}
buflen = buflen - 32;
}
b2 = d;
if (buflen > 0)
{
for (s = 0; s <= 31; ++s)
{
if (d + buflen == b2)
{
b2 = d;
temp[s] = temp[s] ^ encryptkeys[s];
} else
{
temp[s] = temp[s] ^ buf[b2];
b2 = b2 + 1;
}
}
}
for (s = 0; s <= 31; ++s)
temp[s] = temp[s] ^ lon[s & 3];
shuffle1(temp, target);
}
static void
nw_encrypt(const unsigned char *fra,
const unsigned char *buf,
unsigned char *til)
{
buf32 k;
int s;
shuffle(&(fra[0]), buf, 16, &(k[0]));
shuffle(&(fra[4]), buf, 16, &(k[16]));
for (s = 0; s <= 15; ++s)
k[s] = k[s] ^ k[31 - s];
for (s = 0; s <= 7; ++s)
til[s] = k[s] ^ k[15 - s];
}
/*****************************************************************************/
/* */
/* The following code was contributed by */
/* Guntram Blohm <gbl%th7csun1@str.daimler-benz.com> */
/* */
/*****************************************************************************/
/* server side (mars etc.) should:
* store the *encrypted* password internally (output from shuffle)
* verify if nw_encrypt(cryptkey from GetCryptKey, old stored password)
== cryptkey in EncryptedChangePassword request buffer (this means
old password was correct)
* decrypt new password in request buffer using (yet to write) inverse of
newpassencrypt with old stored password as parameter
* compute the length of the unencrypted new password as len ^ (first byte of
old internal password) ^ (second byte of old internal password)
*/
static char
newshuffle[256 + 16] =
{
0x0f, 0x08, 0x05, 0x07, 0x0c, 0x02, 0x0e, 0x09,
0x00, 0x01, 0x06, 0x0d, 0x03, 0x04, 0x0b, 0x0a,
0x02, 0x0c, 0x0e, 0x06, 0x0f, 0x00, 0x01, 0x08,
0x0d, 0x03, 0x0a, 0x04, 0x09, 0x0b, 0x05, 0x07,
0x05, 0x02, 0x09, 0x0f, 0x0c, 0x04, 0x0d, 0x00,
0x0e, 0x0a, 0x06, 0x08, 0x0b, 0x01, 0x03, 0x07,
0x0f, 0x0d, 0x02, 0x06, 0x07, 0x08, 0x05, 0x09,
0x00, 0x04, 0x0c, 0x03, 0x01, 0x0a, 0x0b, 0x0e,
0x05, 0x0e, 0x02, 0x0b, 0x0d, 0x0a, 0x07, 0x00,
0x08, 0x06, 0x04, 0x01, 0x0f, 0x0c, 0x03, 0x09,
0x08, 0x02, 0x0f, 0x0a, 0x05, 0x09, 0x06, 0x0c,
0x00, 0x0b, 0x01, 0x0d, 0x07, 0x03, 0x04, 0x0e,
0x0e, 0x08, 0x00, 0x09, 0x04, 0x0b, 0x02, 0x07,
0x0c, 0x03, 0x0a, 0x05, 0x0d, 0x01, 0x06, 0x0f,
0x01, 0x04, 0x08, 0x0a, 0x0d, 0x0b, 0x07, 0x0e,
0x05, 0x0f, 0x03, 0x09, 0x00, 0x02, 0x06, 0x0c,
0x05, 0x03, 0x0c, 0x08, 0x0b, 0x02, 0x0e, 0x0a,
0x04, 0x01, 0x0d, 0x00, 0x06, 0x07, 0x0f, 0x09,
0x06, 0x00, 0x0b, 0x0e, 0x0d, 0x04, 0x0c, 0x0f,
0x07, 0x02, 0x08, 0x0a, 0x01, 0x05, 0x03, 0x09,
0x0b, 0x05, 0x0a, 0x0e, 0x0f, 0x01, 0x0c, 0x00,
0x06, 0x04, 0x02, 0x09, 0x03, 0x0d, 0x07, 0x08,
0x07, 0x02, 0x0a, 0x00, 0x0e, 0x08, 0x0f, 0x04,
0x0c, 0x0b, 0x09, 0x01, 0x05, 0x0d, 0x03, 0x06,
0x07, 0x04, 0x0f, 0x09, 0x05, 0x01, 0x0c, 0x0b,
0x00, 0x03, 0x08, 0x0e, 0x02, 0x0a, 0x06, 0x0d,
0x09, 0x04, 0x08, 0x00, 0x0a, 0x03, 0x01, 0x0c,
0x05, 0x0f, 0x07, 0x02, 0x0b, 0x0e, 0x06, 0x0d,
0x09, 0x05, 0x04, 0x07, 0x0e, 0x08, 0x03, 0x01,
0x0d, 0x0b, 0x0c, 0x02, 0x00, 0x0f, 0x06, 0x0a,
0x09, 0x0a, 0x0b, 0x0d, 0x05, 0x03, 0x0f, 0x00,
0x01, 0x0c, 0x08, 0x07, 0x06, 0x04, 0x0e, 0x02,
0x03, 0x0e, 0x0f, 0x02, 0x0d, 0x0c, 0x04, 0x05,
0x09, 0x06, 0x00, 0x01, 0x0b, 0x07, 0x0a, 0x08,
};
/*
* verschluesseln des neuen Passworts fuer keyed change password
* Verwendung:
* - Shuffle (aus nwcrypt.c) altes passwort nach old (16 bytes)
* - shuffle neues passwort nach new (16 bytes)
* - nwpassencrypt (diese Funktion) zweimal aufrufen fuer je 8 bytes:
* nwpassencrypt(old+0, new+0, out+0)
* nwpassencrypt(old+8, new+8, out+8)
* - NCP-Buffer aufbauen:
* 2 byte Laenge im Hi-Lo-Format
* 1 byte Funktion (0x4b)
* 8 byte (nwcrypt Ergebnis analog login/verify password)
* 2 byte Objecttype
* 1 byte Objectname-Laenge
* n byte Objectname
* 1 byte (Laenge des eingegebenen neuen Passworts ^ old[0] ^ old[1])&0x7f|0x40
* 16 byte (Ergebnis dieser Funktion doppelt aufgerufen, s.o.)
*/
/*
* Encrypt the new password for keyed change password
* For info on how to use this function, look at ncp_change_login_passwd
* in ncplib.c.
*/
static void
newpassencrypt(char *old, char *new, char *out)
{
char *p, *bx;
char copy[8];
int i, di, ax;
char cl, dl, ch;
memcpy(copy, new, 8);
for (i = 0; i < 16; i++)
{
for (di = 0, ax = 0, p = old; di < 8; di++, ax += 0x20, p++)
{
cl = newshuffle[(((copy[di] ^ *p) >> 4) & 0x0f) + ax + 0x10] << 4;
dl = newshuffle[((copy[di] ^ *p) & 0xf) + ax];
copy[di] = cl | dl;
}
ch = old[7];
for (bx = old + 7; bx > old; bx--)
{
*bx = ((bx[-1] >> 4) & 0x0f) | ((*bx) << 4);
}
*old = ((ch >> 4) & 0x0f) | (*old) << 4;
memset(out, '\0', 8);
for (di = 0; di < 16; di++)
{
if (newshuffle[di + 0x100] & 1)
ch = ((copy[newshuffle[di + 0x100] / 2] >> 4) & 0x0f);
else
ch = copy[newshuffle[di + 0x100] / 2] & 0x0f;
out[di / 2] |= ((di & 1) ? ch << 4 : ch);
}
memcpy(copy, out, 8);
}
}

View File

@@ -1,16 +1,12 @@
MAN1= slist nprint pqlist
MAN5= nwclient
MAN8= ncpmount ncpumount ipx_configure ipx_interface ipx_internal_net ipx_route
all:
dep:
install:
for i in $(MAN1); do install $$i.1 -m 755 /usr/local/man/man1; done
for i in $(MAN5); do install $$i.5 -m 755 /usr/local/man/man5; done
for i in $(MAN8); do install $$i.8 -m 755 /usr/local/man/man8; done
for i in *.1; do install $$i -m 755 /usr/local/man/man1; done
for i in *.5; do install $$i -m 755 /usr/local/man/man5; done
for i in *.8; do install $$i -m 755 /usr/local/man/man8; done
clean:
rm -f *~

96
man/ncopy.1 Normal file
View 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@math.uni-goettingen.de) for the ncpfs and ncplib which made
ncopy possible.

View File

@@ -37,6 +37,12 @@ ncpmount \- mount all volumes of a specified Novell fileserver.
.B -V
.I volume
] [
.B -t
.I time_out
] [
.B -r
.I retry_count
] [
.B -v
]
mount-point
@@ -51,7 +57,7 @@ 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.
ftp://klokan.sh.cvut.cz/pub/linux for this very interesting program.
.B ncpmount
when invoked with all appropriate arguments attaches, logs in and
@@ -77,7 +83,7 @@ If the real uid of the caller is not root,
checks whether the user is allowed to mount a filesystem on the
mount-point. So it should be safe to make
.B ncpmount
setuid root. The filesystem stores the uid of the user who called
setuid root. The filesystem stores the uid of the user who called
ncpmount. So
.B ncpumount
can check whether the caller is allowed to unmount the filesystem.
@@ -221,6 +227,36 @@ 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
@@ -235,7 +271,7 @@ of your server.
.B USER / LOGNAME
.RS 3
The variables USER or LOGNAME may contain the username of the person
using the client. USER is tried first. If it's emtpy, LOGNAME is
using the client. USER is tried first. If it's empty, LOGNAME is
tried.
.RE
@@ -255,5 +291,5 @@ The encryption code was taken from Dr. Dobbs's Journal 11/93. There
Pawel Szczerbina described it in an article on NCP.
The ncpfs code was initially hacked from smbfs by Volker Lendecke
(lendecke@namu01.gwdg.de). smbfs was put together by Paal-Kr. Engstad
(lendecke@math.uni-goettingen.de). smbfs was put together by Paal-Kr. Engstad
(pke@engstad.ingok.hitos.no) and later polished by Volker.

View File

@@ -14,7 +14,7 @@ nprint \- NetWare print client
] [
.B -P
.I password
|
|
.B -n
] [
.B -C
@@ -219,4 +219,4 @@ printed if a printer operator has put in the correct form.
.B nwclient(5), slist(1), pqlist(1), ncpmount(8), ncpumount(8)
.SH CREDITS
nprint was written by Volker Lendecke (lendecke@namu01.gwdg.de)
nprint was written by Volker Lendecke (lendecke@math.uni-goettingen.de)

108
man/nsend.1 Normal file
View 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 your 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 about using 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>

69
man/nwauth.1 Normal file
View File

@@ -0,0 +1,69 @@
.TH NWAUTH 1 10/27/1996 nwauth nwauth
.SH NAME
nwauth \- Verify username/password
.SH SYNOPSIS
.B nwauth
[
.B -h
] [
.B -S
.I server
] [
.B -U
.I user name
] [
.B -P
.I password
|
.B -n
]
.SH DESCRIPTION
.B nwauth
does nothing but logging into a NetWare server. If the login was
successful, an error code of 0 is returned. If the login was not
successful, an error code of 1 is returned. It was designed for
use by other programs who want authenticate users via a NetWare
server.
nwauth
.B always
expects a password on stdin. If the stdin is a tty, then the user is
prompted for a password. Otherwise nwauth simply reads stdin for a
password.
.B nwauth
looks up the file
.I $HOME/.nwclient
to find a file server and a user name. See nwclient(5) for more
information. Please note that the access permissions of .nwclient MUST
be 600, for security reasons.
.SH OPTIONS
.B -h
.RS 3
.B -h
is used to print 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 your NetWare user name.
.RE
.SH SEE ALSO
.B nwclient(5)
.SH CREDITS
nwauth was written by Volker Lendecke (lendecke@math.uni-goettingen.de)

133
man/nwbocreate.8 Normal file
View File

@@ -0,0 +1,133 @@
.TH NWBOCREATE 8 7/9/1996 nwbocreate nwbocreate
.SH NAME
nwbocreate \- Create a NetWare Bindery Object
.SH SYNOPSIS
.B nwbocreate
[
.B -h
] [
.B -S
.I server
] [
.B -U
.I user name
] [
.B -P
.I password
|
.B -n
] [
.B -C
] [
.B -o
.I object name
] [
.B -t
.I type
] [
.B -r
.I read-flag
] [
.B -w
.I write-flag
]
.SH DESCRIPTION
.B nwbocreate
creates the specified NetWare Bindery Object.
.B nwbocreate
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 $HOME/.nwclient MUST be 600 for security reasons.
.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 user name to use for login.
.RE
.B -P
.I password
.RS 3
.B password
is the password to use for login. If neither
.B -n
nor
.B -P
are given, and the user has no open connection to the server, nwbocreate
prompts for a password.
.RE
.B -n
.RS 3
.B -n
should be given if no password is required for the login.
.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 -o
.I object name
.RS 3
The name of the object to be created.
.RE
.B -t
.I object type
.RS 3
The type of the object.
.I Object type
must be specified as a decimal value. Common values are 1 for user
objects, 2 for group objects and 3 for print queues. Other values are
allowed, but are usually used for specialized applications.
.RE
.B -r
.I read-flag
.B -w
.I write-flag
.RS 3
Read security and write security may each have one of the following values:
ANYONE: Anyone may access the object
LOGGED: Anyone who is logged in may access the
object
OBJECT: Anyone who is logged in as the object or
SUPERVISOR equivalent may access the
object
SUPERVISOR: Anyone who is logged in as SUPERVISOR
equivalent may access the object
NETWARE: Only the Bindery may access the object
.RE
.SH AUTHORS
nwbocreate was written by Volker Lendecke with the corresponding
Caldera utility in mind. See the Changes file of ncpfs for other
contributors.

119
man/nwbols.1 Normal file
View File

@@ -0,0 +1,119 @@
.TH NWBOLS 1 7/9/1996 nwbols nwbols
.SH NAME
nwbols \- List NetWare Bindery Objects
.SH SYNOPSIS
.B nwbols
[
.B -h
] [
.B -S
.I server
] [
.B -U
.I user name
] [
.B -P
.I password
|
.B -n
] [
.B -C
] [
.B -t
.I type
] [
.B -o
.I pattern
] [
.B -v
]
.SH DESCRIPTION
.B nwbols
lists the specified NetWare Bindery Objects visible for the user.
.B nwbols
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 $HOME/.nwclient MUST be 600 for security reasons.
.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 user name to use for login.
.RE
.B -P
.I password
.RS 3
.B password
is the password to use for login. If neither
.B -n
nor
.B -P
are given, and the user has no open connection to the server, nwbols
prompts for a password.
.RE
.B -n
.RS 3
.B -n
should be given if no password is required for the login.
.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 -t
.I type
.RS 3
You can restrict the objects listed by specifying the type of the
objects to be listed.
.I type
must be given as a decimal number.
.RE
.B -o
.I pattern
.RS 3
Specifying a pattern is another way to restrict the objects
listed. Please note that this pattern is evaluated by the NetWare
server. grep would be a better candidate for complex patterns.
.RE
.B -v
.RS 3
By default, the object's name, its ID and its type are listed by
.B nwbols.
In the verbose mode, activated by
.B -v,
the object flags, its security byte and the properties flag is also
listed.
.RE
.SH AUTHORS
nwbols was written by Volker Lendecke. See the Changes file of ncpfs
for other contributors.

118
man/nwboprops.1 Normal file
View File

@@ -0,0 +1,118 @@
.TH NWBOPROPS 1 7/9/1996 nwboprops nwboprops
.SH NAME
nwboprops \- List properies of a NetWare Bindery Object
.SH SYNOPSIS
.B nwboprops
[
.B -h
] [
.B -S
.I server
] [
.B -U
.I user name
] [
.B -P
.I password
|
.B -n
] [
.B -C
] [
.B -o
.I object name
] [
.B -t
.I type
] [
.B -v
]
.SH DESCRIPTION
.B nwboprops
lists all the properties of the specified NetWare Bindery Objects.
.B nwboprops
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 $HOME/.nwclient MUST be 600 for security reasons.
.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 user name to use for login.
.RE
.B -P
.I password
.RS 3
.B password
is the password to use for login. If neither
.B -n
nor
.B -P
are given, and the user has no open connection to the server, nwboprops
prompts for a password.
.RE
.B -n
.RS 3
.B -n
should be given if no password is required for the login.
.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 -o
.I object name
.RS 3
The name of the object to be inspected.
.RE
.B -t
.I object type
.RS 3
The type of the object.
.I Object type
must be specified as a decimal value. Common values are 1 for user
objects, 2 for group objects and 3 for print queues. Other values are
allowed, but are usually used for specialized applications.
.RE
.B -v
.RS 3
By default, only the property name is listed. In verbose mode,
activated by
.B -v,
the property flag, the property security byte and the value flag are
also listed.
.RE
.SH AUTHORS
nwboprops was written by Volker Lendecke with the corresponding
Caldera utility in mind. See the Changes file of ncpfs for other
contributors.

106
man/nwborm.8 Normal file
View File

@@ -0,0 +1,106 @@
.TH NWBORM 8 7/9/1996 nwborm nwborm
.SH NAME
nwborm \- Remove a NetWare Bindery Object
.SH SYNOPSIS
.B nwborm
[
.B -h
] [
.B -S
.I server
] [
.B -U
.I user name
] [
.B -P
.I password
|
.B -n
] [
.B -C
] [
.B -o
.I object name
] [
.B -t
.I type
]
.SH DESCRIPTION
.B nwborm
removes the specified NetWare Bindery Objects.
.B nwborm
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 $HOME/.nwclient MUST be 600 for security reasons.
.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 user name to use for login.
.RE
.B -P
.I password
.RS 3
.B password
is the password to use for login. If neither
.B -n
nor
.B -P
are given, and the user has no open connection to the server, nwborm
prompts for a password.
.RE
.B -n
.RS 3
.B -n
should be given if no password is required for the login.
.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 -o
.I object name
.RS 3
The name of the object to be deleted.
.RE
.B -t
.I object type
.RS 3
The type of the object.
.I Object type
must be specified as a decimal value. Common values are 1 for user
objects, 2 for group objects and 3 for print queues. Other values are
allowed, but are usually used for specialized applications.
.RE
.SH AUTHORS
nwborm was written by Volker Lendecke with the corresponding Caldera
utility in mind. See the Changes file of ncpfs for other contributors.

145
man/nwbpadd.8 Normal file
View File

@@ -0,0 +1,145 @@
.TH NWBPADD 8 7/9/1996 nwbpadd nwbpadd
.SH NAME
nwbpadd \- Set the value of a NetWare Bindery Property
.SH SYNOPSIS
.B nwbpadd
[
.B -h
] [
.B -S
.I server
] [
.B -U
.I user name
] [
.B -P
.I password
|
.B -n
] [
.B -C
] [
.B -o
.I object name
] [
.B -t
.I type
] [
.B -p
.I property
]
.B value
.SH DESCRIPTION
.B nwbpadd
sets the value of a ITEM type property, and adds bindery objects to a
SET type property.
.B nwbpadd
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 $HOME/.nwclient MUST be 600 for security reasons.
.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 user name to use for login.
.RE
.B -P
.I password
.RS 3
.B password
is the password to use for login. If neither
.B -n
nor
.B -P
are given, and the user has no open connection to the server, nwbpadd
prompts for a password.
.RE
.B -n
.RS 3
.B -n
should be given if no password is required for the login.
.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 -o
.I object name
.RS 3
The name of the object to be touched.
.RE
.B -t
.I object type
.RS 3
The type of the object.
.I Object type
must be specified as a decimal value. Common values are 1 for user
objects, 2 for group objects and 3 for print queues. Other values are
allowed, but are usually used for specialized applications.
.RE
.B -p
.I property
.RS 3
The name of the property to be set.
.RE
.B value
.RS 3
If property is of type SET, value is an object id in hexadecimal
notation. Otherwise, value is either a string value to be written, or
a count of bytes to be written. The latter is assumed if more than one
value argument is given. The count is decimal, and the following
arguments are interpreted as bytes in hexadecimal notation.
Examples:
All these examples assume the existence of the file
$HOME/.nwclient. Otherwise, the server and user would have to be
specified.
nwbpadd -o linus -t 1 -p groups_i\\'m_in os_hackers
In this example, user linus is added to the group os_hackers. Please
note that the ' has to be quoted.
nwbpadd -o linus -t 1 -p identification "Linus Torvalds"
User linus is given his real name :-).
nwbpadd -o linus -t 1 -p revision -v 04 00 00 01 0b
A new 4-byte binary value 0x0000010b (hi-lo order, no byte-swapping) is added
to the "REVISION" property of the user "linus".
.SH AUTHORS
nwbpadd was written by Volker Lendecke with the corresponding Caldera
utility in mind. See the Changes file of ncpfs for other contributors.

154
man/nwbpcreate.8 Normal file
View File

@@ -0,0 +1,154 @@
.TH NWBPCREATE 8 7/9/1996 nwbpcreate nwbpcreate
.SH NAME
nwbpcreate \- Create a NetWare Bindery Propery
.SH SYNOPSIS
.B nwbpcreate
[
.B -h
] [
.B -S
.I server
] [
.B -U
.I user name
] [
.B -P
.I password
|
.B -n
] [
.B -C
] [
.B -o
.I object name
] [
.B -t
.I type
] [
.B -p
.I property
] [
.B -s
] [
.B -r
.I read-flag
] [
.B -w
.I write-flag
]
.SH DESCRIPTION
.B nwbpcreate
creates the specified NetWare Bindery Propery.
.B nwbpcreate
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 $HOME/.nwclient MUST be 600 for security reasons.
.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 user name to use for login.
.RE
.B -P
.I password
.RS 3
.B password
is the password to use for login. If neither
.B -n
nor
.B -P
are given, and the user has no open connection to the server, nwbpcreate
prompts for a password.
.RE
.B -n
.RS 3
.B -n
should be given if no password is required for the login.
.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 -o
.I object name
.RS 3
The name of the object to be touched.
.RE
.B -t
.I object type
.RS 3
The type of the object.
.I Object type
must be specified as a decimal value. Common values are 1 for user
objects, 2 for group objects and 3 for print queues. Other values are
allowed, but are usually used for specialized applications.
.RE
.B -p
.I property
.RS 3
The name of the property to be created.
.RE
.B -s
.RS 3
By default,
.B nwbpcreate
creates properties of type ITEM. If you want to create a property of
type SET, such as groups_i\\'m_in, you must use the
.B -s
option.
.RE
.B -r
.I read-flag
.B -w
.I write-flag
.RS 3
Read security and write security may each have one of the following values:
ANYONE: Anyone may access the property
LOGGED: Anyone who is logged in may access the
property
OBJECT: Anyone who is logged in as the object or
SUPERVISOR equivalent may access the
property
SUPERVISOR: Anyone who is logged in as SUPERVISOR
equivalent may access the property
NETWARE: Only the Bindery may access the property
.RE
.SH AUTHORS
nwbpcreate was written by Volker Lendecke with the corresponding
Caldera utility in mind. See the Changes file of ncpfs for other
contributors.

116
man/nwbprm.8 Normal file
View File

@@ -0,0 +1,116 @@
.TH NWBPRM 8 7/9/1996 nwbprm nwbprm
.SH NAME
nwbprm \- Remove a NetWare Bindery Propery
.SH SYNOPSIS
.B nwbprm
[
.B -h
] [
.B -S
.I server
] [
.B -U
.I user name
] [
.B -P
.I password
|
.B -n
] [
.B -C
] [
.B -o
.I object name
] [
.B -t
.I type
] [
.B -p
.I property
]
.SH DESCRIPTION
.B nwbprm
removes the specified NetWare Bindery Propery.
.B nwbprm
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 $HOME/.nwclient MUST be 600 for security reasons.
.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 user name to use for login.
.RE
.B -P
.I password
.RS 3
.B password
is the password to use for login. If neither
.B -n
nor
.B -P
are given, and the user has no open connection to the server, nwbprm
prompts for a password.
.RE
.B -n
.RS 3
.B -n
should be given if no password is required for the login.
.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 -o
.I object name
.RS 3
The name of the object to be touched.
.RE
.B -t
.I object type
.RS 3
The type of the object.
.I Object type
must be specified as a decimal value. Common values are 1 for user
objects, 2 for group objects and 3 for print queues. Other values are
allowed, but are usually used for specialized applications.
.RE
.B -p
.I property
.RS 3
The name of the property to be removed.
.RE
.SH AUTHORS
nwbprm was written by Volker Lendecke with the corresponding
Caldera utility in mind. See the Changes file of ncpfs for other
contributors.

107
man/nwbpset.1 Normal file
View File

@@ -0,0 +1,107 @@
.TH NWBPSET 1 8/7/1996 nwbpset nwbpset
.SH NAME
nwbpset \- Create a bindery property or set its value
.SH SYNOPSIS
.B nwbpset
[
.B -h
] [
.B -S
.I server
] [
.B -U
.I user name
] [
.B -P
.I password
|
.B -n
] [
.B -C
]
.SH DESCRIPTION
.B nwbpset
Reads a property specification from the standard input and creates and
sets the corresponding property. The format is determined by the
output of 'nwbpvalues -c'. nwbpset will hopefully become an important
part of the bindery management suite of ncpfs, together with
'nwbpvalues -c'. See util/nwbpsecurity for an example.
As another example, look at the following command line:
nwbpvalues -t 1 -o supervisor -p user_defaults -c |\\
sed '2s/.*/ME/'|\\
sed '3s/.*/LOGIN_CONTROL/'|\\
nwbpset
With this command, the property user_defaults of the user object
\'supervisor\' is copied into the property login_control of the user
object \'me\'.
nwbpvalues -t 1 -o me -p login_control -c |\\
sed '9s/.*/ff/'|\\
nwbpset
This command disables the user object me.
Feel free to contribute other examples!
.B nwbpset
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 $HOME/.nwclient MUST be 600 for security reasons.
.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 user name to use for login.
.RE
.B -P
.I password
.RS 3
.B password
is the password to use for login. If neither
.B -n
nor
.B -P
are given, and the user has no open connection to the server, nwbpset
prompts for a password.
.RE
.B -n
.RS 3
.B -n
should be given if no password is required for the login.
.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 AUTHORS
nwbpset was written by Volker Lendecke. See the Changes file of ncpfs
for other contributors.

135
man/nwbpvalues.1 Normal file
View File

@@ -0,0 +1,135 @@
.TH NWBPVALUES 8 7/9/1996 nwbpvalues nwbpvalues
.SH NAME
nwbpvalues \- Print a NetWare Bindery Propery's contents
.SH SYNOPSIS
.B nwbpvalues
[
.B -h
] [
.B -S
.I server
] [
.B -U
.I user name
] [
.B -P
.I password
|
.B -n
] [
.B -C
] [
.B -o
.I object name
] [
.B -t
.I type
] [
.B -p
.I property
] [
.B -v
] [
.B -c
]
.SH DESCRIPTION
.B nwbpvalues
prints the contents of a SET property.
.B nwbpvalues
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 $HOME/.nwclient MUST be 600 for security reasons.
.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 user name to use for login.
.RE
.B -P
.I password
.RS 3
.B password
is the password to use for login. If neither
.B -n
nor
.B -P
are given, and the user has no open connection to the server, nwbpvalues
prompts for a password.
.RE
.B -n
.RS 3
.B -n
should be given if no password is required for the login.
.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 -o
.I object name
.RS 3
The name of the object to be looked up.
.RE
.B -t
.I object type
.RS 3
The type of the object.
.I Object type
must be specified as a decimal value. Common values are 1 for user
objects, 2 for group objects and 3 for print queues. Other values are
allowed, but are usually used for specialized applications.
.RE
.B -p
.I property
.RS 3
The name of the property to be printed.
.RE
.B -v
.RS 3
By default, the object's name, its ID and its type are listed by
.B nwbols.
In the verbose mode, activated by
.B -v,
the object flags, its security byte and the properties flag is also
listed.
.RE
.B -c
.RS 3
Use canonical output, to be used with nwbpset.
.RE
.SH AUTHORS
nwbpvalues was written by Volker Lendecke with the corresponding
Caldera utility in mind. See the Changes file of ncpfs for other
contributors.

View File

@@ -1,4 +1,4 @@
.TH NWCLIENT 5 12/27/1995 nwmount nwmount
.TH NWCLIENT 5 12/27/1995 nwclient nwclient
.SH NAME
nwclient \- configuration file for NWClient program suite
.SH DESCRIPTION
@@ -35,11 +35,11 @@ An example might be the following:
# And a passwordless account on another server
CD-SERV/GUEST -
With these lines in $HOME/.nwclient, calling 'nwmount /mnt' will mount
With these lines in $HOME/.nwclient, calling 'ncpmount /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.
\'ncpmount -S cd-serv /cd' will silently mount the server cd-serv on /cd.
.B nprint
,

52
man/nwfsinfo.1 Normal file
View File

@@ -0,0 +1,52 @@
.TH NWFSINFO 1 07/22/1996 nwfsinfo nwfsinfo
.SH NAME
nwfsinfo \- Print some information about the file server
.SH SYNOPSIS
.B nwfsinfo
[
.B -h
] [
.B -S
.I server
] [
.B -t
] [
.B -i
] [
.B -d
]
.SH DESCRIPTION
.B nwfsinfo
prints some of the information the NetWare servers present without
logging in. The options control what is printed. You should try the
different options to find out what is printed when.
.SH OPTIONS
.B -h
.RS 3
With -h nwfsinfo prints a little help text.
.RE
.B -S
.I server
.RS 3
is the name of the server you want to know something about.
.RE
.B -t
.RS 3
Print what the file server believes to be the current time.
.RE
.B -d
.RS 3
Print the so-called file server description strings.
.RE
.B -i
.RS 3
Print the extended file server information such as NetWare version,
maximum connections an others.
.RE

85
man/nwfstime.1 Normal file
View File

@@ -0,0 +1,85 @@
.TH NWFSTIME 1 12/10/1996 nwfstime nwfstime
.SH NAME
nwfstime \- Display / Set a NetWare server's date and time
.SH SYNOPSIS
.B nwfstime
[
.B -h
] [
.B -S
.I server
] [
.B -U
.I user name
] [
.B -P
.I password
|
.B -n
] [
.B -C
] [
.B -s
]
.SH DESCRIPTION
.B nwfstime
displays a NetWare server's date and time. You can also set a NetWare
server's date and time from the local time.
.SH OPTIONS
.B -h
.RS 3
With -h nwfstime prints a little help text.
.RE
.B -S
.I server
.RS 3
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 login. To set the server's time, you need
supervisor privileges.
.RE
.B -P
.I password
.RS 3
.B password
is the password to use for login. If neither
.B -n
nor
.B -P
are given, and the user has no open connection to the server, nwfstime
prompts for a password.
.RE
.B -n
.RS 3
.B -n
should be given if no password is required for the login. As you need
supervisor privileges for setting the date and time, this option is
probably not used very often.
.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 -s
.RS 3
With
.B -s,
nwfstime sets the file server's date and time according to the local
date and time.
.RE

Some files were not shown because too many files have changed in this diff Show More