Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
64f006632a | ||
|
|
92f749a943 | ||
|
|
6cb56005ea | ||
|
|
0520c1d2f7 |
BIN
.downloads/ncpfs-0.19.tgz
Normal file
BIN
.downloads/ncpfs-0.19.tgz
Normal file
Binary file not shown.
BIN
.downloads/ncpfs-0.20.tgz
Normal file
BIN
.downloads/ncpfs-0.20.tgz
Normal file
Binary file not shown.
BIN
.downloads/ncpfs-0.21.tgz
Normal file
BIN
.downloads/ncpfs-0.21.tgz
Normal file
Binary file not shown.
BIN
.downloads/ncpfs-0.22.tgz
Normal file
BIN
.downloads/ncpfs-0.22.tgz
Normal file
Binary file not shown.
40
Changes
40
Changes
@@ -1,5 +1,43 @@
|
|||||||
I only began this file with ncpfs-0.12. If you're interested in older
|
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-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
|
ncpfs-0.17 -> ncpfs-0.18
|
||||||
|
|
||||||
|
|||||||
12
FAQ
12
FAQ
@@ -4,6 +4,18 @@ enough.
|
|||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
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: Does ncpfs support long file names, using the OS/2 namespace?
|
Q: Does ncpfs support long file names, using the OS/2 namespace?
|
||||||
|
|
||||||
No. Not yet. I still have to sort out how that really works. But it should
|
No. Not yet. I still have to sort out how that really works. But it should
|
||||||
|
|||||||
35
Makefile
35
Makefile
@@ -2,31 +2,29 @@
|
|||||||
# Makefile for the linux ncp-filesystem routines.
|
# Makefile for the linux ncp-filesystem routines.
|
||||||
#
|
#
|
||||||
|
|
||||||
VERSION = 0.18
|
VERSION = 0.22
|
||||||
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
|
|
||||||
|
|
||||||
# If you are using kerneld to autoload ncp support,
|
# If you are using kerneld to autoload ncp support,
|
||||||
# uncomment this (kerneld is in linux since about 1.3.57):
|
# uncomment this (kerneld is in linux since about 1.3.57):
|
||||||
#KERNELD = -DHAVE_KERNELD
|
#KERNELD = -DHAVE_KERNELD
|
||||||
|
|
||||||
|
TOPDIR = $(shell pwd)
|
||||||
|
BINDIR = /usr/local/bin
|
||||||
|
SBINDIR = /sbin
|
||||||
|
INTERM_BINDIR = $(TOPDIR)/bin
|
||||||
|
SUBDIRS = util ipx-1.0 man
|
||||||
|
|
||||||
|
KVERSION=$(shell uname -r | cut -b3)
|
||||||
|
|
||||||
|
ifeq ($(KVERSION),2)
|
||||||
|
SUBDIRS += kernel-1.2/src
|
||||||
|
INCLUDES = -I$(TOPDIR)/kernel-1.2
|
||||||
|
endif
|
||||||
|
|
||||||
export INCLUDES BINDIR INTERM_BINDIR SBINDIR KERNELD VERSION
|
export INCLUDES BINDIR INTERM_BINDIR SBINDIR KERNELD VERSION
|
||||||
|
|
||||||
all:
|
all:
|
||||||
for i in $(SUBDIRS); do make -C $$i; done
|
for i in $(SUBDIRS); do make -C $$i all; done
|
||||||
|
|
||||||
dep:
|
dep:
|
||||||
for i in $(SUBDIRS); do make -C $$i dep; done
|
for i in $(SUBDIRS); do make -C $$i dep; done
|
||||||
@@ -43,7 +41,8 @@ clean:
|
|||||||
|
|
||||||
mrproper: clean
|
mrproper: clean
|
||||||
rm -fr $(INTERM_BINDIR)/* ncpfs.tgz
|
rm -fr $(INTERM_BINDIR)/* ncpfs.tgz
|
||||||
make -C util realclean
|
make -C util mrproper
|
||||||
|
(cd ncpd; make clean)
|
||||||
|
|
||||||
modules: ncpfs.o
|
modules: ncpfs.o
|
||||||
|
|
||||||
|
|||||||
25
README
25
README
@@ -22,21 +22,26 @@ asks for ncpfs. After you have rebooted with the new kernel, 'cat
|
|||||||
/proc/filesystems' should show you a line saying that the kernel knows
|
/proc/filesystems' should show you a line saying that the kernel knows
|
||||||
ncpfs.
|
ncpfs.
|
||||||
|
|
||||||
With Kernel 1.3.71 or later you also have to modify the Makefile in the
|
If you are running kerneld, please uncomment the corresponding line in
|
||||||
directory you found this README in. Please see the Makefile for the
|
the Makefile to reflect this.
|
||||||
necessary modifications. Then typing 'make' should work with no
|
|
||||||
problem.
|
|
||||||
|
|
||||||
|
|
||||||
HELP
|
HELP
|
||||||
|
|
||||||
To get more help you can subscribe to the LinWare mailing list:
|
|
||||||
control addr: listserv@sh.cvut.cz
|
|
||||||
posting addr: linware@sh.cvut.cz
|
|
||||||
|
|
||||||
In the meantime my mail volume has grown considerably, so the response
|
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
|
time might be better at the LinWare mailing list than at my personal
|
||||||
email address.
|
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
|
USING NCPFS
|
||||||
|
|||||||
20
TODO
Normal file
20
TODO
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
Here's a list of things I want to do. Feel free to send suggestions,
|
||||||
|
or even help me ;-).
|
||||||
|
|
||||||
|
- little utilities for bindery access, such as nwlsobj, nwlsprop,
|
||||||
|
nwcreateobj and so on.
|
||||||
|
|
||||||
|
- Add flags to pserver's command line, so that the print command can
|
||||||
|
find out the name of user who printed the job.
|
||||||
|
|
||||||
|
- do rtt estimation, like tcp does.
|
||||||
|
|
||||||
|
- Do better connection management. I imagine to create a ncpd.
|
||||||
|
|
||||||
|
- When ncp is done, one can think about mounting several volumes over
|
||||||
|
a single NCP connection. This should make the trade-off mentioned in
|
||||||
|
ncpmount.8 unnecessary.
|
||||||
|
|
||||||
|
- long file names
|
||||||
|
|
||||||
|
- Do some kind of mapping of NCP uid's to unix uid's
|
||||||
BIN
ipxdump/ipxdump
Executable file
BIN
ipxdump/ipxdump
Executable file
Binary file not shown.
@@ -60,7 +60,7 @@ struct ipx_packet
|
|||||||
|
|
||||||
|
|
||||||
void handle_frame (unsigned char *buf, int length, struct sockaddr *saddr);
|
void handle_frame (unsigned char *buf, int length, struct sockaddr *saddr);
|
||||||
void handle_ipx (unsigned char *buf);
|
void handle_ipx(char *frame, unsigned char *buf);
|
||||||
|
|
||||||
static int filter = 0;
|
static int filter = 0;
|
||||||
static IPXNode filter_node;
|
static IPXNode filter_node;
|
||||||
@@ -147,7 +147,7 @@ main (int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
handle_ipx (unsigned char *buf)
|
handle_ipx (char *frame, unsigned char *buf)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct ipx_packet *h = (struct ipx_packet *)buf;
|
struct ipx_packet *h = (struct ipx_packet *)buf;
|
||||||
@@ -179,6 +179,8 @@ handle_ipx (unsigned char *buf)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printf("%s ", frame);
|
||||||
|
|
||||||
for (i = 0; i < length; i++)
|
for (i = 0; i < length; i++)
|
||||||
{
|
{
|
||||||
printf("%2.2X", buf[i]);
|
printf("%2.2X", buf[i]);
|
||||||
@@ -207,23 +209,20 @@ handle_other (unsigned char *buf, int length, struct sockaddr *saddr)
|
|||||||
|
|
||||||
if (*(unsigned short *)p == 0xffff)
|
if (*(unsigned short *)p == 0xffff)
|
||||||
{
|
{
|
||||||
printf("802.3 ");
|
handle_ipx("802.3", p);
|
||||||
handle_ipx(p);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( (*(unsigned short *)p == htons(0xe0e0))
|
if ( (*(unsigned short *)p == htons(0xe0e0))
|
||||||
&& (p[2] == 0x03))
|
&& (p[2] == 0x03))
|
||||||
{
|
{
|
||||||
printf("802.2 ");
|
handle_ipx("802.2", p+3);
|
||||||
handle_ipx(p+3);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (memcmp(p, "\252\252\003\000\000\000\201\067", 8) == 0)
|
if (memcmp(p, "\252\252\003\000\000\000\201\067", 8) == 0)
|
||||||
{
|
{
|
||||||
printf("snap ");
|
handle_ipx("snap", p+8);
|
||||||
handle_ipx(p+8);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -237,8 +236,7 @@ handle_frame (unsigned char *buf, int length, struct sockaddr *saddr)
|
|||||||
switch( packet_type )
|
switch( packet_type )
|
||||||
{
|
{
|
||||||
case __constant_ntohs(ETH_P_IPX):
|
case __constant_ntohs(ETH_P_IPX):
|
||||||
printf("EtherII ");
|
handle_ipx("EtherII", &(buf[sizeof(struct ethhdr)]));
|
||||||
handle_ipx(&(buf[sizeof(struct ethhdr)]));
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
handle_other(buf, length, saddr);
|
handle_other(buf, length, saddr);
|
||||||
|
|||||||
BIN
ipxdump/ipxparse
Executable file
BIN
ipxdump/ipxparse
Executable file
Binary file not shown.
@@ -35,6 +35,8 @@
|
|||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include "ipxutil.h"
|
#include "ipxutil.h"
|
||||||
|
|
||||||
|
#define DUMPALLSAPS /* #define if you want to dump all SAP's */
|
||||||
|
|
||||||
struct ipx_address
|
struct ipx_address
|
||||||
{
|
{
|
||||||
unsigned long net;
|
unsigned long net;
|
||||||
@@ -92,12 +94,58 @@ void handle_ncp (struct sockaddr_ipx *source,
|
|||||||
struct sockaddr_ipx *target,
|
struct sockaddr_ipx *target,
|
||||||
unsigned char *buf, int length, int no);
|
unsigned char *buf, int length, int no);
|
||||||
|
|
||||||
|
#define SAP_MAX_SERVER_NAME_LENGTH 48 /* in network packets */
|
||||||
|
#define SAP_MAX_SAPS_PER_PACKET 7
|
||||||
|
#define SAP_SHUTDOWN 16 /* Magic "hops" value to stop SAP advertising */
|
||||||
|
|
||||||
|
/* SAP Query structure (returned in sap_packet as an array)
|
||||||
|
* NBO == Network Byte Order)
|
||||||
|
*/
|
||||||
|
typedef struct saps {
|
||||||
|
__u16 serverType __attribute__ ((packed)); /* NBO */
|
||||||
|
__u8 serverName[SAP_MAX_SERVER_NAME_LENGTH] __attribute__ ((packed));
|
||||||
|
struct ipx_address serverAddress __attribute__ ((packed));
|
||||||
|
__u16 serverHops __attribute__ ((packed)); /* NBO */
|
||||||
|
} SAPS;
|
||||||
|
|
||||||
|
/* General Service/Nearest Server Response SAP packet */
|
||||||
|
union sap_packet {
|
||||||
|
unsigned short sapOperation;
|
||||||
|
struct sap_query {
|
||||||
|
__u16 sapOperation __attribute__ ((packed));
|
||||||
|
__u16 serverType __attribute__ ((packed));
|
||||||
|
} query;
|
||||||
|
struct sap_response {
|
||||||
|
__u16 sapOperation __attribute__ ((packed));
|
||||||
|
/* each SAP can has a max of SAP_MAX_SAPS_PER_PACKET packets */
|
||||||
|
SAPS sap[SAP_MAX_SAPS_PER_PACKET] __attribute__ ((packed));
|
||||||
|
} response;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* print out one SAP record */
|
||||||
|
static void
|
||||||
|
print_sap(FILE *file, SAPS *sapp)
|
||||||
|
{
|
||||||
|
fprintf(file, " Name:%s, serverType 0x%x, ",
|
||||||
|
sapp->serverName,
|
||||||
|
ntohs(sapp->serverType));
|
||||||
|
ipx_fprint_network(file, ntohl(sapp->serverAddress.net));
|
||||||
|
fprintf(file, ":");
|
||||||
|
ipx_fprint_node(file, sapp->serverAddress.node);
|
||||||
|
fprintf(file, ":");
|
||||||
|
ipx_fprint_port(file, ntohs(sapp->serverAddress.sock));
|
||||||
|
fprintf(file, " (Hops %d)\n", ntohs(sapp->serverHops));
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
handle_ipx (unsigned char *buf, int length, char *frame, int no)
|
handle_ipx (unsigned char *buf, int length, char *frame, int no)
|
||||||
{
|
{
|
||||||
struct ipx_packet *h = (struct ipx_packet *)buf;
|
struct ipx_packet *h = (struct ipx_packet *)buf;
|
||||||
struct sockaddr_ipx s_addr;
|
struct sockaddr_ipx s_addr;
|
||||||
struct sockaddr_ipx d_addr;
|
struct sockaddr_ipx d_addr;
|
||||||
|
union sap_packet *sappacket;
|
||||||
|
int hbo_dsock; /* Host Byte Order of Destination SOCKet */
|
||||||
|
int hbo_sapop; /* Host Byte Order of SAP OPeration */
|
||||||
|
|
||||||
memset(&s_addr, 0, sizeof(s_addr));
|
memset(&s_addr, 0, sizeof(s_addr));
|
||||||
memset(&d_addr, 0, sizeof(d_addr));
|
memset(&d_addr, 0, sizeof(d_addr));
|
||||||
@@ -123,6 +171,86 @@ handle_ipx (unsigned char *buf, int length, char *frame, int no)
|
|||||||
handle_ncp(&s_addr, &d_addr, buf + sizeof(struct ipx_packet),
|
handle_ncp(&s_addr, &d_addr, buf + sizeof(struct ipx_packet),
|
||||||
length - sizeof(struct ipx_packet), no);
|
length - sizeof(struct ipx_packet), no);
|
||||||
}
|
}
|
||||||
|
else /* next 3 handle IPX by type vs by socket (one or other) */
|
||||||
|
/* Note: most things use either ipx_type OR socket, not both */
|
||||||
|
if (h->ipx_type == 0x01)
|
||||||
|
printf(" type 0x01 (RIP packet (router))\n");
|
||||||
|
else
|
||||||
|
if (h->ipx_type == 0x05)
|
||||||
|
printf(" type 0x05 (SPX sequenced packet)\n");
|
||||||
|
else
|
||||||
|
if (h->ipx_type == 0x14)
|
||||||
|
printf(" type 0x14 (propogated Client-NetBios)\n");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hbo_dsock = ntohs(d_addr.sipx_port);
|
||||||
|
if (hbo_dsock == 0x452) /* SAP */
|
||||||
|
{
|
||||||
|
sappacket = (union sap_packet *)
|
||||||
|
(buf + sizeof(struct ipx_packet));
|
||||||
|
hbo_sapop = ntohs(sappacket->sapOperation);
|
||||||
|
if ((hbo_sapop == 0x01) || (hbo_sapop == 0x03))
|
||||||
|
{
|
||||||
|
printf(" type 0x%x, SAP op:0x%x %s Query, "
|
||||||
|
"serverType 0x%x wanted\n",
|
||||||
|
h->ipx_type, hbo_sapop,
|
||||||
|
(hbo_sapop == 0x01)?"General Service" :
|
||||||
|
(hbo_sapop == 0x03)?"Nearest Server" :
|
||||||
|
"Error",
|
||||||
|
ntohs(sappacket->query.serverType));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int hops;
|
||||||
|
|
||||||
|
hops = ntohs(sappacket->
|
||||||
|
response.sap[0].serverHops);
|
||||||
|
printf(" type 0x%x, SAP op:0x%x %s %s\n",
|
||||||
|
h->ipx_type, hbo_sapop,
|
||||||
|
(hbo_sapop == 0x02)
|
||||||
|
? "General Service Response" :
|
||||||
|
(hbo_sapop == 0x04)
|
||||||
|
? "Nearest Server Response" :
|
||||||
|
"Unknown",
|
||||||
|
(hops >= SAP_SHUTDOWN)
|
||||||
|
? "[Shutdown]" : "");
|
||||||
|
|
||||||
|
/* Service ending */
|
||||||
|
if (hops >= SAP_SHUTDOWN)
|
||||||
|
{
|
||||||
|
print_sap(stdout,
|
||||||
|
sappacket->response.sap);
|
||||||
|
}
|
||||||
|
#ifdef DUMPALLSAPS
|
||||||
|
/* If you want to dump all SAP's */
|
||||||
|
else
|
||||||
|
{ int num_saps;
|
||||||
|
SAPS *sapp;
|
||||||
|
|
||||||
|
num_saps = (length
|
||||||
|
- sizeof(struct ipx_packet)
|
||||||
|
- 2) / sizeof(SAPS);
|
||||||
|
|
||||||
|
sapp = sappacket->response.sap;
|
||||||
|
for(; num_saps > 0; sapp++, num_saps--)
|
||||||
|
print_sap(stdout, sapp);
|
||||||
|
}
|
||||||
|
#endif /* DUMPALLSAPS */
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else /* Other IPX types */
|
||||||
|
printf(" type 0x%x, Socket 0x%x (%s)\n", h->ipx_type,
|
||||||
|
hbo_dsock,
|
||||||
|
(hbo_dsock == 0x451) ? "NCP" :
|
||||||
|
/* (hbo_dsock == 0x452) ? "SAP" :*/
|
||||||
|
(hbo_dsock == 0x453) ? "RIP" :
|
||||||
|
(hbo_dsock == 0x455) ? "Client-NetBios" :
|
||||||
|
(hbo_dsock == 0x456) ? "Diags" :
|
||||||
|
(hbo_dsock == 0x002) ? "Xecho" :
|
||||||
|
(hbo_dsock == 0x8063) ? "NVT2" : "Other");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void handle_ncp (struct sockaddr_ipx *source,
|
void handle_ncp (struct sockaddr_ipx *source,
|
||||||
@@ -147,6 +275,124 @@ void handle_ncp (struct sockaddr_ipx *source,
|
|||||||
|
|
||||||
switch(rq->function)
|
switch(rq->function)
|
||||||
{
|
{
|
||||||
|
case 20:
|
||||||
|
printf("fn: %-3d\n", rq->function);
|
||||||
|
printf("Get File Server Date and Time\n");
|
||||||
|
break;
|
||||||
|
case 21:
|
||||||
|
printf("fn: %-3d, subfn: %-3d\n",
|
||||||
|
rq->function, data[2]);
|
||||||
|
switch(data[2])
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
printf("Send Broadcast Message\n");
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
printf("Get Broadcast Message\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
data += 3;
|
||||||
|
data_length -= 3;
|
||||||
|
break;
|
||||||
|
case 22:
|
||||||
|
printf("fn: %-3d, subfn: %-3d\n",
|
||||||
|
rq->function, data[2]);
|
||||||
|
switch(data[2])
|
||||||
|
{
|
||||||
|
case 00:
|
||||||
|
printf("Set Directory Handle\n");
|
||||||
|
break;
|
||||||
|
case 01:
|
||||||
|
printf("Get Directory Path\n");
|
||||||
|
break;
|
||||||
|
case 18:
|
||||||
|
printf("Allocate Permanent Dir Handle\n");
|
||||||
|
break;
|
||||||
|
case 20:
|
||||||
|
printf("Deallocate Directory Handle\n");
|
||||||
|
break;
|
||||||
|
case 21:
|
||||||
|
printf("Get Volume Info with handle\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
data += 3;
|
||||||
|
data_length -= 3;
|
||||||
|
break;
|
||||||
|
case 23:
|
||||||
|
printf("fn: %-3d, subfn: %-3d\n", rq->function,
|
||||||
|
data[2]);
|
||||||
|
switch(data[2])
|
||||||
|
{
|
||||||
|
case 17:
|
||||||
|
printf("Get Fileserver Information\n");
|
||||||
|
break;
|
||||||
|
case 23:
|
||||||
|
printf("Get Crypt Key\n");
|
||||||
|
break;
|
||||||
|
case 24:
|
||||||
|
printf("Encrypted Login\n");
|
||||||
|
break;
|
||||||
|
case 28:
|
||||||
|
printf("Get Connection Information\n");
|
||||||
|
break;
|
||||||
|
case 53:
|
||||||
|
printf("Get Bindery Object ID\n");
|
||||||
|
break;
|
||||||
|
case 55:
|
||||||
|
printf("Scan Bindery Object\n");
|
||||||
|
break;
|
||||||
|
case 61:
|
||||||
|
printf("Read Property Value\n");
|
||||||
|
break;
|
||||||
|
case 62:
|
||||||
|
printf("Write Property Value\n");
|
||||||
|
break;
|
||||||
|
case 70:
|
||||||
|
printf("Get Bindery Access Level\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
data += 3;
|
||||||
|
data_length -= 3;
|
||||||
|
break;
|
||||||
|
case 24:
|
||||||
|
printf("fn: %-3d\n", rq->function);
|
||||||
|
printf("End of Job\n");
|
||||||
|
break;
|
||||||
|
case 34:
|
||||||
|
printf("fn: %-3d, subfn: %-3d\n", rq->function,
|
||||||
|
data[2]);
|
||||||
|
data += 3;
|
||||||
|
data_length -= 3;
|
||||||
|
break;
|
||||||
|
case 62:
|
||||||
|
printf("fn: %-3d\n", rq->function);
|
||||||
|
printf("File Search Initialize\n");
|
||||||
|
break;
|
||||||
|
case 63:
|
||||||
|
printf("fn: %-3d\n", rq->function);
|
||||||
|
printf("File Search Continue\n");
|
||||||
|
break;
|
||||||
|
case 64:
|
||||||
|
printf("fn: %-3d\n", rq->function);
|
||||||
|
printf("Search for a file\n");
|
||||||
|
break;
|
||||||
|
case 66:
|
||||||
|
printf("fn: %-3d\n", rq->function);
|
||||||
|
printf("Close File\n");
|
||||||
|
break;
|
||||||
|
case 72:
|
||||||
|
printf("fn: %-3d\n", rq->function);
|
||||||
|
printf("Read from File\n");
|
||||||
|
break;
|
||||||
|
case 73:
|
||||||
|
printf("fn: %-3d\n", rq->function);
|
||||||
|
printf("Write to File\n");
|
||||||
|
break;
|
||||||
|
case 75:
|
||||||
|
printf("fn: %-3d\n", rq->function);
|
||||||
|
printf("Set File Time Date Stamp\n");
|
||||||
|
break;
|
||||||
case 87:
|
case 87:
|
||||||
printf("fn: %-3d, subfn: %-3d\n",
|
printf("fn: %-3d, subfn: %-3d\n",
|
||||||
rq->function, data[0]);
|
rq->function, data[0]);
|
||||||
@@ -183,58 +429,6 @@ void handle_ncp (struct sockaddr_ipx *source,
|
|||||||
data += 1;
|
data += 1;
|
||||||
data_length -= 1;
|
data_length -= 1;
|
||||||
break;
|
break;
|
||||||
case 22:
|
|
||||||
printf("fn: %-3d, subfn: %-3d\n",
|
|
||||||
rq->function, data[2]);
|
|
||||||
switch(data[2])
|
|
||||||
{
|
|
||||||
case 21:
|
|
||||||
printf("Get Volume Info with handle\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
data += 3;
|
|
||||||
data_length -= 3;
|
|
||||||
break;
|
|
||||||
case 23:
|
|
||||||
printf("fn: %-3d, subfn: %-3d\n", rq->function,
|
|
||||||
data[2]);
|
|
||||||
data += 3;
|
|
||||||
data_length -= 3;
|
|
||||||
break;
|
|
||||||
case 24:
|
|
||||||
printf("fn: %-3d\n", rq->function);
|
|
||||||
printf("End of Job\n");
|
|
||||||
break;
|
|
||||||
case 34:
|
|
||||||
printf("fn: %-3d, subfn: %-3d\n", rq->function,
|
|
||||||
data[2]);
|
|
||||||
data += 3;
|
|
||||||
data_length -= 3;
|
|
||||||
break;
|
|
||||||
case 62:
|
|
||||||
printf("fn: %-3d\n", rq->function);
|
|
||||||
printf("File Search Initialize\n");
|
|
||||||
break;
|
|
||||||
case 63:
|
|
||||||
printf("fn: %-3d\n", rq->function);
|
|
||||||
printf("File Search Continue\n");
|
|
||||||
break;
|
|
||||||
case 64:
|
|
||||||
printf("fn: %-3d\n", rq->function);
|
|
||||||
printf("Search for a file\n");
|
|
||||||
break;
|
|
||||||
case 66:
|
|
||||||
printf("fn: %-3d\n", rq->function);
|
|
||||||
printf("Close File\n");
|
|
||||||
break;
|
|
||||||
case 73:
|
|
||||||
printf("fn: %-3d\n", rq->function);
|
|
||||||
printf("Write to File\n");
|
|
||||||
break;
|
|
||||||
case 75:
|
|
||||||
printf("fn: %-3d\n", rq->function);
|
|
||||||
printf("Set File Time Date Stamp\n");
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
printf("fn: %-3d\n", rq->function);
|
printf("fn: %-3d\n", rq->function);
|
||||||
}
|
}
|
||||||
@@ -342,4 +536,3 @@ main (int argc, char *argv[])
|
|||||||
|
|
||||||
exit (0);
|
exit (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,18 +34,16 @@ struct ncp_fs_info {
|
|||||||
int buffer_size; /* The negotiated buffer size, to be
|
int buffer_size; /* The negotiated buffer size, to be
|
||||||
used for read/write requests! */
|
used for read/write requests! */
|
||||||
|
|
||||||
/* Not used yet, but here some day the namespace numbers will be
|
|
||||||
stored. */
|
|
||||||
int volume_number;
|
int volume_number;
|
||||||
__u32 directory_id;
|
__u32 directory_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define NCP_IOC_NCPREQUEST _IOR('n', 1, unsigned char *)
|
#define NCP_IOC_NCPREQUEST _IOR('n', 1, struct ncp_ioctl_request)
|
||||||
#define NCP_IOC_GETMOUNTUID _IOR('u', 1, uid_t)
|
#define NCP_IOC_GETMOUNTUID _IOW('n', 2, uid_t)
|
||||||
#define NCP_IOC_CONN_LOGGED_IN _IO('l', 1)
|
#define NCP_IOC_CONN_LOGGED_IN _IO('n', 3)
|
||||||
|
|
||||||
#define NCP_GET_FS_INFO_VERSION (1)
|
#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.
|
* The packet size to allocate. One page should be enough.
|
||||||
@@ -63,7 +61,7 @@ struct ncp_fs_info {
|
|||||||
#define NCP_READDIR_CACHE_SIZE 64
|
#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 :-) */
|
/* Guess, what 0x564c is :-) */
|
||||||
#define NCP_SUPER_MAGIC 0x564c
|
#define NCP_SUPER_MAGIC 0x564c
|
||||||
|
|||||||
@@ -200,12 +200,30 @@ static int c_size;
|
|||||||
static int c_seen_eof;
|
static int c_seen_eof;
|
||||||
static int c_last_returned_index;
|
static int c_last_returned_index;
|
||||||
static struct ncp_dirent* c_entry = NULL;
|
static struct ncp_dirent* c_entry = NULL;
|
||||||
|
static int c_lock = 0;
|
||||||
|
static struct wait_queue *c_wait = NULL;
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
ncp_lock_dircache(void)
|
||||||
|
{
|
||||||
|
while (c_lock)
|
||||||
|
sleep_on(&c_wait);
|
||||||
|
c_lock = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
ncp_unlock_dircache(void)
|
||||||
|
{
|
||||||
|
c_lock = 0;
|
||||||
|
wake_up(&c_wait);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
ncp_readdir(struct inode *inode, struct file *filp,
|
ncp_readdir(struct inode *inode, struct file *filp,
|
||||||
struct dirent *dirent, int count)
|
struct dirent *dirent, int count)
|
||||||
{
|
{
|
||||||
int result, i = 0;
|
int result = 0;
|
||||||
|
int i = 0;
|
||||||
int index = 0;
|
int index = 0;
|
||||||
struct ncp_dirent *entry = NULL;
|
struct ncp_dirent *entry = NULL;
|
||||||
struct ncp_server *server = NCP_SERVER(inode);
|
struct ncp_server *server = NCP_SERVER(inode);
|
||||||
@@ -238,6 +256,7 @@ ncp_readdir(struct inode *inode, struct file *filp,
|
|||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ncp_lock_dircache();
|
||||||
if (c_entry == NULL)
|
if (c_entry == NULL)
|
||||||
{
|
{
|
||||||
i = sizeof (struct ncp_dirent) * NCP_READDIR_CACHE_SIZE;
|
i = sizeof (struct ncp_dirent) * NCP_READDIR_CACHE_SIZE;
|
||||||
@@ -245,7 +264,8 @@ ncp_readdir(struct inode *inode, struct file *filp,
|
|||||||
if (c_entry == NULL)
|
if (c_entry == NULL)
|
||||||
{
|
{
|
||||||
printk("ncp_readdir: no MEMORY for cache\n");
|
printk("ncp_readdir: no MEMORY for cache\n");
|
||||||
return -ENOMEM;
|
result = -ENOMEM;
|
||||||
|
goto finished;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -255,10 +275,11 @@ ncp_readdir(struct inode *inode, struct file *filp,
|
|||||||
if (filldir(dirent,".",1, filp->f_pos,
|
if (filldir(dirent,".",1, filp->f_pos,
|
||||||
ncp_info_ino(server, dir)) < 0)
|
ncp_info_ino(server, dir)) < 0)
|
||||||
{
|
{
|
||||||
return 0;
|
goto finished;
|
||||||
}
|
}
|
||||||
filp->f_pos += 1;
|
filp->f_pos += 1;
|
||||||
return ROUND_UP(NAME_OFFSET(dirent)+i+1);
|
result = ROUND_UP(NAME_OFFSET(dirent)+i+1);
|
||||||
|
goto finished;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filp->f_pos == 1)
|
if (filp->f_pos == 1)
|
||||||
@@ -266,10 +287,11 @@ ncp_readdir(struct inode *inode, struct file *filp,
|
|||||||
if (filldir(dirent,"..",2, filp->f_pos,
|
if (filldir(dirent,"..",2, filp->f_pos,
|
||||||
ncp_info_ino(server, dir->dir)) < 0)
|
ncp_info_ino(server, dir->dir)) < 0)
|
||||||
{
|
{
|
||||||
return 0;
|
goto finished;
|
||||||
}
|
}
|
||||||
filp->f_pos += 1;
|
filp->f_pos += 1;
|
||||||
return ROUND_UP(NAME_OFFSET(dirent)+i+1);
|
result = ROUND_UP(NAME_OFFSET(dirent)+i+1);
|
||||||
|
goto finished;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((inode->i_dev == c_dev) && (inode->i_ino == c_ino))
|
if ((inode->i_dev == c_dev) && (inode->i_ino == c_ino))
|
||||||
@@ -286,42 +308,44 @@ ncp_readdir(struct inode *inode, struct file *filp,
|
|||||||
}
|
}
|
||||||
if ((entry == NULL) && c_seen_eof)
|
if ((entry == NULL) && c_seen_eof)
|
||||||
{
|
{
|
||||||
return 0;
|
goto finished;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entry == NULL)
|
if (entry == NULL)
|
||||||
{
|
{
|
||||||
|
int entries;
|
||||||
DDPRINTK("ncp_readdir: Not found in cache.\n");
|
DDPRINTK("ncp_readdir: Not found in cache.\n");
|
||||||
|
|
||||||
if (ncp_is_server_root(inode))
|
if (ncp_is_server_root(inode))
|
||||||
{
|
{
|
||||||
result = ncp_read_volume_list(server, filp->f_pos,
|
entries = ncp_read_volume_list(server, filp->f_pos,
|
||||||
NCP_READDIR_CACHE_SIZE);
|
NCP_READDIR_CACHE_SIZE);
|
||||||
DPRINTK("ncp_read_volume_list returned %d\n", result);
|
DPRINTK("ncp_read_volume_list returned %d\n", entries);
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result = ncp_do_readdir(server, inode, filp->f_pos,
|
entries = ncp_do_readdir(server, inode, filp->f_pos,
|
||||||
NCP_READDIR_CACHE_SIZE,
|
NCP_READDIR_CACHE_SIZE,
|
||||||
c_entry);
|
c_entry);
|
||||||
DPRINTK("ncp_readdir returned %d\n", result);
|
DPRINTK("ncp_readdir returned %d\n", entries);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result < 0)
|
if (entries < 0)
|
||||||
{
|
{
|
||||||
c_dev = 0;
|
c_dev = 0;
|
||||||
c_ino = 0;
|
c_ino = 0;
|
||||||
return result;
|
result = entries;
|
||||||
|
goto finished;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result > 0)
|
if (entries > 0)
|
||||||
{
|
{
|
||||||
c_seen_eof = (result < NCP_READDIR_CACHE_SIZE);
|
c_seen_eof = (entries < NCP_READDIR_CACHE_SIZE);
|
||||||
c_dev = inode->i_dev;
|
c_dev = inode->i_dev;
|
||||||
c_ino = inode->i_ino;
|
c_ino = inode->i_ino;
|
||||||
c_size = result;
|
c_size = entries;
|
||||||
entry = c_entry;
|
entry = c_entry;
|
||||||
c_last_returned_index = 0;
|
c_last_returned_index = 0;
|
||||||
index = 0;
|
index = 0;
|
||||||
@@ -336,7 +360,7 @@ ncp_readdir(struct inode *inode, struct file *filp,
|
|||||||
if (entry == NULL)
|
if (entry == NULL)
|
||||||
{
|
{
|
||||||
/* Nothing found, even from a ncp call */
|
/* Nothing found, even from a ncp call */
|
||||||
return 0;
|
goto finished;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (index < c_size)
|
if (index < c_size)
|
||||||
@@ -374,15 +398,18 @@ ncp_readdir(struct inode *inode, struct file *filp,
|
|||||||
if (filldir(dirent, entry->i.entryName, entry->i.nameLen,
|
if (filldir(dirent, entry->i.entryName, entry->i.nameLen,
|
||||||
entry->f_pos, ino) < 0)
|
entry->f_pos, ino) < 0)
|
||||||
{
|
{
|
||||||
return 0;
|
goto finished;
|
||||||
}
|
}
|
||||||
|
|
||||||
filp->f_pos += 1;
|
filp->f_pos += 1;
|
||||||
index += 1;
|
index += 1;
|
||||||
entry += 1;
|
entry += 1;
|
||||||
return ROUND_UP(NAME_OFFSET(dirent)+i+1);
|
result = ROUND_UP(NAME_OFFSET(dirent)+i+1);
|
||||||
|
goto finished;
|
||||||
}
|
}
|
||||||
return 0;
|
finished:
|
||||||
|
ncp_unlock_dircache();
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@@ -407,7 +434,7 @@ ncp_read_volume_list(struct ncp_server *server, int fpos, int cache_size)
|
|||||||
|
|
||||||
if (ncp_get_volume_info_with_number(server, i, &info) != 0)
|
if (ncp_get_volume_info_with_number(server, i, &info) != 0)
|
||||||
{
|
{
|
||||||
return total_count;
|
return (total_count - fpos);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strlen(info.volume_name) > 0)
|
if (strlen(info.volume_name) > 0)
|
||||||
@@ -723,6 +750,11 @@ ncp_find_dir_inode(struct inode *dir, const char *name)
|
|||||||
if ( (result->dir->finfo.i.DosDirNum == dir_info->DosDirNum)
|
if ( (result->dir->finfo.i.DosDirNum == dir_info->DosDirNum)
|
||||||
&& (result->dir->finfo.i.volNumber == dir_info->volNumber)
|
&& (result->dir->finfo.i.volNumber == dir_info->volNumber)
|
||||||
&& (strcmp(result->finfo.i.entryName, name) == 0)
|
&& (strcmp(result->finfo.i.entryName, name) == 0)
|
||||||
|
/* The root dir is never looked up using this
|
||||||
|
* routine. Without the following test a root
|
||||||
|
* directory 'sys' in a volume named 'sys' could
|
||||||
|
* never be looked up, because
|
||||||
|
* server->root->dir==server->root. */
|
||||||
&& (result != &(server->root)))
|
&& (result != &(server->root)))
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
@@ -824,6 +856,8 @@ ncp_lookup(struct inode *dir, const char *__name, int len,
|
|||||||
|
|
||||||
found_in_cache = 0;
|
found_in_cache = 0;
|
||||||
|
|
||||||
|
ncp_lock_dircache();
|
||||||
|
|
||||||
if ((dir->i_dev == c_dev) && (dir->i_ino == c_ino))
|
if ((dir->i_dev == c_dev) && (dir->i_ino == c_ino))
|
||||||
{
|
{
|
||||||
int first = c_last_returned_index;
|
int first = c_last_returned_index;
|
||||||
@@ -846,6 +880,7 @@ ncp_lookup(struct inode *dir, const char *__name, int len,
|
|||||||
}
|
}
|
||||||
while (i != first);
|
while (i != first);
|
||||||
}
|
}
|
||||||
|
ncp_unlock_dircache();
|
||||||
|
|
||||||
if (found_in_cache == 0)
|
if (found_in_cache == 0)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ ncp_read_inode(struct inode *inode)
|
|||||||
inode->i_nlink = 1;
|
inode->i_nlink = 1;
|
||||||
inode->i_uid = NCP_SERVER(inode)->m.uid;
|
inode->i_uid = NCP_SERVER(inode)->m.uid;
|
||||||
inode->i_gid = NCP_SERVER(inode)->m.gid;
|
inode->i_gid = NCP_SERVER(inode)->m.gid;
|
||||||
inode->i_blksize = 1024;
|
inode->i_blksize = 512;
|
||||||
inode->i_rdev = 0;
|
inode->i_rdev = 0;
|
||||||
|
|
||||||
if ((inode->i_blksize != 0) && (inode->i_size != 0))
|
if ((inode->i_blksize != 0) && (inode->i_size != 0))
|
||||||
|
|||||||
@@ -29,6 +29,26 @@ ncp_ioctl (struct inode * inode, struct file * filp,
|
|||||||
struct ncp_fs_info info;
|
struct ncp_fs_info info;
|
||||||
struct ncp_server *server = NCP_SERVER(inode);
|
struct ncp_server *server = NCP_SERVER(inode);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Binary compatible with 1.3.XX releases.
|
||||||
|
* Take this out in 2.1.0 development series.
|
||||||
|
* <mec@duracef.shout.net> 12 Mar 1996
|
||||||
|
*/
|
||||||
|
switch(cmd) {
|
||||||
|
case _IOR('n', 1, unsigned char *):
|
||||||
|
cmd = NCP_IOC_NCPREQUEST;
|
||||||
|
break;
|
||||||
|
case _IOR('u', 1, uid_t):
|
||||||
|
cmd = NCP_IOC_GETMOUNTUID;
|
||||||
|
break;
|
||||||
|
case _IO('l', 1):
|
||||||
|
cmd = NCP_IOC_CONN_LOGGED_IN;
|
||||||
|
break;
|
||||||
|
case _IOWR('i', 1, unsigned char *):
|
||||||
|
cmd = NCP_IOC_GET_FS_INFO;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
switch(cmd) {
|
switch(cmd) {
|
||||||
case NCP_IOC_NCPREQUEST:
|
case NCP_IOC_NCPREQUEST:
|
||||||
|
|
||||||
@@ -116,6 +136,8 @@ ncp_ioctl (struct inode * inode, struct file * filp,
|
|||||||
info.mounted_uid = server->m.mounted_uid;
|
info.mounted_uid = server->m.mounted_uid;
|
||||||
info.connection = server->connection;
|
info.connection = server->connection;
|
||||||
info.buffer_size = server->buffer_size;
|
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));
|
memcpy_tofs((struct ncp_fs_info *)arg, &info, sizeof(info));
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -222,6 +222,7 @@ do_ncp_rpc_call(struct ncp_server *server, int size)
|
|||||||
int timeout;
|
int timeout;
|
||||||
int retrans;
|
int retrans;
|
||||||
int major_timeout_seen;
|
int major_timeout_seen;
|
||||||
|
int acknowledge_seen;
|
||||||
int n;
|
int n;
|
||||||
int addrlen;
|
int addrlen;
|
||||||
unsigned long old_mask;
|
unsigned long old_mask;
|
||||||
@@ -243,7 +244,8 @@ do_ncp_rpc_call(struct ncp_server *server, int size)
|
|||||||
return -EBADF;
|
return -EBADF;
|
||||||
}
|
}
|
||||||
init_timeout = server->m.time_out;
|
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;
|
retrans = server->m.retry_count;
|
||||||
major_timeout_seen = 0;
|
major_timeout_seen = 0;
|
||||||
old_mask = current->blocked;
|
old_mask = current->blocked;
|
||||||
@@ -296,11 +298,14 @@ do_ncp_rpc_call(struct ncp_server *server, int size)
|
|||||||
{
|
{
|
||||||
if (timeout > max_timeout)
|
if (timeout > max_timeout)
|
||||||
{
|
{
|
||||||
/* JEJB/JSP 2/7/94
|
/* JEJB/JSP 2/7/94
|
||||||
* This is useful to see if the system is
|
* This is useful to see if the system is
|
||||||
* hanging */
|
* hanging */
|
||||||
printk("NCP max timeout reached\n");
|
if (acknowledge_seen == 0)
|
||||||
timeout = max_timeout;
|
{
|
||||||
|
printk("NCP max timeout reached\n");
|
||||||
|
}
|
||||||
|
timeout = max_timeout;
|
||||||
}
|
}
|
||||||
current->timeout = jiffies + timeout;
|
current->timeout = jiffies + timeout;
|
||||||
schedule();
|
schedule();
|
||||||
@@ -373,6 +378,9 @@ do_ncp_rpc_call(struct ncp_server *server, int size)
|
|||||||
sock->ops->recvfrom(sock, (void *)&reply,
|
sock->ops->recvfrom(sock, (void *)&reply,
|
||||||
sizeof(reply), 1, 0,
|
sizeof(reply), 1, 0,
|
||||||
NULL, &addrlen);
|
NULL, &addrlen);
|
||||||
|
n = 0;
|
||||||
|
timeout = max_timeout;
|
||||||
|
acknowledge_seen = 1;
|
||||||
goto re_select;
|
goto re_select;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
MAN1= slist nprint pqlist
|
MAN1= slist nprint pqlist nsend pserver ncopy
|
||||||
MAN5= nwclient
|
MAN5= nwclient
|
||||||
MAN8= ncpmount ncpumount ipx_configure ipx_interface ipx_internal_net ipx_route
|
MAN8= ncpmount ncpumount ipx_configure ipx_interface ipx_internal_net \
|
||||||
|
ipx_route nwmsg
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
96
man/ncopy.1
Normal file
96
man/ncopy.1
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
.\"
|
||||||
|
.\" Man page for the ncopy program
|
||||||
|
.\"
|
||||||
|
.TH NCOPY 1 17/03/1996 ncopy ncopy
|
||||||
|
.SH NAME
|
||||||
|
ncopy \- NetWare file copy
|
||||||
|
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B ncopy -V
|
||||||
|
|
||||||
|
.B ncopy
|
||||||
|
[
|
||||||
|
.B -vn
|
||||||
|
]
|
||||||
|
[
|
||||||
|
.B -s
|
||||||
|
.I amount
|
||||||
|
]
|
||||||
|
.B file destinationfile|directory
|
||||||
|
|
||||||
|
.B ncopy
|
||||||
|
[
|
||||||
|
.B -vn
|
||||||
|
]
|
||||||
|
[
|
||||||
|
.B -s
|
||||||
|
.I amount
|
||||||
|
]
|
||||||
|
.B file1
|
||||||
|
[
|
||||||
|
.B file2 ...
|
||||||
|
]
|
||||||
|
.B directory
|
||||||
|
|
||||||
|
.SH DESCRIPTION
|
||||||
|
With
|
||||||
|
.B ncopy
|
||||||
|
you can copy files to different locations on a single NetWare file
|
||||||
|
server without generating excess network traffic. The program uses
|
||||||
|
a NetWare function to do the copy rather than transferring the file
|
||||||
|
across the network for both the read and write.
|
||||||
|
|
||||||
|
If the last argument is a directory,
|
||||||
|
.B ncopy
|
||||||
|
will copy the source file(s) into the directory. If only two files
|
||||||
|
are given and the last argument is not a directory, it will copy the
|
||||||
|
source file to the destination file.
|
||||||
|
|
||||||
|
If the source and destination files are not on the same NetWare server
|
||||||
|
(or are not on NetWare servers at all),
|
||||||
|
.B ncopy
|
||||||
|
will do a normal file copy.
|
||||||
|
.SH OPTIONS
|
||||||
|
.B -V
|
||||||
|
.RS 3
|
||||||
|
Show version number and exit
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.B -v
|
||||||
|
.RS 3
|
||||||
|
Verbose copy. Will show current file and percentage completion.
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.B -n
|
||||||
|
.RS 3
|
||||||
|
Nice NetWare copy. Will sleep for a second between copying blocks on
|
||||||
|
the NetWare server. Gives other people a chance to do some work on
|
||||||
|
the NetWare server when you are copying large files. This has no
|
||||||
|
effect if you are not copying on a NetWare server.
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.B -s
|
||||||
|
.I amount
|
||||||
|
.RS 3
|
||||||
|
Nice time slice factor. Used in conjunction with the
|
||||||
|
.B -n
|
||||||
|
option, this specifies the number of 100K blocks to copy before sleeping.
|
||||||
|
Default is 10. (1 Megabyte)
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.SH BUGS
|
||||||
|
.B ncopy
|
||||||
|
cannot recurse into directories.
|
||||||
|
Does not work on NetWare volumes mounted with the
|
||||||
|
.I -V
|
||||||
|
option to
|
||||||
|
.B ncpmount.
|
||||||
|
|
||||||
|
.SH "SEE ALSO"
|
||||||
|
.B ncpmount(8), ncpumount(8)
|
||||||
|
|
||||||
|
.SH CREDITS
|
||||||
|
ncopy was written by Brian G. Reid (breid@tim.com) and
|
||||||
|
Tom C. Henderson (thenderson@tim.com).
|
||||||
|
Many thanks to Volker Lendecke (lendecke@namu01.gwdg.de) for the ncpfs
|
||||||
|
and ncplib which made ncopy possible.
|
||||||
108
man/nsend.1
Normal file
108
man/nsend.1
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
.TH NSEND 1 03/21/1996 nsend nsend
|
||||||
|
.SH NAME
|
||||||
|
nsend \- Send messages to users
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B nsend
|
||||||
|
[
|
||||||
|
.B -h
|
||||||
|
] [
|
||||||
|
.B -S
|
||||||
|
.I server
|
||||||
|
] [
|
||||||
|
.B -U
|
||||||
|
.I user name
|
||||||
|
] [
|
||||||
|
.B -P
|
||||||
|
.I password
|
||||||
|
|
|
||||||
|
.B -n
|
||||||
|
] [
|
||||||
|
.B -C
|
||||||
|
]
|
||||||
|
.I user message
|
||||||
|
|
||||||
|
.SH DESCRIPTION
|
||||||
|
With
|
||||||
|
.B nsend,
|
||||||
|
you can send messages to the user's workstations.
|
||||||
|
|
||||||
|
.B nsend
|
||||||
|
looks up the file
|
||||||
|
.I $HOME/.nwclient
|
||||||
|
to find a file server, a user name and possibly a password. See
|
||||||
|
nwclient(5) for more information. Please note that the access
|
||||||
|
permissions of .nwclient MUST be 600, for security reasons.
|
||||||
|
|
||||||
|
.SH OPTIONS
|
||||||
|
|
||||||
|
.B user
|
||||||
|
.RS 3
|
||||||
|
.B user
|
||||||
|
is the NetWare User-ID of the user to receive the message.
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.B message
|
||||||
|
.RS 3
|
||||||
|
.B message
|
||||||
|
is the message to be sent. Please note that this has to be a single
|
||||||
|
command line argument. If you want to send a message that contains
|
||||||
|
spaces, you have to quote them on the command line. For example, to
|
||||||
|
annoy your system administrator, you should try
|
||||||
|
|
||||||
|
nsend supervisor 'I know how this works!'
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.B -S
|
||||||
|
.I server
|
||||||
|
.RS 3
|
||||||
|
.B server
|
||||||
|
is the name of the server you want to use.
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.B -U
|
||||||
|
.I user name
|
||||||
|
.RS 3
|
||||||
|
If the user name your NetWare administrator gave to you differs
|
||||||
|
from your unix user-id, you should use
|
||||||
|
.B -U
|
||||||
|
to tell the server about you NetWare user name.
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.B -P
|
||||||
|
.I password
|
||||||
|
.RS 3
|
||||||
|
You may want to give the password required by the server on the
|
||||||
|
command line. You should be careful to use passwords in scripts.
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.B -n
|
||||||
|
.RS 3
|
||||||
|
.B -n
|
||||||
|
should be given to mount shares which do not require a password to log in.
|
||||||
|
|
||||||
|
If neither
|
||||||
|
.B -n
|
||||||
|
nor
|
||||||
|
.B -P
|
||||||
|
are given, nsend prompts for a password.
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.B -C
|
||||||
|
.RS 3
|
||||||
|
By default, passwords are converted to uppercase before they are sent
|
||||||
|
to the server, because most servers require this. You can turn off
|
||||||
|
this conversion by
|
||||||
|
.B -C.
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.SH BUGS
|
||||||
|
nsend only supports servers with up to 255 connections. I do not know
|
||||||
|
the NCP functions for larger servers. If anybody knows them, please
|
||||||
|
tell me!
|
||||||
|
|
||||||
|
.SH SEE ALSO
|
||||||
|
.B nwclient(5), nprint(1), slist(1), ncpmount(8), ncpumount(8)
|
||||||
|
|
||||||
|
.SH CREDITS
|
||||||
|
nsend was written by looking at mars_nwe's message handling. Thanks to
|
||||||
|
Martin Stover <mstover@freeway.de>
|
||||||
@@ -1,19 +1,19 @@
|
|||||||
Begin3
|
Begin3
|
||||||
Title: ncpfs
|
Title: ncpfs
|
||||||
Version: 0.18
|
Version: 0.22
|
||||||
Entered-date: 09. March 1996
|
Entered-date: 17. April 1996
|
||||||
Description: With ncpfs you can mount volumes of your netware
|
Description: With ncpfs you can mount volumes of your netware
|
||||||
server under Linux. You can also print to netware
|
server under Linux. You can also print to netware
|
||||||
print queues and spool netware print queues to the
|
print queues and spool netware print queues to the
|
||||||
Linux printing system. You need kernel 1.2.x or
|
Linux printing system. You need kernel 1.2.x or
|
||||||
1.3.54 and above. ncpfs does NOT work with any 1.3.x
|
1.3.71 and above. ncpfs does NOT work with any 1.3.x
|
||||||
kernel below 1.3.54.
|
kernel below 1.3.71.
|
||||||
Keywords: filesystem ncp novell netware printing
|
Keywords: filesystem ncp novell netware printing
|
||||||
Author: lendecke@namu01.gwdg.de (Volker Lendecke)
|
Author: lendecke@namu01.gwdg.de (Volker Lendecke)
|
||||||
Maintained-by: lendecke@namu01.gwdg.de (Volker Lendecke)
|
Maintained-by: lendecke@namu01.gwdg.de (Volker Lendecke)
|
||||||
Primary-site: linux01.gwdg.de:/pub/ncpfs
|
Primary-site: ftp.gwdg.de:/pub/linux/misc/ncpfs
|
||||||
Alternate-site: sunsite.unc.edu:/pub/system/Filesystems/
|
Alternate-site: sunsite.unc.edu:/pub/system/Filesystems/
|
||||||
~83k ncpfs-0.18.tgz
|
~120k ncpfs-0.22.tgz
|
||||||
~ 1k ncpfs-0.18.lsm
|
~ 1k ncpfs-0.22.lsm
|
||||||
Copying-policy: GPL
|
Copying-policy: GPL
|
||||||
End
|
End
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
# Makefile for the linux ncp-filesystem routines.
|
# Makefile for the linux ncp-filesystem routines.
|
||||||
#
|
#
|
||||||
|
|
||||||
USERUTILS = slist pqlist nwfsinfo pserver nprint
|
USERUTILS = slist pqlist nwfsinfo pserver nprint nsend ncopy
|
||||||
UIDUTILS = ncpmount ncpumount
|
UIDUTILS = ncpmount ncpumount
|
||||||
SBINUTILS = nwmsg
|
SBINUTILS = nwmsg
|
||||||
|
|
||||||
@@ -13,6 +13,9 @@ UTILS = $(addprefix $(INTERM_BINDIR)/,$(UTIL_EXECS))
|
|||||||
CFLAGS = -Wall $(INCLUDES) $(KERNELD) -O2 -DNCPFS_VERSION=\"$(VERSION)\"
|
CFLAGS = -Wall $(INCLUDES) $(KERNELD) -O2 -DNCPFS_VERSION=\"$(VERSION)\"
|
||||||
CC = gcc
|
CC = gcc
|
||||||
|
|
||||||
|
default:
|
||||||
|
make -C ..
|
||||||
|
|
||||||
all: $(UTILS) ncptest
|
all: $(UTILS) ncptest
|
||||||
|
|
||||||
install: all
|
install: all
|
||||||
@@ -23,25 +26,43 @@ install: all
|
|||||||
for i in $(SBINUTILS); \
|
for i in $(SBINUTILS); \
|
||||||
do install $(INTERM_BINDIR)/$$i -m 755 $(SBINDIR); done
|
do install $(INTERM_BINDIR)/$$i -m 755 $(SBINDIR); done
|
||||||
|
|
||||||
$(UTILS): $(addsuffix .o,$(UTIL_EXECS)) ncplib.o
|
$(UTILS): $(addsuffix .o,$(UTIL_EXECS)) libncp.a
|
||||||
$(CC) -o $@ $(addsuffix .o,$(notdir $@)) ncplib.o
|
$(CC) -o $@ $(addsuffix .o,$(notdir $@)) -L. -lncp
|
||||||
|
|
||||||
ncplib.o: ncplib.c ncplib.h
|
ncplib.o: ncplib.c ncplib.h ncplib_err.h
|
||||||
$(CC) $(CFLAGS) -finline-functions -c ncplib.c
|
$(CC) $(CFLAGS) -finline-functions -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
|
||||||
|
|
||||||
|
libncp.a: ncplib.o ncplib_err.o $(COM_ERR_CFILES)
|
||||||
|
make -C com_err
|
||||||
|
ar r libncp.a ncplib.o ncplib_err.o \
|
||||||
|
com_err/com_err.o com_err/error_message.o com_err/et_name.o \
|
||||||
|
com_err/init_et.o
|
||||||
|
|
||||||
|
ncplib_err.h: ncplib_err.et
|
||||||
|
com_err/compile_et ncplib_err
|
||||||
|
|
||||||
|
ncplib_err.c: ncplib_err.et
|
||||||
|
com_err/compile_et ncplib_err
|
||||||
|
|
||||||
test: test.o ncplib.o
|
test: test.o ncplib.o
|
||||||
$(CC) -o test test.o ncplib.o
|
$(CC) -o test test.o ncplib.o
|
||||||
|
|
||||||
ncptest: ncptest.o ncplib.o
|
ncptest: ncptest.o libncp.a
|
||||||
$(CC) -o ncptest ncptest.o ncplib.o
|
$(CC) -o ncptest ncptest.o -L. -lncp
|
||||||
|
|
||||||
dep:
|
dep: ncplib_err.h
|
||||||
|
make -C com_err dep
|
||||||
$(CPP) -M $(INCLUDES) *.c > .depend
|
$(CPP) -M $(INCLUDES) *.c > .depend
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f *.o *~ slist test ncptest
|
make -C com_err clean
|
||||||
|
rm -f *.o *~ slist test ncptest ncplib_err.[ch] libncp.a
|
||||||
|
|
||||||
realclean: clean
|
mrproper: clean
|
||||||
|
make -C com_err mrproper
|
||||||
rm -f $(UTILS) .depend $(DISTFILE)
|
rm -f $(UTILS) .depend $(DISTFILE)
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|||||||
1
util/com_err.h
Symbolic link
1
util/com_err.h
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
com_err/com_err.h
|
||||||
49
util/com_err/ChangeLog
Normal file
49
util/com_err/ChangeLog
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
Wed Jan 31 11:06:08 1996 <tytso@rsts-11.mit.edu>
|
||||||
|
|
||||||
|
* Release of E2fsprogs version 1.02
|
||||||
|
|
||||||
|
Mon Sep 4 21:44:47 1995 Remy Card <card@bbj>
|
||||||
|
|
||||||
|
* Makefile.in: Added support for BSD shared libraries.
|
||||||
|
|
||||||
|
Sat Aug 12 03:11:28 1995 Remy Card <card@bbj>
|
||||||
|
|
||||||
|
* Makefile.in (install): Install static libraries in $(ulibdir)
|
||||||
|
(/usr/lib on Linux) instead of $(libdir) (/lib on Linux).
|
||||||
|
|
||||||
|
Sat Aug 5 11:44:17 1995 Theodore Y. Ts'o <tytso@lurch.mit.edu>
|
||||||
|
|
||||||
|
* Makefile.in (DLL_INSTALL_DIR, ELF_INSTALL_DIR): Set the
|
||||||
|
installation directories correctly.
|
||||||
|
|
||||||
|
Thu Jun 15 23:39:51 1995 Remy Card <card@bbj>
|
||||||
|
|
||||||
|
* Makefile.in: Added support for ELF shared libraries.
|
||||||
|
Fixed typos in the compilation rules.
|
||||||
|
(distclean): Added compile_et.sh.
|
||||||
|
|
||||||
|
Sat Jun 10 19:56:13 1995 Theodore Y. Ts'o <tytso@lurch.mit.edu>
|
||||||
|
|
||||||
|
* compile_et.sh.in: Use ET_DIR instead of srcdir to determine the
|
||||||
|
location of the et directory.
|
||||||
|
|
||||||
|
Thu Jun 8 12:45:41 1995 Miles Bader <miles@churchy.gnu.ai.mit.edu>
|
||||||
|
|
||||||
|
* vfprintf.c (vfprintf): Only compile this function if vfprintf
|
||||||
|
doesn't already exist and _doprnt does.
|
||||||
|
|
||||||
|
* compile_et.sh: Moved to compile_et.sh.in.
|
||||||
|
|
||||||
|
* Makefile.in: Rewritten to conform to GNU coding standards and
|
||||||
|
support separate compilation directories.
|
||||||
|
Don't preprocess compile_et.sh, as this is now done by configure.
|
||||||
|
|
||||||
|
Mon Nov 7 21:17:48 1994 Remy Card <card@bbj>
|
||||||
|
|
||||||
|
* Makefile: Added a dummy install target in case shared libraries
|
||||||
|
are not built.
|
||||||
|
|
||||||
|
Thu Sep 8 22:33:33 1994 (tytso@rsx-11)
|
||||||
|
|
||||||
|
* com_err.c (default_com_err_proc): Reversed order of \n\r to make
|
||||||
|
jik happy.
|
||||||
25
util/com_err/Makefile
Normal file
25
util/com_err/Makefile
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
#
|
||||||
|
# Makefile for the com_err library
|
||||||
|
#
|
||||||
|
|
||||||
|
OBJECTS = com_err.o error_message.o et_name.o init_et.o
|
||||||
|
CFLAGS = -Wall -O2
|
||||||
|
|
||||||
|
all: $(OBJECTS)
|
||||||
|
|
||||||
|
dep:
|
||||||
|
$(CPP) -M $(INCLUDES) *.c > .depend
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f *.o
|
||||||
|
|
||||||
|
mrproper: clean
|
||||||
|
rm -f .depend
|
||||||
|
|
||||||
|
#
|
||||||
|
# include a dependency file if one exists
|
||||||
|
#
|
||||||
|
ifeq (.depend,$(wildcard .depend))
|
||||||
|
include .depend
|
||||||
|
endif
|
||||||
|
|
||||||
96
util/com_err/com_err.3
Normal file
96
util/com_err/com_err.3
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
.\" Copyright (c) 1988 Massachusetts Institute of Technology,
|
||||||
|
.\" Student Information Processing Board. All rights reserved.
|
||||||
|
.\"
|
||||||
|
.\" $Header: /mit/krb5/.cvsroot/src/util/et/com_err.3,v 1.1 1993/06/03 12:29:34 tytso Exp $
|
||||||
|
.\"
|
||||||
|
.TH COM_ERR 3 "22 Nov 1988" SIPB
|
||||||
|
.SH NAME
|
||||||
|
com_err \- common error display routine
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.nf
|
||||||
|
#include <com_err.h>
|
||||||
|
.PP
|
||||||
|
void com_err (whoami, code, format, ...);
|
||||||
|
const char *whoami;
|
||||||
|
long code;
|
||||||
|
const char *format;
|
||||||
|
.PP
|
||||||
|
proc = set_com_err_hook (proc);
|
||||||
|
.fi
|
||||||
|
void (*
|
||||||
|
.I proc
|
||||||
|
) (const char *, long, const char *, va_list);
|
||||||
|
.nf
|
||||||
|
.PP
|
||||||
|
proc = reset_com_err_hook ();
|
||||||
|
.PP
|
||||||
|
void initialize_XXXX_error_table ();
|
||||||
|
.fi
|
||||||
|
.SH DESCRIPTION
|
||||||
|
.I Com_err
|
||||||
|
displays an error message on the standard error stream
|
||||||
|
.I stderr
|
||||||
|
(see
|
||||||
|
.IR stdio (3S))
|
||||||
|
composed of the
|
||||||
|
.I whoami
|
||||||
|
string, which should specify the program name or some subportion of
|
||||||
|
a program, followed by an error message generated from the
|
||||||
|
.I code
|
||||||
|
value (derived from
|
||||||
|
.IR compile_et (1)),
|
||||||
|
and a string produced using the
|
||||||
|
.I format
|
||||||
|
string and any following arguments, in the same style as
|
||||||
|
.IR fprintf (3).
|
||||||
|
|
||||||
|
The behavior of
|
||||||
|
.I com_err
|
||||||
|
can be modified using
|
||||||
|
.I set_com_err_hook;
|
||||||
|
this defines a procedure which is called with the arguments passed to
|
||||||
|
.I com_err,
|
||||||
|
instead of the default internal procedure which sends the formatted
|
||||||
|
text to error output. Thus the error messages from a program can all
|
||||||
|
easily be diverted to another form of diagnostic logging, such as
|
||||||
|
.IR syslog (3).
|
||||||
|
.I Reset_com_err_hook
|
||||||
|
may be used to restore the behavior of
|
||||||
|
.I com_err
|
||||||
|
to its default form. Both procedures return the previous ``hook''
|
||||||
|
value. These ``hook'' procedures must have the declaration given for
|
||||||
|
.I proc
|
||||||
|
above in the synopsis.
|
||||||
|
|
||||||
|
The
|
||||||
|
.I initialize_XXXX_error_table
|
||||||
|
routine is generated mechanically by
|
||||||
|
.IR compile_et (1)
|
||||||
|
from a source file containing names and associated strings. Each
|
||||||
|
table has a name of up to four characters, which is used in place of
|
||||||
|
the
|
||||||
|
.B XXXX
|
||||||
|
in the name of the routine. These routines should be called before
|
||||||
|
any of the corresponding error codes are used, so that the
|
||||||
|
.I com_err
|
||||||
|
library will recognize error codes from these tables when they are
|
||||||
|
used.
|
||||||
|
|
||||||
|
The
|
||||||
|
.B com_err.h
|
||||||
|
header file should be included in any source file that uses routines
|
||||||
|
from the
|
||||||
|
.I com_err
|
||||||
|
library; executable files must be linked using
|
||||||
|
.I ``-lcom_err''
|
||||||
|
in order to cause the
|
||||||
|
.I com_err
|
||||||
|
library to be included.
|
||||||
|
|
||||||
|
.\" .IR for manual entries
|
||||||
|
.\" .PP for paragraph breaks
|
||||||
|
|
||||||
|
.SH "SEE ALSO"
|
||||||
|
compile_et (1), syslog (3).
|
||||||
|
|
||||||
|
Ken Raeburn, "A Common Error Description Library for UNIX".
|
||||||
114
util/com_err/com_err.c
Normal file
114
util/com_err/com_err.c
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 1987, 1988 by MIT Student Information Processing Board.
|
||||||
|
*
|
||||||
|
* For copyright info, see mit-sipb-copyright.h.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "com_err.h"
|
||||||
|
#include "mit-sipb-copyright.h"
|
||||||
|
#include "error_table.h"
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
#if !defined(__STDC__) && !defined(STDARG_PROTOTYPES)
|
||||||
|
#include <varargs.h>
|
||||||
|
#define VARARGS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void
|
||||||
|
#ifdef __STDC__
|
||||||
|
default_com_err_proc (const char *whoami, errcode_t code, const
|
||||||
|
char *fmt, va_list args)
|
||||||
|
#else
|
||||||
|
default_com_err_proc (whoami, code, fmt, args)
|
||||||
|
const char *whoami;
|
||||||
|
errcode_t code;
|
||||||
|
const char *fmt;
|
||||||
|
va_list args;
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
if (whoami) {
|
||||||
|
fputs(whoami, stderr);
|
||||||
|
fputs(": ", stderr);
|
||||||
|
}
|
||||||
|
if (code) {
|
||||||
|
fputs(error_message(code), stderr);
|
||||||
|
fputs(" ", stderr);
|
||||||
|
}
|
||||||
|
if (fmt) {
|
||||||
|
vfprintf (stderr, fmt, args);
|
||||||
|
}
|
||||||
|
/* should do this only on a tty in raw mode */
|
||||||
|
putc('\r', stderr);
|
||||||
|
putc('\n', stderr);
|
||||||
|
fflush(stderr);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __STDC__
|
||||||
|
typedef void (*errf) (const char *, errcode_t, const char *, va_list);
|
||||||
|
#else
|
||||||
|
typedef void (*errf) ();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
errf com_err_hook = default_com_err_proc;
|
||||||
|
|
||||||
|
#ifdef __STDC__
|
||||||
|
void com_err_va (const char *whoami, errcode_t code, const char *fmt,
|
||||||
|
va_list args)
|
||||||
|
#else
|
||||||
|
void com_err_va (whoami, code, fmt, args)
|
||||||
|
const char *whoami;
|
||||||
|
errcode_t code;
|
||||||
|
const char *fmt;
|
||||||
|
va_list args;
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
(*com_err_hook) (whoami, code, fmt, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef VARARGS
|
||||||
|
void com_err (const char *whoami,
|
||||||
|
errcode_t code,
|
||||||
|
const char *fmt, ...)
|
||||||
|
{
|
||||||
|
#else
|
||||||
|
void com_err (va_alist)
|
||||||
|
va_dcl
|
||||||
|
{
|
||||||
|
const char *whoami, *fmt;
|
||||||
|
errcode_t code;
|
||||||
|
#endif
|
||||||
|
va_list pvar;
|
||||||
|
|
||||||
|
if (!com_err_hook)
|
||||||
|
com_err_hook = default_com_err_proc;
|
||||||
|
#ifdef VARARGS
|
||||||
|
va_start (pvar);
|
||||||
|
whoami = va_arg (pvar, const char *);
|
||||||
|
code = va_arg (pvar, errcode_t);
|
||||||
|
fmt = va_arg (pvar, const char *);
|
||||||
|
#else
|
||||||
|
va_start(pvar, fmt);
|
||||||
|
#endif
|
||||||
|
com_err_va (whoami, code, fmt, pvar);
|
||||||
|
va_end(pvar);
|
||||||
|
}
|
||||||
|
|
||||||
|
errf set_com_err_hook (new_proc)
|
||||||
|
errf new_proc;
|
||||||
|
{
|
||||||
|
errf x = com_err_hook;
|
||||||
|
|
||||||
|
if (new_proc)
|
||||||
|
com_err_hook = new_proc;
|
||||||
|
else
|
||||||
|
com_err_hook = default_com_err_proc;
|
||||||
|
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
errf reset_com_err_hook () {
|
||||||
|
errf x = com_err_hook;
|
||||||
|
com_err_hook = default_com_err_proc;
|
||||||
|
return x;
|
||||||
|
}
|
||||||
40
util/com_err/com_err.h
Normal file
40
util/com_err/com_err.h
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* Header file for common error description library.
|
||||||
|
*
|
||||||
|
* Copyright 1988, Student Information Processing Board of the
|
||||||
|
* Massachusetts Institute of Technology.
|
||||||
|
*
|
||||||
|
* For copyright and distribution info, see the documentation supplied
|
||||||
|
* with this package.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __COM_ERR_H
|
||||||
|
|
||||||
|
typedef long errcode_t;
|
||||||
|
|
||||||
|
#ifdef __STDC__
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
/* ANSI C -- use prototypes etc */
|
||||||
|
void com_err (const char *, long, const char *, ...);
|
||||||
|
void com_err_va (const char *whoami, errcode_t code, const char *fmt,
|
||||||
|
va_list args);
|
||||||
|
char const *error_message (long);
|
||||||
|
extern void (*com_err_hook) (const char *, long, const char *, va_list);
|
||||||
|
void (*set_com_err_hook (void (*) (const char *, long, const char *, va_list)))
|
||||||
|
(const char *, long, const char *, va_list);
|
||||||
|
void (*reset_com_err_hook (void)) (const char *, long, const char *, va_list);
|
||||||
|
int init_error_table(const char * const *msgs, int base, int count);
|
||||||
|
#else
|
||||||
|
/* no prototypes */
|
||||||
|
void com_err ();
|
||||||
|
void com_err_va ();
|
||||||
|
char *error_message ();
|
||||||
|
extern void (*com_err_hook) ();
|
||||||
|
void (*set_com_err_hook ()) ();
|
||||||
|
void (*reset_com_err_hook ()) ();
|
||||||
|
int init_error_table();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define __COM_ERR_H
|
||||||
|
#endif /* ! defined(__COM_ERR_H) */
|
||||||
554
util/com_err/com_err.texinfo
Normal file
554
util/com_err/com_err.texinfo
Normal file
@@ -0,0 +1,554 @@
|
|||||||
|
\input texinfo @c -*-texinfo-*-
|
||||||
|
|
||||||
|
@c $Header: /mit/krb5/.cvsroot/src/util/et/com_err.texinfo,v 1.1 1993/06/03 12:29:38 tytso Exp $
|
||||||
|
@c $Source: /mit/krb5/.cvsroot/src/util/et/com_err.texinfo,v $
|
||||||
|
@c $Locker: $
|
||||||
|
|
||||||
|
@c Note that although this source file is in texinfo format (more
|
||||||
|
@c or less), it is not yet suitable for turning into an ``info''
|
||||||
|
@c file. Sorry, maybe next time.
|
||||||
|
@c
|
||||||
|
@c In order to produce hardcopy documentation from a texinfo file,
|
||||||
|
@c run ``tex com_err.texinfo'' which will load in texinfo.tex,
|
||||||
|
@c provided in this distribution. (texinfo.tex is from the Free
|
||||||
|
@c Software Foundation, and is under different copyright restrictions
|
||||||
|
@c from the rest of this package.)
|
||||||
|
|
||||||
|
@ifinfo
|
||||||
|
@barfo
|
||||||
|
@end ifinfo
|
||||||
|
|
||||||
|
@iftex
|
||||||
|
@tolerance 10000
|
||||||
|
|
||||||
|
@c Mutate section headers...
|
||||||
|
@begingroup
|
||||||
|
@catcode#=6
|
||||||
|
@gdef@secheading#1#2#3{@secheadingi {#3@enspace #1}}
|
||||||
|
@endgroup
|
||||||
|
@end iftex
|
||||||
|
|
||||||
|
@setfilename com_err
|
||||||
|
@settitle A Common Error Description Library for UNIX
|
||||||
|
|
||||||
|
@ifinfo
|
||||||
|
This file documents the use of the Common Error Description library.
|
||||||
|
|
||||||
|
Copyright (C) 1987, 1988 Student Information Processing Board of the
|
||||||
|
Massachusetts Institute of Technology.
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and distribute this software and its
|
||||||
|
documentation for any purpose and without fee is hereby granted, provided
|
||||||
|
that the above copyright notice appear in all copies and that both that
|
||||||
|
copyright notice and this permission notice appear in supporting
|
||||||
|
documentation, and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
|
||||||
|
used in advertising or publicity pertaining to distribution of the software
|
||||||
|
without specific, written prior permission. M.I.T. and the M.I.T. S.I.P.B.
|
||||||
|
make no representations about the suitability of this software for any
|
||||||
|
purpose. It is provided "as is" without express or implied warranty.
|
||||||
|
|
||||||
|
Note that the file texinfo.tex, provided with this distribution, is from
|
||||||
|
the Free Software Foundation, and is under different copyright restrictions
|
||||||
|
from the remainder of this package.
|
||||||
|
|
||||||
|
@end ifinfo
|
||||||
|
|
||||||
|
@ignore
|
||||||
|
Permission is granted to process this file through Tex and print the
|
||||||
|
results, provided the printed document carries copying permission
|
||||||
|
notice identical to this one except for the removal of this paragraph
|
||||||
|
(this paragraph not being relevant to the printed manual).
|
||||||
|
|
||||||
|
@end ignore
|
||||||
|
|
||||||
|
@setchapternewpage odd
|
||||||
|
|
||||||
|
@titlepage
|
||||||
|
@center @titlefont{A Common Error Description}
|
||||||
|
@center @titlefont{Library for UNIX}
|
||||||
|
@sp 2
|
||||||
|
@center Ken Raeburn
|
||||||
|
@center Bill Sommerfeld
|
||||||
|
@sp 1
|
||||||
|
@center MIT Student Information Processing Board
|
||||||
|
@sp 3
|
||||||
|
@center last updated 1 January 1989
|
||||||
|
@center for version 1.2
|
||||||
|
@center ***DRAFT COPY ONLY***
|
||||||
|
|
||||||
|
@vskip 2in
|
||||||
|
|
||||||
|
@center @b{Abstract}
|
||||||
|
|
||||||
|
UNIX has always had a clean and simple system call interface, with a
|
||||||
|
standard set of error codes passed between the kernel and user
|
||||||
|
programs. Unfortunately, the same cannot be said of many of the
|
||||||
|
libraries layered on top of the primitives provided by the kernel.
|
||||||
|
Typically, each one has used a different style of indicating errors to
|
||||||
|
their callers, leading to a total hodgepodge of error handling, and
|
||||||
|
considerable amounts of work for the programmer. This paper describes
|
||||||
|
a library and associated utilities which allows a more uniform way for
|
||||||
|
libraries to return errors to their callers, and for programs to
|
||||||
|
describe errors and exceptional conditions to their users.
|
||||||
|
|
||||||
|
@page
|
||||||
|
@vskip 0pt plus 1filll
|
||||||
|
|
||||||
|
Copyright @copyright{} 1987, 1988 by the Student Information Processing
|
||||||
|
Board of the Massachusetts Institute of Technology.
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and distribute this software and its
|
||||||
|
documentation for any purpose and without fee is hereby granted, provided
|
||||||
|
that the above copyright notice appear in all copies and that both that
|
||||||
|
copyright notice and this permission notice appear in supporting
|
||||||
|
documentation, and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
|
||||||
|
used in advertising or publicity pertaining to distribution of the software
|
||||||
|
without specific, written prior permission. M.I.T. and the M.I.T. S.I.P.B.
|
||||||
|
make no representations about the suitability of this software for any
|
||||||
|
purpose. It is provided "as is" without express or implied warranty.
|
||||||
|
|
||||||
|
Note that the file texinfo.tex, provided with this distribution, is from
|
||||||
|
the Free Software Foundation, and is under different copyright restrictions
|
||||||
|
from the remainder of this package.
|
||||||
|
|
||||||
|
@end titlepage
|
||||||
|
|
||||||
|
@ifinfo
|
||||||
|
@c should put a menu here someday....
|
||||||
|
@end ifinfo
|
||||||
|
|
||||||
|
@page
|
||||||
|
|
||||||
|
@section Why com_err?
|
||||||
|
|
||||||
|
In building application software packages, a programmer often has to
|
||||||
|
deal with a number of libraries, each of which can use a different
|
||||||
|
error-reporting mechanism. Sometimes one of two values is returned,
|
||||||
|
indicating simply SUCCESS or FAILURE, with no description of errors
|
||||||
|
encountered. Sometimes it is an index into a table of text strings,
|
||||||
|
where the name of the table used is dependent on the library being
|
||||||
|
used when the error is generated; since each table starts numbering at
|
||||||
|
0 or 1, additional information as to the source of the error code is
|
||||||
|
needed to determine which table to look at. Sometimes no text messages are
|
||||||
|
supplied at all, and the programmer must supply them at any point at which
|
||||||
|
he may wish to report error conditions.
|
||||||
|
Often, a global variable is assigned some value describing the error, but
|
||||||
|
the programmer has to know in each case whether to look at @code{errno},
|
||||||
|
@code{h_errno}, the return value from @code{hes_err()}, or whatever other
|
||||||
|
variables or routines are specified.
|
||||||
|
And what happens if something
|
||||||
|
in the procedure of
|
||||||
|
examining or reporting the error changes the same variable?
|
||||||
|
|
||||||
|
The package we have developed is an attempt to present a common
|
||||||
|
error-handling mechanism to manipulate the most common form of error code
|
||||||
|
in a fashion that does not have the problems listed above.
|
||||||
|
|
||||||
|
A list of up to 256 text messages is supplied to a translator we have
|
||||||
|
written, along with the three- to four-character ``name'' of the error
|
||||||
|
table. The library using this error table need only call a routine
|
||||||
|
generated from this error-table source to make the table ``known'' to the
|
||||||
|
com_err library, and any error code the library generates can be converted
|
||||||
|
to the corresponding error message. There is also a default format for
|
||||||
|
error codes accidentally returned before making the table known, which is
|
||||||
|
of the form @samp{unknown code foo 32}, where @samp{foo} would be the name
|
||||||
|
of the table.
|
||||||
|
|
||||||
|
@section Error codes
|
||||||
|
|
||||||
|
Error codes themselves are 32 bit (signed) integers, of which the high
|
||||||
|
order 24 bits are an identifier of which error table the error code is
|
||||||
|
from, and the low order 8 bits are a sequential error number within
|
||||||
|
the table. An error code may thus be easily decomposed into its component
|
||||||
|
parts. Only the lowest 32 bits of an error code are considered significant
|
||||||
|
on systems which support wider values.
|
||||||
|
|
||||||
|
Error table 0 is defined to match the UNIX system call error table
|
||||||
|
(@code{sys_errlist}); this allows @code{errno} values to be used directly
|
||||||
|
in the library (assuming that @code{errno} is of a type with the same width
|
||||||
|
as @t{long}). Other error table numbers are formed by compacting together
|
||||||
|
the first four characters of the error table name. The mapping between
|
||||||
|
characters in the name and numeric values in the error code are defined in
|
||||||
|
a system-independent fashion, so that two systems that can pass integral
|
||||||
|
values between them can reliably pass error codes without loss of meaning;
|
||||||
|
this should work even if the character sets used are not the same.
|
||||||
|
(However, if this is to be done, error table 0 should be avoided, since the
|
||||||
|
local system call error tables may differ.)
|
||||||
|
|
||||||
|
Any variable which is to contain an error code should be declared @t{long}.
|
||||||
|
The draft proposed American National Standard for C (as of May, 1988)
|
||||||
|
requires that @t{long} variables be at least 32 bits; any system which does
|
||||||
|
not support 32-bit @t{long} values cannot make use of this package (nor
|
||||||
|
much other software that assumes an ANSI-C environment base) without
|
||||||
|
significant effort.
|
||||||
|
|
||||||
|
@section Error table source file
|
||||||
|
|
||||||
|
The error table source file begins with the declaration of the table name,
|
||||||
|
as
|
||||||
|
|
||||||
|
@example
|
||||||
|
error_table @var{tablename}
|
||||||
|
@end example
|
||||||
|
|
||||||
|
Individual error codes are
|
||||||
|
specified with
|
||||||
|
|
||||||
|
@example
|
||||||
|
error_code @var{ERROR_NAME}, @var{"text message"}
|
||||||
|
@end example
|
||||||
|
|
||||||
|
where @samp{ec} can also be used as a short form of @samp{error_code}. To
|
||||||
|
indicate the end of the table, use @samp{end}. Thus, a (short) sample
|
||||||
|
error table might be:
|
||||||
|
|
||||||
|
@example
|
||||||
|
|
||||||
|
error_table dsc
|
||||||
|
|
||||||
|
error_code DSC_DUP_MTG_NAME,
|
||||||
|
"Meeting already exists"
|
||||||
|
|
||||||
|
ec DSC_BAD_PATH,
|
||||||
|
"A bad meeting pathname was given"
|
||||||
|
|
||||||
|
ec DSC_BAD_MODES,
|
||||||
|
"Invalid mode for this access control list"
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
@end example
|
||||||
|
|
||||||
|
@section The error-table compiler
|
||||||
|
|
||||||
|
The error table compiler is named @code{compile_et}. It takes one
|
||||||
|
argument, the pathname of a file (ending in @samp{.et}, e.g.,
|
||||||
|
@samp{dsc_err.et}) containing an error table source file. It parses the
|
||||||
|
error table, and generates two output files -- a C header file
|
||||||
|
(@samp{discuss_err.h}) which contains definitions of the numerical values
|
||||||
|
of the error codes defined in the error table, and a C source file which
|
||||||
|
should be compiled and linked with the executable. The header file must be
|
||||||
|
included in the source of a module which wishes to reference the error
|
||||||
|
codes defined; the object module generated from the C code may be linked in
|
||||||
|
to a program which wishes to use the printed forms of the error codes.
|
||||||
|
|
||||||
|
This translator accepts a @kbd{-language @var{lang}} argument, which
|
||||||
|
determines for which language (or language variant) the output should be
|
||||||
|
written. At the moment, @var{lang} is currently limited to @kbd{ANSI-C}
|
||||||
|
and @kbd{K&R-C}, and some abbreviated forms of each. Eventually, this will
|
||||||
|
be extended to include some support for C++. The default is currently
|
||||||
|
@kbd{K&R-C}, though the generated sources will have ANSI-C code
|
||||||
|
conditionalized on the symbol @t{__STDC__}.
|
||||||
|
|
||||||
|
@section Run-time support routines
|
||||||
|
|
||||||
|
Any source file which uses the routines supplied with or produced by the
|
||||||
|
com_err package should include the header file @file{<com_err.h>}. It
|
||||||
|
contains declarations and definitions which may be needed on some systems.
|
||||||
|
(Some functions cannot be referenced properly without the return type
|
||||||
|
declarations in this file. Some functions may work properly on most
|
||||||
|
architectures even without the header file, but relying on this is not
|
||||||
|
recommended.)
|
||||||
|
|
||||||
|
The run-time support routines and variables provided via this package
|
||||||
|
include the following:
|
||||||
|
|
||||||
|
@example
|
||||||
|
void initialize_@var{xxxx}_error_table (void);
|
||||||
|
@end example
|
||||||
|
|
||||||
|
One of these routines is built by the error compiler for each error table.
|
||||||
|
It makes the @var{xxxx} error table ``known'' to the error reporting
|
||||||
|
system. By convention, this routine should be called in the initialization
|
||||||
|
routine of the @var{xxxx} library. If the library has no initialization
|
||||||
|
routine, some combination of routines which form the core of the library
|
||||||
|
should ensure that this routine is called. It is not advised to leave it
|
||||||
|
the caller to make this call.
|
||||||
|
|
||||||
|
There is no harm in calling this routine more than once.
|
||||||
|
|
||||||
|
@example
|
||||||
|
#define ERROR_TABLE_BASE_@var{xxxx} @var{nnnnn}L
|
||||||
|
@end example
|
||||||
|
|
||||||
|
This symbol contains the value of the first error code entry in the
|
||||||
|
specified table.
|
||||||
|
This rarely needs be used by the
|
||||||
|
programmer.
|
||||||
|
|
||||||
|
@example
|
||||||
|
const char *error_message (long code);
|
||||||
|
@end example
|
||||||
|
|
||||||
|
This routine returns the character string error message associated
|
||||||
|
with @code{code}; if this is associated with an unknown error table, or
|
||||||
|
if the code is associated with a known error table but the code is not
|
||||||
|
in the table, a string of the form @samp{Unknown code @var{xxxx nn}} is
|
||||||
|
returned, where @var{xxxx} is the error table name produced by
|
||||||
|
reversing the compaction performed on the error table number implied
|
||||||
|
by that error code, and @var{nn} is the offset from that base value.
|
||||||
|
|
||||||
|
Although this routine is available for use when needed, its use should be
|
||||||
|
left to circumstances which render @code{com_err} (below) unusable.
|
||||||
|
|
||||||
|
@example
|
||||||
|
void com_err (const char *whoami, /* module reporting error */
|
||||||
|
long code, /* error code */
|
||||||
|
const char *format, /* format for additional detail */
|
||||||
|
...); /* (extra parameters) */
|
||||||
|
@end example
|
||||||
|
|
||||||
|
This routine provides an alternate way to print error messages to
|
||||||
|
standard error; it allows the error message to be passed in as a
|
||||||
|
parameter, rather than in an external variable. @emph{Provide grammatical
|
||||||
|
context for ``message.''}
|
||||||
|
|
||||||
|
If @var{format} is @code{(char *)NULL}, the formatted message will not be
|
||||||
|
printed. @var{format} may not be omitted.
|
||||||
|
|
||||||
|
@example
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
void com_err_va (const char *whoami,
|
||||||
|
long code,
|
||||||
|
const char *format,
|
||||||
|
va_list args);
|
||||||
|
@end example
|
||||||
|
|
||||||
|
This routine provides an interface, equivalent to @code{com_err} above,
|
||||||
|
which may be used by higher-level variadic functions (functions which
|
||||||
|
accept variable numbers of arguments).
|
||||||
|
|
||||||
|
@example
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
void (*set_com_err_hook (void (*proc) ())) ();
|
||||||
|
|
||||||
|
void (*@var{proc}) (const char *whoami, long code, va_list args);
|
||||||
|
|
||||||
|
void reset_com_err_hook ();
|
||||||
|
@end example
|
||||||
|
|
||||||
|
These two routines allow a routine to be dynamically substituted for
|
||||||
|
@samp{com_err}. After @samp{set_com_err_hook} has been called,
|
||||||
|
calls to @samp{com_err} will turn into calls to the new hook routine.
|
||||||
|
@samp{reset_com_err_hook} turns off this hook. This may intended to
|
||||||
|
be used in daemons (to use a routine which calls @var{syslog(3)}), or
|
||||||
|
in a window system application (which could pop up a dialogue box).
|
||||||
|
|
||||||
|
If a program is to be used in an environment in which simply printing
|
||||||
|
messages to the @code{stderr} stream would be inappropriate (such as in a
|
||||||
|
daemon program which runs without a terminal attached),
|
||||||
|
@code{set_com_err_hook} may be used to redirect output from @code{com_err}.
|
||||||
|
The following is an example of an error handler which uses @var{syslog(3)}
|
||||||
|
as supplied in BSD 4.3:
|
||||||
|
|
||||||
|
@example
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <syslog.h>
|
||||||
|
|
||||||
|
/* extern openlog (const char * name, int logopt, int facility); */
|
||||||
|
/* extern syslog (int priority, char * message, ...); */
|
||||||
|
|
||||||
|
void hook (const char * whoami, long code,
|
||||||
|
const char * format, va_list args)
|
||||||
|
@{
|
||||||
|
char buffer[BUFSIZ];
|
||||||
|
static int initialized = 0;
|
||||||
|
if (!initialized) @{
|
||||||
|
openlog (whoami,
|
||||||
|
LOG_NOWAIT|LOG_CONS|LOG_PID|LOG_NDELAY,
|
||||||
|
LOG_DAEMON);
|
||||||
|
initialized = 1;
|
||||||
|
@}
|
||||||
|
vsprintf (buffer, format, args);
|
||||||
|
syslog (LOG_ERR, "%s %s", error_message (code), buffer);
|
||||||
|
@}
|
||||||
|
@end example
|
||||||
|
|
||||||
|
After making the call
|
||||||
|
@code{set_com_err_hook (hook);},
|
||||||
|
any calls to @code{com_err} will result in messages being sent to the
|
||||||
|
@var{syslogd} daemon for logging.
|
||||||
|
The name of the program, @samp{whoami}, is supplied to the
|
||||||
|
@samp{openlog()} call, and the message is formatted into a buffer and
|
||||||
|
passed to @code{syslog}.
|
||||||
|
|
||||||
|
Note that since the extra arguments to @code{com_err} are passed by
|
||||||
|
reference via the @code{va_list} value @code{args}, the hook routine may
|
||||||
|
place any form of interpretation on them, including ignoring them. For
|
||||||
|
consistency, @code{printf}-style interpretation is suggested, via
|
||||||
|
@code{vsprintf} (or @code{_doprnt} on BSD systems without full support for
|
||||||
|
the ANSI C library).
|
||||||
|
|
||||||
|
@section Coding Conventions
|
||||||
|
|
||||||
|
The following conventions are just some general stylistic conventions
|
||||||
|
to follow when writing robust libraries and programs. Conventions
|
||||||
|
similar to this are generally followed inside the UNIX kernel and most
|
||||||
|
routines in the Multics operating system. In general, a routine
|
||||||
|
either succeeds (returning a zero error code, and doing some side
|
||||||
|
effects in the process), or it fails, doing minimal side effects; in
|
||||||
|
any event, any invariant which the library assumes must be maintained.
|
||||||
|
|
||||||
|
In general, it is not in the domain of non user-interface library
|
||||||
|
routines to write error messages to the user's terminal, or halt the
|
||||||
|
process. Such forms of ``error handling'' should be reserved for
|
||||||
|
failures of internal invariants and consistancy checks only, as it
|
||||||
|
provides the user of the library no way to clean up for himself in the
|
||||||
|
event of total failure.
|
||||||
|
|
||||||
|
Library routines which can fail should be set up to return an error
|
||||||
|
code. This should usually be done as the return value of the
|
||||||
|
function; if this is not acceptable, the routine should return a
|
||||||
|
``null'' value, and put the error code into a parameter passed by
|
||||||
|
reference.
|
||||||
|
|
||||||
|
Routines which use the first style of interface can be used from
|
||||||
|
user-interface levels of a program as follows:
|
||||||
|
|
||||||
|
@example
|
||||||
|
@{
|
||||||
|
if ((code = initialize_world(getuid(), random())) != 0) @{
|
||||||
|
com_err("demo", code,
|
||||||
|
"when trying to initialize world");
|
||||||
|
exit(1);
|
||||||
|
@}
|
||||||
|
if ((database = open_database("my_secrets", &code))==NULL) @{
|
||||||
|
com_err("demo", code,
|
||||||
|
"while opening my_secrets");
|
||||||
|
exit(1);
|
||||||
|
@}
|
||||||
|
@}
|
||||||
|
@end example
|
||||||
|
|
||||||
|
A caller which fails to check the return status is in error. It is
|
||||||
|
possible to look for code which ignores error returns by using lint;
|
||||||
|
look for error messages of the form ``foobar returns value which is
|
||||||
|
sometimes ignored'' or ``foobar returns value which is always
|
||||||
|
ignored.''
|
||||||
|
|
||||||
|
Since libraries may be built out of other libraries, it is often necessary
|
||||||
|
for the success of one routine to depend on another. When a lower level
|
||||||
|
routine returns an error code, the middle level routine has a few possible
|
||||||
|
options. It can simply return the error code to its caller after doing
|
||||||
|
some form of cleanup, it can substitute one of its own, or it can take
|
||||||
|
corrective action of its own and continue normally. For instance, a
|
||||||
|
library routine which makes a ``connect'' system call to make a network
|
||||||
|
connection may reflect the system error code @code{ECONNREFUSED}
|
||||||
|
(Connection refused) to its caller, or it may return a ``server not
|
||||||
|
available, try again later,'' or it may try a different server.
|
||||||
|
|
||||||
|
Cleanup which is typically necessary may include, but not be limited
|
||||||
|
to, freeing allocated memory which will not be needed any more,
|
||||||
|
unlocking concurrancy locks, dropping reference counts, closing file
|
||||||
|
descriptors, or otherwise undoing anything which the procedure did up
|
||||||
|
to this point. When there are a lot of things which can go wrong, it
|
||||||
|
is generally good to write one block of error-handling code which is
|
||||||
|
branched to, using a goto, in the event of failure. A common source
|
||||||
|
of errors in UNIX programs is failing to close file descriptors on
|
||||||
|
error returns; this leaves a number of ``zombied'' file descriptors
|
||||||
|
open, which eventually causes the process to run out of file
|
||||||
|
descriptors and fall over.
|
||||||
|
|
||||||
|
@example
|
||||||
|
@{
|
||||||
|
FILE *f1=NULL, *f2=NULL, *f3=NULL;
|
||||||
|
int status = 0;
|
||||||
|
|
||||||
|
if ( (f1 = fopen(FILE1, "r")) == NULL) @{
|
||||||
|
status = errno;
|
||||||
|
goto error;
|
||||||
|
@}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Crunch for a while
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ( (f2 = fopen(FILE2, "w")) == NULL) @{
|
||||||
|
status = errno;
|
||||||
|
goto error;
|
||||||
|
@}
|
||||||
|
|
||||||
|
if ( (f3 = fopen(FILE3, "a+")) == NULL) @{
|
||||||
|
status = errno;
|
||||||
|
goto error;
|
||||||
|
@}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Do more processing.
|
||||||
|
*/
|
||||||
|
fclose(f1);
|
||||||
|
fclose(f2);
|
||||||
|
fclose(f3);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
error:
|
||||||
|
if (f1) fclose(f1);
|
||||||
|
if (f2) fclose(f2);
|
||||||
|
if (f3) fclose(f3);
|
||||||
|
return status;
|
||||||
|
@}
|
||||||
|
@end example
|
||||||
|
|
||||||
|
@section Building and Installation
|
||||||
|
|
||||||
|
The distribution of this package will probably be done as a compressed
|
||||||
|
``tar''-format file available via anonymous FTP from SIPB.MIT.EDU.
|
||||||
|
Retrieve @samp{pub/com_err.tar.Z} and extract the contents. A subdirectory
|
||||||
|
@t{profiled} should be created to hold objects compiled for profiling.
|
||||||
|
Running ``make all'' should then be sufficient to build the library and
|
||||||
|
error-table compiler. The files @samp{libcom_err.a},
|
||||||
|
@samp{libcom_err_p.a}, @samp{com_err.h}, and @samp{compile_et} should be
|
||||||
|
installed for use; @samp{com_err.3} and @samp{compile_et.1} can also be
|
||||||
|
installed as manual pages.
|
||||||
|
|
||||||
|
Potential problems:
|
||||||
|
|
||||||
|
@itemize @bullet
|
||||||
|
|
||||||
|
@item Use of @code{strcasecmp}, a routine provided in BSD for
|
||||||
|
case-insensitive string comparisons. If an equivalent routine is
|
||||||
|
available, you can modify @code{CFLAGS} in the makefile to define
|
||||||
|
@code{strcasecmp} to the name of that routine.
|
||||||
|
|
||||||
|
@item Compilers that defined @code{__STDC__} without providing the header
|
||||||
|
file @code{<stdarg.h>}. One such example is Metaware's High ``C''
|
||||||
|
compiler, as provided at Project Athena on the IBM RT/PC workstation; if
|
||||||
|
@code{__HIGHC__} is defined, it is assumed that @code{<stdarg.h>} is not
|
||||||
|
available, and therefore @code{<varargs.h>} must be used. If the symbol
|
||||||
|
@code{VARARGS} is defined (e.g., in the makefile), @code{<varargs.h>} will
|
||||||
|
be used.
|
||||||
|
|
||||||
|
@item If your linker rejects symbols that are simultaneously defined in two
|
||||||
|
library files, edit @samp{Makefile} to remove @samp{perror.c} from the
|
||||||
|
library. This file contains a version of @var{perror(3)} which calls
|
||||||
|
@code{com_err} instead of calling @code{write} directly.
|
||||||
|
|
||||||
|
@end itemize
|
||||||
|
|
||||||
|
As I do not have access to non-BSD systems, there are probably
|
||||||
|
bugs present that may interfere with building or using this package on
|
||||||
|
other systems. If they are reported to me, they can probably be fixed for
|
||||||
|
the next version.
|
||||||
|
|
||||||
|
@section Bug Reports
|
||||||
|
|
||||||
|
Please send any comments or bug reports to the principal author: Ken
|
||||||
|
Raeburn, @t{Raeburn@@Athena.MIT.EDU}.
|
||||||
|
|
||||||
|
@section Acknowledgements
|
||||||
|
|
||||||
|
I would like to thank: Bill Sommerfeld, for his help with some of this
|
||||||
|
documentation, and catching some of the bugs the first time around;
|
||||||
|
Honeywell Information Systems, for not killing off the @emph{Multics}
|
||||||
|
operating system before I had an opportunity to use it; Honeywell's
|
||||||
|
customers, who persuaded them not to do so, for a while; Ted Anderson of
|
||||||
|
CMU, for catching some problems before version 1.2 left the nest; Stan
|
||||||
|
Zanarotti and several others of MIT's Student Information Processing Board,
|
||||||
|
for getting us started with ``discuss,'' for which this package was
|
||||||
|
originally written; and everyone I've talked into --- I mean, asked to read
|
||||||
|
this document and the ``man'' pages.
|
||||||
|
|
||||||
|
@bye
|
||||||
11
util/com_err/compile_et
Executable file
11
util/com_err/compile_et
Executable file
@@ -0,0 +1,11 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
#
|
||||||
|
AWK=/usr/bin/awk
|
||||||
|
DIR=com_err/
|
||||||
|
|
||||||
|
ROOT=`echo $1 | sed -e s/.et$//`
|
||||||
|
BASE=`basename $ROOT`
|
||||||
|
|
||||||
|
$AWK -f ${DIR}/et_h.awk outfile=${BASE}.h $ROOT.et
|
||||||
|
$AWK -f ${DIR}/et_c.awk outfile=${BASE}.c $ROOT.et
|
||||||
79
util/com_err/compile_et.1
Normal file
79
util/com_err/compile_et.1
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
.\" Copyright (c) 1988 Massachusetts Institute of Technology,
|
||||||
|
.\" Student Information Processing Board. All rights reserved.
|
||||||
|
.\"
|
||||||
|
.\" $Header: /mit/krb5/.cvsroot/src/util/et/compile_et.1,v 1.1 1993/06/03 12:29:46 tytso Exp $
|
||||||
|
.\"
|
||||||
|
.TH COMPILE_ET 1 "22 Nov 1988" SIPB
|
||||||
|
.SH NAME
|
||||||
|
compile_et \- error table compiler
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B compile_et
|
||||||
|
file
|
||||||
|
.SH DESCRIPTION
|
||||||
|
.B Compile_et
|
||||||
|
converts a table listing error-code names and associated messages into
|
||||||
|
a C source file suitable for use with the
|
||||||
|
.IR com_err (3)
|
||||||
|
library.
|
||||||
|
|
||||||
|
The source file name must end with a suffix of ``.et''; the file
|
||||||
|
consists of a declaration supplying the name (up to four characters
|
||||||
|
long) of the error-code table:
|
||||||
|
|
||||||
|
.B error_table
|
||||||
|
.I name
|
||||||
|
|
||||||
|
followed by up to 256 entries of the form:
|
||||||
|
|
||||||
|
.B error_code
|
||||||
|
.I name,
|
||||||
|
"
|
||||||
|
.I string
|
||||||
|
"
|
||||||
|
|
||||||
|
and a final
|
||||||
|
|
||||||
|
.B end
|
||||||
|
|
||||||
|
to indicate the end of the table.
|
||||||
|
|
||||||
|
The name of the table is used to construct the name of a subroutine
|
||||||
|
.I initialize_XXXX_error_table
|
||||||
|
which must be called in order for the
|
||||||
|
.I com_err
|
||||||
|
library to recognize the error table.
|
||||||
|
|
||||||
|
The various error codes defined are assigned sequentially increasing
|
||||||
|
numbers (starting with a large number computed as a hash function of
|
||||||
|
the name of the table); thus for compatibility it is suggested that
|
||||||
|
new codes be added only to the end of an existing table, and that no
|
||||||
|
codes be removed from tables.
|
||||||
|
|
||||||
|
The names defined in the table are placed into a C header file with
|
||||||
|
preprocessor directives defining them as integer constants of up to
|
||||||
|
32 bits in magnitude.
|
||||||
|
|
||||||
|
A C source file is also generated which should be compiled and linked
|
||||||
|
with the object files which reference these error codes; it contains
|
||||||
|
the text of the messages and the initialization subroutine. Both C
|
||||||
|
files have names derived from that of the original source file, with
|
||||||
|
the ``.et'' suffix replaced by ``.c'' and ``.h''.
|
||||||
|
|
||||||
|
A ``#'' in the source file is treated as a comment character, and all
|
||||||
|
remaining text to the end of the source line will be ignored.
|
||||||
|
|
||||||
|
.SH BUGS
|
||||||
|
|
||||||
|
Since
|
||||||
|
.B compile_et
|
||||||
|
uses a very simple parser based on
|
||||||
|
.IR yacc (1),
|
||||||
|
its error recovery leaves much to be desired.
|
||||||
|
|
||||||
|
.\" .IR for manual entries
|
||||||
|
.\" .PP for paragraph breaks
|
||||||
|
|
||||||
|
.SH "SEE ALSO"
|
||||||
|
com_err (3).
|
||||||
|
|
||||||
|
Ken Raeburn, "A Common Error Description Library for UNIX".
|
||||||
82
util/com_err/error_message.c
Normal file
82
util/com_err/error_message.c
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
* $Header: /mit/krb5/.cvsroot/src/util/et/error_message.c,v 5.0 1993/04/13 19:56:17 tytso Exp $
|
||||||
|
* $Source: /mit/krb5/.cvsroot/src/util/et/error_message.c,v $
|
||||||
|
* $Locker: $
|
||||||
|
*
|
||||||
|
* Copyright 1987 by the Student Information Processing Board
|
||||||
|
* of the Massachusetts Institute of Technology
|
||||||
|
*
|
||||||
|
* For copyright info, see "mit-sipb-copyright.h".
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include "com_err.h"
|
||||||
|
#include "error_table.h"
|
||||||
|
#include "mit-sipb-copyright.h"
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
static char buffer[25];
|
||||||
|
|
||||||
|
struct et_list * _et_list = (struct et_list *) NULL;
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __STDC__
|
||||||
|
const char * error_message (errcode_t code)
|
||||||
|
#else
|
||||||
|
const char * error_message (code)
|
||||||
|
errcode_t code;
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
int offset;
|
||||||
|
struct et_list *et;
|
||||||
|
int table_num;
|
||||||
|
int started = 0;
|
||||||
|
char *cp;
|
||||||
|
|
||||||
|
offset = code & ((1<<ERRCODE_RANGE)-1);
|
||||||
|
table_num = code - offset;
|
||||||
|
if (!table_num) {
|
||||||
|
#ifdef HAS_SYS_ERRLIST
|
||||||
|
if (offset < sys_nerr)
|
||||||
|
return(sys_errlist[offset]);
|
||||||
|
else
|
||||||
|
goto oops;
|
||||||
|
#else
|
||||||
|
cp = strerror(offset);
|
||||||
|
if (cp)
|
||||||
|
return(cp);
|
||||||
|
else
|
||||||
|
goto oops;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
for (et = _et_list; et; et = et->next) {
|
||||||
|
if (et->table->base == table_num) {
|
||||||
|
/* This is the right table */
|
||||||
|
if (et->table->n_msgs <= offset)
|
||||||
|
goto oops;
|
||||||
|
return(et->table->msgs[offset]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
oops:
|
||||||
|
strcpy (buffer, "Unknown code ");
|
||||||
|
if (table_num) {
|
||||||
|
strcat (buffer, error_table_name (table_num));
|
||||||
|
strcat (buffer, " ");
|
||||||
|
}
|
||||||
|
for (cp = buffer; *cp; cp++)
|
||||||
|
;
|
||||||
|
if (offset >= 100) {
|
||||||
|
*cp++ = '0' + offset / 100;
|
||||||
|
offset %= 100;
|
||||||
|
started++;
|
||||||
|
}
|
||||||
|
if (started || offset >= 10) {
|
||||||
|
*cp++ = '0' + offset / 10;
|
||||||
|
offset %= 10;
|
||||||
|
}
|
||||||
|
*cp++ = '0' + offset;
|
||||||
|
*cp = '\0';
|
||||||
|
return(buffer);
|
||||||
|
}
|
||||||
35
util/com_err/error_table.h
Normal file
35
util/com_err/error_table.h
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 1988 by the Student Information Processing Board of the
|
||||||
|
* Massachusetts Institute of Technology.
|
||||||
|
*
|
||||||
|
* For copyright info, see mit-sipb-copyright.h.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _ET_H
|
||||||
|
/* Are we using ANSI C? */
|
||||||
|
#ifndef __STDC__
|
||||||
|
#define const
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct error_table {
|
||||||
|
char const * const * msgs;
|
||||||
|
long base;
|
||||||
|
int n_msgs;
|
||||||
|
};
|
||||||
|
struct et_list {
|
||||||
|
struct et_list *next;
|
||||||
|
const struct error_table *table;
|
||||||
|
};
|
||||||
|
extern struct et_list * _et_list;
|
||||||
|
|
||||||
|
#define ERRCODE_RANGE 8 /* # of bits to shift table number */
|
||||||
|
#define BITS_PER_CHAR 6 /* # bits to shift per character in name */
|
||||||
|
|
||||||
|
#ifdef __STDC__
|
||||||
|
extern const char *error_table_name(int num);
|
||||||
|
#else
|
||||||
|
extern const char *error_table_name();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define _ET_H
|
||||||
|
#endif
|
||||||
185
util/com_err/et_c.awk
Normal file
185
util/com_err/et_c.awk
Normal file
@@ -0,0 +1,185 @@
|
|||||||
|
BEGIN {
|
||||||
|
char_shift=64
|
||||||
|
## "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
|
||||||
|
c2n["A"]=1
|
||||||
|
c2n["B"]=2
|
||||||
|
c2n["C"]=3
|
||||||
|
c2n["D"]=4
|
||||||
|
c2n["E"]=5
|
||||||
|
c2n["F"]=6
|
||||||
|
c2n["G"]=7
|
||||||
|
c2n["H"]=8
|
||||||
|
c2n["I"]=9
|
||||||
|
c2n["J"]=10
|
||||||
|
c2n["K"]=11
|
||||||
|
c2n["L"]=12
|
||||||
|
c2n["M"]=13
|
||||||
|
c2n["N"]=14
|
||||||
|
c2n["O"]=15
|
||||||
|
c2n["P"]=16
|
||||||
|
c2n["Q"]=17
|
||||||
|
c2n["R"]=18
|
||||||
|
c2n["S"]=19
|
||||||
|
c2n["T"]=20
|
||||||
|
c2n["U"]=21
|
||||||
|
c2n["V"]=22
|
||||||
|
c2n["W"]=23
|
||||||
|
c2n["X"]=24
|
||||||
|
c2n["Y"]=25
|
||||||
|
c2n["Z"]=26
|
||||||
|
c2n["a"]=27
|
||||||
|
c2n["b"]=28
|
||||||
|
c2n["c"]=29
|
||||||
|
c2n["d"]=30
|
||||||
|
c2n["e"]=31
|
||||||
|
c2n["f"]=32
|
||||||
|
c2n["g"]=33
|
||||||
|
c2n["h"]=34
|
||||||
|
c2n["i"]=35
|
||||||
|
c2n["j"]=36
|
||||||
|
c2n["k"]=37
|
||||||
|
c2n["l"]=38
|
||||||
|
c2n["m"]=39
|
||||||
|
c2n["n"]=40
|
||||||
|
c2n["o"]=41
|
||||||
|
c2n["p"]=42
|
||||||
|
c2n["q"]=43
|
||||||
|
c2n["r"]=44
|
||||||
|
c2n["s"]=45
|
||||||
|
c2n["t"]=46
|
||||||
|
c2n["u"]=47
|
||||||
|
c2n["v"]=48
|
||||||
|
c2n["w"]=49
|
||||||
|
c2n["x"]=50
|
||||||
|
c2n["y"]=51
|
||||||
|
c2n["z"]=52
|
||||||
|
c2n["0"]=53
|
||||||
|
c2n["1"]=54
|
||||||
|
c2n["2"]=55
|
||||||
|
c2n["3"]=56
|
||||||
|
c2n["4"]=57
|
||||||
|
c2n["5"]=58
|
||||||
|
c2n["6"]=59
|
||||||
|
c2n["7"]=60
|
||||||
|
c2n["8"]=61
|
||||||
|
c2n["9"]=62
|
||||||
|
c2n["_"]=63
|
||||||
|
}
|
||||||
|
/^#/ { next }
|
||||||
|
/^[ \t]*(error_table|et)[ \t]+[a-zA-Z][a-zA-Z0-9_]+/ {
|
||||||
|
table_number = 0
|
||||||
|
table_name = $2
|
||||||
|
mod_base = 1000000
|
||||||
|
for(i=1; i<=length(table_name); i++) {
|
||||||
|
table_number=(table_number*char_shift)+c2n[substr(table_name,i,1)]
|
||||||
|
}
|
||||||
|
|
||||||
|
# We start playing *_high, *low games here because the some
|
||||||
|
# awk programs do not have the necessary precision (sigh)
|
||||||
|
tab_base_low = table_number % mod_base
|
||||||
|
tab_base_high = int(table_number / mod_base)
|
||||||
|
tab_base_sign = 1;
|
||||||
|
|
||||||
|
# figure out: table_number_base=table_number*256
|
||||||
|
tab_base_low = tab_base_low * 256
|
||||||
|
tab_base_high = (tab_base_high * 256) + \
|
||||||
|
int(tab_base_low / mod_base)
|
||||||
|
tab_base_low = tab_base_low % mod_base
|
||||||
|
|
||||||
|
if (table_number > 128*256*256) {
|
||||||
|
# figure out: table_number_base -= 256*256*256*256
|
||||||
|
# sub_high, sub_low is 256*256*256*256
|
||||||
|
sub_low = 256*256*256 % mod_base
|
||||||
|
sub_high = int(256*256*256 / mod_base)
|
||||||
|
|
||||||
|
sub_low = sub_low * 256
|
||||||
|
sub_high = (sub_high * 256) + int(sub_low / mod_base)
|
||||||
|
sub_low = sub_low % mod_base
|
||||||
|
|
||||||
|
tab_base_low = sub_low - tab_base_low;
|
||||||
|
tab_base_high = sub_high - tab_base_high;
|
||||||
|
tab_base_sign = -1;
|
||||||
|
if (tab_base_low < 0) {
|
||||||
|
tab_base_low = tab_base_low + mod_base
|
||||||
|
tab_base_high--
|
||||||
|
}
|
||||||
|
}
|
||||||
|
print "/*" > outfile
|
||||||
|
print " * " outfile ":" > outfile
|
||||||
|
print " * This file is automatically generated; please do not edit it." > outfile
|
||||||
|
print " */" > outfile
|
||||||
|
|
||||||
|
print "#ifdef __STDC__" > outfile
|
||||||
|
print "#define NOARGS void" > outfile
|
||||||
|
print "#else" > outfile
|
||||||
|
print "#define NOARGS" > outfile
|
||||||
|
print "#define const" > outfile
|
||||||
|
print "#endif" > outfile
|
||||||
|
print "" > outfile
|
||||||
|
print "static const char * const text[] = {" > outfile
|
||||||
|
table_item_count = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
/^[ \t]*(error_code|ec)[ \t]+[A-Z_0-9]+,[ \t]*$/ {
|
||||||
|
skipone=1
|
||||||
|
next
|
||||||
|
}
|
||||||
|
|
||||||
|
/^[ \t]*(error_code|ec)[ \t]+[A-Z_0-9]+,[ \t]*".*"[ \t]*$/ {
|
||||||
|
text=""
|
||||||
|
for (i=3; i<=NF; i++) {
|
||||||
|
text = text FS $i
|
||||||
|
}
|
||||||
|
text=substr(text,2,length(text)-1);
|
||||||
|
printf "\t%s,\n", text > outfile
|
||||||
|
table_item_count++
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
if (skipone) {
|
||||||
|
printf "\t%s,\n", $0 > outfile
|
||||||
|
table_item_count++
|
||||||
|
}
|
||||||
|
skipone=0
|
||||||
|
}
|
||||||
|
END {
|
||||||
|
|
||||||
|
|
||||||
|
print " 0" > outfile
|
||||||
|
print "};" > outfile
|
||||||
|
print "" > outfile
|
||||||
|
print "struct error_table {" > outfile
|
||||||
|
print " char const * const * msgs;" > outfile
|
||||||
|
print " long base;" > outfile
|
||||||
|
print " int n_msgs;" > outfile
|
||||||
|
print "};" > outfile
|
||||||
|
print "struct et_list {" > outfile
|
||||||
|
print " struct et_list *next;" > outfile
|
||||||
|
print " const struct error_table * table;" > outfile
|
||||||
|
print "};" > outfile
|
||||||
|
print "extern struct et_list *_et_list;" > outfile
|
||||||
|
print "" > outfile
|
||||||
|
if (tab_base_high == 0) {
|
||||||
|
print "static const struct error_table et = { text, " \
|
||||||
|
sprintf("%dL, %d };", tab_base_sign*tab_base_low, \
|
||||||
|
table_item_count) > outfile
|
||||||
|
} else {
|
||||||
|
print "static const struct error_table et = { text, " \
|
||||||
|
sprintf("%d%06dL, %d };", tab_base_sign*tab_base_high, \
|
||||||
|
tab_base_low, table_item_count) > outfile
|
||||||
|
}
|
||||||
|
print "" > outfile
|
||||||
|
print "static struct et_list link = { 0, 0 };" > outfile
|
||||||
|
print "" > outfile
|
||||||
|
print "void initialize_" table_name "_error_table (NOARGS);" > outfile
|
||||||
|
print "" > outfile
|
||||||
|
print "void initialize_" table_name "_error_table (NOARGS) {" > outfile
|
||||||
|
print " if (!link.table) {" > outfile
|
||||||
|
print " link.next = _et_list;" > outfile
|
||||||
|
print " link.table = &et;" > outfile
|
||||||
|
print " _et_list = &link;" > outfile
|
||||||
|
print " }" > outfile
|
||||||
|
print "}" > outfile
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
157
util/com_err/et_h.awk
Normal file
157
util/com_err/et_h.awk
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
BEGIN {
|
||||||
|
char_shift=64
|
||||||
|
## "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
|
||||||
|
c2n["A"]=1
|
||||||
|
c2n["B"]=2
|
||||||
|
c2n["C"]=3
|
||||||
|
c2n["D"]=4
|
||||||
|
c2n["E"]=5
|
||||||
|
c2n["F"]=6
|
||||||
|
c2n["G"]=7
|
||||||
|
c2n["H"]=8
|
||||||
|
c2n["I"]=9
|
||||||
|
c2n["J"]=10
|
||||||
|
c2n["K"]=11
|
||||||
|
c2n["L"]=12
|
||||||
|
c2n["M"]=13
|
||||||
|
c2n["N"]=14
|
||||||
|
c2n["O"]=15
|
||||||
|
c2n["P"]=16
|
||||||
|
c2n["Q"]=17
|
||||||
|
c2n["R"]=18
|
||||||
|
c2n["S"]=19
|
||||||
|
c2n["T"]=20
|
||||||
|
c2n["U"]=21
|
||||||
|
c2n["V"]=22
|
||||||
|
c2n["W"]=23
|
||||||
|
c2n["X"]=24
|
||||||
|
c2n["Y"]=25
|
||||||
|
c2n["Z"]=26
|
||||||
|
c2n["a"]=27
|
||||||
|
c2n["b"]=28
|
||||||
|
c2n["c"]=29
|
||||||
|
c2n["d"]=30
|
||||||
|
c2n["e"]=31
|
||||||
|
c2n["f"]=32
|
||||||
|
c2n["g"]=33
|
||||||
|
c2n["h"]=34
|
||||||
|
c2n["i"]=35
|
||||||
|
c2n["j"]=36
|
||||||
|
c2n["k"]=37
|
||||||
|
c2n["l"]=38
|
||||||
|
c2n["m"]=39
|
||||||
|
c2n["n"]=40
|
||||||
|
c2n["o"]=41
|
||||||
|
c2n["p"]=42
|
||||||
|
c2n["q"]=43
|
||||||
|
c2n["r"]=44
|
||||||
|
c2n["s"]=45
|
||||||
|
c2n["t"]=46
|
||||||
|
c2n["u"]=47
|
||||||
|
c2n["v"]=48
|
||||||
|
c2n["w"]=49
|
||||||
|
c2n["x"]=50
|
||||||
|
c2n["y"]=51
|
||||||
|
c2n["z"]=52
|
||||||
|
c2n["0"]=53
|
||||||
|
c2n["1"]=54
|
||||||
|
c2n["2"]=55
|
||||||
|
c2n["3"]=56
|
||||||
|
c2n["4"]=57
|
||||||
|
c2n["5"]=58
|
||||||
|
c2n["6"]=59
|
||||||
|
c2n["7"]=60
|
||||||
|
c2n["8"]=61
|
||||||
|
c2n["9"]=62
|
||||||
|
c2n["_"]=63
|
||||||
|
}
|
||||||
|
/^#/ { next }
|
||||||
|
/^[ \t]*(error_table|et)[ \t]+[a-zA-Z][a-zA-Z0-9_]+/ {
|
||||||
|
table_number = 0
|
||||||
|
table_name = $2
|
||||||
|
mod_base = 1000000
|
||||||
|
for(i=1; i<=length(table_name); i++) {
|
||||||
|
table_number=(table_number*char_shift)+c2n[substr(table_name,i,1)]
|
||||||
|
}
|
||||||
|
# We start playing *_high, *low games here because the some
|
||||||
|
# awk programs do not have the necessary precision (sigh)
|
||||||
|
tab_base_low = table_number % mod_base
|
||||||
|
tab_base_high = int(table_number / mod_base)
|
||||||
|
tab_base_sign = 1;
|
||||||
|
|
||||||
|
# figure out: table_number_base=table_number*256
|
||||||
|
tab_base_low = tab_base_low * 256
|
||||||
|
tab_base_high = (tab_base_high * 256) + \
|
||||||
|
int(tab_base_low / mod_base)
|
||||||
|
tab_base_low = tab_base_low % mod_base
|
||||||
|
|
||||||
|
if (table_number > 128*256*256) {
|
||||||
|
# figure out: table_number_base -= 256*256*256*256
|
||||||
|
# sub_high, sub_low is 256*256*256*256
|
||||||
|
sub_low = 256*256*256 % mod_base
|
||||||
|
sub_high = int(256*256*256 / mod_base)
|
||||||
|
|
||||||
|
sub_low = sub_low * 256
|
||||||
|
sub_high = (sub_high * 256) + int(sub_low / mod_base)
|
||||||
|
sub_low = sub_low % mod_base
|
||||||
|
|
||||||
|
tab_base_low = sub_low - tab_base_low;
|
||||||
|
tab_base_high = sub_high - tab_base_high;
|
||||||
|
tab_base_sign = -1;
|
||||||
|
if (tab_base_low < 0) {
|
||||||
|
tab_base_low = tab_base_low + mod_base
|
||||||
|
tab_base_high--
|
||||||
|
}
|
||||||
|
}
|
||||||
|
curr_low = tab_base_low
|
||||||
|
curr_high = tab_base_high
|
||||||
|
curr_sign = tab_base_sign
|
||||||
|
print "/*" > outfile
|
||||||
|
print " * " outfile ":" > outfile
|
||||||
|
print " * This file is automatically generated; please do not edit it." > outfile
|
||||||
|
print " */" > outfile
|
||||||
|
print "#ifdef __STDC__" > outfile
|
||||||
|
print "#define NOARGS void" > outfile
|
||||||
|
print "#else" > outfile
|
||||||
|
print "#define NOARGS" > outfile
|
||||||
|
print "#define const" > outfile
|
||||||
|
print "#endif" > outfile
|
||||||
|
print "" > outfile
|
||||||
|
}
|
||||||
|
|
||||||
|
/^[ \t]*(error_code|ec)[ \t]+[A-Z_0-9]+,/ {
|
||||||
|
tag=substr($2,1,length($2)-1)
|
||||||
|
if (curr_high == 0) {
|
||||||
|
printf "#define %-40s (%dL)\n", tag, \
|
||||||
|
curr_sign*curr_low > outfile
|
||||||
|
} else {
|
||||||
|
printf "#define %-40s (%d%06dL)\n", tag, curr_high*curr_sign, \
|
||||||
|
curr_low > outfile
|
||||||
|
}
|
||||||
|
curr_low += curr_sign;
|
||||||
|
if (curr_low >= mod_base) {
|
||||||
|
curr_low -= mod_base;
|
||||||
|
curr_high++
|
||||||
|
}
|
||||||
|
if (curr_low < 0) {
|
||||||
|
cur_low += mod_base
|
||||||
|
cur_high--
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
END {
|
||||||
|
print "extern void initialize_" table_name "_error_table (NOARGS);" > outfile
|
||||||
|
if (tab_base_high == 0) {
|
||||||
|
print "#define ERROR_TABLE_BASE_" table_name " (" \
|
||||||
|
sprintf("%d", tab_base_sign*tab_base_low) \
|
||||||
|
"L)" > outfile
|
||||||
|
} else {
|
||||||
|
print "#define ERROR_TABLE_BASE_" table_name " (" \
|
||||||
|
sprintf("%d%06d", tab_base_sign*tab_base_high, \
|
||||||
|
tab_base_low) "L)" > outfile
|
||||||
|
}
|
||||||
|
print "" > outfile
|
||||||
|
print "/* for compatibility with older versions... */" > outfile
|
||||||
|
print "#define init_" table_name "_err_tbl initialize_" table_name "_error_table" > outfile
|
||||||
|
print "#define " table_name "_err_base ERROR_TABLE_BASE_" table_name > outfile
|
||||||
|
}
|
||||||
36
util/com_err/et_name.c
Normal file
36
util/com_err/et_name.c
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 1987 by MIT Student Information Processing Board
|
||||||
|
*
|
||||||
|
* For copyright info, see mit-sipb-copyright.h.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "error_table.h"
|
||||||
|
#include "mit-sipb-copyright.h"
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
static const char char_set[] =
|
||||||
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
|
||||||
|
|
||||||
|
static char buf[6];
|
||||||
|
|
||||||
|
const char * error_table_name(num)
|
||||||
|
int num;
|
||||||
|
{
|
||||||
|
int ch;
|
||||||
|
int i;
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
/* num = aa aaa abb bbb bcc ccc cdd ddd d?? ??? ??? */
|
||||||
|
p = buf;
|
||||||
|
num >>= ERRCODE_RANGE;
|
||||||
|
/* num = ?? ??? ??? aaa aaa bbb bbb ccc ccc ddd ddd */
|
||||||
|
num &= 077777777;
|
||||||
|
/* num = 00 000 000 aaa aaa bbb bbb ccc ccc ddd ddd */
|
||||||
|
for (i = 4; i >= 0; i--) {
|
||||||
|
ch = (num >> BITS_PER_CHAR * i) & ((1 << BITS_PER_CHAR) - 1);
|
||||||
|
if (ch != 0)
|
||||||
|
*p++ = char_set[ch-1];
|
||||||
|
}
|
||||||
|
*p = '\0';
|
||||||
|
return(buf);
|
||||||
|
}
|
||||||
58
util/com_err/init_et.c
Normal file
58
util/com_err/init_et.c
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* $Header: /mit/krb5/.cvsroot/src/util/et/init_et.c,v 5.0 1993/04/13 19:56:25 tytso Exp $
|
||||||
|
* $Source: /mit/krb5/.cvsroot/src/util/et/init_et.c,v $
|
||||||
|
* $Locker: $
|
||||||
|
*
|
||||||
|
* Copyright 1986, 1987, 1988 by MIT Information Systems and
|
||||||
|
* the MIT Student Information Processing Board.
|
||||||
|
*
|
||||||
|
* For copyright info, see mit-sipb-copyright.h.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#ifdef HAVE_STDLIB_H
|
||||||
|
#include <stdlib.h>
|
||||||
|
#endif
|
||||||
|
#include "com_err.h"
|
||||||
|
#include "error_table.h"
|
||||||
|
#include "mit-sipb-copyright.h"
|
||||||
|
|
||||||
|
#ifndef __STDC__
|
||||||
|
#define const
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct foobar {
|
||||||
|
struct et_list etl;
|
||||||
|
struct error_table et;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct et_list * _et_list;
|
||||||
|
|
||||||
|
#ifdef __STDC__
|
||||||
|
int init_error_table(const char * const *msgs, int base, int count)
|
||||||
|
#else
|
||||||
|
int init_error_table(msgs, base, count)
|
||||||
|
const char * const * msgs;
|
||||||
|
int base;
|
||||||
|
int count;
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
struct foobar * new_et;
|
||||||
|
|
||||||
|
if (!base || !count || !msgs)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
new_et = (struct foobar *) malloc(sizeof(struct foobar));
|
||||||
|
if (!new_et)
|
||||||
|
return ENOMEM; /* oops */
|
||||||
|
new_et->etl.table = &new_et->et;
|
||||||
|
new_et->et.msgs = msgs;
|
||||||
|
new_et->et.base = base;
|
||||||
|
new_et->et.n_msgs= count;
|
||||||
|
|
||||||
|
new_et->etl.next = _et_list;
|
||||||
|
_et_list = &new_et->etl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
22
util/com_err/internal.h
Normal file
22
util/com_err/internal.h
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* internal include file for com_err package
|
||||||
|
*/
|
||||||
|
#include "mit-sipb-copyright.h"
|
||||||
|
#ifndef __STDC__
|
||||||
|
#undef const
|
||||||
|
#define const
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#ifdef NEED_SYS_ERRLIST
|
||||||
|
extern char const * const sys_errlist[];
|
||||||
|
extern const int sys_nerr;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* AIX and Ultrix have standard conforming header files. */
|
||||||
|
#if !defined(ultrix) && !defined(_AIX)
|
||||||
|
#ifdef __STDC__
|
||||||
|
void perror (const char *);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
19
util/com_err/mit-sipb-copyright.h
Normal file
19
util/com_err/mit-sipb-copyright.h
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 1987, 1988 by the Student Information Processing Board
|
||||||
|
of the Massachusetts Institute of Technology
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and distribute this software
|
||||||
|
and its documentation for any purpose and without fee is
|
||||||
|
hereby granted, provided that the above copyright notice
|
||||||
|
appear in all copies and that both that copyright notice and
|
||||||
|
this permission notice appear in supporting documentation,
|
||||||
|
and that the names of M.I.T. and the M.I.T. S.I.P.B. not be
|
||||||
|
used in advertising or publicity pertaining to distribution
|
||||||
|
of the software without specific, written prior permission.
|
||||||
|
M.I.T. and the M.I.T. S.I.P.B. make no representations about
|
||||||
|
the suitability of this software for any purpose. It is
|
||||||
|
provided "as is" without express or implied warranty.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
32
util/ipx_sap_types
Normal file
32
util/ipx_sap_types
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
0001 User
|
||||||
|
0002 User Group
|
||||||
|
0003 Print Queue
|
||||||
|
0004 File Server
|
||||||
|
0005 Job Server
|
||||||
|
0006 Gateway
|
||||||
|
0007 Print Server
|
||||||
|
0008 Archive Server
|
||||||
|
0009 Archive Server
|
||||||
|
000A Job Queue
|
||||||
|
000B Administration
|
||||||
|
0021 NAS SNA Gateway
|
||||||
|
0024 Remote Bridge
|
||||||
|
0026 Bridge Server
|
||||||
|
0027 TCP/IP Gateway
|
||||||
|
002D Time Synchronization VAP
|
||||||
|
002E Archive Server Dynamic SAP
|
||||||
|
0047 Advertising Print Server
|
||||||
|
004B Btrieve VAP 5.0
|
||||||
|
0050 Btrieve VAP
|
||||||
|
0053 Print Queue User
|
||||||
|
007A TES NetWare for VMS
|
||||||
|
0098 NetWare Access Server
|
||||||
|
009A Named Pipe Server
|
||||||
|
009E Portable NetWare Unix
|
||||||
|
0107 NetWare 386
|
||||||
|
0111 Test Server
|
||||||
|
0133 NetWare Name Service
|
||||||
|
0166 NetWare Management
|
||||||
|
026A NetWare Management
|
||||||
|
026B Time Server (NetWare 4.0)
|
||||||
|
0278 NetWare Directory Server (NetWare 4.0)
|
||||||
849
util/ncopy.c
Normal file
849
util/ncopy.c
Normal file
@@ -0,0 +1,849 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* ncopy.c
|
||||||
|
*
|
||||||
|
* Copy file on a Netware server without Network Traffic
|
||||||
|
*
|
||||||
|
* Copyright (C) 1996 by Brian Reid and Tom Henderson.
|
||||||
|
*
|
||||||
|
* Send bug reports for ncopy to "breid@tim.com"
|
||||||
|
*
|
||||||
|
* Still to do: support recursive copy with two arguments
|
||||||
|
* Both must be directories. (similar to rcp -r)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <mntent.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include "ncplib.h"
|
||||||
|
|
||||||
|
|
||||||
|
struct NCPMountRec
|
||||||
|
{
|
||||||
|
char *mountDir;
|
||||||
|
char *server;
|
||||||
|
struct ncp_conn *conn;
|
||||||
|
};
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Globals:
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
const char *VersionStr = "0.1";
|
||||||
|
char * ProgramName;
|
||||||
|
|
||||||
|
struct NCPMountRec *NcpMountTable = NULL;
|
||||||
|
int ncpCount = 0;
|
||||||
|
|
||||||
|
/* (initialized) command options */
|
||||||
|
|
||||||
|
int optVersion=0; /* -V TRUE if just want version */
|
||||||
|
int optVerbose=0; /* -v TRUE if want verbose output */
|
||||||
|
int optNice=0; /* -n TRUE if we are cooperative (nice) */
|
||||||
|
int optNiceFactorSel=0; /* -s TRUE if we selected a nice factor */
|
||||||
|
int optNiceFactor=10; /* -s arg, number of 100K blocks to copy
|
||||||
|
before sleeping for a second */
|
||||||
|
__u32 CopyBlockSize = 100000; /* Size of the default block copy size */
|
||||||
|
unsigned int NiceSleepTime=1; /* Number of seconds to sleep in Nice Mode */
|
||||||
|
|
||||||
|
int BlocksCopied=0; /* Number of blocks copied */
|
||||||
|
int MaxNcopyRetries=25; /* Maximum number of times to retry a failed
|
||||||
|
copy before giving up */
|
||||||
|
|
||||||
|
/* Globals needed for signal handlers */
|
||||||
|
int OutputOpen=0; /* True if the ncp output file is open */
|
||||||
|
struct ncp_conn *CurrentConn = NULL; /* Connection of output file */
|
||||||
|
struct ncp_file_info *CurrentFile = NULL; /* File info of output file */
|
||||||
|
|
||||||
|
/* Signal control structures */
|
||||||
|
static struct sigaction sHangupSig;
|
||||||
|
static struct sigaction sInterruptSig;
|
||||||
|
static struct sigaction sQuitSig;
|
||||||
|
static struct sigaction sTermSig;
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static void usage()
|
||||||
|
{
|
||||||
|
fprintf(stderr,"usage: %s [-V]\n", ProgramName);
|
||||||
|
fprintf(stderr," %s [-vn] [-s amt] sourcefile destinationfile|directory\n", ProgramName);
|
||||||
|
fprintf(stderr," %s [-vn] [-s amt] sourcefile [...] directory\n", ProgramName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Return pointer to last component of the path.
|
||||||
|
* Returned string may have one or more "/" left on the end.
|
||||||
|
* ("/" returns pointer to "/", null returns pointer to null)
|
||||||
|
* Return pointer to original string if no "/" in string. (except at end)
|
||||||
|
*/
|
||||||
|
static const char *myBaseName(const char *path)
|
||||||
|
{
|
||||||
|
const char *p;
|
||||||
|
|
||||||
|
for(p = &path[strlen(path)]; p != path; p--) { /* skip ENDING "/" chars */
|
||||||
|
if(*p && *p != '/') break;
|
||||||
|
}
|
||||||
|
if(p==path) return p;
|
||||||
|
for( ; p != path || *p == '/'; p--) {
|
||||||
|
if(*p == '/') return ++p;
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static const char *notDir(const char *path)
|
||||||
|
{
|
||||||
|
struct stat buf;
|
||||||
|
static const char *notDirectory="not a directory";
|
||||||
|
|
||||||
|
if(stat(path, &buf)) return strerror(errno); /* no permission? not exist? */
|
||||||
|
if(!S_ISDIR(buf.st_mode)) return notDirectory; /* not a directory */
|
||||||
|
return (char *) 0; /* OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static int handleOptions(const int argc, char * const argv[])
|
||||||
|
{
|
||||||
|
int opt;
|
||||||
|
|
||||||
|
while ((opt = getopt(argc, argv, "vVns:")) != EOF)
|
||||||
|
{
|
||||||
|
switch (opt) {
|
||||||
|
|
||||||
|
case 'V': /* Version */
|
||||||
|
optVersion=1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'v': /* Verbose output */
|
||||||
|
optVerbose=1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'n': /* Nice, cooperative copy */
|
||||||
|
optNice=1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 's': /* Nice Factor */
|
||||||
|
optNiceFactorSel=1;
|
||||||
|
optNiceFactor=atoi(optarg);
|
||||||
|
if (optNiceFactor < 1) {
|
||||||
|
fprintf(stderr,"%s: -s option requires positive numeric argument > 0\n",
|
||||||
|
ProgramName);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: /* invalid options or options without required arguments */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* TODO: if recursive flag last MUST be a directory, even if only 2 args.
|
||||||
|
*/
|
||||||
|
static int validateFileArgs(const int argc, char * const argv[])
|
||||||
|
{
|
||||||
|
const char *p;
|
||||||
|
if (argc == 0) {
|
||||||
|
fprintf(stderr,"%s: No arguments specified.\n", ProgramName);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if(argc == 1) {
|
||||||
|
fprintf(stderr,"%s: No destination specified.\n", ProgramName);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if((argc > 2) && (p=notDir(argv[argc-1]))) { /* last arg MUST be dir */
|
||||||
|
fprintf(stderr,"%s: %s: %s\n", ProgramName, argv[argc-1], p);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Duplicate a string.
|
||||||
|
*/
|
||||||
|
char *duplicateStr(const char *InStr)
|
||||||
|
{
|
||||||
|
char *dup;
|
||||||
|
if (!InStr) return NULL;
|
||||||
|
dup = (char*)malloc(strlen(InStr)+1);
|
||||||
|
if (dup)
|
||||||
|
strcpy(dup,InStr);
|
||||||
|
return dup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* load a table of ncpfs mount points.
|
||||||
|
*/
|
||||||
|
int loadMountTable()
|
||||||
|
{
|
||||||
|
FILE *mountedFile;
|
||||||
|
struct mntent *mountEntry = NULL;
|
||||||
|
ncpCount = 0;
|
||||||
|
if ( (mountedFile = fopen(MOUNTED,"r")) == NULL) {
|
||||||
|
fprintf(stderr,"ncopy: cannot open %s, %s\n",MOUNTED,strerror(errno));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ( (mountEntry = getmntent(mountedFile)) != NULL) {
|
||||||
|
if (!strcmp(mountEntry->mnt_type,"ncpfs"))
|
||||||
|
ncpCount++;
|
||||||
|
}
|
||||||
|
if (ncpCount) {
|
||||||
|
NcpMountTable = (struct NCPMountRec*)
|
||||||
|
malloc(ncpCount * sizeof(struct NCPMountRec));
|
||||||
|
if (!NcpMountTable) {
|
||||||
|
fprintf(stderr,"Out of memory\n");
|
||||||
|
fclose(mountedFile);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
fseek(mountedFile,0,SEEK_SET);
|
||||||
|
ncpCount = 0;
|
||||||
|
while ( (mountEntry = getmntent(mountedFile)) != NULL) {
|
||||||
|
if (!strcmp(mountEntry->mnt_type,"ncpfs")) {
|
||||||
|
NcpMountTable[ncpCount].mountDir = duplicateStr(mountEntry->mnt_dir);
|
||||||
|
NcpMountTable[ncpCount].server =
|
||||||
|
duplicateStr(mountEntry->mnt_fsname);
|
||||||
|
NcpMountTable[ncpCount].conn = NULL;
|
||||||
|
ncpCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(mountedFile);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Releases the table of ncpfs mount points.
|
||||||
|
*/
|
||||||
|
void releaseMountTable()
|
||||||
|
{
|
||||||
|
int loop;
|
||||||
|
if (!ncpCount) return;
|
||||||
|
for (loop = ncpCount; loop; loop--,ncpCount--) {
|
||||||
|
if (NcpMountTable[loop-1].conn) {
|
||||||
|
ncp_close(NcpMountTable[loop-1].conn);
|
||||||
|
NcpMountTable[loop-1].conn = NULL;
|
||||||
|
}
|
||||||
|
free(NcpMountTable[loop-1].server);
|
||||||
|
free(NcpMountTable[loop-1].mountDir);
|
||||||
|
}
|
||||||
|
free(NcpMountTable);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Finds the index into the mount point table that enables ncp copy for
|
||||||
|
* the file.
|
||||||
|
* Returns -1 if the files do not reference the same server.
|
||||||
|
*/
|
||||||
|
int ncpIndex(const char *InputFile, const char *OutputFile)
|
||||||
|
{
|
||||||
|
int loop;
|
||||||
|
char *mountDir;
|
||||||
|
if (!ncpCount) return -1;
|
||||||
|
|
||||||
|
for (loop = 0; loop < ncpCount; loop++) {
|
||||||
|
mountDir = NcpMountTable[loop].mountDir;
|
||||||
|
if (!strncmp(mountDir,InputFile,strlen(mountDir)) &&
|
||||||
|
!strncmp(mountDir,OutputFile,strlen(mountDir))) return loop;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Does a regular buffered file copy.
|
||||||
|
* This is used if we cannot use the Netware file copy.
|
||||||
|
*/
|
||||||
|
int normalFileCopy(const char *InputFile, const char *OutputFile,
|
||||||
|
char *Buffer,int BufferSize,
|
||||||
|
const char *paramInputFile,
|
||||||
|
const char *paramOutputFile)
|
||||||
|
{
|
||||||
|
int fdIn, fdOut;
|
||||||
|
long fileSize,totalSize;
|
||||||
|
struct stat statBuf;
|
||||||
|
fdIn = open(InputFile,O_RDONLY);
|
||||||
|
if (fdIn == -1) {
|
||||||
|
fprintf(stderr,"%s: Cannot open %s, %s\n",ProgramName,paramInputFile,
|
||||||
|
strerror(errno));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (fstat(fdIn,&statBuf)) {
|
||||||
|
fprintf(stderr,"%s: Cannot stat %s, %s\n",ProgramName,paramInputFile,
|
||||||
|
strerror(errno));
|
||||||
|
close(fdIn);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if(S_ISDIR(statBuf.st_mode)) {
|
||||||
|
close(fdIn);
|
||||||
|
fprintf(stderr,"%s: %s: omitting directory\n",ProgramName,paramInputFile);
|
||||||
|
return 0; /* At this point, don't consider this a fatal error */
|
||||||
|
}
|
||||||
|
|
||||||
|
fdOut = open(OutputFile,O_CREAT | O_TRUNC | O_WRONLY,statBuf.st_mode);
|
||||||
|
if (fdOut == -1) {
|
||||||
|
fprintf(stderr,"%s: Cannot create %s, %s\n",ProgramName,paramOutputFile,
|
||||||
|
strerror(errno));
|
||||||
|
close(fdIn);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
fileSize = lseek(fdIn,0,SEEK_END);
|
||||||
|
if (fileSize < 0) {
|
||||||
|
fprintf(stderr,"%s: lseek error on %s, %s\n",ProgramName,paramInputFile,
|
||||||
|
strerror(errno));
|
||||||
|
close(fdOut);
|
||||||
|
close(fdIn);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
lseek(fdIn,0,SEEK_SET);
|
||||||
|
if (optVerbose) {
|
||||||
|
printf("Normal copy: %s -> %s 0%%",paramInputFile,paramOutputFile);
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
totalSize = fileSize;
|
||||||
|
while (fileSize) {
|
||||||
|
int currentMove;
|
||||||
|
int writeAmt;
|
||||||
|
currentMove = (fileSize > BufferSize) ? BufferSize : fileSize;
|
||||||
|
if (read(fdIn,Buffer,currentMove) != currentMove) {
|
||||||
|
fprintf(stderr,"%s: Error reading %s, %s\n",ProgramName,paramInputFile,
|
||||||
|
strerror(errno));
|
||||||
|
close(fdIn);
|
||||||
|
close(fdOut);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
writeAmt = write(fdOut,Buffer,currentMove);
|
||||||
|
if (writeAmt < 0) {
|
||||||
|
fprintf(stderr,"%s: Error writing %s, %s\n",ProgramName,paramOutputFile,
|
||||||
|
strerror(errno));
|
||||||
|
close(fdIn);
|
||||||
|
close(fdOut);
|
||||||
|
return 1;
|
||||||
|
} else if (writeAmt == 0) {
|
||||||
|
fprintf(stderr,"%s: Out of space on destination device writing %s\n",
|
||||||
|
ProgramName,OutputFile);
|
||||||
|
close(fdIn);
|
||||||
|
close(fdOut);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
fileSize -= currentMove;
|
||||||
|
if (optVerbose) {
|
||||||
|
printf("\rNormal copy: %s -> %s %ld%%",paramInputFile,paramOutputFile,(100 - (fileSize * 100/totalSize)));
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close(fdOut);
|
||||||
|
close(fdIn);
|
||||||
|
if (optVerbose)
|
||||||
|
printf("\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Converts a string to upper case.
|
||||||
|
* Netware file names need to be all upper case.
|
||||||
|
*/
|
||||||
|
char *upString(char *str)
|
||||||
|
{
|
||||||
|
char *alias = str;
|
||||||
|
while (*alias) {
|
||||||
|
*alias = toupper(*alias);
|
||||||
|
++alias;
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Locates the first occurrance of a single character in the input string.
|
||||||
|
* returns -1 if the character is not found.
|
||||||
|
*/
|
||||||
|
int stringPosition(const char *str,char token)
|
||||||
|
{
|
||||||
|
const char *alias = str;
|
||||||
|
while (*alias) {
|
||||||
|
if (*alias == token) return alias - str;
|
||||||
|
alias++;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Walks up the directory path building info structures along the way
|
||||||
|
* in order to get a dir_handle.
|
||||||
|
* This will mangle the input "FileString", leaving just the file name
|
||||||
|
* component in it when it is finished.
|
||||||
|
*/
|
||||||
|
int getDirHandle(struct ncp_conn *conn, char *FileString, __u8 *NewDirHandle)
|
||||||
|
{
|
||||||
|
struct nw_info_struct info1,info2;
|
||||||
|
int currentLevel = 0;
|
||||||
|
int k;
|
||||||
|
struct nw_info_struct *parentInfo = NULL;
|
||||||
|
struct nw_info_struct *currentInfo = NULL;
|
||||||
|
|
||||||
|
while ( (k = stringPosition(FileString,'/')) >= 0) {
|
||||||
|
FileString[k] = 0;
|
||||||
|
if (!currentLevel) {
|
||||||
|
parentInfo = NULL;
|
||||||
|
currentInfo = &info1;
|
||||||
|
} else if (currentLevel % 2) {
|
||||||
|
parentInfo = &info1;
|
||||||
|
currentInfo = &info2;
|
||||||
|
} else {
|
||||||
|
parentInfo = &info2;
|
||||||
|
currentInfo = &info1;
|
||||||
|
}
|
||||||
|
if (ncp_do_lookup(conn, parentInfo, FileString,
|
||||||
|
currentInfo) != 0) {
|
||||||
|
fprintf(stderr,"%s: Ncp lookup failed on directory %s--%s\n",
|
||||||
|
ProgramName,FileString,strerror(errno));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
++currentLevel;
|
||||||
|
memmove(FileString,FileString+k+1,strlen(FileString+k+1)+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ncp_alloc_short_dir_handle(conn, currentInfo, NCP_ALLOC_TEMPORARY,
|
||||||
|
NewDirHandle) != 0) {
|
||||||
|
fprintf(stderr,"%s: Ncp alloc dir handle failed--%s\n",
|
||||||
|
ProgramName,strerror(errno));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Interfaces with the ncplib to do the netware copy of the file.
|
||||||
|
*/
|
||||||
|
int netwareCopyFile(int ncpMountIndex, const char *sourcefile,
|
||||||
|
const char *destfile,
|
||||||
|
const char *paramInputFile,
|
||||||
|
const char *paramOutputFile)
|
||||||
|
{
|
||||||
|
__u8 source_dir_handle;
|
||||||
|
__u8 dest_dir_handle;
|
||||||
|
struct ncp_file_info source_file;
|
||||||
|
struct ncp_file_info dest_file;
|
||||||
|
__u32 amountCopied;
|
||||||
|
__u32 amtLeft;
|
||||||
|
__u32 totalSize;
|
||||||
|
__u32 sourceOff;
|
||||||
|
__u32 thisMove;
|
||||||
|
int stroffset;
|
||||||
|
int retValue;
|
||||||
|
char *sourceDup;
|
||||||
|
char *destDup;
|
||||||
|
struct ncp_conn *sourceconn;
|
||||||
|
int retryCount;
|
||||||
|
long err = 0;
|
||||||
|
|
||||||
|
/* Establish a connection to a Netware mount point if
|
||||||
|
one is not already established. */
|
||||||
|
if (!NcpMountTable[ncpMountIndex].conn) {
|
||||||
|
NcpMountTable[ncpMountIndex].conn =
|
||||||
|
ncp_open_mount(NcpMountTable[ncpMountIndex].mountDir,&err);
|
||||||
|
if (err) {
|
||||||
|
com_err(ProgramName,err,"opening ncp connection on mount point %s",
|
||||||
|
NcpMountTable[ncpMountIndex].mountDir);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sourceconn = NcpMountTable[ncpMountIndex].conn;
|
||||||
|
|
||||||
|
/* Duplicate and upper case the file names so we do not trample
|
||||||
|
on the input strings */
|
||||||
|
stroffset = strlen(NcpMountTable[ncpMountIndex].mountDir) + 1;
|
||||||
|
sourceDup = duplicateStr(sourcefile+stroffset);
|
||||||
|
destDup = duplicateStr(destfile+stroffset);
|
||||||
|
if (!sourceDup || !destDup) {
|
||||||
|
fprintf(stderr,"%s: Malloc failed duplicating file names\n",
|
||||||
|
ProgramName);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
upString(sourceDup);
|
||||||
|
upString(destDup);
|
||||||
|
|
||||||
|
/* Get Handles to the input and output directories */
|
||||||
|
if (getDirHandle(sourceconn,sourceDup,&source_dir_handle) ||
|
||||||
|
getDirHandle(sourceconn,destDup,&dest_dir_handle)) {
|
||||||
|
free(sourceDup);
|
||||||
|
free(destDup);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Open the input and output files. */
|
||||||
|
if (ncp_open_file(sourceconn, source_dir_handle, sourceDup,0,AR_READ,
|
||||||
|
&source_file) != 0) {
|
||||||
|
fprintf(stderr,"%s: Cannot open %s--%s\n",
|
||||||
|
ProgramName,paramInputFile,strerror(errno));
|
||||||
|
free(sourceDup);
|
||||||
|
free(destDup);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ncp_create_file(sourceconn, dest_dir_handle, destDup,
|
||||||
|
source_file.file_attributes, &dest_file) != 0) {
|
||||||
|
fprintf(stderr,"%s: Cannot create %s--%s\n",ProgramName, paramOutputFile,
|
||||||
|
strerror(errno));
|
||||||
|
ncp_close_file(sourceconn,source_file.file_id);
|
||||||
|
free(sourceDup);
|
||||||
|
free(destDup);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/* Set globals in case a signal happens while copying */
|
||||||
|
CurrentConn = sourceconn;
|
||||||
|
CurrentFile = &dest_file;
|
||||||
|
OutputOpen = 1;
|
||||||
|
|
||||||
|
free(sourceDup);
|
||||||
|
free(destDup);
|
||||||
|
|
||||||
|
retValue = 0;
|
||||||
|
if (optVerbose) {
|
||||||
|
printf("NetWare copy: %s -> %s 0%%",paramInputFile,paramOutputFile);
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The main copy loop. */
|
||||||
|
|
||||||
|
amtLeft = totalSize = source_file.file_length;
|
||||||
|
sourceOff = 0;
|
||||||
|
retryCount = 0;
|
||||||
|
|
||||||
|
while (amtLeft && retryCount < MaxNcopyRetries) {
|
||||||
|
int ncopyRetValue;
|
||||||
|
if (amtLeft > CopyBlockSize)
|
||||||
|
thisMove = CopyBlockSize;
|
||||||
|
else
|
||||||
|
thisMove = amtLeft;
|
||||||
|
/* If we are being nice and we've copied enough blocks, go to sleep */
|
||||||
|
if (optNice) {
|
||||||
|
if (BlocksCopied == optNiceFactor) {
|
||||||
|
sleep(NiceSleepTime);
|
||||||
|
BlocksCopied=0;
|
||||||
|
} else
|
||||||
|
++BlocksCopied;
|
||||||
|
}
|
||||||
|
ncopyRetValue = ncp_copy_file(sourceconn, source_file.file_id,
|
||||||
|
dest_file.file_id, sourceOff,sourceOff,
|
||||||
|
thisMove,&amountCopied);
|
||||||
|
if (ncopyRetValue != 0) {
|
||||||
|
/* In my testing this only happens when you run out of space
|
||||||
|
on the server.
|
||||||
|
Netware seems to wait a bit before reporting space recently
|
||||||
|
free'd. I will just wait a bit before bombin */
|
||||||
|
sleep(1); /* Sleep for a second and try again */
|
||||||
|
retryCount++;
|
||||||
|
amountCopied = thisMove = 0;
|
||||||
|
}
|
||||||
|
if (amountCopied != thisMove) {
|
||||||
|
fprintf(stderr,"%s: Warning, amountCopied (%u) != thisMove (%u)\n",
|
||||||
|
ProgramName,(unsigned int)amountCopied,(unsigned int)thisMove);
|
||||||
|
}
|
||||||
|
#ifdef NCOPY_DEBUG
|
||||||
|
fprintf(stderr,"Copied %u (actual %u)\n",(unsigned int)thisMove,
|
||||||
|
(unsigned int)amountCopied);
|
||||||
|
#endif
|
||||||
|
amtLeft -= amountCopied;
|
||||||
|
sourceOff += amountCopied;
|
||||||
|
if (optVerbose) {
|
||||||
|
printf("\rNetWare copy: %s -> %s %ld%%",paramInputFile,paramOutputFile,
|
||||||
|
(100 - (long)((float)amtLeft /(float)totalSize * 100.0)));
|
||||||
|
if (retryCount)
|
||||||
|
printf(" %d retries",retryCount);
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (retryCount >= MaxNcopyRetries)
|
||||||
|
retValue = 1;
|
||||||
|
if (optVerbose)
|
||||||
|
printf("\n");
|
||||||
|
if (ncp_close_file(sourceconn,dest_file.file_id) != 0) {
|
||||||
|
fprintf(stderr,"%s: Close failed for %s\n",ProgramName,paramOutputFile);
|
||||||
|
retValue = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clear signal handling globals */
|
||||||
|
OutputOpen = 0;
|
||||||
|
CurrentConn = NULL;
|
||||||
|
CurrentFile = NULL;
|
||||||
|
|
||||||
|
if (ncp_close_file(sourceconn,source_file.file_id) != 0) {
|
||||||
|
fprintf(stderr,"%s: Close failed for %s\n",ProgramName,paramInputFile);
|
||||||
|
retValue = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ncp_dealloc_dir_handle(sourceconn, dest_dir_handle) != 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr,"%s: Dealloc dir handle error for %s\n",ProgramName,
|
||||||
|
paramOutputFile);
|
||||||
|
retValue = 1;
|
||||||
|
}
|
||||||
|
if (ncp_dealloc_dir_handle(sourceconn, source_dir_handle) != 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr,"%s: Dealloc dir handle error for %s\n",ProgramName,
|
||||||
|
paramInputFile);
|
||||||
|
retValue = 1;
|
||||||
|
}
|
||||||
|
return retValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Decides whether to use the traditional file copy or the netware remote
|
||||||
|
* file copy.
|
||||||
|
*/
|
||||||
|
int copyFiles(const char *realsource, const char *realdestination,
|
||||||
|
const char *paraminputfile, const char *paramoutputfile)
|
||||||
|
{
|
||||||
|
int oldUMask;
|
||||||
|
char fileBuffer[24000];
|
||||||
|
int retVal = 0;
|
||||||
|
int ncpMountIndex = ncpIndex(realsource,realdestination);
|
||||||
|
#ifdef NCOPY_DEBUG
|
||||||
|
printf("Real Source '%s'\n"
|
||||||
|
"Real Dest '%s'\n"
|
||||||
|
"Param Src '%s'\n"
|
||||||
|
"Param Dest '%s'\n",realsource,realdestination,paraminputfile,
|
||||||
|
paramoutputfile);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
oldUMask = umask(0);
|
||||||
|
if (ncpMountIndex < 0)
|
||||||
|
retVal = normalFileCopy(realsource,realdestination,fileBuffer,
|
||||||
|
sizeof(fileBuffer),
|
||||||
|
paraminputfile,paramoutputfile);
|
||||||
|
else
|
||||||
|
retVal = netwareCopyFile(ncpMountIndex,realsource,realdestination,
|
||||||
|
paraminputfile,paramoutputfile);
|
||||||
|
umask(oldUMask);
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
*
|
||||||
|
* HERE
|
||||||
|
*
|
||||||
|
* Brian may NEED "fake" path if he prints error messages?
|
||||||
|
* or I may need a way to get his error messages so I can
|
||||||
|
* print them with the "fake" path.
|
||||||
|
* My current error messages are on the REAL path, which would be confusing...
|
||||||
|
*
|
||||||
|
* (1-source problem, 2-destination problem, 3-other fatal)
|
||||||
|
* We need to decide when to exit or continue the loop,
|
||||||
|
* and what to return when we do exit the loop.
|
||||||
|
* Is it failure if 3 files are to be copied, and 1 fails?
|
||||||
|
* If one copy fails, we stay in the loop, right?
|
||||||
|
* Is it failure if destination fails?
|
||||||
|
* Do we Stay in the loop?
|
||||||
|
*/
|
||||||
|
static int copyRealPaths(const char *source, const char *destination)
|
||||||
|
{
|
||||||
|
char realsource[MAXPATHLEN*2];
|
||||||
|
char realdestination[MAXPATHLEN*2];
|
||||||
|
char dirPart[MAXPATHLEN+1];
|
||||||
|
char filePart[MAXPATHLEN+1];
|
||||||
|
const char *p;
|
||||||
|
|
||||||
|
if(realpath(source, realsource) == 0) { /* the source must at least exist */
|
||||||
|
fprintf(stderr,"%s: %s: %s\n",
|
||||||
|
ProgramName, source, strerror(errno));
|
||||||
|
return 1; /* indicate a "source" problem */
|
||||||
|
}
|
||||||
|
if(realpath(destination, realdestination) == 0) {/* dest file missing? OK */
|
||||||
|
strncpy(dirPart, destination, MAXPATHLEN); /* but "dirpart" must work */
|
||||||
|
dirPart[MAXPATHLEN] = 0;
|
||||||
|
p=myBaseName(dirPart);
|
||||||
|
strcpy(filePart, p);
|
||||||
|
dirPart[p - dirPart] = 0; /* isolates "directory" part from "file part" */
|
||||||
|
if(realpath(dirPart, realdestination) == 0) {
|
||||||
|
fprintf(stderr,"%s: %s: %s\n",
|
||||||
|
ProgramName, dirPart, strerror(errno));
|
||||||
|
return 2; /* indicate a "destination" problem */
|
||||||
|
}
|
||||||
|
if(*realdestination != '/' || *(realdestination+1)) strcat(realdestination, "/");
|
||||||
|
strcat(realdestination, filePart);
|
||||||
|
}
|
||||||
|
/* becomes prog exit code */
|
||||||
|
|
||||||
|
/* Test Cases: (Where file/dir may or may not exist)
|
||||||
|
* "", file, file/, dir, dir/
|
||||||
|
* /, //, /dir, /dir/, /file, /file/,
|
||||||
|
* /tmp/file, /tmp/file/, tmp/file, tmp/file/,
|
||||||
|
* /tmp/dir, /tmp/dir/, tmp/dir, tmp/dir/
|
||||||
|
*/
|
||||||
|
return copyFiles(realsource, realdestination,source,destination);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* guaranteed argc is at least 2 and
|
||||||
|
* if argc > 2 last parameter is a directory
|
||||||
|
* by validateFileArgs()
|
||||||
|
*/
|
||||||
|
static int handleFileArgs(int argc, char * const argv[])
|
||||||
|
{
|
||||||
|
int loop;
|
||||||
|
const char *destination;
|
||||||
|
int copyStatus;
|
||||||
|
int returnCode=0; /* default program exit code */
|
||||||
|
const char *baseNamePtr;
|
||||||
|
char destinationfile[MAXPATHLEN*2];
|
||||||
|
|
||||||
|
destination=argv[argc-1]; /* get LAST argument */
|
||||||
|
for (loop = 0; loop < (argc-1); loop++) { /* all file arguments, but last */
|
||||||
|
strncpy(destinationfile, destination, MAXPATHLEN);
|
||||||
|
destinationfile[MAXPATHLEN]=0;
|
||||||
|
if((argc > 2) || (!notDir(argv[argc-1]))) { /* destination is a dir */
|
||||||
|
if(*destinationfile != '/' || *(destinationfile+1)) strcat(destinationfile,"/");
|
||||||
|
baseNamePtr=myBaseName(argv[loop]); /* get the file name */
|
||||||
|
strcat(destinationfile,baseNamePtr); /* add it on end of directory */
|
||||||
|
}
|
||||||
|
copyStatus=copyRealPaths(argv[loop], destinationfile); /* do the copy */
|
||||||
|
if(copyStatus > 1) return copyStatus; /* fatal failure? bye */
|
||||||
|
if(copyStatus == 1) returnCode=1; /* a partial failure? we can continue */
|
||||||
|
}
|
||||||
|
return returnCode; /* return what will be the program exit code */
|
||||||
|
}
|
||||||
|
/****************************************************************************
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static void handleSignals(int sigNumber)
|
||||||
|
{
|
||||||
|
/* Ignore Signal Handling while cleaning up */
|
||||||
|
|
||||||
|
/* SIGHUP */
|
||||||
|
sHangupSig.sa_handler=SIG_IGN;
|
||||||
|
if(sigaction(SIGHUP, &sHangupSig, NULL) == -1) {
|
||||||
|
fprintf(stderr,"%s: Reset to ignore SIGHUP signal failed: %s",
|
||||||
|
ProgramName, strerror(errno));
|
||||||
|
}
|
||||||
|
/* SIGINT */
|
||||||
|
sInterruptSig.sa_handler=SIG_IGN;
|
||||||
|
if(sigaction(SIGINT, &sInterruptSig, NULL) == -1) {
|
||||||
|
fprintf(stderr,"%s: Reset to ignore SIGINT signal failed: %s",
|
||||||
|
ProgramName, strerror(errno));
|
||||||
|
}
|
||||||
|
/* SIGQUIT */
|
||||||
|
sQuitSig.sa_handler=SIG_IGN;
|
||||||
|
if(sigaction(SIGQUIT, &sQuitSig, NULL) == -1) {
|
||||||
|
fprintf(stderr,"%s: Reset to ignore SIGQUIT signal failed: %s",
|
||||||
|
ProgramName, strerror(errno));
|
||||||
|
}
|
||||||
|
/* SIGTERM */
|
||||||
|
sTermSig.sa_handler=SIG_IGN;
|
||||||
|
if(sigaction(SIGTERM, &sTermSig, NULL) == -1) {
|
||||||
|
fprintf(stderr,"%s: Reset to ignore SIGTERM signal failed: %s",
|
||||||
|
ProgramName, strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we don't close the ncp output file, we have to ncpumount and
|
||||||
|
ncpmount before we can get rid of it. */
|
||||||
|
if (OutputOpen) {
|
||||||
|
/* Issue a warning if we cannot close the file */
|
||||||
|
/* If an error occurs we probably have to umount/mount to
|
||||||
|
remove the file */
|
||||||
|
if (ncp_close_file(CurrentConn,CurrentFile->file_id) != 0) {
|
||||||
|
fprintf(stderr,"%s: unclean close of output file",ProgramName);
|
||||||
|
}
|
||||||
|
OutputOpen = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
exit(128 + sigNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* We'll trap Hangup, Interrupt, Quit or Terminate
|
||||||
|
*/
|
||||||
|
static int trapSignals()
|
||||||
|
{
|
||||||
|
if(sigaction(SIGHUP, NULL, &sHangupSig)) { /* init structure fields */
|
||||||
|
fprintf(stderr,"%s: Get HANGUP signal action failed: %s",
|
||||||
|
ProgramName, strerror(errno));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
sHangupSig.sa_handler = handleSignals;
|
||||||
|
if(sigaction(SIGHUP, &sHangupSig, NULL) == -1) {
|
||||||
|
fprintf(stderr,"%s: Reset HANGUP signal action failed: %s",
|
||||||
|
ProgramName, strerror(errno));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if(sigaction(SIGINT, NULL, &sInterruptSig)) { /* init structure fields */
|
||||||
|
fprintf(stderr,"%s: Get INTERRUPT signal action failed: %s",
|
||||||
|
ProgramName, strerror(errno));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
sInterruptSig.sa_handler = handleSignals;
|
||||||
|
if(sigaction(SIGINT, &sInterruptSig, NULL) == -1) {
|
||||||
|
fprintf(stderr,"%s: Reset INTERRUPT signal action failed: %s",
|
||||||
|
ProgramName, strerror(errno));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if(sigaction(SIGQUIT, NULL, &sQuitSig)) { /* init structure fields */
|
||||||
|
fprintf(stderr,"%s: Get QUIT signal action failed: %s",
|
||||||
|
ProgramName, strerror(errno));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
sQuitSig.sa_handler = handleSignals;
|
||||||
|
if(sigaction(SIGQUIT, &sQuitSig, NULL) == -1) {
|
||||||
|
fprintf(stderr,"%s: Reset QUIT signal action failed: %s",
|
||||||
|
ProgramName, strerror(errno));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if(sigaction(SIGTERM, NULL, &sTermSig)) { /* init structure fields */
|
||||||
|
fprintf(stderr,"%s: Get TERMINATE signal action failed: %s",
|
||||||
|
ProgramName, strerror(errno));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
sTermSig.sa_handler = handleSignals;
|
||||||
|
if(sigaction(SIGTERM, &sTermSig, NULL) == -1) {
|
||||||
|
fprintf(stderr,"%s: Reset TERMINATE signal action failed: %s",
|
||||||
|
ProgramName, strerror(errno));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int main(int argc, char * const argv[])
|
||||||
|
{
|
||||||
|
int returnCode;
|
||||||
|
ProgramName=argv[0];
|
||||||
|
|
||||||
|
if(handleOptions(argc, argv)) { /* bad option, missing option parameter */
|
||||||
|
usage();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if(optVersion) { /* only option not requiring any arguments */
|
||||||
|
printf("%s version %s\n", ProgramName, VersionStr);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(validateFileArgs(argc - optind, argv + optind)) {
|
||||||
|
usage();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if(trapSignals()) return 1;
|
||||||
|
loadMountTable();
|
||||||
|
returnCode = handleFileArgs(argc - optind, argv + optind);
|
||||||
|
releaseMountTable();
|
||||||
|
return returnCode;
|
||||||
|
}
|
||||||
1277
util/ncplib.c
1277
util/ncplib.c
File diff suppressed because it is too large
Load Diff
218
util/ncplib.h
218
util/ncplib.h
@@ -17,6 +17,7 @@
|
|||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
#include "ipxlib.h"
|
#include "ipxlib.h"
|
||||||
|
#include "com_err.h"
|
||||||
|
|
||||||
#ifndef memzero
|
#ifndef memzero
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -78,46 +79,51 @@ struct ncp_search_seq {
|
|||||||
int namespace;
|
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
|
/* 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
|
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
|
the argument list, opens the connection and removes the arguments
|
||||||
from the list. It was designed after the X Windows init
|
from the list. It was designed after the X Windows init
|
||||||
functions. */
|
functions. */
|
||||||
int
|
struct ncp_conn *
|
||||||
ncp_initialize(struct ncp_conn *conn,
|
ncp_initialize(int *argc, char **argv,
|
||||||
int *argc, char **argv,
|
int login_necessary, long *err);
|
||||||
int login_necessary);
|
|
||||||
|
|
||||||
/* You can login as another object by this procedure. As a first use
|
/* You can login as another object by this procedure. As a first use
|
||||||
pserver comes to mind. */
|
pserver comes to mind. */
|
||||||
int
|
struct ncp_conn *
|
||||||
ncp_initialize_as(struct ncp_conn *conn,
|
ncp_initialize_as(int *argc, char **argv,
|
||||||
int *argc, char **argv,
|
int login_necessary, int login_type, long *err);
|
||||||
int login_necessary, int login_type);
|
|
||||||
|
|
||||||
|
|
||||||
/* Open an existing permanent connection */
|
/* Open an existing permanent connection */
|
||||||
int
|
struct ncp_conn *
|
||||||
ncp_open(struct ncp_conn *conn,
|
ncp_open(const struct ncp_conn_spec *spec, long *err);
|
||||||
const struct ncp_conn_spec *spec);
|
|
||||||
|
|
||||||
/* Open a connection on an existing mount point */
|
/* Open a connection on an existing mount point */
|
||||||
int
|
struct ncp_conn *
|
||||||
ncp_open_mount(struct ncp_conn *conn,
|
ncp_open_mount(const char *mount_point, long *err);
|
||||||
const char *mount_point);
|
|
||||||
|
|
||||||
/* Detach from and destroy a permanent connection */
|
/* Find a permanent connection that fits the spec, return NULL if
|
||||||
int
|
* there is none. */
|
||||||
ncp_destroy_permanent(struct ncp_conn *conn);
|
char *
|
||||||
|
ncp_find_permanent(const struct ncp_conn_spec *spec);
|
||||||
|
|
||||||
/* Create a temporary connection */
|
/* Find the address of a file server */
|
||||||
int
|
struct sockaddr_ipx *
|
||||||
ncp_open_temporary(struct ncp_conn *conn,
|
ncp_find_fileserver(const char *server_name, long *err);
|
||||||
const struct ncp_conn_spec *spec);
|
|
||||||
|
|
||||||
/* Detach from a permanent connection or destroy a temporary
|
/* Detach from a permanent connection or destroy a temporary
|
||||||
connection */
|
connection */
|
||||||
int
|
long
|
||||||
ncp_close(struct ncp_conn *conn);
|
ncp_close(struct ncp_conn *conn);
|
||||||
|
|
||||||
/* like getmntent, get_ncp_conn_ent scans /etc/mtab for usable
|
/* like getmntent, get_ncp_conn_ent scans /etc/mtab for usable
|
||||||
@@ -140,124 +146,200 @@ ncp_get_conn_ent(FILE *filep);
|
|||||||
|
|
||||||
struct ncp_conn_spec *
|
struct ncp_conn_spec *
|
||||||
ncp_find_conn_spec(const char *server, const char *user, const char *password,
|
ncp_find_conn_spec(const char *server, const char *user, const char *password,
|
||||||
uid_t uid);
|
uid_t uid, long *err);
|
||||||
|
|
||||||
int
|
long
|
||||||
ncp_get_file_server_description_strings(struct ncp_conn *conn,
|
ncp_get_file_server_description_strings(struct ncp_conn *conn,
|
||||||
char target[512]);
|
char target[512]);
|
||||||
|
|
||||||
int
|
long
|
||||||
ncp_get_file_server_time(struct ncp_conn *conn, time_t *target);
|
ncp_get_file_server_time(struct ncp_conn *conn, time_t *target);
|
||||||
|
|
||||||
int
|
long
|
||||||
ncp_get_connlist(struct ncp_conn *conn, __u32 last_id,
|
ncp_get_connlist(struct ncp_conn *conn,
|
||||||
__u16 object_type, const char *object_name,
|
__u16 object_type, const char *object_name,
|
||||||
int *returned_no, __u16 conn_numbers[256]);
|
int *returned_no, __u8 conn_numbers[256]);
|
||||||
|
|
||||||
int
|
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,
|
ncp_get_encryption_key(struct ncp_conn *conn,
|
||||||
char *target);
|
char *target);
|
||||||
int
|
long
|
||||||
ncp_get_bindery_object_id(struct ncp_conn *conn,
|
ncp_get_bindery_object_id(struct ncp_conn *conn,
|
||||||
__u16 object_type,
|
__u16 object_type,
|
||||||
const char *object_name,
|
const char *object_name,
|
||||||
struct ncp_bindery_object *target);
|
struct ncp_bindery_object *target);
|
||||||
int
|
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,
|
ncp_scan_bindery_object(struct ncp_conn *conn,
|
||||||
__u32 last_id, __u16 object_type, char *search_string,
|
__u32 last_id, __u16 object_type, char *search_string,
|
||||||
struct ncp_bindery_object *target);
|
struct ncp_bindery_object *target);
|
||||||
int
|
long
|
||||||
|
ncp_create_bindery_object(struct ncp_conn *conn,
|
||||||
|
struct ncp_bindery_object *source);
|
||||||
|
long
|
||||||
|
ncp_delete_bindery_object(struct ncp_conn *conn,
|
||||||
|
__u16 object_type,
|
||||||
|
const char *object_name);
|
||||||
|
|
||||||
|
struct ncp_prop_login_control {
|
||||||
|
__u8 AccountExpireDate[3] __attribute__ ((packed));
|
||||||
|
__u8 Disabled __attribute__ ((packed));
|
||||||
|
__u8 PasswordExpireDate[3] __attribute__ ((packed));
|
||||||
|
__u8 GraceLogins __attribute__ ((packed));
|
||||||
|
__u16 PasswordExpireInterval __attribute__ ((packed));
|
||||||
|
__u8 MaxGraceLogins __attribute__ ((packed));
|
||||||
|
__u8 MinPasswordLength __attribute__ ((packed));
|
||||||
|
__u16 MaxConnections __attribute__ ((packed));
|
||||||
|
__u8 ConnectionTimeMask[42] __attribute__ ((packed));
|
||||||
|
__u8 LastLogin[6] __attribute__ ((packed));
|
||||||
|
__u8 RestrictionMask __attribute__ ((packed));
|
||||||
|
__u8 reserved __attribute__ ((packed));
|
||||||
|
__u32 MaxDiskUsage __attribute__ ((packed));
|
||||||
|
__u16 BadLoginCount __attribute__ ((packed));
|
||||||
|
__u32 BadLoginCountDown __attribute__ ((packed));
|
||||||
|
__u8 LastIntruder[8] __attribute__ ((packed));
|
||||||
|
};
|
||||||
|
|
||||||
|
long
|
||||||
ncp_read_property_value(struct ncp_conn *conn,
|
ncp_read_property_value(struct ncp_conn *conn,
|
||||||
int object_type, const char *object_name,
|
int object_type, const char *object_name,
|
||||||
int segment, const char *prop_name,
|
int segment, const char *prop_name,
|
||||||
struct nw_property *target);
|
struct nw_property *target);
|
||||||
int
|
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);
|
||||||
|
long
|
||||||
ncp_login_encrypted(struct ncp_conn *conn,
|
ncp_login_encrypted(struct ncp_conn *conn,
|
||||||
const struct ncp_bindery_object *object,
|
const struct ncp_bindery_object *object,
|
||||||
const unsigned char *key,
|
const unsigned char *key,
|
||||||
const unsigned char *passwd);
|
const unsigned char *passwd);
|
||||||
int
|
|
||||||
|
#define NCP_GRACE_PERIOD (0xdf)
|
||||||
|
|
||||||
|
long
|
||||||
ncp_login_user(struct ncp_conn *conn,
|
ncp_login_user(struct ncp_conn *conn,
|
||||||
const unsigned char *username,
|
const unsigned char *username,
|
||||||
const unsigned char *password);
|
const unsigned char *password);
|
||||||
int
|
long
|
||||||
ncp_get_volume_info_with_number(struct ncp_conn *conn, int n,
|
ncp_get_volume_info_with_number(struct ncp_conn *conn, int n,
|
||||||
struct ncp_volume_info *target);
|
struct ncp_volume_info *target);
|
||||||
|
|
||||||
int
|
long
|
||||||
ncp_get_volume_number(struct ncp_conn *conn, const char *name,
|
ncp_get_volume_number(struct ncp_conn *conn, const char *name,
|
||||||
int *target);
|
int *target);
|
||||||
|
|
||||||
int
|
long
|
||||||
ncp_file_search_init(struct ncp_conn *conn,
|
ncp_file_search_init(struct ncp_conn *conn,
|
||||||
int dir_handle, const char *path,
|
int dir_handle, const char *path,
|
||||||
struct ncp_filesearch_info *target);
|
struct ncp_filesearch_info *target);
|
||||||
|
|
||||||
int
|
long
|
||||||
ncp_file_search_continue(struct ncp_conn *conn,
|
ncp_file_search_continue(struct ncp_conn *conn,
|
||||||
struct ncp_filesearch_info *fsinfo,
|
struct ncp_filesearch_info *fsinfo,
|
||||||
int attributes, const char *path,
|
int attributes, const char *path,
|
||||||
struct ncp_file_info *target);
|
struct ncp_file_info *target);
|
||||||
|
|
||||||
int
|
long
|
||||||
ncp_get_finfo(struct ncp_conn *conn,
|
ncp_get_finfo(struct ncp_conn *conn,
|
||||||
int dir_handle, const char *path, const char *name,
|
int dir_handle, const char *path, const char *name,
|
||||||
struct ncp_file_info *target);
|
struct ncp_file_info *target);
|
||||||
|
|
||||||
int
|
long
|
||||||
ncp_open_file(struct ncp_conn *conn,
|
ncp_open_file(struct ncp_conn *conn,
|
||||||
int dir_handle, const char *path,
|
int dir_handle, const char *path,
|
||||||
int attr, int access,
|
int attr, int access,
|
||||||
struct ncp_file_info *target);
|
struct ncp_file_info *target);
|
||||||
int
|
long
|
||||||
ncp_close_file(struct ncp_conn *conn, const char *file_id);
|
ncp_close_file(struct ncp_conn *conn, const char *file_id);
|
||||||
|
|
||||||
int
|
long
|
||||||
ncp_create_newfile(struct ncp_conn *conn,
|
ncp_create_newfile(struct ncp_conn *conn,
|
||||||
int dir_handle, const char *path,
|
int dir_handle, const char *path,
|
||||||
int attr,
|
int attr,
|
||||||
struct ncp_file_info *target);
|
struct ncp_file_info *target);
|
||||||
|
|
||||||
int
|
long
|
||||||
ncp_create_file(struct ncp_conn *conn,
|
ncp_create_file(struct ncp_conn *conn,
|
||||||
int dir_handle, const char *path,
|
int dir_handle, const char *path,
|
||||||
int attr,
|
int attr,
|
||||||
struct ncp_file_info *target);
|
struct ncp_file_info *target);
|
||||||
|
|
||||||
int
|
long
|
||||||
ncp_erase_file(struct ncp_conn *conn,
|
ncp_erase_file(struct ncp_conn *conn,
|
||||||
int dir_handle, const char *path,
|
int dir_handle, const char *path,
|
||||||
int attr);
|
int attr);
|
||||||
|
|
||||||
int
|
long
|
||||||
ncp_rename_file(struct ncp_conn *conn,
|
ncp_rename_file(struct ncp_conn *conn,
|
||||||
int old_handle, const char *old_path,
|
int old_handle, const char *old_path,
|
||||||
int attr,
|
int attr,
|
||||||
int new_handle, const char *new_path);
|
int new_handle, const char *new_path);
|
||||||
|
|
||||||
int
|
long
|
||||||
ncp_create_directory(struct ncp_conn *conn,
|
ncp_create_directory(struct ncp_conn *conn,
|
||||||
int dir_handle, const char *path,
|
int dir_handle, const char *path,
|
||||||
int inherit_mask);
|
int inherit_mask);
|
||||||
|
|
||||||
int
|
long
|
||||||
ncp_delete_directory(struct ncp_conn *conn,
|
ncp_delete_directory(struct ncp_conn *conn,
|
||||||
int dir_handle, const char *path);
|
int dir_handle, const char *path);
|
||||||
|
|
||||||
int
|
long
|
||||||
ncp_rename_directory(struct ncp_conn *conn,
|
ncp_rename_directory(struct ncp_conn *conn,
|
||||||
int dir_handle,
|
int dir_handle,
|
||||||
const char *old_path, const char *new_path);
|
const char *old_path, const char *new_path);
|
||||||
|
|
||||||
int
|
long
|
||||||
ncp_read(struct ncp_conn *conn, const char *file_id,
|
ncp_read(struct ncp_conn *conn, const char *file_id,
|
||||||
off_t offset, size_t count, char *target);
|
off_t offset, size_t count, char *target);
|
||||||
|
|
||||||
int
|
long
|
||||||
ncp_write(struct ncp_conn *conn, const char *file_id,
|
ncp_write(struct ncp_conn *conn, const char *file_id,
|
||||||
off_t offset, size_t count, const char *source);
|
off_t offset, size_t count, const char *source);
|
||||||
|
|
||||||
int
|
long
|
||||||
ncp_copy_file(struct ncp_conn *conn,
|
ncp_copy_file(struct ncp_conn *conn,
|
||||||
const char source_file[6],
|
const char source_file[6],
|
||||||
const char target_file[6],
|
const char target_file[6],
|
||||||
@@ -266,24 +348,24 @@ ncp_copy_file(struct ncp_conn *conn,
|
|||||||
__u32 count,
|
__u32 count,
|
||||||
__u32 *copied_count);
|
__u32 *copied_count);
|
||||||
|
|
||||||
int
|
long
|
||||||
ncp_do_lookup(struct ncp_conn *conn,
|
ncp_do_lookup(struct ncp_conn *conn,
|
||||||
struct nw_info_struct *dir,
|
struct nw_info_struct *dir,
|
||||||
char *path, /* may only be one component */
|
char *path, /* may only be one component */
|
||||||
struct nw_info_struct *target);
|
struct nw_info_struct *target);
|
||||||
|
|
||||||
int
|
long
|
||||||
ncp_modify_file_or_subdir_dos_info(struct ncp_conn *conn,
|
ncp_modify_file_or_subdir_dos_info(struct ncp_conn *conn,
|
||||||
struct nw_info_struct *file,
|
struct nw_info_struct *file,
|
||||||
__u32 info_mask,
|
__u32 info_mask,
|
||||||
struct nw_modify_dos_info *info);
|
struct nw_modify_dos_info *info);
|
||||||
|
|
||||||
int
|
long
|
||||||
ncp_del_file_or_subdir(struct ncp_conn *conn,
|
ncp_del_file_or_subdir(struct ncp_conn *conn,
|
||||||
struct nw_info_struct *dir, char *name);
|
struct nw_info_struct *dir, char *name);
|
||||||
|
|
||||||
|
|
||||||
int
|
long
|
||||||
ncp_open_create_file_or_subdir(struct ncp_conn *conn,
|
ncp_open_create_file_or_subdir(struct ncp_conn *conn,
|
||||||
struct nw_info_struct *dir, char *name,
|
struct nw_info_struct *dir, char *name,
|
||||||
int open_create_mode,
|
int open_create_mode,
|
||||||
@@ -291,63 +373,63 @@ ncp_open_create_file_or_subdir(struct ncp_conn *conn,
|
|||||||
int desired_acc_rights,
|
int desired_acc_rights,
|
||||||
struct nw_file_info *target);
|
struct nw_file_info *target);
|
||||||
|
|
||||||
int
|
long
|
||||||
ncp_initialize_search(struct ncp_conn *conn,
|
ncp_initialize_search(struct ncp_conn *conn,
|
||||||
const struct nw_info_struct *dir,
|
const struct nw_info_struct *dir,
|
||||||
int namespace,
|
int namespace,
|
||||||
struct ncp_search_seq *target);
|
struct ncp_search_seq *target);
|
||||||
|
|
||||||
int
|
long
|
||||||
ncp_search_for_file_or_subdir(struct ncp_conn *conn,
|
ncp_search_for_file_or_subdir(struct ncp_conn *conn,
|
||||||
struct ncp_search_seq *seq,
|
struct ncp_search_seq *seq,
|
||||||
struct nw_info_struct *target);
|
struct nw_info_struct *target);
|
||||||
|
|
||||||
int
|
long
|
||||||
ncp_ren_or_mov_file_or_subdir(struct ncp_conn *conn,
|
ncp_ren_or_mov_file_or_subdir(struct ncp_conn *conn,
|
||||||
struct nw_info_struct *old_dir, char *old_name,
|
struct nw_info_struct *old_dir, char *old_name,
|
||||||
struct nw_info_struct *new_dir, char *new_name);
|
struct nw_info_struct *new_dir, char *new_name);
|
||||||
|
|
||||||
int
|
long
|
||||||
ncp_create_queue_job_and_file(struct ncp_conn *conn,
|
ncp_create_queue_job_and_file(struct ncp_conn *conn,
|
||||||
__u32 queue_id,
|
__u32 queue_id,
|
||||||
struct queue_job *job);
|
struct queue_job *job);
|
||||||
|
|
||||||
int
|
long
|
||||||
ncp_close_file_and_start_job(struct ncp_conn *conn,
|
ncp_close_file_and_start_job(struct ncp_conn *conn,
|
||||||
__u32 queue_id,
|
__u32 queue_id,
|
||||||
struct queue_job *job);
|
struct queue_job *job);
|
||||||
|
|
||||||
int
|
long
|
||||||
ncp_attach_to_queue(struct ncp_conn *conn,
|
ncp_attach_to_queue(struct ncp_conn *conn,
|
||||||
__u32 queue_id);
|
__u32 queue_id);
|
||||||
|
|
||||||
int
|
long
|
||||||
ncp_detach_from_queue(struct ncp_conn *conn,
|
ncp_detach_from_queue(struct ncp_conn *conn,
|
||||||
__u32 queue_id);
|
__u32 queue_id);
|
||||||
|
|
||||||
int
|
long
|
||||||
ncp_service_queue_job(struct ncp_conn *conn, __u32 queue_id, __u16 job_type,
|
ncp_service_queue_job(struct ncp_conn *conn, __u32 queue_id, __u16 job_type,
|
||||||
struct queue_job *job);
|
struct queue_job *job);
|
||||||
|
|
||||||
int
|
long
|
||||||
ncp_finish_servicing_job(struct ncp_conn *conn, __u32 queue_id,
|
ncp_finish_servicing_job(struct ncp_conn *conn, __u32 queue_id,
|
||||||
__u32 job_number, __u32 charge_info);
|
__u32 job_number, __u32 charge_info);
|
||||||
|
|
||||||
int
|
long
|
||||||
ncp_abort_servicing_job(struct ncp_conn *conn, __u32 queue_id,
|
ncp_abort_servicing_job(struct ncp_conn *conn, __u32 queue_id,
|
||||||
__u32 job_number);
|
__u32 job_number);
|
||||||
|
|
||||||
int
|
long
|
||||||
ncp_get_broadcast_message(struct ncp_conn *conn, char message[256]);
|
ncp_get_broadcast_message(struct ncp_conn *conn, char message[256]);
|
||||||
|
|
||||||
int
|
long
|
||||||
ncp_dealloc_dir_handle(struct ncp_conn *conn, __u8 dir_handle);
|
ncp_dealloc_dir_handle(struct ncp_conn *conn, __u8 dir_handle);
|
||||||
|
|
||||||
#define NCP_ALLOC_PERMANENT (0x0000)
|
#define NCP_ALLOC_PERMANENT (0x0000)
|
||||||
#define NCP_ALLOC_TEMPORARY (0x0001)
|
#define NCP_ALLOC_TEMPORARY (0x0001)
|
||||||
#define NCP_ALLOC_SPECIAL (0x0002)
|
#define NCP_ALLOC_SPECIAL (0x0002)
|
||||||
|
|
||||||
int
|
long
|
||||||
ncp_alloc_short_dir_handle(struct ncp_conn *conn,
|
ncp_alloc_short_dir_handle(struct ncp_conn *conn,
|
||||||
struct nw_info_struct *dir,
|
struct nw_info_struct *dir,
|
||||||
__u16 alloc_mode,
|
__u16 alloc_mode,
|
||||||
|
|||||||
27
util/ncplib_err.et
Normal file
27
util/ncplib_err.et
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
error_table NCPL
|
||||||
|
|
||||||
|
ec NCPL_ET_NO_SERVER,
|
||||||
|
"No server found"
|
||||||
|
|
||||||
|
ec NCPL_ET_HOST_UNKNOWN,
|
||||||
|
"Server Unknown"
|
||||||
|
|
||||||
|
ec NCPL_ET_REQUEST_ERROR,
|
||||||
|
"NCP Request returned error code"
|
||||||
|
|
||||||
|
ec NCPL_ET_NAMETOOLONG,
|
||||||
|
"Name too long"
|
||||||
|
|
||||||
|
ec NCPL_ET_MSG_TOO_LONG,
|
||||||
|
"Message too long"
|
||||||
|
|
||||||
|
ec NCPL_ET_NO_SPEC,
|
||||||
|
"Could not find valid connection spec"
|
||||||
|
|
||||||
|
ec NCPL_ET_INVALID_MODE,
|
||||||
|
"$HOME/.nwclient has invalid mode"
|
||||||
|
|
||||||
|
ec NCPL_ET_LOGIN_FAILED,
|
||||||
|
"Login failed"
|
||||||
|
|
||||||
|
end
|
||||||
@@ -45,6 +45,7 @@ extern pid_t waitpid(pid_t, int *, int);
|
|||||||
#include <linux/ncp_fs.h>
|
#include <linux/ncp_fs.h>
|
||||||
#include <linux/ncp_mount.h>
|
#include <linux/ncp_mount.h>
|
||||||
#include "ncplib.h"
|
#include "ncplib.h"
|
||||||
|
#include "com_err.h"
|
||||||
|
|
||||||
static char *progname;
|
static char *progname;
|
||||||
static void usage(void);
|
static void usage(void);
|
||||||
@@ -153,9 +154,11 @@ main(int argc, char *argv[])
|
|||||||
|
|
||||||
int fd, result;
|
int fd, result;
|
||||||
struct sockaddr_ipx addr;
|
struct sockaddr_ipx addr;
|
||||||
|
struct sockaddr_ipx *server_addr;
|
||||||
int addrlen;
|
int addrlen;
|
||||||
|
|
||||||
int upcase_password;
|
int upcase_password;
|
||||||
|
long err;
|
||||||
|
|
||||||
int um;
|
int um;
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
@@ -163,6 +166,7 @@ main(int argc, char *argv[])
|
|||||||
char mount_point[MAXPATHLEN];
|
char mount_point[MAXPATHLEN];
|
||||||
struct mntent ment;
|
struct mntent ment;
|
||||||
FILE *mtab;
|
FILE *mtab;
|
||||||
|
char *tmp_mount;
|
||||||
|
|
||||||
char *server = NULL;
|
char *server = NULL;
|
||||||
char *user = NULL;
|
char *user = NULL;
|
||||||
@@ -171,13 +175,13 @@ main(int argc, char *argv[])
|
|||||||
|
|
||||||
uid_t conn_uid = getuid();
|
uid_t conn_uid = getuid();
|
||||||
|
|
||||||
struct ncp_conn conn;
|
struct ncp_conn *conn;
|
||||||
|
|
||||||
int opt;
|
int opt;
|
||||||
|
|
||||||
progname = argv[0];
|
progname = argv[0];
|
||||||
|
|
||||||
memzero(data); memzero(spec); memzero(conn);
|
memzero(data); memzero(spec);
|
||||||
|
|
||||||
if (geteuid() != 0)
|
if (geteuid() != 0)
|
||||||
{
|
{
|
||||||
@@ -317,10 +321,10 @@ main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((spec = ncp_find_conn_spec(server, user, password, data.uid))
|
if ((spec = ncp_find_conn_spec(server, user, password, data.uid, &err))
|
||||||
== NULL)
|
== NULL)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Could not find valid server/user\n");
|
com_err(progname, err, "in find_conn_spec");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -376,32 +380,28 @@ main(int argc, char *argv[])
|
|||||||
data.dir_mode |= S_IXOTH;
|
data.dir_mode |= S_IXOTH;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ncp_open(&conn, spec) != 0)
|
if ((tmp_mount = ncp_find_permanent(spec)) != NULL)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "could not connect to server %s: %s\n",
|
|
||||||
server, strerror(errno));
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (conn.is_connected == CONN_PERMANENT)
|
|
||||||
{
|
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"You already have mounted server %s\nas user "
|
"You already have mounted server %s\nas user "
|
||||||
"%s\non mount point %s\n", spec->server, spec->user,
|
"%s\non mount point %s\n", spec->server, spec->user,
|
||||||
conn.mount_point);
|
tmp_mount);
|
||||||
ncp_close(&conn);
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
data.serv_addr = conn.i.addr;
|
if ((server_addr = ncp_find_fileserver(spec->server, &err)) == NULL)
|
||||||
|
{
|
||||||
ncp_close(&conn);
|
com_err("ncpmount", err, "when trying to find %s",
|
||||||
|
spec->server);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
data.serv_addr = *server_addr;
|
||||||
|
|
||||||
data.ncp_fd = socket(AF_IPX, SOCK_DGRAM, PF_IPX);
|
data.ncp_fd = socket(AF_IPX, SOCK_DGRAM, PF_IPX);
|
||||||
if (data.ncp_fd == -1)
|
if (data.ncp_fd == -1)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "could not open ncp socket: %s\n",
|
com_err("ncpmount", err, "opening ncp_socket");
|
||||||
strerror(errno));
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -472,7 +472,11 @@ main(int argc, char *argv[])
|
|||||||
|
|
||||||
flags = MS_MGC_VAL;
|
flags = MS_MGC_VAL;
|
||||||
|
|
||||||
result = mount(NULL, mount_point, "ncpfs", flags, (char *)&data);
|
strcpy(mount_name, spec->server);
|
||||||
|
strcat(mount_name, "/");
|
||||||
|
strcat(mount_name, spec->user);
|
||||||
|
|
||||||
|
result = mount(mount_name, mount_point, "ncpfs", flags, (char *)&data);
|
||||||
|
|
||||||
if (result < 0)
|
if (result < 0)
|
||||||
{
|
{
|
||||||
@@ -480,20 +484,47 @@ main(int argc, char *argv[])
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( (ncp_open_mount(&conn, mount_point) != 0)
|
if ((conn = ncp_open_mount(mount_point, &err)) == NULL)
|
||||||
|| (ncp_login_user(&conn, spec->user, spec->password) != 0)
|
|
||||||
|| (ioctl(conn.mount_fid, NCP_IOC_CONN_LOGGED_IN, NULL) != 0))
|
|
||||||
{
|
{
|
||||||
fprintf(stderr, "%s: login failed\n", strerror(errno));
|
com_err("ncpmount", err, "attempt to open mount point");
|
||||||
ncp_close(&conn);
|
|
||||||
umount(mount_point);
|
umount(mount_point);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
ncp_close(&conn);
|
|
||||||
|
|
||||||
strcpy(mount_name, spec->server);
|
if ((err = ncp_login_user(conn, spec->user, spec->password)) != 0)
|
||||||
strcat(mount_name, "/");
|
{
|
||||||
strcat(mount_name, spec->user);
|
struct nw_property p;
|
||||||
|
struct ncp_prop_login_control *l
|
||||||
|
= (struct ncp_prop_login_control *)&p;
|
||||||
|
|
||||||
|
if (conn->completion != NCP_GRACE_PERIOD)
|
||||||
|
{
|
||||||
|
com_err("ncpmount", err, "in login");
|
||||||
|
fprintf(stderr, "Login denied\n");
|
||||||
|
ncp_close(conn);
|
||||||
|
umount(mount_point);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "Your password has expired\n");
|
||||||
|
|
||||||
|
if ((err = ncp_read_property_value(conn, NCP_BINDERY_USER,
|
||||||
|
spec->user, 1,
|
||||||
|
"LOGIN_CONTROL", &p)) == 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "You have %d login attempts left\n",
|
||||||
|
l->GraceLogins);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((err = ioctl(conn->mount_fid, NCP_IOC_CONN_LOGGED_IN, NULL)) != 0)
|
||||||
|
{
|
||||||
|
com_err("ncpmount", err, "in logged_indication");
|
||||||
|
ncp_close(conn);
|
||||||
|
umount(mount_point);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
ncp_close(conn);
|
||||||
|
|
||||||
ment.mnt_fsname = mount_name;
|
ment.mnt_fsname = mount_name;
|
||||||
ment.mnt_dir = mount_point;
|
ment.mnt_dir = mount_point;
|
||||||
|
|||||||
133
util/ncptest.c
133
util/ncptest.c
@@ -38,115 +38,35 @@ extern pid_t waitpid(pid_t, int *, int);
|
|||||||
#include "ncplib.h"
|
#include "ncplib.h"
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
test_print(struct ncp_conn *conn)
|
|
||||||
{
|
|
||||||
struct ncp_bindery_object q;
|
|
||||||
struct queue_job j;
|
|
||||||
struct print_job_record pj;
|
|
||||||
int written;
|
|
||||||
|
|
||||||
if (ncp_get_bindery_object_id(conn, NCP_BINDERY_PQUEUE,
|
|
||||||
"Q_DJ500", &q) != 0) {
|
|
||||||
printf("get oid error\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(&j, 0, sizeof(j));
|
|
||||||
|
|
||||||
j.j.TargetServerID = 0xffffffff; /* any server */
|
|
||||||
/* at once */
|
|
||||||
memset(&(j.j.TargetExecTime), 0xff, sizeof(j.j.TargetExecTime));
|
|
||||||
j.j.JobType = htons(0);
|
|
||||||
strcpy(j.j.JobTextDescription, "Test Job");
|
|
||||||
|
|
||||||
memset(&pj, 0, sizeof(pj));
|
|
||||||
|
|
||||||
pj.Version = 0;
|
|
||||||
pj.TabSize = 8;
|
|
||||||
pj.Copies = htons(1);
|
|
||||||
pj.CtrlFlags = 0;
|
|
||||||
pj.Lines = htons(66);
|
|
||||||
pj.Rows = htons(80);
|
|
||||||
strcpy(pj.FormName, "test");
|
|
||||||
strcpy(pj.BannerName, "BannerName");
|
|
||||||
strcpy(pj.FnameBanner, "BannerFile");
|
|
||||||
strcpy(pj.FnameHeader, "HeaderName");
|
|
||||||
strcpy(pj.Path, "");
|
|
||||||
|
|
||||||
memcpy(j.j.ClientRecordArea, &pj, sizeof(pj));
|
|
||||||
|
|
||||||
if (ncp_create_queue_job_and_file(conn, q.object_id, &j) != 0) {
|
|
||||||
printf("create error\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((written = ncp_write(conn, j.file_handle, 0, 15,
|
|
||||||
"hallo, wie geht's?")) < 0) {
|
|
||||||
printf("write error\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ncp_close_file_and_start_job(conn, q.object_id, &j) != 0) {
|
|
||||||
printf("close error\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
test_ls(struct ncp_conn *server)
|
|
||||||
{
|
|
||||||
struct nw_info_struct sys;
|
|
||||||
struct nw_info_struct public;
|
|
||||||
struct ncp_search_seq seq;
|
|
||||||
struct nw_info_struct found;
|
|
||||||
int res;
|
|
||||||
|
|
||||||
if (ncp_do_lookup(server, NULL, "SYS", &sys) != 0)
|
|
||||||
{
|
|
||||||
printf("lookup error\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (ncp_do_lookup(server, &sys, "PUBLIC", &public) != 0)
|
|
||||||
{
|
|
||||||
printf("lookup public error\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (ncp_initialize_search(server, &public, 4, &seq) != 0)
|
|
||||||
{
|
|
||||||
printf("init error\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
while ((res=ncp_search_for_file_or_subdir(server,&seq,&found)) == 0)
|
|
||||||
{
|
|
||||||
printf("found %s: %s\n",
|
|
||||||
(found.attributes & aDIR) ? "dir " : "file",
|
|
||||||
found.entryName);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (res == 0xfe)
|
|
||||||
{
|
|
||||||
printf("result: no more files\n");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
printf("other error: %x\n", res);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
test_connlist(struct ncp_conn *conn)
|
test_connlist(struct ncp_conn *conn)
|
||||||
{
|
{
|
||||||
__u16 conn_list[256];
|
__u8 conn_list[256] = {0,};
|
||||||
int no;
|
int no;
|
||||||
|
|
||||||
ncp_get_connlist(conn, 0, NCP_BINDERY_USER, "*", &no, conn_list);
|
ncp_get_connlist(conn, NCP_BINDERY_USER, "SUPERVISOR", &no,
|
||||||
|
conn_list);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
test_send(struct ncp_conn *conn)
|
||||||
|
{
|
||||||
|
__u8 conn_list[256] = {0,};
|
||||||
|
int no;
|
||||||
|
|
||||||
|
if (ncp_get_connlist(conn, NCP_BINDERY_USER, "ME", &no,
|
||||||
|
conn_list) != 0)
|
||||||
|
{
|
||||||
|
no = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (no > 0)
|
||||||
|
{
|
||||||
|
ncp_send_broadcast(conn, no, conn_list, "Hallo");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
void
|
void
|
||||||
test_create(struct ncp_conn *conn)
|
test_create(struct ncp_conn *conn)
|
||||||
{
|
{
|
||||||
@@ -191,15 +111,16 @@ test_create(struct ncp_conn *conn)
|
|||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
struct ncp_conn conn;
|
struct ncp_conn *conn;
|
||||||
|
long err;
|
||||||
|
|
||||||
if (ncp_initialize(&conn, &argc, argv, 1) != 0)
|
if ((conn = ncp_initialize(&argc, argv, 1, &err)) == NULL)
|
||||||
{
|
{
|
||||||
perror("ncp_initialize");
|
com_err(argv[0], err, "in ncp_initialize");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
test_create(&conn);
|
test_send(conn);
|
||||||
ncp_close(&conn);
|
ncp_close(conn);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ static void help(void);
|
|||||||
void
|
void
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
struct ncp_conn conn;
|
struct ncp_conn *conn;
|
||||||
|
|
||||||
char default_queue[] = "*";
|
char default_queue[] = "*";
|
||||||
char *queue = default_queue;
|
char *queue = default_queue;
|
||||||
@@ -42,10 +42,11 @@ main(int argc, char *argv[])
|
|||||||
|
|
||||||
char *file_name;
|
char *file_name;
|
||||||
int file;
|
int file;
|
||||||
|
long err;
|
||||||
|
|
||||||
progname = argv[0];
|
progname = argv[0];
|
||||||
|
|
||||||
memzero(j); memzero(pj); memzero(q); memzero(conn);
|
memzero(j); memzero(pj); memzero(q);
|
||||||
|
|
||||||
if ( (argc == 2)
|
if ( (argc == 2)
|
||||||
&& (strcmp(argv[1], "-h") == 0))
|
&& (strcmp(argv[1], "-h") == 0))
|
||||||
@@ -54,9 +55,9 @@ main(int argc, char *argv[])
|
|||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ncp_initialize(&conn, &argc, argv, 1) != 0)
|
if ((conn = ncp_initialize(&argc, argv, 1, &err)) == NULL)
|
||||||
{
|
{
|
||||||
perror("Could not open connection");
|
com_err(argv[0], err, "in ncp_initialize");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,7 +83,7 @@ main(int argc, char *argv[])
|
|||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'h':
|
case 'h':
|
||||||
help();
|
help();
|
||||||
ncp_close(&conn);
|
ncp_close(conn);
|
||||||
exit(1);
|
exit(1);
|
||||||
case 'p':
|
case 'p':
|
||||||
/* Path */
|
/* Path */
|
||||||
@@ -191,7 +192,7 @@ main(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
printf("queue name too long: %s\n",
|
printf("queue name too long: %s\n",
|
||||||
optarg);
|
optarg);
|
||||||
ncp_close(&conn);
|
ncp_close(conn);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
queue = optarg;
|
queue = optarg;
|
||||||
@@ -212,7 +213,7 @@ main(int argc, char *argv[])
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
usage();
|
usage();
|
||||||
ncp_close(&conn);
|
ncp_close(conn);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -220,7 +221,7 @@ main(int argc, char *argv[])
|
|||||||
if (optind != argc-1)
|
if (optind != argc-1)
|
||||||
{
|
{
|
||||||
usage();
|
usage();
|
||||||
ncp_close(&conn);
|
ncp_close(conn);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -236,7 +237,7 @@ main(int argc, char *argv[])
|
|||||||
if (file < 0)
|
if (file < 0)
|
||||||
{
|
{
|
||||||
perror("could not open file");
|
perror("could not open file");
|
||||||
ncp_close(&conn);
|
ncp_close(conn);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -268,18 +269,18 @@ main(int argc, char *argv[])
|
|||||||
|
|
||||||
str_upper(queue);
|
str_upper(queue);
|
||||||
|
|
||||||
if (ncp_scan_bindery_object(&conn, 0xffffffff, NCP_BINDERY_PQUEUE,
|
if (ncp_scan_bindery_object(conn, 0xffffffff, NCP_BINDERY_PQUEUE,
|
||||||
queue, &q) != 0)
|
queue, &q) != 0)
|
||||||
{
|
{
|
||||||
printf("could not find queue %s\n", queue);
|
printf("could not find queue %s\n", queue);
|
||||||
ncp_close(&conn);
|
ncp_close(conn);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ncp_create_queue_job_and_file(&conn, q.object_id, &j) != 0)
|
if (ncp_create_queue_job_and_file(conn, q.object_id, &j) != 0)
|
||||||
{
|
{
|
||||||
printf("create error\n");
|
printf("create error\n");
|
||||||
ncp_close(&conn);
|
ncp_close(conn);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -292,7 +293,7 @@ main(int argc, char *argv[])
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ncp_write(&conn, j.file_handle,
|
if (ncp_write(conn, j.file_handle,
|
||||||
written, read_this_time, buf) < read_this_time)
|
written, read_this_time, buf) < read_this_time)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
@@ -303,13 +304,13 @@ main(int argc, char *argv[])
|
|||||||
|
|
||||||
close(file);
|
close(file);
|
||||||
|
|
||||||
if (ncp_close_file_and_start_job(&conn, q.object_id, &j) != 0) {
|
if (ncp_close_file_and_start_job(conn, q.object_id, &j) != 0) {
|
||||||
printf("close error\n");
|
printf("close error\n");
|
||||||
ncp_close(&conn);
|
ncp_close(conn);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ncp_close(&conn);
|
ncp_close(conn);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
65
util/nsend.c
Normal file
65
util/nsend.c
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* nsend.c
|
||||||
|
*
|
||||||
|
* Send Messages to users
|
||||||
|
*
|
||||||
|
* Copyright (C) 1996 by Volker Lendecke
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include "ncplib.h"
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
struct ncp_conn *conn;
|
||||||
|
__u8 conn_list[256] = {0,};
|
||||||
|
int no_conn;
|
||||||
|
|
||||||
|
char *message = NULL;
|
||||||
|
char *user = NULL;
|
||||||
|
long err;
|
||||||
|
|
||||||
|
if ((conn = ncp_initialize(&argc, argv, 1, &err)) == NULL)
|
||||||
|
{
|
||||||
|
com_err(argv[0], err, "in ncp_initialize");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argc != 3)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "usage: %s [options] user message\n", argv[0]);
|
||||||
|
ncp_close(conn);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
user = argv[1];
|
||||||
|
message = argv[2];
|
||||||
|
|
||||||
|
if ((err = ncp_get_connlist(conn, NCP_BINDERY_USER, user, &no_conn,
|
||||||
|
conn_list)) != 0)
|
||||||
|
{
|
||||||
|
com_err(argv[0], err, "in get_connlist");
|
||||||
|
ncp_close(conn);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (no_conn == 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "No connection found for %s\n", user);
|
||||||
|
ncp_close(conn);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((err = ncp_send_broadcast(conn, no_conn, conn_list, message)) != 0)
|
||||||
|
{
|
||||||
|
com_err(argv[0], err, "in send_broadcast");
|
||||||
|
ncp_close(conn);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
ncp_close(conn);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -14,12 +14,13 @@
|
|||||||
int
|
int
|
||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
struct ncp_conn conn;
|
struct ncp_conn *conn;
|
||||||
int opt;
|
int opt;
|
||||||
|
long err;
|
||||||
|
|
||||||
if (ncp_initialize(&conn, &argc, argv, 0) != 0)
|
if ((conn = ncp_initialize(&argc, argv, 0, &err)) == NULL)
|
||||||
{
|
{
|
||||||
perror("Could not open connection");
|
com_err(argv[0], err, "in ncp_initialize");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32,12 +33,12 @@ main(int argc, char **argv)
|
|||||||
char strings[512];
|
char strings[512];
|
||||||
char *s;
|
char *s;
|
||||||
|
|
||||||
if (ncp_get_file_server_description_strings(&conn,
|
if (ncp_get_file_server_description_strings(conn,
|
||||||
strings)
|
strings)
|
||||||
!= 0)
|
!= 0)
|
||||||
{
|
{
|
||||||
perror("could not get strings");
|
perror("could not get strings");
|
||||||
ncp_close(&conn);
|
ncp_close(conn);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,10 +58,10 @@ main(int argc, char **argv)
|
|||||||
{
|
{
|
||||||
time_t t;
|
time_t t;
|
||||||
|
|
||||||
if (ncp_get_file_server_time(&conn, &t) != 0)
|
if (ncp_get_file_server_time(conn, &t) != 0)
|
||||||
{
|
{
|
||||||
perror("could not get server time");
|
perror("could not get server time");
|
||||||
ncp_close(&conn);
|
ncp_close(conn);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,6 +74,6 @@ main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ncp_close(&conn);
|
ncp_close(conn);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
62
util/nwlsobj.c
Normal file
62
util/nwlsobj.c
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* nwlsobj.c
|
||||||
|
*
|
||||||
|
* List bindery objects
|
||||||
|
*
|
||||||
|
* Copyright (C) 1996 by Volker Lendecke
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include "ncplib.h"
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
struct ncp_conn *conn;
|
||||||
|
struct ncp_bindery_object o;
|
||||||
|
int found = 0;
|
||||||
|
|
||||||
|
char default_pattern[] = "*";
|
||||||
|
char *pattern = default_pattern;
|
||||||
|
char *p;
|
||||||
|
long err;
|
||||||
|
|
||||||
|
if ((conn = ncp_initialize(&argc, argv, 1, &err)) == NULL)
|
||||||
|
{
|
||||||
|
com_err(argv[0], err, "in ncp_initialize");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argc > 2)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "usage: %s [options]\n", argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argc == 2)
|
||||||
|
{
|
||||||
|
pattern = argv[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (p = pattern; *p != '\0'; p++)
|
||||||
|
{
|
||||||
|
*p = toupper(*p);
|
||||||
|
}
|
||||||
|
|
||||||
|
o.object_id = 0xffffffff;
|
||||||
|
|
||||||
|
while (ncp_scan_bindery_object(conn, o.object_id,
|
||||||
|
0xffff, pattern, &o) == 0)
|
||||||
|
{
|
||||||
|
found = 1;
|
||||||
|
printf("%s %08X %04X\n",
|
||||||
|
o.object_name, (unsigned int)o.object_id,
|
||||||
|
(unsigned int)o.object_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
ncp_close(conn);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
20
util/nwmsg.c
20
util/nwmsg.c
@@ -30,7 +30,7 @@ static char *progname;
|
|||||||
void
|
void
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
struct ncp_conn conn;
|
struct ncp_conn *conn;
|
||||||
char message[256];
|
char message[256];
|
||||||
struct ncp_fs_info info;
|
struct ncp_fs_info info;
|
||||||
struct passwd *pwd;
|
struct passwd *pwd;
|
||||||
@@ -39,6 +39,7 @@ main(int argc, char *argv[])
|
|||||||
FILE *tty_file;
|
FILE *tty_file;
|
||||||
FILE *mtab;
|
FILE *mtab;
|
||||||
struct mntent *mnt;
|
struct mntent *mnt;
|
||||||
|
long err;
|
||||||
|
|
||||||
|
|
||||||
progname = argv[0];
|
progname = argv[0];
|
||||||
@@ -52,18 +53,17 @@ main(int argc, char *argv[])
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ncp_open_mount(&conn, argv[1]) != 0)
|
if ((conn = ncp_open_mount(argv[1], &err)) == NULL)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "%s: could not open connection %s\n",
|
com_err(progname, err, "in ncp_open_mount");
|
||||||
progname, argv[1]);
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ncp_get_broadcast_message(&conn, message) != 0)
|
if (ncp_get_broadcast_message(conn, message) != 0)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "%s: could not get broadcast message\n",
|
fprintf(stderr, "%s: could not get broadcast message\n",
|
||||||
progname);
|
progname);
|
||||||
ncp_close(&conn);
|
ncp_close(conn);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,15 +78,15 @@ main(int argc, char *argv[])
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
info.version = NCP_GET_FS_INFO_VERSION;
|
info.version = NCP_GET_FS_INFO_VERSION;
|
||||||
if (ioctl(conn.mount_fid, NCP_IOC_GET_FS_INFO, &info) < 0)
|
if (ioctl(conn->mount_fid, NCP_IOC_GET_FS_INFO, &info) < 0)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "%s: could not ioctl on connection: %s\n",
|
fprintf(stderr, "%s: could not ioctl on connection: %s\n",
|
||||||
progname, strerror(errno));
|
progname, strerror(errno));
|
||||||
ncp_close(&conn);
|
ncp_close(conn);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
ncp_close(&conn);
|
ncp_close(conn);
|
||||||
|
|
||||||
if ((pwd = getpwuid(info.mounted_uid)) == NULL)
|
if ((pwd = getpwuid(info.mounted_uid)) == NULL)
|
||||||
{
|
{
|
||||||
@@ -104,7 +104,7 @@ main(int argc, char *argv[])
|
|||||||
|
|
||||||
while ((mnt = getmntent(mtab)) != NULL)
|
while ((mnt = getmntent(mtab)) != NULL)
|
||||||
{
|
{
|
||||||
if (strcmp(mnt->mnt_dir, conn.mount_point) == 0)
|
if (strcmp(mnt->mnt_dir, conn->mount_point) == 0)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,17 +15,18 @@
|
|||||||
int
|
int
|
||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
struct ncp_conn conn;
|
struct ncp_conn *conn;
|
||||||
struct ncp_bindery_object q;
|
struct ncp_bindery_object q;
|
||||||
int found = 0;
|
int found = 0;
|
||||||
|
|
||||||
char default_pattern[] = "*";
|
char default_pattern[] = "*";
|
||||||
char *pattern = default_pattern;
|
char *pattern = default_pattern;
|
||||||
char *p;
|
char *p;
|
||||||
|
long err;
|
||||||
|
|
||||||
if (ncp_initialize(&conn, &argc, argv, 1) != 0)
|
if ((conn = ncp_initialize(&argc, argv, 1, &err)) == NULL)
|
||||||
{
|
{
|
||||||
perror("Could not open connection");
|
com_err(argv[0], err, "in ncp_initialize");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,7 +48,7 @@ main(int argc, char **argv)
|
|||||||
|
|
||||||
if (isatty(1))
|
if (isatty(1))
|
||||||
{
|
{
|
||||||
printf("\nServer: %s\n", conn.server);
|
printf("\nServer: %s\n", conn->server);
|
||||||
printf("%-52s%-10s\n"
|
printf("%-52s%-10s\n"
|
||||||
"-----------------------------------------------"
|
"-----------------------------------------------"
|
||||||
"-------------\n",
|
"-------------\n",
|
||||||
@@ -57,8 +58,8 @@ main(int argc, char **argv)
|
|||||||
|
|
||||||
q.object_id = 0xffffffff;
|
q.object_id = 0xffffffff;
|
||||||
|
|
||||||
while (ncp_scan_bindery_object(&conn, q.object_id,
|
while (ncp_scan_bindery_object(conn, q.object_id,
|
||||||
NCP_BINDERY_PQUEUE, "*", &q) == 0)
|
NCP_BINDERY_PQUEUE, pattern, &q) == 0)
|
||||||
{
|
{
|
||||||
found = 1;
|
found = 1;
|
||||||
printf("%-52s", q.object_name);
|
printf("%-52s", q.object_name);
|
||||||
@@ -70,6 +71,6 @@ main(int argc, char **argv)
|
|||||||
printf("No queues found\n");
|
printf("No queues found\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
ncp_close(&conn);
|
ncp_close(conn);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -107,12 +107,13 @@ daemon_init(void)
|
|||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
struct ncp_conn conn;
|
struct ncp_conn *conn;
|
||||||
int poll_timeout = 30;
|
int poll_timeout = 30;
|
||||||
int opt;
|
int opt;
|
||||||
int job_type = 0xffff;
|
int job_type = 0xffff;
|
||||||
int debug = 0;
|
int debug = 0;
|
||||||
int i;
|
int i;
|
||||||
|
long err;
|
||||||
|
|
||||||
char *queue_name = NULL;
|
char *queue_name = NULL;
|
||||||
|
|
||||||
@@ -146,9 +147,10 @@ main(int argc, char *argv[])
|
|||||||
openlog("pserver", LOG_PID, LOG_LPR);
|
openlog("pserver", LOG_PID, LOG_LPR);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ncp_initialize_as(&conn, &argc, argv, 1, NCP_BINDERY_PSERVER) != 0)
|
if ((conn = ncp_initialize_as(&argc, argv, 1,
|
||||||
|
NCP_BINDERY_PSERVER, &err)) == NULL)
|
||||||
{
|
{
|
||||||
perror("Could not open connection");
|
com_err(argv[0], err, "in ncp_initialize");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -193,10 +195,10 @@ main(int argc, char *argv[])
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (init_queue(&conn, queue_name, command, &q) != 0)
|
if (init_queue(conn, queue_name, command, &q) != 0)
|
||||||
{
|
{
|
||||||
perror("Could not init queue");
|
perror("Could not init queue");
|
||||||
ncp_close(&conn);
|
ncp_close(conn);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -221,9 +223,9 @@ main(int argc, char *argv[])
|
|||||||
sleep(poll_timeout);
|
sleep(poll_timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
ncp_detach_from_queue(&conn, q.queue_id);
|
ncp_detach_from_queue(conn, q.queue_id);
|
||||||
|
|
||||||
ncp_close(&conn);
|
ncp_close(conn);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
13
util/slist.c
13
util/slist.c
@@ -17,12 +17,13 @@
|
|||||||
void
|
void
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
struct ncp_conn conn;
|
struct ncp_conn *conn;
|
||||||
struct ncp_bindery_object obj;
|
struct ncp_bindery_object obj;
|
||||||
int found = 0;
|
int found = 0;
|
||||||
char default_pattern[] = "*";
|
char default_pattern[] = "*";
|
||||||
char *pattern = default_pattern;
|
char *pattern = default_pattern;
|
||||||
char *p;
|
char *p;
|
||||||
|
long err;
|
||||||
|
|
||||||
if (argc > 2)
|
if (argc > 2)
|
||||||
{
|
{
|
||||||
@@ -40,9 +41,9 @@ main(int argc, char *argv[])
|
|||||||
*p = toupper(*p);
|
*p = toupper(*p);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ncp_initialize(&conn, &argc, argv, 0) != 0)
|
if ((conn = ncp_initialize(&argc, argv, 0, &err)) == NULL)
|
||||||
{
|
{
|
||||||
perror("ncp_connect");
|
com_err(argv[0], err, "in ncp_initialize");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,7 +59,7 @@ main(int argc, char *argv[])
|
|||||||
|
|
||||||
obj.object_id = 0xffffffff;
|
obj.object_id = 0xffffffff;
|
||||||
|
|
||||||
while (ncp_scan_bindery_object(&conn, obj.object_id,
|
while (ncp_scan_bindery_object(conn, obj.object_id,
|
||||||
NCP_BINDERY_FSERVER, pattern,
|
NCP_BINDERY_FSERVER, pattern,
|
||||||
&obj) == 0)
|
&obj) == 0)
|
||||||
{
|
{
|
||||||
@@ -70,7 +71,7 @@ main(int argc, char *argv[])
|
|||||||
|
|
||||||
printf("%-52s", obj.object_name);
|
printf("%-52s", obj.object_name);
|
||||||
|
|
||||||
if (ncp_read_property_value(&conn, NCP_BINDERY_FSERVER,
|
if (ncp_read_property_value(conn, NCP_BINDERY_FSERVER,
|
||||||
obj.object_name, 1, "NET_ADDRESS",
|
obj.object_name, 1, "NET_ADDRESS",
|
||||||
&prop) == 0)
|
&prop) == 0)
|
||||||
{
|
{
|
||||||
@@ -86,6 +87,6 @@ main(int argc, char *argv[])
|
|||||||
printf("No servers found\n");
|
printf("No servers found\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
ncp_close(&conn);
|
ncp_close(conn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user