mirror of
https://github.com/freebsd/freebsd-src.git
synced 2026-10-31 21:06:18 +01:00
Compare commits
298
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
17d68b04ff | ||
|
|
ce6a5b7bc2 | ||
|
|
c2b805c3e2 | ||
|
|
3bd426de32 | ||
|
|
725728d3f1 | ||
|
|
6d14058c93 | ||
|
|
0732cb7664 | ||
|
|
1dc3787975 | ||
|
|
336a99a142 | ||
|
|
e7573d045e | ||
|
|
54eacce011 | ||
|
|
95f3479e86 | ||
|
|
d4b8a803d2 | ||
|
|
3edb5b8243 | ||
|
|
9e1e69007e | ||
|
|
6b131fd325 | ||
|
|
96f6ce831d | ||
|
|
722da8795b | ||
|
|
2a161a564f | ||
|
|
ef6315440d | ||
|
|
257b64e655 | ||
|
|
5400a1d50b | ||
|
|
cb6db0be82 | ||
|
|
efc20b9b20 | ||
|
|
3a4a0410ce | ||
|
|
89ff02f2cd | ||
|
|
a395a8ddaa | ||
|
|
c02d319382 | ||
|
|
e8170c615e | ||
|
|
86f0017da6 | ||
|
|
0f2f75d4cd | ||
|
|
760b3ff032 | ||
|
|
2007fa5423 | ||
|
|
2826b97699 | ||
|
|
cad0dd6541 | ||
|
|
a7536a22f1 | ||
|
|
ec8cca06a4 | ||
|
|
956e27c432 | ||
|
|
365e7a5627 | ||
|
|
036dc9deb5 | ||
|
|
588b2ee1f4 | ||
|
|
4e0d7f1eeb | ||
|
|
41865c3eb8 | ||
|
|
6a1d5c6111 | ||
|
|
ae96b458b8 | ||
|
|
53cdd7b2cc | ||
|
|
138d328594 | ||
|
|
779181d670 | ||
|
|
ea440f5a8c | ||
|
|
00647e5628 | ||
|
|
582231348c | ||
|
|
b23677495a | ||
|
|
c34d79a043 | ||
|
|
3a27de6a11 | ||
|
|
6b98c5e881 | ||
|
|
d5eb22b779 | ||
|
|
f7a19e923f | ||
|
|
c259a2c856 | ||
|
|
2ec38507c3 | ||
|
|
d3c6824031 | ||
|
|
cd5baeac25 | ||
|
|
b12d22be7d | ||
|
|
2bf0e027c9 | ||
|
|
ee11a1bf89 | ||
|
|
6a1cb1770f | ||
|
|
1ee8ce5356 | ||
|
|
b8498bde4a | ||
|
|
28aa8fa144 | ||
|
|
aad26cb372 | ||
|
|
9e6e907a18 | ||
|
|
dccedb5e05 | ||
|
|
3ec2d329a6 | ||
|
|
44075fb26d | ||
|
|
019765e155 | ||
|
|
13c01cc282 | ||
|
|
b8680a4f43 | ||
|
|
bc879ddf95 | ||
|
|
8f3fec335d | ||
|
|
b3c2e1fc0f | ||
|
|
78b2207ca1 | ||
|
|
ed00024f56 | ||
|
|
f2b4a33021 | ||
|
|
9451b7b706 | ||
|
|
864e2d4780 | ||
|
|
d4cc0dd698 | ||
|
|
19ea613108 | ||
|
|
1f8e33d2b6 | ||
|
|
f500949472 | ||
|
|
ad461bea1f | ||
|
|
aa1af3afc4 | ||
|
|
3a888d6a17 | ||
|
|
89b9ab35d9 | ||
|
|
32bc8b104a | ||
|
|
03675f50e3 | ||
|
|
2241cdc84a | ||
|
|
10bc76be64 | ||
|
|
0ecdbb412d | ||
|
|
ff8eca7f6e | ||
|
|
f21c1795b5 | ||
|
|
fd65bb44b6 | ||
|
|
4af1c15ea4 | ||
|
|
13c72f074c | ||
|
|
296ea871fa | ||
|
|
3c56cf9a5f | ||
|
|
06176b545f | ||
|
|
fb5aed6a17 | ||
|
|
1fd9820da2 | ||
|
|
a2d44b961b | ||
|
|
972b9cf163 | ||
|
|
7c5e88b7dc | ||
|
|
748e263e1d | ||
|
|
d737fb0b8e | ||
|
|
7b1fa34c8d | ||
|
|
6acd4084ec | ||
|
|
7a5430c00e | ||
|
|
adc988f73d | ||
|
|
1352103803 | ||
|
|
257c17f29a | ||
|
|
d5f02160ba | ||
|
|
ed288be5ba | ||
|
|
e92eaf1075 | ||
|
|
5e3393116c | ||
|
|
093b091bd8 | ||
|
|
9474c9643e | ||
|
|
5e5326a1ba | ||
|
|
378c58eff0 | ||
|
|
05d21356fb | ||
|
|
cfb83353fd | ||
|
|
8cd360ec17 | ||
|
|
1bf5c58257 | ||
|
|
f54ce65bb9 | ||
|
|
ac613515db | ||
|
|
289746cecf | ||
|
|
625b109de1 | ||
|
|
a42a785e4d | ||
|
|
207002ac9e | ||
|
|
29388f8fe8 | ||
|
|
c470a93b9f | ||
|
|
9808520bd1 | ||
|
|
69111243d3 | ||
|
|
f176719027 | ||
|
|
6f8161632a | ||
|
|
c0b59cd1b1 | ||
|
|
5d53a74cd7 | ||
|
|
6d9a276234 | ||
|
|
52b82940fc | ||
|
|
b96a4cd26a | ||
|
|
18938e7ffe | ||
|
|
6c5f963f37 | ||
|
|
8690eb7f95 | ||
|
|
c3a6c79d36 | ||
|
|
c27b7c7993 | ||
|
|
933a44e8a8 | ||
|
|
f6f114b411 | ||
|
|
bc22467b56 | ||
|
|
3c4e06b3f4 | ||
|
|
ea12cfd3b2 | ||
|
|
fd32efcf44 | ||
|
|
5f3610e40a | ||
|
|
e8e6fd2156 | ||
|
|
f0fd609eff | ||
|
|
af20617bdb | ||
|
|
73ff38eacc | ||
|
|
f3e7959b32 | ||
|
|
5d87a35849 | ||
|
|
6e0edc431b | ||
|
|
8f64c1238a | ||
|
|
d527b359a9 | ||
|
|
883fbfddd6 | ||
|
|
5d8a5196cf | ||
|
|
31ccf96e84 | ||
|
|
1fa8d01d37 | ||
|
|
b77d339c49 | ||
|
|
dc9b9ab5d2 | ||
|
|
8053682ed7 | ||
|
|
e7a2318397 | ||
|
|
60a0e13292 | ||
|
|
4cfb401d60 | ||
|
|
fa82ca0529 | ||
|
|
dab80884bf | ||
|
|
2ce156e490 | ||
|
|
7987ae06be | ||
|
|
5bfa20bad8 | ||
|
|
7cc9ceeccb | ||
|
|
19f5c35ec2 | ||
|
|
c31f183aa3 | ||
|
|
0f825d05b2 | ||
|
|
027d958ed8 | ||
|
|
43346dc696 | ||
|
|
506ed58087 | ||
|
|
0e818078c8 | ||
|
|
a1dfdf15cc | ||
|
|
5f1e86edf1 | ||
|
|
12519f8ccf | ||
|
|
c97f49c252 | ||
|
|
2fa0b5b21b | ||
|
|
e3888f5ce3 | ||
|
|
16802300ec | ||
|
|
248b7a9530 | ||
|
|
00a9c6e916 | ||
|
|
f62abeca53 | ||
|
|
dde9b27a7b | ||
|
|
690701f2a4 | ||
|
|
23c24233d9 | ||
|
|
259b77225b | ||
|
|
95546cc5be | ||
|
|
db0f082dd4 | ||
|
|
09326b338e | ||
|
|
349ef01462 | ||
|
|
a85a4c1fcb | ||
|
|
2e771ebce0 | ||
|
|
1f30a75dfe | ||
|
|
fe74552ec0 | ||
|
|
5a997d2b6a | ||
|
|
bde21cce2d | ||
|
|
a4f1d29d68 | ||
|
|
79f1f6e793 | ||
|
|
547feaa15b | ||
|
|
2bb83d0f01 | ||
|
|
db2a660432 | ||
|
|
dc71bf63a3 | ||
|
|
d850279036 | ||
|
|
6ba396b65f | ||
|
|
2552197c18 | ||
|
|
40489a8e51 | ||
|
|
162e9e4306 | ||
|
|
a6dad8aa23 | ||
|
|
401fcb586a | ||
|
|
8f93d972a9 | ||
|
|
dd92706c78 | ||
|
|
4cf2407013 | ||
|
|
6773ede3bd | ||
|
|
334e2320d8 | ||
|
|
bc0439b6c9 | ||
|
|
bb5056e7ae | ||
|
|
a970253b52 | ||
|
|
6b05ddd343 | ||
|
|
19698bb448 | ||
|
|
a470134aa5 | ||
|
|
b849008b41 | ||
|
|
1801493821 | ||
|
|
28d42418bd | ||
|
|
3d33b451be | ||
|
|
127220ad3c | ||
|
|
d5b27f6340 | ||
|
|
d6577c47a3 | ||
|
|
0bf20bab81 | ||
|
|
67fb80aeab | ||
|
|
1bb4051af6 | ||
|
|
f8fd263ecd | ||
|
|
b19c0d128c | ||
|
|
86788fb75c | ||
|
|
252c42d64e | ||
|
|
b113287a33 | ||
|
|
e2fca6c703 | ||
|
|
f215037ee6 | ||
|
|
a6678ed23e | ||
|
|
c4999ac8d4 | ||
|
|
ee0893b9cc | ||
|
|
82276f4c64 | ||
|
|
e0dee0b17f | ||
|
|
f8cca2dc47 | ||
|
|
647cde13c4 | ||
|
|
3ebd05b37a | ||
|
|
c3aa9d2d1d | ||
|
|
46088c5d77 | ||
|
|
4f5e3a6468 | ||
|
|
ba0389a43b | ||
|
|
2a1a24deec | ||
|
|
cb2edcd185 | ||
|
|
218be1b49c | ||
|
|
de67d6db6a | ||
|
|
3b7e12abe4 | ||
|
|
83198763b6 | ||
|
|
d5b2bafb44 | ||
|
|
aa1c206c46 | ||
|
|
10a87ad77e | ||
|
|
1f219de96c | ||
|
|
ce0a993ca4 | ||
|
|
fbb8be5c8f | ||
|
|
3f0139e934 | ||
|
|
79efae40a2 | ||
|
|
8fd529e8dc | ||
|
|
bb4e613445 | ||
|
|
0188ecc7f2 | ||
|
|
6c3f241e16 | ||
|
|
52360938a3 | ||
|
|
a6189554c0 | ||
|
|
7afb7e7ace | ||
|
|
69aaa91ec3 | ||
|
|
1bb33e2a0b | ||
|
|
93552a48be | ||
|
|
92fc438c2a | ||
|
|
e0b2901d8f | ||
|
|
5ac7c3a69f | ||
|
|
55e572c101 | ||
|
|
796b13787e | ||
|
|
323b5b1147 |
No files matched your search
@@ -1,4 +1,4 @@
|
||||
# $Id: Makefile,v 1.57.4.16 1996/06/21 19:41:35 markm Exp $
|
||||
# $Id: Makefile,v 1.57.4.18 1996/08/11 03:05:16 rgrimes Exp $
|
||||
#
|
||||
# Make command line options:
|
||||
# -DCLOBBER will remove /usr/include and MOST of /usr/lib
|
||||
@@ -216,17 +216,21 @@ includes:
|
||||
.endif
|
||||
cd ${.CURDIR}/include && ${MAKE} install
|
||||
cd ${.CURDIR}/gnu/include && ${MAKE} install
|
||||
cd ${.CURDIR}/gnu/lib/libdialog && ${MAKE} beforeinstall
|
||||
cd ${.CURDIR}/gnu/lib/libg++ && ${MAKE} beforeinstall
|
||||
cd ${.CURDIR}/gnu/lib/libgmp && ${MAKE} beforeinstall
|
||||
cd ${.CURDIR}/gnu/lib/libmp && ${MAKE} beforeinstall
|
||||
cd ${.CURDIR}/gnu/lib/libreadline && ${MAKE} beforeinstall
|
||||
cd ${.CURDIR}/gnu/lib/libregex && ${MAKE} beforeinstall
|
||||
cd ${.CURDIR}/gnu/lib/libg++ && ${MAKE} beforeinstall
|
||||
cd ${.CURDIR}/gnu/lib/libdialog && ${MAKE} beforeinstall
|
||||
.if exists(eBones) && !defined(NOCRYPT) && defined(MAKE_EBONES)
|
||||
cd ${.CURDIR}/eBones/include && ${MAKE} beforeinstall
|
||||
cd ${.CURDIR}/eBones/lib/libkrb && ${MAKE} beforeinstall
|
||||
cd ${.CURDIR}/eBones/lib/libkadm && ${MAKE} beforeinstall
|
||||
.endif
|
||||
cd ${.CURDIR}/lib/csu/${MACHINE} && ${MAKE} beforeinstall
|
||||
cd ${.CURDIR}/lib/libc && ${MAKE} beforeinstall
|
||||
cd ${.CURDIR}/lib/libcurses && ${MAKE} beforeinstall
|
||||
cd ${.CURDIR}/lib/libdisk && ${MAKE} beforeinstall
|
||||
cd ${.CURDIR}/lib/libedit && ${MAKE} beforeinstall
|
||||
cd ${.CURDIR}/lib/libftpio && ${MAKE} beforeinstall
|
||||
cd ${.CURDIR}/lib/libmd && ${MAKE} beforeinstall
|
||||
@@ -243,6 +247,9 @@ includes:
|
||||
cd ${.CURDIR}/lib/libss && ${MAKE} beforeinstall
|
||||
cd ${.CURDIR}/lib/libscsi && ${MAKE} beforeinstall
|
||||
cd ${.CURDIR}/lib/libutil && ${MAKE} beforeinstall
|
||||
.if exists(secure) && !defined(NOCRYPT) && !defined(NOSECURE)
|
||||
cd ${.CURDIR}/secure/lib/libdes && ${MAKE} beforeinstall
|
||||
.endif
|
||||
|
||||
lib-tools:
|
||||
@echo "--------------------------------------------------------------"
|
||||
@@ -288,6 +295,12 @@ libraries:
|
||||
cd ${.CURDIR}/lib/libtermcap && \
|
||||
${MAKE} depend all install
|
||||
.endif
|
||||
.if exists(lib)
|
||||
cd ${.CURDIR}/lib/csu/i386 && \
|
||||
${MAKE} depend all install ${CLEANDIR} ${OBJDIR}
|
||||
cd ${.CURDIR}/lib && \
|
||||
${MAKE} depend all install ${CLEANDIR} ${OBJDIR}
|
||||
.endif
|
||||
.if exists(gnu)
|
||||
cd ${.CURDIR}/gnu/lib && \
|
||||
${MAKE} depend all install ${CLEANDIR} ${OBJDIR}
|
||||
@@ -297,12 +310,6 @@ libraries:
|
||||
.if exists(secure) && !defined(NOCRYPT) && !defined(NOSECURE)
|
||||
cd ${.CURDIR}/secure/lib && \
|
||||
${MAKE} depend all install ${CLEANDIR} ${OBJDIR}
|
||||
.endif
|
||||
.if exists(lib)
|
||||
cd ${.CURDIR}/lib/csu/i386 && \
|
||||
${MAKE} depend all install ${CLEANDIR} ${OBJDIR}
|
||||
cd ${.CURDIR}/lib && \
|
||||
${MAKE} depend all install ${CLEANDIR} ${OBJDIR}
|
||||
.endif
|
||||
cd ${.CURDIR}/usr.bin/lex/lib && \
|
||||
${MAKE} depend all install ${CLEANDIR} ${OBJDIR}
|
||||
|
||||
@@ -1,4 +1,15 @@
|
||||
# @(#)Makefile.inc 8.1 (Berkeley) 5/31/93
|
||||
# $Id: Makefile.inc,v 1.7 1996/09/22 21:51:04 wosch Exp $
|
||||
|
||||
BINDIR?= /bin
|
||||
NOSHARED?= YES
|
||||
|
||||
.if exists (${.CURDIR}/../../secure)
|
||||
|
||||
.if exists(${.CURDIR}/../../secure/lib/libcipher/obj)
|
||||
CIPHEROBJDIR= ${.CURDIR}/../../secure/lib/libcipher/obj
|
||||
.else
|
||||
CIPHEROBJDIR= ${.CURDIR}/../../secure/lib/libcipher
|
||||
.endif
|
||||
|
||||
.endif
|
||||
+9
-2
@@ -1,8 +1,15 @@
|
||||
# $Id: Makefile,v 1.10 1994/12/18 15:15:10 jkh Exp $
|
||||
# $Id: Makefile,v 1.13 1995/10/22 20:14:13 ache Exp $
|
||||
|
||||
PROG= ed
|
||||
SRCS= buf.c cbc.c glbl.c io.c main.c re.c sub.c undo.c
|
||||
SRCS= buf.c cbc.c glbl.c io.c main.c re.c sub.c undo.c
|
||||
LINKS= ${BINDIR}/ed ${BINDIR}/red
|
||||
MLINKS= ed.1 red.1
|
||||
|
||||
.if exists(../../secure) && !defined(NOCRYPT) && !defined(NOSECURE)
|
||||
DISTRIBUTION=des
|
||||
CFLAGS+=-DDES
|
||||
LDADD+= -L${CIPHEROBJDIR} -lcipher
|
||||
DPADD+= ${CIPHEROBJDIR}/libcipher.a
|
||||
.endif
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
+10
-6
@@ -33,7 +33,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: main.c,v 1.2 1994/09/24 02:57:48 davidg Exp $
|
||||
* $Id: main.c,v 1.3 1995/05/30 00:07:18 rgrimes Exp $
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
@@ -152,14 +152,18 @@ main(argc, argv) char **argv; {
|
||||
read_profile("/etc/profile");
|
||||
state1:
|
||||
state = 2;
|
||||
read_profile(".profile");
|
||||
if (privileged == 0)
|
||||
read_profile(".profile");
|
||||
else
|
||||
read_profile("/etc/suid_profile");
|
||||
}
|
||||
state2:
|
||||
state = 3;
|
||||
if ((shinit = lookupvar("ENV")) != NULL &&
|
||||
*shinit != '\0') {
|
||||
state = 3;
|
||||
read_profile(shinit);
|
||||
if (privileged == 0) {
|
||||
if ((shinit = lookupvar("ENV")) != NULL && *shinit != '\0') {
|
||||
state = 3;
|
||||
read_profile(shinit);
|
||||
}
|
||||
}
|
||||
state3:
|
||||
state = 4;
|
||||
|
||||
+10
-1
@@ -33,7 +33,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: options.c,v 1.3.4.2 1995/10/02 07:55:18 davidg Exp $
|
||||
* $Id: options.c,v 1.3.4.3 1995/10/10 01:04:38 davidg Exp $
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
@@ -91,6 +91,7 @@ procargs(argc, argv)
|
||||
argptr++;
|
||||
for (i = 0; i < NOPTS; i++)
|
||||
optlist[i].val = 2;
|
||||
privileged = (getuid() != geteuid() || getgid() != getegid());
|
||||
options(1);
|
||||
if (*argptr == NULL && minusc == NULL)
|
||||
sflag = 1;
|
||||
@@ -177,6 +178,10 @@ options(cmdline) {
|
||||
if (*argptr)
|
||||
argptr++;
|
||||
} else {
|
||||
if (c == 'p' && !val && privileged) {
|
||||
(void) setuid(getuid());
|
||||
(void) setgid(getgid());
|
||||
}
|
||||
setoption(c, val);
|
||||
}
|
||||
}
|
||||
@@ -198,6 +203,10 @@ minus_o(name, val)
|
||||
} else {
|
||||
for (i = 0; i < NOPTS; i++)
|
||||
if (equal(name, optlist[i].name)) {
|
||||
if (!val && privileged && equal(name, "privileged")) {
|
||||
(void) setuid(getuid());
|
||||
(void) setgid(getgid());
|
||||
}
|
||||
setoption(optlist[i].letter, val);
|
||||
return;
|
||||
}
|
||||
|
||||
+4
-2
@@ -34,7 +34,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)options.h 8.1 (Berkeley) 5/31/93
|
||||
* $Id$
|
||||
* $Id: options.h,v 1.2 1994/09/24 02:58:05 davidg Exp $
|
||||
*/
|
||||
|
||||
struct shparam {
|
||||
@@ -62,8 +62,9 @@ struct shparam {
|
||||
#define aflag optlist[12].val
|
||||
#define bflag optlist[13].val
|
||||
#define uflag optlist[14].val
|
||||
#define privileged optlist[15].val
|
||||
|
||||
#define NOPTS 15
|
||||
#define NOPTS 16
|
||||
|
||||
struct optent {
|
||||
const char *name;
|
||||
@@ -88,6 +89,7 @@ struct optent optlist[NOPTS] = {
|
||||
"allexport", 'a', 0,
|
||||
"notify", 'b', 0,
|
||||
"nounset", 'u', 0,
|
||||
"privileged", 'p', 0,
|
||||
};
|
||||
#else
|
||||
extern struct optent optlist[NOPTS];
|
||||
|
||||
+11
-2
@@ -33,7 +33,7 @@
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" @(#)sh.1 8.4 (Berkeley) 4/18/94
|
||||
.\" $Id: sh.1,v 1.5 1995/10/21 00:47:32 joerg Exp $
|
||||
.\" $Id: sh.1,v 1.3.4.1 1995/12/11 23:04:55 joerg Exp $
|
||||
.\"
|
||||
.\"
|
||||
.\"
|
||||
@@ -42,7 +42,7 @@
|
||||
.SH NAME
|
||||
sh \- command interpreter (shell)
|
||||
.SH SYNOPSIS
|
||||
sh [-/+aCefnuvxIimsVEb] [-/+o longname] [arg ...]
|
||||
sh [-/+aCefnpuvxIimsVEb] [-/+o longname] [arg ...]
|
||||
.SH DESCRIPTION
|
||||
.LP
|
||||
Sh is the standard command interpreter for the system.
|
||||
@@ -161,6 +161,15 @@ If not interactive, read commands but do not
|
||||
execute them. This is useful for checking the
|
||||
syntax of shell scripts.
|
||||
.TP
|
||||
-p privileged
|
||||
Turn on privileged mode. This mode is enabled on startup
|
||||
if either the effective user or group id is not equal to the
|
||||
real user or group id. Turning this mode off sets the
|
||||
effective user and group ids to the real user and group ids.
|
||||
Also on interactive shells and when enabled, this mode sources
|
||||
/etc/suid_profile (instead of ~/.profile) after /etc/profile
|
||||
and ignores the contents of the \fBENV\fP variable.
|
||||
.TP
|
||||
-u nounset
|
||||
Write a message to standard error when attempting
|
||||
to expand a variable that is not set, and if the
|
||||
|
||||
@@ -81,7 +81,8 @@ if [ ! -f $bak/master.passwd.bak ] ; then
|
||||
fi
|
||||
if cmp -s $bak/master.passwd.bak /etc/master.passwd; then :; else
|
||||
echo "$host passwd diffs:"
|
||||
diff $bak/master.passwd.bak /etc/master.passwd
|
||||
diff $bak/master.passwd.bak /etc/master.passwd |\
|
||||
sed 's/^\([<>] [^:]*\):[^:]*:/\1:(password):/'
|
||||
mv $bak/master.passwd.bak $bak/master.passwd.bak2
|
||||
cp -p /etc/master.passwd $bak/master.passwd.bak
|
||||
fi
|
||||
|
||||
@@ -189,3 +189,8 @@ mta3230|mo230|IBM MTA-3230 230 Meg 3.5inch Magneto-Optical:\
|
||||
:se#512:nt#64:ns#32:nc#216:sc#2048:su#444384:\
|
||||
:pa#444384:oa#0:ba#4096:fa#0:ta=4.2BSD:\
|
||||
:pc#444384:oc#0:
|
||||
|
||||
minimum:ty=mfs:se#512:nt#1:rm#300:\
|
||||
:ns#2880:nc#1:\
|
||||
:pa#2880:oa#0:ba#4096:fa#512:\
|
||||
:pc#2880:oc#0:bc#4096:fc#512:
|
||||
+4
-4
@@ -27,10 +27,10 @@ discard dgram udp wait root internal
|
||||
#daytime dgram udp wait root internal
|
||||
#time dgram udp wait root internal
|
||||
# Kerberos authenticated services
|
||||
klogin stream tcp nowait root /usr/libexec/rlogind rlogind -k
|
||||
eklogin stream tcp nowait root /usr/libexec/rlogind rlogind -k -x
|
||||
kshell stream tcp nowait root /usr/libexec/rshd rshd -k
|
||||
rkinit stream tcp nowait root /usr/libexec/rkinitd rkinitd
|
||||
#klogin stream tcp nowait root /usr/libexec/rlogind rlogind -k
|
||||
#eklogin stream tcp nowait root /usr/libexec/rlogind rlogind -k -x
|
||||
#kshell stream tcp nowait root /usr/libexec/rshd rshd -k
|
||||
#rkinit stream tcp nowait root /usr/libexec/rkinitd rkinitd
|
||||
# Services run ONLY on the Kerberos server
|
||||
# Neither of these work in FreeBSD 1.x.
|
||||
#krbupdate stream tcp nowait root /usr/libexec/registerd registerd
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
root::0:0::0:0:Charlie &:/root:/bin/csh
|
||||
toor:*:0:0::0:0:Bourne-again Superuser:/root:
|
||||
daemon:*:1:31::0:0:Owner of many system processes:/root:
|
||||
daemon:*:1:1::0:0:Owner of many system processes:/root:
|
||||
operator:*:2:20::0:0:System &:/usr/guest/operator:/bin/csh
|
||||
bin:*:3:7::0:0:Binaries Commands and Source,,,:/:/nonexistent
|
||||
games:*:7:13::0:0:Games pseudo-user:/usr/games:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# $Id: BSD.local.dist,v 1.11.4.4 1996/06/11 22:04:55 asami Exp $
|
||||
# $Id: BSD.local.dist,v 1.11.4.5 1996/06/16 22:33:58 asami Exp $
|
||||
#
|
||||
|
||||
/set type=dir uname=bin gname=bin mode=0755
|
||||
@@ -38,6 +38,54 @@
|
||||
..
|
||||
catl uname=man
|
||||
..
|
||||
catn uname=man
|
||||
..
|
||||
ja_JP.EUC
|
||||
cat1 uname=man
|
||||
..
|
||||
cat2 uname=man
|
||||
..
|
||||
cat3 uname=man
|
||||
..
|
||||
cat4 uname=man
|
||||
..
|
||||
cat5 uname=man
|
||||
..
|
||||
cat6 uname=man
|
||||
..
|
||||
cat7 uname=man
|
||||
..
|
||||
cat8 uname=man
|
||||
..
|
||||
cat9 uname=man
|
||||
..
|
||||
catl uname=man
|
||||
..
|
||||
catn uname=man
|
||||
..
|
||||
man1
|
||||
..
|
||||
man2
|
||||
..
|
||||
man3
|
||||
..
|
||||
man4
|
||||
..
|
||||
man5
|
||||
..
|
||||
man6
|
||||
..
|
||||
man7
|
||||
..
|
||||
man8
|
||||
..
|
||||
man9
|
||||
..
|
||||
manl
|
||||
..
|
||||
mann
|
||||
..
|
||||
..
|
||||
man1
|
||||
..
|
||||
man2
|
||||
@@ -58,12 +106,20 @@
|
||||
..
|
||||
manl
|
||||
..
|
||||
mann
|
||||
..
|
||||
..
|
||||
sbin
|
||||
..
|
||||
share
|
||||
dict
|
||||
..
|
||||
doc
|
||||
..
|
||||
examples
|
||||
..
|
||||
misc
|
||||
..
|
||||
nls
|
||||
C
|
||||
..
|
||||
@@ -103,6 +159,8 @@
|
||||
..
|
||||
ja_JP.EUC
|
||||
..
|
||||
lt_LN.ASCII
|
||||
..
|
||||
lt_LN.ISO_8859-1
|
||||
..
|
||||
nl_BE.ISO_8859-1
|
||||
@@ -113,6 +171,8 @@
|
||||
..
|
||||
pt_PT.ISO_8859-1
|
||||
..
|
||||
ru_SU.CP866
|
||||
..
|
||||
ru_SU.KOI8-R
|
||||
..
|
||||
sv_SE.ISO_8859-1
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# $Id: BSD.usr.dist,v 1.40.4.9 1996/06/05 02:36:59 jkh Exp $
|
||||
# $Id: BSD.usr.dist,v 1.40.4.10 1996/06/25 08:40:13 jkh Exp $
|
||||
#
|
||||
|
||||
/set type=dir uname=bin gname=bin mode=0755
|
||||
@@ -54,6 +54,8 @@
|
||||
papers
|
||||
..
|
||||
psd
|
||||
05.sysman
|
||||
..
|
||||
12.make
|
||||
..
|
||||
18.gprof
|
||||
@@ -437,6 +439,8 @@
|
||||
Africa
|
||||
..
|
||||
America
|
||||
Indiana
|
||||
..
|
||||
..
|
||||
Asia
|
||||
..
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# $Id: BSD.var.dist,v 1.23.4.2 1996/06/05 02:37:00 jkh Exp $
|
||||
# $Id: BSD.var.dist,v 1.23.4.3 1996/06/17 09:17:40 jkh Exp $
|
||||
#
|
||||
|
||||
/set type=dir uname=bin gname=bin mode=0755
|
||||
@@ -40,7 +40,7 @@
|
||||
..
|
||||
run uname=bin
|
||||
..
|
||||
rwho uname=bin
|
||||
rwho uname=bin gname=daemon mode=0775
|
||||
..
|
||||
/set type=dir uname=uucp gname=daemon mode=0755
|
||||
spool uname=bin gname=bin
|
||||
|
||||
+12
-2
@@ -12,8 +12,8 @@
|
||||
; submenu InterNIC Registration Archives
|
||||
; file named.root
|
||||
;
|
||||
; last update: Nov 8, 1995
|
||||
; related version of root zone: 1995110800
|
||||
; last update: Jan 22, 1997
|
||||
; related version of root zone: 1997012200
|
||||
;
|
||||
;
|
||||
; formerly NS.INTERNIC.NET
|
||||
@@ -60,4 +60,14 @@ H.ROOT-SERVERS.NET. 3600000 A 128.63.2.53
|
||||
;
|
||||
. 3600000 NS I.ROOT-SERVERS.NET.
|
||||
I.ROOT-SERVERS.NET. 3600000 A 192.36.148.17
|
||||
;
|
||||
; temporarily housed at NSI (InterNIC)
|
||||
;
|
||||
. 3600000 NS J.ROOT-SERVERS.NET.
|
||||
J.ROOT-SERVERS.NET. 3600000 A 198.41.0.10
|
||||
;
|
||||
; temporarily housed at NSI (InterNIC)
|
||||
;
|
||||
. 3600000 NS K.ROOT-SERVERS.NET.
|
||||
K.ROOT-SERVERS.NET. 3600000 A 198.41.0.11
|
||||
; End of File
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
#!/bin/sh -
|
||||
#
|
||||
# @(#)security 5.3 (Berkeley) 5/28/91
|
||||
# $Id: security,v 1.8.4.2 1996/06/05 02:36:37 jkh Exp $
|
||||
# $Id: security,v 1.8.4.3 1996/06/17 09:17:12 jkh Exp $
|
||||
#
|
||||
PATH=/sbin:/bin:/usr/bin
|
||||
LC_ALL=C; export LC_ALL
|
||||
@@ -10,7 +10,7 @@ host=`hostname -s`
|
||||
echo "Subject: $host security check output"
|
||||
|
||||
LOG=/var/log
|
||||
TMP=/tmp/_secure.$$
|
||||
TMP=/var/run/_secure.$$
|
||||
|
||||
umask 027
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# Really quick and evil Makefile for building all the tests. I wish that bmake was friendlier to
|
||||
# the concept of multiple progs/libs in the same directory.
|
||||
# $Id: Makefile,v 1.1.2.1 1996/01/02 06:42:45 jkh Exp $
|
||||
# $Id$
|
||||
|
||||
PROGS= msg yesno prgbox gauge dselect fselect text menu1 menu2 menu3 \
|
||||
input1 check1 check2 check3 radio1 radio2 radio3
|
||||
input1 input2 check1 check2 check3 radio1 radio2 radio3
|
||||
|
||||
CFLAGS+= -Wall -Wstrict-prototypes
|
||||
LDFLAGS += -ldialog -lncurses -lmytinfo
|
||||
@@ -13,55 +13,4 @@ all: ${PROGS}
|
||||
clean:
|
||||
rm -f ${PROGS}
|
||||
|
||||
msg: ${.CURDIR}/msg.c
|
||||
${CC} ${.CURDIR}/msg.c -o msg ${LDFLAGS}
|
||||
|
||||
yesno: ${.CURDIR}/yesno.c
|
||||
${CC} ${.CURDIR}/yesno.c -o yesno ${LDFLAGS}
|
||||
|
||||
prgbox: ${.CURDIR}/prgbox.c
|
||||
${CC} ${.CURDIR}/prgbox.c -o prgbox ${LDFLAGS}
|
||||
|
||||
gauge: ${.CURDIR}/gauge.c
|
||||
${CC} ${.CURDIR}/gauge.c -o gauge ${LDFLAGS}
|
||||
|
||||
dselect: ${.CURDIR}/dselect.c
|
||||
${CC} ${.CURDIR}/dselect.c -o dselect ${LDFLAGS}
|
||||
|
||||
fselect: ${.CURDIR}/fselect.c
|
||||
${CC} ${.CURDIR}/fselect.c -o fselect ${LDFLAGS}
|
||||
|
||||
text: ${.CURDIR}/text.c
|
||||
${CC} ${.CURDIR}/text.c -o text ${LDFLAGS}
|
||||
|
||||
menu1: ${.CURDIR}/menu1.c
|
||||
${CC} ${.CURDIR}/menu1.c -o menu1 ${LDFLAGS}
|
||||
|
||||
menu2: ${.CURDIR}/menu2.c
|
||||
${CC} ${.CURDIR}/menu2.c -o menu2 ${LDFLAGS}
|
||||
|
||||
menu3: ${.CURDIR}/menu3.c
|
||||
${CC} ${.CURDIR}/menu3.c -o menu3 ${LDFLAGS}
|
||||
|
||||
input1: ${.CURDIR}/input1.c
|
||||
${CC} ${.CURDIR}/input1.c -o input1 ${LDFLAGS}
|
||||
|
||||
check1: ${.CURDIR}/check1.c
|
||||
${CC} ${.CURDIR}/check1.c -o check1 ${LDFLAGS}
|
||||
|
||||
check2: ${.CURDIR}/check2.c
|
||||
${CC} ${.CURDIR}/check2.c -o check2 ${LDFLAGS}
|
||||
|
||||
check3: ${.CURDIR}/check3.c
|
||||
${CC} ${.CURDIR}/check3.c -o check3 ${LDFLAGS}
|
||||
|
||||
radio1: ${.CURDIR}/radio1.c
|
||||
${CC} ${.CURDIR}/radio1.c -o radio1 ${LDFLAGS}
|
||||
|
||||
radio2: ${.CURDIR}/radio2.c
|
||||
${CC} ${.CURDIR}/radio2.c -o radio2 ${LDFLAGS}
|
||||
|
||||
radio3: ${.CURDIR}/radio3.c
|
||||
${CC} ${.CURDIR}/radio3.c -o radio3 ${LDFLAGS}
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* small test-driver for new dialog functionality
|
||||
*
|
||||
* Copyright (c) 1995, Jordan Hubbard
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code may be used, modified, copied, distributed, and
|
||||
* sold, in both source and binary form provided that the above
|
||||
* copyright and these terms are retained, verbatim, as the first
|
||||
* lines of this file. Under no circumstances is the author
|
||||
* responsible for the proper functioning of the software nor does
|
||||
* the author assume any responsibility for damages incurred with
|
||||
* its use.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
#include <dialog.h>
|
||||
|
||||
/* Kick it off, James! */
|
||||
int
|
||||
main(int argc, unsigned char *argv[])
|
||||
{
|
||||
int retval;
|
||||
unsigned char result[128];
|
||||
|
||||
init_dialog();
|
||||
|
||||
result[0]='\0';
|
||||
DialogInputAttrs |= DITEM_NO_ECHO;
|
||||
retval = dialog_inputbox("this is dialog_inputbox() in action, test #2 (no echo)",
|
||||
"Enter something really secret below, please.",
|
||||
-1, -1, result);
|
||||
DialogInputAttrs &= DITEM_NO_ECHO;
|
||||
dialog_clear();
|
||||
fprintf(stderr, "returned value for dialog_inputbox was %d (%s)\n", retval, result);
|
||||
|
||||
end_dialog();
|
||||
return 0;
|
||||
}
|
||||
@@ -40,9 +40,10 @@ int
|
||||
dialog_checklist(unsigned char *title, unsigned char *prompt, int height, int width,
|
||||
int list_height, int cnt, void *it, unsigned char *result)
|
||||
{
|
||||
int i, j, x, y, cur_x, cur_y, box_x, box_y, key = 0, button = 0, choice = 0,
|
||||
l, k, scroll = 0, max_choice, item_no = 0, *status;
|
||||
int i, j, x, y, cur_x, cur_y, box_x, box_y, key = 0, button, choice,
|
||||
l, k, scroll, max_choice, item_no = 0, *status;
|
||||
int redraw_menu = FALSE;
|
||||
int rval = 0;
|
||||
char okButton, cancelButton;
|
||||
WINDOW *dialog, *list;
|
||||
unsigned char **items = NULL;
|
||||
@@ -56,6 +57,7 @@ dialog_checklist(unsigned char *title, unsigned char *prompt, int height, int wi
|
||||
}
|
||||
|
||||
draw:
|
||||
choice = scroll = button = 0;
|
||||
/* Previous calling syntax, e.g. just a list of strings? */
|
||||
if (cnt >= 0) {
|
||||
items = it;
|
||||
@@ -170,14 +172,14 @@ draw:
|
||||
|
||||
/* Print the list */
|
||||
for (i = 0; i < max_choice; i++)
|
||||
print_item(list, items[i*3], items[i*3 + 1], status[i], i, i == choice, DREF(ditems, i));
|
||||
print_item(list, items[i * 3], items[i * 3 + 1], status[i], i, i == choice, DREF(ditems, i));
|
||||
wnoutrefresh(list);
|
||||
print_arrows(dialog, scroll, list_height, item_no, box_x, box_y, check_x + 4, cur_x, cur_y);
|
||||
|
||||
display_helpline(dialog, height-1, width);
|
||||
display_helpline(dialog, height - 1, width);
|
||||
|
||||
x = width/2-11;
|
||||
y = height-2;
|
||||
x = width / 2 - 11;
|
||||
y = height - 2;
|
||||
/* Is this a fancy new style argument string where we get to override
|
||||
* the buttons, or an old style one where they're fixed?
|
||||
*/
|
||||
@@ -225,12 +227,13 @@ draw:
|
||||
}
|
||||
}
|
||||
}
|
||||
delwin(list);
|
||||
delwin(dialog);
|
||||
return 0;
|
||||
rval = 0;
|
||||
key = ESC; /* Lemme out! */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Shortcut to cancel? */
|
||||
else if (toupper(key) == cancelButton) {
|
||||
if (toupper(key) == cancelButton) {
|
||||
if (ditems && result && ditems[CANCEL_BUTTON].fire) {
|
||||
int st;
|
||||
WINDOW *save;
|
||||
@@ -244,9 +247,9 @@ draw:
|
||||
}
|
||||
delwin(save);
|
||||
}
|
||||
delwin(list);
|
||||
delwin(dialog);
|
||||
return 1;
|
||||
rval = 1;
|
||||
key = ESC; /* I gotta go! */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check if key pressed matches first character of any item tag in list */
|
||||
@@ -254,26 +257,28 @@ draw:
|
||||
if (key < 0x100 && toupper(key) == toupper(items[(scroll+i)*3][0]))
|
||||
break;
|
||||
|
||||
if (i < max_choice || (key >= '1' && key <= MIN('9', '0'+max_choice)) || key == KEY_UP ||
|
||||
key == KEY_DOWN || key == ' ' || key == '+' || key == '-' ) {
|
||||
if (i < max_choice || (key >= '1' && key <= MIN('9', '0'+max_choice)) ||
|
||||
KEY_IS_UP(key) || KEY_IS_DOWN(key) || key == ' ') {
|
||||
|
||||
if (key >= '1' && key <= MIN('9', '0'+max_choice))
|
||||
i = key - '1';
|
||||
|
||||
else if (key == KEY_UP || key == '-') {
|
||||
else if (KEY_IS_UP(key)) {
|
||||
if (!choice) {
|
||||
if (scroll) {
|
||||
/* Scroll list down */
|
||||
getyx(dialog, cur_y, cur_x); /* Save cursor position */
|
||||
if (list_height > 1) {
|
||||
/* De-highlight current first item before scrolling down */
|
||||
print_item(list, items[scroll*3], items[scroll*3 + 1], status[scroll], 0, FALSE, DREF(ditems, scroll));
|
||||
print_item(list, items[scroll * 3], items[scroll * 3 + 1], status[scroll], 0,
|
||||
FALSE, DREF(ditems, scroll));
|
||||
scrollok(list, TRUE);
|
||||
wscrl(list, -1);
|
||||
scrollok(list, FALSE);
|
||||
}
|
||||
scroll--;
|
||||
print_item(list, items[scroll*3], items[scroll*3 + 1], status[scroll], 0, TRUE, DREF(ditems, scroll));
|
||||
print_item(list, items[scroll*3], items[scroll*3 + 1], status[scroll], 0,
|
||||
TRUE, DREF(ditems, scroll));
|
||||
wnoutrefresh(list);
|
||||
print_arrows(dialog, scroll, list_height, item_no, box_x, box_y, check_x + 4, cur_x, cur_y);
|
||||
wrefresh(dialog);
|
||||
@@ -283,22 +288,26 @@ draw:
|
||||
else
|
||||
i = choice - 1;
|
||||
}
|
||||
else if (key == KEY_DOWN || key == '+') {
|
||||
else if (KEY_IS_DOWN(key)) {
|
||||
if (choice == max_choice - 1) {
|
||||
if (scroll+choice < item_no-1) {
|
||||
if (scroll + choice < item_no - 1) {
|
||||
/* Scroll list up */
|
||||
getyx(dialog, cur_y, cur_x); /* Save cursor position */
|
||||
if (list_height > 1) {
|
||||
/* De-highlight current last item before scrolling up */
|
||||
print_item(list, items[(scroll+max_choice-1)*3], items[(scroll+max_choice-1)*3 + 1],
|
||||
status[scroll+max_choice-1], max_choice-1, FALSE, DREF(ditems, scroll + max_choice - 1));
|
||||
print_item(list, items[(scroll + max_choice - 1) * 3],
|
||||
items[(scroll + max_choice - 1) * 3 + 1],
|
||||
status[scroll + max_choice - 1], max_choice - 1,
|
||||
FALSE, DREF(ditems, scroll + max_choice - 1));
|
||||
scrollok(list, TRUE);
|
||||
scroll(list);
|
||||
scrollok(list, FALSE);
|
||||
}
|
||||
scroll++;
|
||||
print_item(list, items[(scroll+max_choice-1)*3], items[(scroll+max_choice-1)*3 + 1],
|
||||
status[scroll+max_choice-1], max_choice-1, TRUE, DREF(ditems, scroll + max_choice - 1));
|
||||
print_item(list, items[(scroll + max_choice - 1) * 3],
|
||||
items[(scroll + max_choice - 1) * 3 + 1],
|
||||
status[scroll + max_choice - 1], max_choice - 1, TRUE,
|
||||
DREF(ditems, scroll + max_choice - 1));
|
||||
wnoutrefresh(list);
|
||||
print_arrows(dialog, scroll, list_height, item_no, box_x, box_y, check_x + 4, cur_x, cur_y);
|
||||
wrefresh(dialog);
|
||||
@@ -317,13 +326,14 @@ draw:
|
||||
WINDOW *save;
|
||||
|
||||
save = dupwin(newscr);
|
||||
st = ditems[scroll + choice].fire(&ditems[scroll + choice]);
|
||||
st = ditems[scroll + choice].fire(&ditems[scroll + choice]); /* Call "fire" action */
|
||||
if (st & DITEM_RESTORE) {
|
||||
touchwin(save);
|
||||
wrefresh(save);
|
||||
}
|
||||
delwin(save);
|
||||
if (st & DITEM_REDRAW) {
|
||||
wmove(dialog, cur_y, cur_x); /* Restore cursor to previous position */
|
||||
wclear(list);
|
||||
for (i = 0; i < item_no; i++)
|
||||
status[i] = ditems[i].checked ? ditems[i].checked(&ditems[i]) : FALSE;
|
||||
for (i = 0; i < max_choice; i++) {
|
||||
@@ -335,10 +345,10 @@ draw:
|
||||
cur_x, cur_y);
|
||||
wrefresh(dialog);
|
||||
}
|
||||
delwin(save);
|
||||
if (st & DITEM_LEAVE_MENU) {
|
||||
/* Allow a fire action to take us out of the menu */
|
||||
key = ESC;
|
||||
rval = 0;
|
||||
break;
|
||||
}
|
||||
else if (st & DITEM_RECREATE) {
|
||||
@@ -365,7 +375,7 @@ draw:
|
||||
rbra = ']';
|
||||
if (!mark)
|
||||
mark = 'X';
|
||||
wprintw(list, "%c%c%c", lbra, status[scroll+choice] ? mark : ' ', rbra);
|
||||
wprintw(list, "%c%c%c", lbra, status[scroll + choice] ? mark : ' ', rbra);
|
||||
wnoutrefresh(list);
|
||||
wmove(dialog, cur_y, cur_x); /* Restore cursor to previous position */
|
||||
wrefresh(dialog);
|
||||
@@ -375,13 +385,13 @@ draw:
|
||||
if (i != choice) {
|
||||
/* De-highlight current item */
|
||||
getyx(dialog, cur_y, cur_x); /* Save cursor position */
|
||||
print_item(list, items[(scroll+choice)*3], items[(scroll+choice)*3 + 1], status[scroll+choice], choice, FALSE,
|
||||
DREF(ditems, scroll + choice));
|
||||
print_item(list, items[(scroll + choice) * 3], items[(scroll + choice) * 3 + 1],
|
||||
status[scroll + choice], choice, FALSE, DREF(ditems, scroll + choice));
|
||||
|
||||
/* Highlight new item */
|
||||
choice = i;
|
||||
print_item(list, items[(scroll+choice)*3], items[(scroll+choice)*3 + 1], status[scroll+choice], choice, TRUE,
|
||||
DREF(ditems, scroll + choice));
|
||||
print_item(list, items[(scroll + choice) * 3], items[(scroll + choice) * 3 + 1],
|
||||
status[scroll + choice], choice, TRUE, DREF(ditems, scroll + choice));
|
||||
wnoutrefresh(list);
|
||||
wmove(dialog, cur_y, cur_x); /* Restore cursor to previous position */
|
||||
wrefresh(dialog);
|
||||
@@ -469,26 +479,27 @@ draw:
|
||||
}
|
||||
}
|
||||
}
|
||||
delwin(list);
|
||||
delwin(dialog);
|
||||
return button;
|
||||
rval = button;
|
||||
key = ESC; /* Bail out! */
|
||||
break;
|
||||
|
||||
/* Let me outta here! */
|
||||
case ESC:
|
||||
rval = -1;
|
||||
break;
|
||||
|
||||
/* Help! */
|
||||
case KEY_F(1):
|
||||
case '?':
|
||||
display_helpfile();
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
if (redraw_menu) {
|
||||
wclear(list);
|
||||
for (i = 0; i < max_choice; i++)
|
||||
print_item(list, items[(scroll+i)*3], items[(scroll+i)*3 + 1], status[scroll+i], i, i == choice,
|
||||
DREF(ditems, scroll + i));
|
||||
print_item(list, items[(scroll + i) * 3], items[(scroll + i) * 3 + 1], status[scroll + i],
|
||||
i, i == choice, DREF(ditems, scroll + i));
|
||||
wnoutrefresh(list);
|
||||
print_arrows(dialog, scroll, list_height, item_no, box_x, box_y, check_x + 4, cur_x, cur_y);
|
||||
wrefresh(dialog);
|
||||
@@ -497,9 +508,8 @@ draw:
|
||||
}
|
||||
delwin(list);
|
||||
delwin(dialog);
|
||||
return -1; /* ESC pressed */
|
||||
return rval;
|
||||
}
|
||||
/* End of dialog_checklist() */
|
||||
|
||||
|
||||
/*
|
||||
|
||||
@@ -50,6 +50,9 @@
|
||||
#define DITEM_RESTORE (1 << 19)
|
||||
#define DITEM_CONTINUE (1 << 20)
|
||||
|
||||
/* Attributes as used by entry fields right now */
|
||||
#define DITEM_NO_ECHO 0x0001
|
||||
|
||||
|
||||
/* negative offsets for buttons in item lists, if specified */
|
||||
#define OK_BUTTON -2
|
||||
@@ -77,7 +80,7 @@ typedef struct _dmenu_item {
|
||||
#define FALSE (0)
|
||||
#endif
|
||||
|
||||
extern int DialogX, DialogY;
|
||||
extern int DialogX, DialogY, DialogInputAttrs;
|
||||
|
||||
/*
|
||||
* Attribute names
|
||||
@@ -122,7 +125,7 @@ extern bool use_shadow;
|
||||
void draw_shadow(WINDOW *win, int y, int x, int height, int width);
|
||||
#endif
|
||||
void draw_box(WINDOW *win, int y, int x, int height, int width, chtype box, chtype border);
|
||||
int line_edit(WINDOW *dialog, int box_y, int box_x, int flen, int box_width, chtype attrs, int first, unsigned char *result);
|
||||
int line_edit(WINDOW *dialog, int box_y, int box_x, int flen, int box_width, chtype attrs, int first, unsigned char *result, int attr_mask);
|
||||
int strheight(const char *p);
|
||||
int strwidth(const char *p);
|
||||
|
||||
|
||||
@@ -85,6 +85,10 @@
|
||||
#endif
|
||||
#endif /* HAVE_NCURSES */
|
||||
|
||||
/* Travel key conventions */
|
||||
#define KEY_IS_UP(key) ((key) == KEY_UP || (key) == '-' || key == '\020' /* ^P */)
|
||||
#define KEY_IS_DOWN(key) ((key) == KEY_DOWN || (key) == '+' || key == '\016' /* ^N */)
|
||||
|
||||
/*
|
||||
* Global variables
|
||||
*/
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* Program: dir.c
|
||||
@@ -22,20 +21,21 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#if !defined sgi
|
||||
#include <unistd.h> /* XXX for _POSIX_VERSION ifdefs */
|
||||
|
||||
#if !defined sgi && !defined _POSIX_VERSION
|
||||
#include <sys/dir.h>
|
||||
#endif
|
||||
#if defined __sun__
|
||||
#include <sys/dirent.h>
|
||||
#endif
|
||||
#if defined sgi
|
||||
#if defined sgi || defined _POSIX_VERSION
|
||||
#include <dirent.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fnmatch.h>
|
||||
#include <sys/param.h>
|
||||
#include "dir.h"
|
||||
|
||||
@@ -106,7 +106,7 @@ int dialog_inputbox(unsigned char *title, unsigned char *prompt, int height, int
|
||||
while (key != ESC) {
|
||||
|
||||
if (button == -1) { /* Input box selected */
|
||||
key = line_edit(dialog, box_y, box_x, -1, box_width, inputbox_attr, first, instr);
|
||||
key = line_edit(dialog, box_y, box_x, -1, box_width, inputbox_attr, first, instr, DialogInputAttrs);
|
||||
first = 0;
|
||||
}
|
||||
else
|
||||
|
||||
@@ -90,6 +90,9 @@
|
||||
*/
|
||||
int DialogX, DialogY;
|
||||
|
||||
/* This "secret" global allows you to change the behavior of an input field */
|
||||
int DialogInputAttrs;
|
||||
|
||||
/*
|
||||
* Do some initialization for dialog
|
||||
*/
|
||||
@@ -328,14 +331,12 @@ void print_button(WINDOW *win, unsigned char *label, int y, int x, int selected)
|
||||
waddstr(win, selected ? "[" : " ");
|
||||
temp = strspn(label, " ");
|
||||
label += temp;
|
||||
wattrset(win, selected ? button_label_active_attr : button_label_inactive_attr);
|
||||
for (i = 0; i < temp; i++)
|
||||
waddch(win, ' ');
|
||||
wattrset(win, selected ? button_key_active_attr : button_key_inactive_attr);
|
||||
waddch(win, label[0]);
|
||||
wattrset(win, selected ? button_label_active_attr : button_label_inactive_attr);
|
||||
waddstr(win, label+1);
|
||||
wattrset(win, selected ? button_active_attr : button_inactive_attr);
|
||||
waddstr(win, label+1);
|
||||
waddstr(win, selected ? "]" : " ");
|
||||
wmove(win, y, x+temp+1);
|
||||
}
|
||||
|
||||
@@ -24,12 +24,12 @@
|
||||
#include <dialog.h>
|
||||
#include "dialog.priv.h"
|
||||
|
||||
static void redraw_field(WINDOW *dialog, int box_y, int box_x, int flen, int box_width, unsigned char instr[], int input_x, int scroll, chtype attr, chtype old_attr, int fexit);
|
||||
static void redraw_field(WINDOW *dialog, int box_y, int box_x, int flen, int box_width, unsigned char instr[], int input_x, int scroll, chtype attr, chtype old_attr, int fexit, int attr_mask);
|
||||
|
||||
/*
|
||||
* Line editor
|
||||
*/
|
||||
int line_edit(WINDOW* dialog, int box_y, int box_x, int flen, int box_width, chtype attr, int first, unsigned char *result)
|
||||
int line_edit(WINDOW* dialog, int box_y, int box_x, int flen, int box_width, chtype attr, int first, unsigned char *result, int attr_mask)
|
||||
{
|
||||
int i, key;
|
||||
chtype old_attr;
|
||||
@@ -53,7 +53,7 @@ int line_edit(WINDOW* dialog, int box_y, int box_x, int flen, int box_width, cht
|
||||
/* scroll = i - input_x;*/
|
||||
scroll = (i > box_width) ? i - box_width + 1: 0;
|
||||
}
|
||||
redraw_field(dialog, box_y, box_x, flen, box_width, instr, input_x, scroll, attr, old_attr, FALSE);
|
||||
redraw_field(dialog, box_y, box_x, flen, box_width, instr, input_x, scroll, attr, old_attr, FALSE, attr_mask);
|
||||
|
||||
for (;;) {
|
||||
wattrset(dialog, attr);
|
||||
@@ -86,12 +86,12 @@ int line_edit(WINDOW* dialog, int box_y, int box_x, int flen, int box_width, cht
|
||||
case '\013':
|
||||
case KEY_EOL:
|
||||
memset(instr + scroll + input_x, '\0', sizeof(instr) - scroll - input_x);
|
||||
redraw_field(dialog, box_y, box_x, flen, box_width, instr, input_x, scroll, attr, old_attr, FALSE);
|
||||
redraw_field(dialog, box_y, box_x, flen, box_width, instr, input_x, scroll, attr, old_attr, FALSE, attr_mask);
|
||||
continue;
|
||||
case '\001':
|
||||
case KEY_HOME:
|
||||
input_x = scroll = 0;
|
||||
redraw_field(dialog, box_y, box_x, flen, box_width, instr, input_x, scroll, attr, old_attr, FALSE);
|
||||
redraw_field(dialog, box_y, box_x, flen, box_width, instr, input_x, scroll, attr, old_attr, FALSE, attr_mask);
|
||||
continue;
|
||||
case '\005':
|
||||
case KEY_END:
|
||||
@@ -100,7 +100,7 @@ int line_edit(WINDOW* dialog, int box_y, int box_x, int flen, int box_width, cht
|
||||
i++;
|
||||
input_x = i % box_width;
|
||||
scroll = i - input_x;
|
||||
redraw_field(dialog, box_y, box_x, flen, box_width, instr, input_x, scroll, attr, old_attr, FALSE);
|
||||
redraw_field(dialog, box_y, box_x, flen, box_width, instr, input_x, scroll, attr, old_attr, FALSE, attr_mask);
|
||||
continue;
|
||||
case '\002':
|
||||
case KEY_LEFT:
|
||||
@@ -109,7 +109,7 @@ int line_edit(WINDOW* dialog, int box_y, int box_x, int flen, int box_width, cht
|
||||
int oldscroll = scroll;
|
||||
scroll = scroll < box_width-1 ? 0 : scroll-(box_width-1);
|
||||
input_x = oldscroll - 1 - scroll;
|
||||
redraw_field(dialog, box_y, box_x, flen, box_width, instr, input_x, scroll, attr, old_attr, FALSE);
|
||||
redraw_field(dialog, box_y, box_x, flen, box_width, instr, input_x, scroll, attr, old_attr, FALSE, attr_mask);
|
||||
} else {
|
||||
input_x--;
|
||||
wmove(dialog, box_y, input_x + box_x);
|
||||
@@ -126,7 +126,7 @@ int line_edit(WINDOW* dialog, int box_y, int box_x, int flen, int box_width, cht
|
||||
instr[scroll+input_x] = ' ';
|
||||
if (input_x == box_width-1) {
|
||||
scroll++;
|
||||
redraw_field(dialog, box_y, box_x, flen, box_width, instr, input_x, scroll, attr, old_attr, FALSE);
|
||||
redraw_field(dialog, box_y, box_x, flen, box_width, instr, input_x, scroll, attr, old_attr, FALSE, attr_mask);
|
||||
}
|
||||
else {
|
||||
wmove(dialog, box_y, input_x + box_x);
|
||||
@@ -149,7 +149,7 @@ int line_edit(WINDOW* dialog, int box_y, int box_x, int flen, int box_width, cht
|
||||
input_x = oldscroll - 1 - scroll;
|
||||
} else
|
||||
input_x--;
|
||||
redraw_field(dialog, box_y, box_x, flen, box_width, instr, input_x, scroll, attr, old_attr, FALSE);
|
||||
redraw_field(dialog, box_y, box_x, flen, box_width, instr, input_x, scroll, attr, old_attr, FALSE, attr_mask);
|
||||
} else
|
||||
beep();
|
||||
continue;
|
||||
@@ -163,7 +163,7 @@ int line_edit(WINDOW* dialog, int box_y, int box_x, int flen, int box_width, cht
|
||||
continue;
|
||||
}
|
||||
memmove(instr+scroll+input_x, instr+scroll+input_x+1, i-(scroll+input_x));
|
||||
redraw_field(dialog, box_y, box_x, flen, box_width, instr, input_x, scroll, attr, old_attr, FALSE);
|
||||
redraw_field(dialog, box_y, box_x, flen, box_width, instr, input_x, scroll, attr, old_attr, FALSE, attr_mask);
|
||||
continue;
|
||||
default:
|
||||
if (CCEQ(key, erase_char))
|
||||
@@ -182,7 +182,7 @@ int line_edit(WINDOW* dialog, int box_y, int box_x, int flen, int box_width, cht
|
||||
scroll++;
|
||||
else
|
||||
input_x++;
|
||||
redraw_field(dialog, box_y, box_x, flen, box_width, instr, input_x, scroll, attr, old_attr, FALSE);
|
||||
redraw_field(dialog, box_y, box_x, flen, box_width, instr, input_x, scroll, attr, old_attr, FALSE, attr_mask);
|
||||
} else
|
||||
beep(); /* Alarm user about overflow */
|
||||
continue;
|
||||
@@ -190,14 +190,14 @@ int line_edit(WINDOW* dialog, int box_y, int box_x, int flen, int box_width, cht
|
||||
}
|
||||
}
|
||||
ret:
|
||||
redraw_field(dialog, box_y, box_x, flen, box_width, instr, input_x, scroll, attr, old_attr, TRUE);
|
||||
redraw_field(dialog, box_y, box_x, flen, box_width, instr, input_x, scroll, attr, old_attr, TRUE, attr_mask);
|
||||
wrefresh(dialog);
|
||||
strcpy(result, instr);
|
||||
return key;
|
||||
}
|
||||
|
||||
static void
|
||||
redraw_field(WINDOW *dialog, int box_y, int box_x, int flen, int box_width, unsigned char instr[], int input_x, int scroll, chtype attr, chtype old_attr, int fexit)
|
||||
redraw_field(WINDOW *dialog, int box_y, int box_x, int flen, int box_width, unsigned char instr[], int input_x, int scroll, chtype attr, chtype old_attr, int fexit, int attr_mask)
|
||||
{
|
||||
int i, fix_len;
|
||||
|
||||
@@ -205,9 +205,9 @@ redraw_field(WINDOW *dialog, int box_y, int box_x, int flen, int box_width, unsi
|
||||
wmove(dialog, box_y, box_x);
|
||||
fix_len = flen >= 0 ? MIN(flen-scroll,box_width) : box_width;
|
||||
for (i = 0; i < fix_len; i++)
|
||||
waddch(dialog, instr[scroll+i] ? instr[scroll+i] : ' ');
|
||||
waddch(dialog, instr[scroll+i] ? ((attr_mask & DITEM_NO_ECHO) ? '*' : instr[scroll+i]) : ' ');
|
||||
wattrset(dialog, old_attr);
|
||||
for ( ; i < box_width; i++)
|
||||
waddch(dialog, instr[scroll+i] ? instr[scroll+i] : ' ');
|
||||
waddch(dialog, instr[scroll+i] ? ((attr_mask & DITEM_NO_ECHO) ? '*' : instr[scroll+i]) : ' ');
|
||||
wmove(dialog, box_y, input_x + box_x);
|
||||
}
|
||||
+74
-65
@@ -39,18 +39,18 @@ int
|
||||
dialog_menu(unsigned char *title, unsigned char *prompt, int height, int width, int menu_height,
|
||||
int cnt, void *it, unsigned char *result, int *ch, int *sc)
|
||||
{
|
||||
int i, j, x, y, cur_x, cur_y, box_x, box_y, key = 0, button = 0, choice = 0,
|
||||
l, k, scroll = 0, max_choice, item_no, redraw_menu = FALSE;
|
||||
int i, j, x, y, cur_x, cur_y, box_x, box_y, key = 0, button, choice,
|
||||
l, k, scroll, max_choice, item_no, redraw_menu = FALSE;
|
||||
char okButton, cancelButton;
|
||||
int rval = 0;
|
||||
WINDOW *dialog, *menu;
|
||||
unsigned char **items = NULL;
|
||||
dialogMenuItem *ditems;
|
||||
|
||||
draw:
|
||||
if (ch) /* restore menu item info */
|
||||
choice = *ch;
|
||||
if (sc)
|
||||
scroll = *sc;
|
||||
choice = ch ? *ch : 0;
|
||||
scroll = sc ? *sc : 0;
|
||||
button = 0;
|
||||
|
||||
/* If item_no is a positive integer, use old item specification format */
|
||||
if (cnt >= 0) {
|
||||
@@ -77,30 +77,30 @@ draw:
|
||||
item_x = 0;
|
||||
/* Find length of longest item in order to center menu */
|
||||
for (i = 0; i < item_no; i++) {
|
||||
l = strlen(items[i*2]);
|
||||
l = strlen(items[i * 2]);
|
||||
for (j = 0; j < item_no; j++) {
|
||||
k = strlen(items[j*2 + 1]);
|
||||
k = strlen(items[j * 2 + 1]);
|
||||
tag_x = MAX(tag_x, l + k + 2);
|
||||
}
|
||||
item_x = MAX(item_x, l);
|
||||
}
|
||||
if (height < 0)
|
||||
height = strheight(prompt)+menu_height+4+2;
|
||||
height = strheight(prompt) + menu_height + 4 + 2;
|
||||
if (width < 0) {
|
||||
i = strwidth(prompt);
|
||||
j = ((title != NULL) ? strwidth(title) : 0);
|
||||
width = MAX(i,j);
|
||||
width = MAX(width,tag_x+4)+4;
|
||||
width = MAX(i, j);
|
||||
width = MAX(width, tag_x + 4) + 4;
|
||||
}
|
||||
width = MAX(width,24);
|
||||
width = MAX(width, 24);
|
||||
|
||||
if (width > COLS)
|
||||
width = COLS;
|
||||
if (height > LINES)
|
||||
height = LINES;
|
||||
/* center dialog box on screen */
|
||||
x = DialogX ? DialogX : (COLS - width)/2;
|
||||
y = DialogY ? DialogY : (LINES - height)/2;
|
||||
x = DialogX ? DialogX : (COLS - width) / 2;
|
||||
y = DialogY ? DialogY : (LINES - height) / 2;
|
||||
|
||||
#ifdef HAVE_NCURSES
|
||||
if (use_shadow)
|
||||
@@ -109,45 +109,46 @@ draw:
|
||||
dialog = newwin(height, width, y, x);
|
||||
if (dialog == NULL) {
|
||||
endwin();
|
||||
fprintf(stderr, "\nnewwin(%d,%d,%d,%d) failed, maybe wrong dims\n", height,width,y,x);
|
||||
fprintf(stderr, "\nnewwin(%d,%d,%d,%d) failed, maybe wrong dims\n", height, width, y, x);
|
||||
return -1;
|
||||
}
|
||||
keypad(dialog, TRUE);
|
||||
|
||||
draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr);
|
||||
wattrset(dialog, border_attr);
|
||||
wmove(dialog, height-3, 0);
|
||||
wmove(dialog, height - 3, 0);
|
||||
waddch(dialog, ACS_LTEE);
|
||||
for (i = 0; i < width-2; i++)
|
||||
for (i = 0; i < width - 2; i++)
|
||||
waddch(dialog, ACS_HLINE);
|
||||
wattrset(dialog, dialog_attr);
|
||||
waddch(dialog, ACS_RTEE);
|
||||
wmove(dialog, height-2, 1);
|
||||
for (i = 0; i < width-2; i++)
|
||||
wmove(dialog, height - 2, 1);
|
||||
for (i = 0; i < width - 2; i++)
|
||||
waddch(dialog, ' ');
|
||||
|
||||
if (title != NULL) {
|
||||
wattrset(dialog, title_attr);
|
||||
wmove(dialog, 0, (width - strlen(title))/2 - 1);
|
||||
wmove(dialog, 0, (width - strlen(title)) / 2 - 1);
|
||||
waddch(dialog, ' ');
|
||||
waddstr(dialog, title);
|
||||
waddch(dialog, ' ');
|
||||
}
|
||||
wattrset(dialog, dialog_attr);
|
||||
wmove(dialog, 1, 2);
|
||||
print_autowrap(dialog, prompt, height-1, width-2, width, 1, 2, TRUE, FALSE);
|
||||
print_autowrap(dialog, prompt, height - 1, width - 2, width, 1, 2, TRUE, FALSE);
|
||||
|
||||
menu_width = width-6;
|
||||
menu_width = width - 6;
|
||||
getyx(dialog, cur_y, cur_x);
|
||||
box_y = cur_y + 1;
|
||||
box_x = (width - menu_width)/2 - 1;
|
||||
box_x = (width - menu_width) / 2 - 1;
|
||||
|
||||
/* create new window for the menu */
|
||||
menu = subwin(dialog, menu_height, menu_width, y + box_y + 1, x + box_x + 1);
|
||||
if (menu == NULL) {
|
||||
delwin(dialog);
|
||||
endwin();
|
||||
fprintf(stderr, "\nsubwin(dialog,%d,%d,%d,%d) failed, maybe wrong dims\n", menu_height,menu_width,y+box_y+1,x+box_x+1);
|
||||
fprintf(stderr, "\nsubwin(dialog,%d,%d,%d,%d) failed, maybe wrong dims\n", menu_height, menu_width,
|
||||
y + box_y + 1, x + box_x + 1);
|
||||
return -1;
|
||||
}
|
||||
keypad(menu, TRUE);
|
||||
@@ -160,14 +161,15 @@ draw:
|
||||
|
||||
/* Print the menu */
|
||||
for (i = 0; i < max_choice; i++)
|
||||
print_item(menu, items[(scroll+i)*2], items[(scroll+i)*2 + 1], i, i == choice, DREF(ditems, scroll + i));
|
||||
print_item(menu, items[(scroll + i) * 2], items[(scroll + i) * 2 + 1], i,
|
||||
i == choice, DREF(ditems, scroll + i));
|
||||
wnoutrefresh(menu);
|
||||
print_arrows(dialog, scroll, menu_height, item_no, box_x, box_y, tag_x, cur_x, cur_y);
|
||||
|
||||
display_helpline(dialog, height-1, width);
|
||||
display_helpline(dialog, height - 1, width);
|
||||
|
||||
x = width/2-11;
|
||||
y = height-2;
|
||||
x = width / 2 - 11;
|
||||
y = height - 2;
|
||||
|
||||
if (ditems && result) {
|
||||
cancelButton = toupper(ditems[CANCEL_BUTTON].prompt[0]);
|
||||
@@ -185,7 +187,6 @@ draw:
|
||||
}
|
||||
|
||||
wrefresh(dialog);
|
||||
|
||||
while (key != ESC) {
|
||||
key = wgetch(dialog);
|
||||
|
||||
@@ -207,12 +208,13 @@ draw:
|
||||
}
|
||||
else if (result)
|
||||
strcpy(result, items[(scroll + choice) * 2]);
|
||||
delwin(menu);
|
||||
delwin(dialog);
|
||||
return 0;
|
||||
rval = 0;
|
||||
key = ESC; /* Punt! */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Shortcut to cancel? */
|
||||
else if (toupper(key) == cancelButton) {
|
||||
if (toupper(key) == cancelButton) {
|
||||
if (ditems && result && ditems[CANCEL_BUTTON].fire) {
|
||||
int status;
|
||||
WINDOW *save;
|
||||
@@ -225,34 +227,33 @@ draw:
|
||||
}
|
||||
delwin(save);
|
||||
}
|
||||
delwin(menu);
|
||||
delwin(dialog);
|
||||
return 1;
|
||||
rval = 1;
|
||||
key = ESC; /* Run away! */
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
/* Check if key pressed matches first character of any item tag in menu */
|
||||
for (i = 0; i < max_choice; i++)
|
||||
if (key < 0x100 && toupper(key) == toupper(items[(scroll+i)*2][0]))
|
||||
if (key < 0x100 && toupper(key) == toupper(items[(scroll + i) * 2][0]))
|
||||
break;
|
||||
|
||||
if (i < max_choice || (key >= '1' && key <= MIN('9', '0'+max_choice)) ||
|
||||
key == KEY_UP || key == KEY_DOWN || key == '-' || key == '+') {
|
||||
if (i < max_choice || (key >= '1' && key <= MIN('9', '0'+max_choice)) || KEY_IS_UP(key) || KEY_IS_DOWN(key)) {
|
||||
if (key >= '1' && key <= MIN('9', '0'+max_choice))
|
||||
i = key - '1';
|
||||
else if (key == KEY_UP || key == '-') {
|
||||
else if (KEY_IS_UP(key)) {
|
||||
if (!choice) {
|
||||
if (scroll) {
|
||||
/* Scroll menu down */
|
||||
getyx(dialog, cur_y, cur_x); /* Save cursor position */
|
||||
if (menu_height > 1) {
|
||||
/* De-highlight current first item before scrolling down */
|
||||
print_item(menu, items[scroll*2], items[scroll*2 + 1], 0, FALSE, DREF(ditems, scroll));
|
||||
print_item(menu, items[scroll * 2], items[scroll * 2 + 1], 0, FALSE, DREF(ditems, scroll));
|
||||
scrollok(menu, TRUE);
|
||||
wscrl(menu, -1);
|
||||
scrollok(menu, FALSE);
|
||||
}
|
||||
scroll--;
|
||||
print_item(menu, items[scroll*2], items[scroll*2 + 1], 0, TRUE, DREF(ditems, scroll));
|
||||
print_item(menu, items[scroll * 2], items[scroll * 2 + 1], 0, TRUE, DREF(ditems, scroll));
|
||||
wnoutrefresh(menu);
|
||||
print_arrows(dialog, scroll, menu_height, item_no, box_x, box_y, tag_x, cur_x, cur_y);
|
||||
wrefresh(dialog);
|
||||
@@ -262,21 +263,23 @@ draw:
|
||||
else
|
||||
i = choice - 1;
|
||||
}
|
||||
else if (key == KEY_DOWN || key == '+')
|
||||
else if (KEY_IS_DOWN(key))
|
||||
if (choice == max_choice - 1) {
|
||||
if (scroll+choice < item_no-1) {
|
||||
if (scroll + choice < item_no - 1) {
|
||||
/* Scroll menu up */
|
||||
getyx(dialog, cur_y, cur_x); /* Save cursor position */
|
||||
if (menu_height > 1) {
|
||||
/* De-highlight current last item before scrolling up */
|
||||
print_item(menu, items[(scroll + max_choice - 1) * 2], items[(scroll + max_choice - 1) * 2 + 1],
|
||||
print_item(menu, items[(scroll + max_choice - 1) * 2],
|
||||
items[(scroll + max_choice - 1) * 2 + 1],
|
||||
max_choice-1, FALSE, DREF(ditems, scroll + max_choice - 1));
|
||||
scrollok(menu, TRUE);
|
||||
scroll(menu);
|
||||
scrollok(menu, FALSE);
|
||||
}
|
||||
scroll++;
|
||||
print_item(menu, items[(scroll + max_choice - 1) * 2], items[(scroll + max_choice - 1) * 2 + 1],
|
||||
print_item(menu, items[(scroll + max_choice - 1) * 2],
|
||||
items[(scroll + max_choice - 1) * 2 + 1],
|
||||
max_choice - 1, TRUE, DREF(ditems, scroll + max_choice - 1));
|
||||
wnoutrefresh(menu);
|
||||
print_arrows(dialog, scroll, menu_height, item_no, box_x, box_y, tag_x, cur_x, cur_y);
|
||||
@@ -304,16 +307,10 @@ draw:
|
||||
continue; /* wait for another key press */
|
||||
}
|
||||
|
||||
/* save info about menu item position */
|
||||
if (ch)
|
||||
*ch = choice;
|
||||
if (sc)
|
||||
*sc = scroll;
|
||||
|
||||
switch (key) {
|
||||
case KEY_PPAGE:
|
||||
if (scroll > height-4) { /* can we go up? */
|
||||
scroll -= (height-4);
|
||||
if (scroll > height - 4) { /* can we go up? */
|
||||
scroll -= (height - 4);
|
||||
} else {
|
||||
scroll = 0;
|
||||
}
|
||||
@@ -323,7 +320,8 @@ draw:
|
||||
case KEY_NPAGE:
|
||||
if (scroll + menu_height >= item_no-1 - menu_height) { /* can we go down a full page? */
|
||||
scroll = item_no - menu_height;
|
||||
if (scroll < 0) scroll = 0;
|
||||
if (scroll < 0)
|
||||
scroll = 0;
|
||||
} else {
|
||||
scroll += menu_height;
|
||||
}
|
||||
@@ -338,7 +336,8 @@ draw:
|
||||
|
||||
case KEY_END:
|
||||
scroll = item_no - menu_height;
|
||||
if (scroll < 0) scroll = 0;
|
||||
if (scroll < 0)
|
||||
scroll = 0;
|
||||
choice = max_choice - 1;
|
||||
redraw_menu = TRUE;
|
||||
break;
|
||||
@@ -381,7 +380,12 @@ draw:
|
||||
delwin(save);
|
||||
if (status & DITEM_CONTINUE)
|
||||
continue;
|
||||
else if (status & DITEM_RECREATE && !(status & DITEM_LEAVE_MENU)) {
|
||||
else if (status & DITEM_LEAVE_MENU) {
|
||||
/* Allow a fire action to take us out of the menu */
|
||||
key = ESC;
|
||||
break;
|
||||
}
|
||||
else if (status & DITEM_RECREATE) {
|
||||
delwin(menu);
|
||||
delwin(dialog);
|
||||
dialog_clear();
|
||||
@@ -392,19 +396,26 @@ draw:
|
||||
else if (result)
|
||||
strcpy(result, items[(scroll+choice)*2]);
|
||||
}
|
||||
delwin(menu);
|
||||
delwin(dialog);
|
||||
return button;
|
||||
rval = button;
|
||||
key = ESC;
|
||||
break;
|
||||
|
||||
case ESC:
|
||||
rval = -1;
|
||||
break;
|
||||
|
||||
case KEY_F(1):
|
||||
case '?':
|
||||
display_helpfile();
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
/* save info about menu item position */
|
||||
if (ch)
|
||||
*ch = choice;
|
||||
if (sc)
|
||||
*sc = scroll;
|
||||
|
||||
if (redraw_menu) {
|
||||
for (i = 0; i < max_choice; i++) {
|
||||
print_item(menu, items[(scroll + i) * 2], items[(scroll + i) * 2 + 1], i, i == choice,
|
||||
@@ -416,12 +427,10 @@ draw:
|
||||
redraw_menu = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
delwin(menu);
|
||||
delwin(dialog);
|
||||
return -1; /* ESC pressed */
|
||||
return rval;
|
||||
}
|
||||
/* End of dialog_menu() */
|
||||
|
||||
|
||||
/*
|
||||
|
||||
@@ -93,7 +93,7 @@ int dialog_msgbox(unsigned char *title, unsigned char *prompt, int height, int w
|
||||
for (i = 0; i < width-2; i++)
|
||||
waddch(dialog, ' ');
|
||||
display_helpline(dialog, height-1, width);
|
||||
print_button(dialog, " OK ", height-2, width/2-4, TRUE);
|
||||
print_button(dialog, " OK ", height-2, width/2-6, TRUE);
|
||||
wrefresh(dialog);
|
||||
while (key != ESC && key != '\n' && key != ' ' && key != '\r')
|
||||
key = wgetch(dialog);
|
||||
@@ -171,7 +171,7 @@ dialog_mesgbox(unsigned char *title, unsigned char *prompt, int height, int widt
|
||||
for (i = 0; i < width-2; i++)
|
||||
waddch(dialog, ' ');
|
||||
display_helpline(dialog, height-1, width);
|
||||
print_button(dialog, " CONTINUE ", height-2, width/2-8, TRUE);
|
||||
print_button(dialog, " OK ", height-2, width/2-6, TRUE);
|
||||
wattrset(dialog, dialog_attr);
|
||||
|
||||
theight = height - 4;
|
||||
@@ -193,9 +193,11 @@ dialog_mesgbox(unsigned char *title, unsigned char *prompt, int height, int widt
|
||||
startline = max_lines - theight;
|
||||
if (startline < 0) startline = 0;
|
||||
break;
|
||||
case '\020': /* ^P */
|
||||
case KEY_UP:
|
||||
if (startline > 0) startline--;
|
||||
break;
|
||||
case '\016': /* ^N */
|
||||
case KEY_DOWN:
|
||||
if (startline < max_lines - theight) startline++;
|
||||
break;
|
||||
|
||||
@@ -130,7 +130,7 @@ int dialog_prgbox(unsigned char *title, const unsigned char *line, int height, i
|
||||
for (i = 0; i < width-2; i++)
|
||||
waddch(dialog, ' ');
|
||||
display_helpline(dialog, height-1, width);
|
||||
print_button(dialog, " OK ", height-2, width/2-4, TRUE);
|
||||
print_button(dialog, " OK ", height-2, width/2-6, TRUE);
|
||||
wrefresh(dialog);
|
||||
while (key != ESC && key != '\n' && key != ' ' && key != '\r')
|
||||
key = wgetch(dialog);
|
||||
|
||||
@@ -40,9 +40,10 @@ int
|
||||
dialog_radiolist(unsigned char *title, unsigned char *prompt, int height, int width, int list_height,
|
||||
int cnt, void *it, unsigned char *result)
|
||||
{
|
||||
int i, j, x, y, cur_x, cur_y, box_x, box_y, key = 0, button = 0, choice = 0,
|
||||
l, k, scroll = 0, max_choice, *status, item_no = 0, was_on = 0;
|
||||
int i, j, x, y, cur_x, cur_y, box_x, box_y, key = 0, button, choice,
|
||||
l, k, scroll, max_choice, *status, item_no = 0, was_on = 0;
|
||||
int redraw_menu = FALSE;
|
||||
int rval = 0;
|
||||
char okButton, cancelButton;
|
||||
WINDOW *dialog, *list;
|
||||
unsigned char **items = NULL;
|
||||
@@ -56,6 +57,7 @@ dialog_radiolist(unsigned char *title, unsigned char *prompt, int height, int wi
|
||||
}
|
||||
|
||||
draw:
|
||||
button = choice = scroll = 0;
|
||||
/* Previous calling syntax, e.g. just a list of strings? */
|
||||
if (cnt >= 0) {
|
||||
items = it;
|
||||
@@ -98,30 +100,30 @@ draw:
|
||||
item_x = 0;
|
||||
/* Find length of longest item in order to center radiolist */
|
||||
for (i = 0; i < item_no; i++) {
|
||||
l = strlen(items[i*3]);
|
||||
l = strlen(items[i * 3]);
|
||||
for (j = 0; j < item_no; j++) {
|
||||
k = strlen(items[j*3 + 1]);
|
||||
k = strlen(items[j * 3 + 1]);
|
||||
check_x = MAX(check_x, l + k + 6);
|
||||
}
|
||||
item_x = MAX(item_x, l);
|
||||
}
|
||||
if (height < 0)
|
||||
height = strheight(prompt)+list_height+4+2;
|
||||
height = strheight(prompt) + list_height + 4 + 2;
|
||||
if (width < 0) {
|
||||
i = strwidth(prompt);
|
||||
j = ((title != NULL) ? strwidth(title) : 0);
|
||||
width = MAX(i,j);
|
||||
width = MAX(width,check_x+4)+4;
|
||||
width = MAX(i, j);
|
||||
width = MAX(width, check_x + 4) + 4;
|
||||
}
|
||||
width = MAX(width,24);
|
||||
width = MAX(width, 24);
|
||||
|
||||
if (width > COLS)
|
||||
width = COLS;
|
||||
if (height > LINES)
|
||||
height = LINES;
|
||||
/* center dialog box on screen */
|
||||
x = DialogX ? DialogX : (COLS - width)/2;
|
||||
y = DialogY ? DialogY : (LINES - height)/2;
|
||||
x = DialogX ? DialogX : (COLS - width) / 2;
|
||||
y = DialogY ? DialogY : (LINES - height) / 2;
|
||||
|
||||
#ifdef HAVE_NCURSES
|
||||
if (use_shadow)
|
||||
@@ -130,45 +132,46 @@ draw:
|
||||
dialog = newwin(height, width, y, x);
|
||||
if (dialog == NULL) {
|
||||
endwin();
|
||||
fprintf(stderr, "\nnewwin(%d,%d,%d,%d) failed, maybe wrong dims\n", height,width,y,x);
|
||||
fprintf(stderr, "\nnewwin(%d,%d,%d,%d) failed, maybe wrong dims\n", height, width, y, x);
|
||||
return -1;
|
||||
}
|
||||
keypad(dialog, TRUE);
|
||||
|
||||
draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr);
|
||||
wattrset(dialog, border_attr);
|
||||
wmove(dialog, height-3, 0);
|
||||
wmove(dialog, height - 3, 0);
|
||||
waddch(dialog, ACS_LTEE);
|
||||
for (i = 0; i < width-2; i++)
|
||||
for (i = 0; i < width - 2; i++)
|
||||
waddch(dialog, ACS_HLINE);
|
||||
wattrset(dialog, dialog_attr);
|
||||
waddch(dialog, ACS_RTEE);
|
||||
wmove(dialog, height-2, 1);
|
||||
for (i = 0; i < width-2; i++)
|
||||
wmove(dialog, height - 2, 1);
|
||||
for (i = 0; i < width - 2; i++)
|
||||
waddch(dialog, ' ');
|
||||
|
||||
if (title != NULL) {
|
||||
wattrset(dialog, title_attr);
|
||||
wmove(dialog, 0, (width - strlen(title))/2 - 1);
|
||||
wmove(dialog, 0, (width - strlen(title)) / 2 - 1);
|
||||
waddch(dialog, ' ');
|
||||
waddstr(dialog, title);
|
||||
waddch(dialog, ' ');
|
||||
}
|
||||
wattrset(dialog, dialog_attr);
|
||||
wmove(dialog, 1, 2);
|
||||
print_autowrap(dialog, prompt, height-1, width-2, width, 1, 2, TRUE, FALSE);
|
||||
print_autowrap(dialog, prompt, height - 1, width - 2, width, 1, 2, TRUE, FALSE);
|
||||
|
||||
list_width = width-6;
|
||||
list_width = width - 6;
|
||||
getyx(dialog, cur_y, cur_x);
|
||||
box_y = cur_y + 1;
|
||||
box_x = (width - list_width)/2 - 1;
|
||||
box_x = (width - list_width) / 2 - 1;
|
||||
|
||||
/* create new window for the list */
|
||||
list = subwin(dialog, list_height, list_width, y + box_y + 1, x + box_x + 1);
|
||||
if (list == NULL) {
|
||||
delwin(dialog);
|
||||
endwin();
|
||||
fprintf(stderr, "\nsubwin(dialog,%d,%d,%d,%d) failed, maybe wrong dims\n", list_height,list_width,y+box_y+1,x+box_x+1);
|
||||
fprintf(stderr, "\nsubwin(dialog,%d,%d,%d,%d) failed, maybe wrong dims\n", list_height, list_width,
|
||||
y + box_y + 1,x + box_x + 1);
|
||||
return -1;
|
||||
}
|
||||
keypad(list, TRUE);
|
||||
@@ -181,14 +184,14 @@ draw:
|
||||
|
||||
/* Print the list */
|
||||
for (i = 0; i < max_choice; i++)
|
||||
print_item(list, items[i*3], items[i*3 + 1], status[i], i, i == choice, DREF(ditems, i));
|
||||
print_item(list, items[i * 3], items[i * 3 + 1], status[i], i, i == choice, DREF(ditems, i));
|
||||
wnoutrefresh(list);
|
||||
print_arrows(dialog, scroll, list_height, item_no, box_x, box_y, check_x + 4, cur_x, cur_y);
|
||||
|
||||
display_helpline(dialog, height-1, width);
|
||||
|
||||
x = width/2-11;
|
||||
y = height-2;
|
||||
x = width/ 2 - 11;
|
||||
y = height - 2;
|
||||
if (ditems && result) {
|
||||
cancelButton = toupper(ditems[CANCEL_BUTTON].prompt[0]);
|
||||
print_button(dialog, ditems[CANCEL_BUTTON].prompt, y, x + strlen(ditems[OK_BUTTON].prompt) + 5,
|
||||
@@ -203,8 +206,8 @@ draw:
|
||||
okButton = 'O';
|
||||
print_button(dialog, " OK ", y, x, TRUE);
|
||||
}
|
||||
|
||||
wrefresh(dialog);
|
||||
|
||||
while (key != ESC) {
|
||||
key = wgetch(dialog);
|
||||
|
||||
@@ -233,12 +236,13 @@ draw:
|
||||
}
|
||||
}
|
||||
}
|
||||
delwin(list);
|
||||
delwin(dialog);
|
||||
return 0;
|
||||
rval = 0;
|
||||
key = ESC;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Shortcut to cancel */
|
||||
else if (toupper(key) == cancelButton) {
|
||||
if (toupper(key) == cancelButton) {
|
||||
if (ditems && result && ditems[CANCEL_BUTTON].fire) {
|
||||
int st;
|
||||
WINDOW *save;
|
||||
@@ -251,9 +255,9 @@ draw:
|
||||
}
|
||||
delwin(save);
|
||||
}
|
||||
delwin(list);
|
||||
delwin(dialog);
|
||||
return 1;
|
||||
rval = 1;
|
||||
key = ESC;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check if key pressed matches first character of any item tag in list */
|
||||
@@ -262,23 +266,25 @@ draw:
|
||||
break;
|
||||
|
||||
if (i < max_choice || (key >= '1' && key <= MIN('9', '0' + max_choice)) ||
|
||||
key == KEY_UP || key == KEY_DOWN || key == ' ' || key == '+' || key == '-' ) {
|
||||
KEY_IS_UP(key) || KEY_IS_DOWN(key) || key == ' ') {
|
||||
if (key >= '1' && key <= MIN('9', '0' + max_choice))
|
||||
i = key - '1';
|
||||
else if (key == KEY_UP || key == '-') {
|
||||
else if (KEY_IS_UP(key)) {
|
||||
if (!choice) {
|
||||
if (scroll) {
|
||||
/* Scroll list down */
|
||||
getyx(dialog, cur_y, cur_x); /* Save cursor position */
|
||||
if (list_height > 1) {
|
||||
/* De-highlight current first item before scrolling down */
|
||||
print_item(list, items[scroll*3], items[scroll*3 + 1], status[scroll], 0, FALSE, DREF(ditems, scroll));
|
||||
print_item(list, items[scroll*3], items[scroll*3 + 1], status[scroll], 0,
|
||||
FALSE, DREF(ditems, scroll));
|
||||
scrollok(list, TRUE);
|
||||
wscrl(list, -1);
|
||||
scrollok(list, FALSE);
|
||||
}
|
||||
scroll--;
|
||||
print_item(list, items[scroll*3], items[scroll*3 + 1], status[scroll], 0, TRUE, DREF(ditems, scroll));
|
||||
print_item(list, items[scroll*3], items[scroll*3 + 1], status[scroll], 0,
|
||||
TRUE, DREF(ditems, scroll));
|
||||
wnoutrefresh(list);
|
||||
print_arrows(dialog, scroll, list_height, item_no, box_x, box_y, check_x + 4, cur_x, cur_y);
|
||||
wrefresh(dialog);
|
||||
@@ -288,22 +294,26 @@ draw:
|
||||
else
|
||||
i = choice - 1;
|
||||
}
|
||||
else if (key == KEY_DOWN || key == '+') {
|
||||
else if (KEY_IS_DOWN(key)) {
|
||||
if (choice == max_choice - 1) {
|
||||
if (scroll + choice < item_no - 1) {
|
||||
/* Scroll list up */
|
||||
getyx(dialog, cur_y, cur_x); /* Save cursor position */
|
||||
if (list_height > 1) {
|
||||
/* De-highlight current last item before scrolling up */
|
||||
print_item(list, items[(scroll + max_choice - 1) * 3], items[(scroll + max_choice - 1) * 3 + 1],
|
||||
status[scroll + max_choice - 1], max_choice - 1, FALSE, DREF(ditems, scroll + max_choice - 1));
|
||||
print_item(list, items[(scroll + max_choice - 1) * 3],
|
||||
items[(scroll + max_choice - 1) * 3 + 1],
|
||||
status[scroll + max_choice - 1], max_choice - 1,
|
||||
FALSE, DREF(ditems, scroll + max_choice - 1));
|
||||
scrollok(list, TRUE);
|
||||
scroll(list);
|
||||
scrollok(list, FALSE);
|
||||
}
|
||||
scroll++;
|
||||
print_item(list, items[(scroll + max_choice - 1) * 3], items[(scroll + max_choice - 1) * 3 + 1],
|
||||
status[scroll + max_choice - 1], max_choice - 1, TRUE, DREF(ditems, scroll + max_choice - 1));
|
||||
print_item(list, items[(scroll + max_choice - 1) * 3],
|
||||
items[(scroll + max_choice - 1) * 3 + 1],
|
||||
status[scroll + max_choice - 1], max_choice - 1,
|
||||
TRUE, DREF(ditems, scroll + max_choice - 1));
|
||||
wnoutrefresh(list);
|
||||
print_arrows(dialog, scroll, list_height, item_no, box_x, box_y, check_x + 4, cur_x, cur_y);
|
||||
wrefresh(dialog);
|
||||
@@ -327,7 +337,9 @@ draw:
|
||||
touchwin(save);
|
||||
wrefresh(save);
|
||||
}
|
||||
delwin(save);
|
||||
if (st & DITEM_REDRAW) {
|
||||
wclear(list);
|
||||
for (i = 0; i < item_no; i++)
|
||||
status[i] = ditems[i].checked ? ditems[i].checked(&ditems[i]) : FALSE;
|
||||
|
||||
@@ -340,7 +352,6 @@ draw:
|
||||
wmove(dialog, cur_y, cur_x); /* Restore cursor to previous position */
|
||||
wrefresh(dialog);
|
||||
}
|
||||
delwin(save);
|
||||
if (st & DITEM_LEAVE_MENU) {
|
||||
/* Allow a fire action to take us out of the menu */
|
||||
key = ESC;
|
||||
@@ -363,8 +374,8 @@ draw:
|
||||
}
|
||||
getyx(dialog, cur_y, cur_x); /* Save cursor position */
|
||||
for (i = 0; i < max_choice; i++)
|
||||
print_item(list, items[(scroll + i) * 3], items[(scroll + i) * 3 + 1], status[scroll + i], i, i == choice,
|
||||
DREF(ditems, scroll + i));
|
||||
print_item(list, items[(scroll + i) * 3], items[(scroll + i) * 3 + 1],
|
||||
status[scroll + i], i, i == choice, DREF(ditems, scroll + i));
|
||||
wnoutrefresh(list);
|
||||
wmove(dialog, cur_y, cur_x); /* Restore cursor to previous position */
|
||||
wrefresh(dialog);
|
||||
@@ -464,24 +475,24 @@ draw:
|
||||
}
|
||||
}
|
||||
}
|
||||
delwin(list);
|
||||
delwin(dialog);
|
||||
return button;
|
||||
rval = button;
|
||||
key = ESC;
|
||||
break;
|
||||
|
||||
case ESC:
|
||||
rval = -1;
|
||||
break;
|
||||
|
||||
case KEY_F(1):
|
||||
case '?':
|
||||
display_helpfile();
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
if (redraw_menu) {
|
||||
for (i = 0; i < max_choice; i++)
|
||||
print_item(list, items[(scroll + i) * 3], items[(scroll + i) * 3 + 1], status[scroll + i], i, i == choice,
|
||||
DREF(ditems, scroll + i));
|
||||
print_item(list, items[(scroll + i) * 3], items[(scroll + i) * 3 + 1], status[scroll + i],
|
||||
i, i == choice, DREF(ditems, scroll + i));
|
||||
wnoutrefresh(list);
|
||||
print_arrows(dialog, scroll, list_height, item_no, box_x, box_y, check_x + 4, cur_x, cur_y);
|
||||
wrefresh(dialog);
|
||||
@@ -491,11 +502,8 @@ draw:
|
||||
|
||||
delwin(list);
|
||||
delwin(dialog);
|
||||
free(status);
|
||||
return -1; /* ESC pressed */
|
||||
return rval; /* ESC pressed */
|
||||
}
|
||||
/* End of dialog_radiolist() */
|
||||
|
||||
|
||||
/*
|
||||
* Print list item
|
||||
|
||||
@@ -136,7 +136,7 @@ int dialog_textbox(unsigned char *title, unsigned char *file, int height, int wi
|
||||
}
|
||||
display_helpline(dialog, height-1, width);
|
||||
|
||||
print_button(dialog, " CONTINUE ", height-2, width/2-8, TRUE);
|
||||
print_button(dialog, " OK ", height-2, width/2-6, TRUE);
|
||||
wnoutrefresh(dialog);
|
||||
getyx(dialog, cur_y, cur_x); /* Save cursor position */
|
||||
|
||||
@@ -219,6 +219,7 @@ int dialog_textbox(unsigned char *title, unsigned char *file, int height, int wi
|
||||
break;
|
||||
case 'K': /* Previous line */
|
||||
case 'k':
|
||||
case '\020': /* ^P */
|
||||
case KEY_UP:
|
||||
if (!begin_reached) {
|
||||
back_lines(page_length+1);
|
||||
@@ -266,6 +267,7 @@ int dialog_textbox(unsigned char *title, unsigned char *file, int height, int wi
|
||||
break;
|
||||
case 'J': /* Next line */
|
||||
case 'j':
|
||||
case '\016': /* ^N */
|
||||
case KEY_DOWN:
|
||||
if (!end_reached) {
|
||||
begin_reached = 0;
|
||||
@@ -657,7 +659,7 @@ static int get_search_term(WINDOW *win, unsigned char *search_term, int height,
|
||||
|
||||
first = 1;
|
||||
while (key != ESC) {
|
||||
key = line_edit(win, y+1, x+1, -1, box_width-2, searchbox_attr, first, search_term);
|
||||
key = line_edit(win, y+1, x+1, -1, box_width-2, searchbox_attr, first, search_term, 0);
|
||||
first = 0;
|
||||
switch (key) {
|
||||
case '\n':
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
|
||||
#define ESC 27
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* Obj routines
|
||||
@@ -122,6 +121,7 @@ ReadObj(ComposeObj *Obj)
|
||||
break;
|
||||
}
|
||||
switch(ret) {
|
||||
case KEY_DOWN:
|
||||
case SEL_CR:
|
||||
case SEL_TAB: /* move to the next object in the list */
|
||||
if (o->next != NULL) {
|
||||
@@ -130,6 +130,8 @@ ReadObj(ComposeObj *Obj)
|
||||
o = Obj; /* beginning of the list */
|
||||
}
|
||||
break;
|
||||
|
||||
case KEY_UP:
|
||||
case SEL_BACKTAB: /* move to the previous object in the list */
|
||||
if (o->prev != NULL) {
|
||||
o = o->prev; /* previous object */
|
||||
@@ -137,6 +139,7 @@ ReadObj(ComposeObj *Obj)
|
||||
o = last; /* end of the list */
|
||||
}
|
||||
break;
|
||||
|
||||
case KEY_F(1): /* display help_file */
|
||||
case '?':
|
||||
display_helpfile();
|
||||
@@ -177,6 +180,7 @@ PollObj(ComposeObj **Obj)
|
||||
break;
|
||||
}
|
||||
switch(ret) {
|
||||
case KEY_DOWN:
|
||||
case SEL_CR:
|
||||
case SEL_TAB: /* move to the next object in the list */
|
||||
if ((*Obj)->next != NULL) {
|
||||
@@ -185,6 +189,8 @@ PollObj(ComposeObj **Obj)
|
||||
*Obj = first; /* beginning of the list */
|
||||
}
|
||||
break;
|
||||
|
||||
case KEY_UP:
|
||||
case SEL_BACKTAB: /* move to the previous object in the list */
|
||||
if ((*Obj)->prev != NULL) {
|
||||
*Obj = (*Obj)->prev; /* previous object */
|
||||
@@ -232,6 +238,22 @@ DelObj(ComposeObj *Obj)
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
static void
|
||||
outstr(WINDOW *win, char *str, int attrs)
|
||||
{
|
||||
if (attrs & DITEM_NO_ECHO) {
|
||||
char *cpy;
|
||||
int n = strlen(str);
|
||||
|
||||
cpy = alloca(n + 1);
|
||||
memset(cpy, '*', n);
|
||||
cpy[n] = '\0';
|
||||
waddstr(win, cpy);
|
||||
}
|
||||
else
|
||||
waddstr(win, str);
|
||||
}
|
||||
|
||||
void
|
||||
RefreshStringObj(StringObj *so)
|
||||
/*
|
||||
@@ -249,9 +271,9 @@ RefreshStringObj(StringObj *so)
|
||||
wmove(so->win, so->y+2, so->x+1);
|
||||
if (strlen(so->s) > so->w-2) {
|
||||
strncpy(tmp, (char *) so->s + strlen(so->s) - so->w + 2, so->w - 1);
|
||||
waddstr(so->win, tmp);
|
||||
outstr(so->win, tmp, so->attr_mask);
|
||||
} else {
|
||||
waddstr(so->win, so->s);
|
||||
outstr(so->win, so->s, so->attr_mask);
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -285,6 +307,7 @@ NewStringObj(WINDOW *win, char *title, char *s, int y, int x, int w, int len)
|
||||
so->w = w;
|
||||
so->len = len;
|
||||
so->win = win;
|
||||
so->attr_mask = DialogInputAttrs; /* Grossly use a global to avoid changing API */
|
||||
|
||||
/* Draw it on the screen */
|
||||
RefreshStringObj(so);
|
||||
@@ -303,7 +326,7 @@ SelectStringObj(StringObj *so)
|
||||
|
||||
strcpy(tmp, so->s);
|
||||
key = line_edit(so->win, so->y+2, so->x+1,
|
||||
so->len, so->w-2, inputbox_attr, TRUE, tmp);
|
||||
so->len, so->w-2, inputbox_attr, TRUE, tmp, so->attr_mask);
|
||||
if ((key == '\n') || (key == '\r') || (key == '\t') || key == (KEY_BTAB) ) {
|
||||
strcpy(so->s, tmp);
|
||||
}
|
||||
|
||||
@@ -53,6 +53,7 @@ typedef struct {
|
||||
int x, y, w, len; /* the (y, x) position of the upperleft */
|
||||
/* corner and the width <w> of the display */
|
||||
/* and length <len> of the field */
|
||||
int attr_mask; /* special attributes */
|
||||
} StringObj;
|
||||
|
||||
typedef struct {
|
||||
|
||||
@@ -1,139 +0,0 @@
|
||||
/* Like vsprintf but provides a pointer to malloc'd storage, which must
|
||||
be freed by the caller.
|
||||
Copyright (C) 1994 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the libiberty library.
|
||||
Libiberty is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
Libiberty is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with libiberty; see the file COPYING.LIB. If
|
||||
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
|
||||
Cambridge, MA 02139, USA. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <varargs.h>
|
||||
|
||||
#ifdef TEST
|
||||
int global_total_width;
|
||||
#endif
|
||||
|
||||
unsigned long strtoul ();
|
||||
char *malloc ();
|
||||
|
||||
int
|
||||
vasprintf (result, format, args)
|
||||
char **result;
|
||||
char *format;
|
||||
va_list args;
|
||||
{
|
||||
char *p = format;
|
||||
/* Add one to make sure that it is never zero, which might cause malloc
|
||||
to return NULL. */
|
||||
int total_width = strlen (format) + 1;
|
||||
va_list ap = args;
|
||||
|
||||
while (*p != '\0')
|
||||
{
|
||||
if (*p++ == '%')
|
||||
{
|
||||
while (strchr ("-+ #0", *p))
|
||||
++p;
|
||||
if (*p == '*')
|
||||
{
|
||||
++p;
|
||||
total_width += abs (va_arg (ap, int));
|
||||
}
|
||||
else
|
||||
total_width += strtoul (p, &p, 10);
|
||||
if (*p == '.')
|
||||
{
|
||||
++p;
|
||||
if (*p == '*')
|
||||
{
|
||||
++p;
|
||||
total_width += abs (va_arg (ap, int));
|
||||
}
|
||||
else
|
||||
total_width += strtoul (p, &p, 10);
|
||||
}
|
||||
while (strchr ("hlL", *p))
|
||||
++p;
|
||||
/* Should be big enough for any format specifier except %s. */
|
||||
total_width += 30;
|
||||
switch (*p)
|
||||
{
|
||||
case 'd':
|
||||
case 'i':
|
||||
case 'o':
|
||||
case 'u':
|
||||
case 'x':
|
||||
case 'X':
|
||||
case 'c':
|
||||
va_arg (ap, int);
|
||||
break;
|
||||
case 'f':
|
||||
case 'e':
|
||||
case 'E':
|
||||
case 'g':
|
||||
case 'G':
|
||||
va_arg (ap, double);
|
||||
break;
|
||||
case 's':
|
||||
total_width += strlen (va_arg (ap, char *));
|
||||
break;
|
||||
case 'p':
|
||||
case 'n':
|
||||
va_arg (ap, char *);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef TEST
|
||||
global_total_width = total_width;
|
||||
#endif
|
||||
*result = malloc (total_width);
|
||||
if (*result != NULL)
|
||||
return vsprintf (*result, format, args);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
void
|
||||
checkit (va_alist)
|
||||
va_dcl
|
||||
{
|
||||
va_list args;
|
||||
char *format;
|
||||
char *result;
|
||||
|
||||
va_start (args);
|
||||
format = va_arg (args, char *);
|
||||
vasprintf (&result, format, args);
|
||||
if (strlen (result) < global_total_width)
|
||||
printf ("PASS: ");
|
||||
else
|
||||
printf ("FAIL: ");
|
||||
printf ("%d %s\n", global_total_width, result);
|
||||
}
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
checkit ("%d", 0x12345678);
|
||||
checkit ("%200d", 5);
|
||||
checkit ("%.300d", 6);
|
||||
checkit ("%100.150d", 7);
|
||||
checkit ("%s", "jjjjjjjjjiiiiiiiiiiiiiiioooooooooooooooooppppppppppppaa\n\
|
||||
777777777777777777333333333333366666666666622222222222777777777777733333");
|
||||
checkit ("%f%s%d%s", 1.0, "foo", 77, "asdjffffffffffffffiiiiiiiiiiixxxxx");
|
||||
}
|
||||
#endif /* TEST */
|
||||
@@ -26,7 +26,7 @@
|
||||
#include "uucp.h"
|
||||
|
||||
#if USE_RCS_ID
|
||||
const char serial_rcsid[] = "$Id: serial.c,v 1.6 1995/08/19 21:25:56 ache Exp $";
|
||||
const char serial_rcsid[] = "$Id: serial.c,v 1.5.4.1 1995/09/01 06:02:58 davidg Exp $";
|
||||
#endif
|
||||
|
||||
#include "uudefs.h"
|
||||
@@ -2371,7 +2371,7 @@ fsysdep_conn_read (qconn, zbuf, pclen, cmin, ctimeout, freport)
|
||||
else
|
||||
csleepchars = MAX_INPUT - 10;
|
||||
|
||||
isleep = (int) (((long) csleepchars * 10000L) / q->ibaud);
|
||||
isleep = (int) (((long) csleepchars * 10000L) / (q->ibaud? q->ibaud: (long)1200));
|
||||
isleep -= 10;
|
||||
|
||||
if (isleep > 10)
|
||||
@@ -2773,8 +2773,8 @@ fsysdep_conn_io (qconn, zwrite, pcwrite, zread, pcread)
|
||||
/ baud bits/sec)
|
||||
* 10 bits/byte)
|
||||
*/
|
||||
stime.tv_sec = (long) 10240 / q->ibaud;
|
||||
stime.tv_usec = ((((long) 1024000000 / q->ibaud) * (long) 10)
|
||||
stime.tv_sec = (long) 10240 / (q->ibaud? q->ibaud: (long)1200);
|
||||
stime.tv_usec = ((((long) 1024000000 / (q->ibaud? q->ibaud: (long)1200)) * (long) 10)
|
||||
% (long) 1000000);
|
||||
|
||||
imask = 1 << q->o;
|
||||
@@ -2846,7 +2846,7 @@ fsysdep_conn_io (qconn, zwrite, pcwrite, zread, pcread)
|
||||
we don't need to use the catch stuff, since we know
|
||||
that HAVE_RESTARTABLE_SYSCALLS is 0. */
|
||||
usset_signal (SIGALRM, usalarm, TRUE, (boolean *) NULL);
|
||||
alarm ((int) ((long) 10240 / q->ibaud) + 1);
|
||||
alarm ((int) ((long) 10240 / (q->ibaud? q->ibaud: (long)1200)) + 1);
|
||||
|
||||
/* There is a race condition here: on a severely loaded
|
||||
system, we could get the alarm before we start the
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
LIB= iberty
|
||||
SRCS= argv.c basename.c concat.c cplus-dem.c fdmatch.c getopt.c \
|
||||
getopt1.c ieee-float.c obstack.c spaces.c strerror.c strsignal.c \
|
||||
vasprintf.c xmalloc.c
|
||||
xmalloc.c
|
||||
|
||||
CFLAGS+= -I$(.CURDIR)/../gdb/.
|
||||
NOPROFILE=no
|
||||
|
||||
@@ -1,139 +0,0 @@
|
||||
/* Like vsprintf but provides a pointer to malloc'd storage, which must
|
||||
be freed by the caller.
|
||||
Copyright (C) 1994 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the libiberty library.
|
||||
Libiberty is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
Libiberty is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with libiberty; see the file COPYING.LIB. If
|
||||
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
|
||||
Cambridge, MA 02139, USA. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <varargs.h>
|
||||
|
||||
#ifdef TEST
|
||||
int global_total_width;
|
||||
#endif
|
||||
|
||||
unsigned long strtoul ();
|
||||
char *malloc ();
|
||||
|
||||
int
|
||||
vasprintf (result, format, args)
|
||||
char **result;
|
||||
char *format;
|
||||
va_list args;
|
||||
{
|
||||
char *p = format;
|
||||
/* Add one to make sure that it is never zero, which might cause malloc
|
||||
to return NULL. */
|
||||
int total_width = strlen (format) + 1;
|
||||
va_list ap = args;
|
||||
|
||||
while (*p != '\0')
|
||||
{
|
||||
if (*p++ == '%')
|
||||
{
|
||||
while (strchr ("-+ #0", *p))
|
||||
++p;
|
||||
if (*p == '*')
|
||||
{
|
||||
++p;
|
||||
total_width += abs (va_arg (ap, int));
|
||||
}
|
||||
else
|
||||
total_width += strtoul (p, &p, 10);
|
||||
if (*p == '.')
|
||||
{
|
||||
++p;
|
||||
if (*p == '*')
|
||||
{
|
||||
++p;
|
||||
total_width += abs (va_arg (ap, int));
|
||||
}
|
||||
else
|
||||
total_width += strtoul (p, &p, 10);
|
||||
}
|
||||
while (strchr ("hlL", *p))
|
||||
++p;
|
||||
/* Should be big enough for any format specifier except %s. */
|
||||
total_width += 30;
|
||||
switch (*p)
|
||||
{
|
||||
case 'd':
|
||||
case 'i':
|
||||
case 'o':
|
||||
case 'u':
|
||||
case 'x':
|
||||
case 'X':
|
||||
case 'c':
|
||||
va_arg (ap, int);
|
||||
break;
|
||||
case 'f':
|
||||
case 'e':
|
||||
case 'E':
|
||||
case 'g':
|
||||
case 'G':
|
||||
va_arg (ap, double);
|
||||
break;
|
||||
case 's':
|
||||
total_width += strlen (va_arg (ap, char *));
|
||||
break;
|
||||
case 'p':
|
||||
case 'n':
|
||||
va_arg (ap, char *);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef TEST
|
||||
global_total_width = total_width;
|
||||
#endif
|
||||
*result = malloc (total_width);
|
||||
if (*result != NULL)
|
||||
return vsprintf (*result, format, args);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
void
|
||||
checkit (va_alist)
|
||||
va_dcl
|
||||
{
|
||||
va_list args;
|
||||
char *format;
|
||||
char *result;
|
||||
|
||||
va_start (args);
|
||||
format = va_arg (args, char *);
|
||||
vasprintf (&result, format, args);
|
||||
if (strlen (result) < global_total_width)
|
||||
printf ("PASS: ");
|
||||
else
|
||||
printf ("FAIL: ");
|
||||
printf ("%d %s\n", global_total_width, result);
|
||||
}
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
checkit ("%d", 0x12345678);
|
||||
checkit ("%200d", 5);
|
||||
checkit ("%.300d", 6);
|
||||
checkit ("%100.150d", 7);
|
||||
checkit ("%s", "jjjjjjjjjiiiiiiiiiiiiiiioooooooooooooooooppppppppppppaa\n\
|
||||
777777777777777777333333333333366666666666622222222222777777777777733333");
|
||||
checkit ("%f%s%d%s", 1.0, "foo", 77, "asdjffffffffffffffiiiiiiiiiiixxxxx");
|
||||
}
|
||||
#endif /* TEST */
|
||||
@@ -27,7 +27,7 @@
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $Id: ldconfig.c,v 1.12 1996/02/26 02:22:33 pst Exp $
|
||||
* $Id: ldconfig.c,v 1.9.4.3 1996/04/02 13:10:30 phk Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
@@ -39,6 +39,8 @@
|
||||
#include <sys/resource.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <err.h>
|
||||
#include <ctype.h>
|
||||
#include <fcntl.h>
|
||||
#include <ar.h>
|
||||
#include <ranlib.h>
|
||||
@@ -114,7 +116,7 @@ char *argv[];
|
||||
return rval;
|
||||
if (justread) {
|
||||
listhints();
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -288,7 +290,7 @@ buildhints()
|
||||
hdr.hh_ehints = hdr.hh_strtab + hdr.hh_strtab_sz;
|
||||
|
||||
if (verbose)
|
||||
printf("Totals: entries %d, buckets %d, string size %d\n",
|
||||
printf("Totals: entries %d, buckets %ld, string size %d\n",
|
||||
nhints, hdr.hh_nbucket, strtab_sz);
|
||||
|
||||
/* Allocate buckets and string table */
|
||||
|
||||
@@ -59,7 +59,8 @@ downcase (s)
|
||||
while ((c = *s) != '\0')
|
||||
{
|
||||
if (isalpha (c))
|
||||
*s++ = tolower (c);
|
||||
*s = tolower (c);
|
||||
s++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+243
-131
@@ -16,11 +16,16 @@
|
||||
|
||||
#define MAN_MAIN
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#ifdef __FreeBSD__
|
||||
#include <locale.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include "config.h"
|
||||
#include "gripes.h"
|
||||
@@ -57,14 +62,7 @@ extern int fclose ();
|
||||
extern char *sprintf ();
|
||||
#endif
|
||||
|
||||
extern char *strdup ();
|
||||
|
||||
extern char **glob_vector ();
|
||||
extern char **glob_filename ();
|
||||
extern int access ();
|
||||
extern int unlink ();
|
||||
extern int system ();
|
||||
extern int chmod ();
|
||||
extern int is_newer ();
|
||||
extern int is_directory ();
|
||||
extern int do_system_command ();
|
||||
@@ -131,6 +129,10 @@ main (argc, argv)
|
||||
|
||||
prognam = mkprogname (argv[0]);
|
||||
|
||||
unsetenv("IFS");
|
||||
#ifdef __FreeBSD__
|
||||
(void) setlocale(LC_ALL, "");
|
||||
#endif
|
||||
man_getopt (argc, argv);
|
||||
|
||||
if (optind == argc)
|
||||
@@ -175,10 +177,14 @@ main (argc, argv)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (apropos)
|
||||
if (apropos) {
|
||||
do_apropos (nextarg);
|
||||
else if (whatis)
|
||||
status = (status ? 0 : 1); /* reverts status, see below */
|
||||
}
|
||||
else if (whatis) {
|
||||
do_whatis (nextarg);
|
||||
status = (status ? 0 : 1); /* reverts status, see below */
|
||||
}
|
||||
else
|
||||
{
|
||||
status = man (nextarg);
|
||||
@@ -313,6 +319,8 @@ man_getopt (argc, argv)
|
||||
break;
|
||||
case 'P':
|
||||
pager = strdup (optarg);
|
||||
if (setenv("PAGER", pager, 1) != 0)
|
||||
(void)fprintf(stderr, "setenv PAGER=%s\n", pager);
|
||||
break;
|
||||
case 'S':
|
||||
colon_sep_section_list = strdup (optarg);
|
||||
@@ -411,6 +419,10 @@ man_getopt (argc, argv)
|
||||
mp = manpathlist;
|
||||
for (p = manp; ; p = end+1)
|
||||
{
|
||||
if (mp == manpathlist + MAXDIRS - 1) {
|
||||
fprintf (stderr, "Warning: too many directories in manpath, truncated!\n");
|
||||
break;
|
||||
}
|
||||
if ((end = strchr (p, ':')) != NULL)
|
||||
*end = '\0';
|
||||
|
||||
@@ -423,9 +435,7 @@ man_getopt (argc, argv)
|
||||
fprintf (stderr, "Alternate system `%s' specified\n",
|
||||
alt_system_name);
|
||||
|
||||
strcpy (buf, p);
|
||||
strcat (buf, "/");
|
||||
strcat (buf, alt_system_name);
|
||||
snprintf(buf, sizeof(buf), "%s/%s", p, alt_system_name);
|
||||
|
||||
mp = add_dir_to_mpath_list (mp, buf);
|
||||
}
|
||||
@@ -525,15 +535,17 @@ convert_name (name, to_cat)
|
||||
#ifdef DO_COMPRESS
|
||||
if (to_cat)
|
||||
{
|
||||
int len = strlen (name) + 3;
|
||||
int olen = strlen(name);
|
||||
int cextlen = strlen(COMPRESS_EXT);
|
||||
int len = olen + cextlen;
|
||||
|
||||
to_name = (char *) malloc (len);
|
||||
to_name = malloc (len+1);
|
||||
if (to_name == NULL)
|
||||
gripe_alloc (len, "to_name");
|
||||
gripe_alloc (len+1, "to_name");
|
||||
strcpy (to_name, name);
|
||||
olen -= cextlen;
|
||||
/* Avoid tacking it on twice */
|
||||
if (strcmp(name + (len - (3 + cextlen)), COMPRESS_EXT))
|
||||
if (olen >= 1 && strcmp(name + olen, COMPRESS_EXT) != 0)
|
||||
strcat (to_name, COMPRESS_EXT);
|
||||
}
|
||||
else
|
||||
@@ -591,9 +603,9 @@ glob_for_file (path, section, name, cat)
|
||||
char **gf;
|
||||
|
||||
if (cat)
|
||||
sprintf (pathname, "%s/cat%s/%s.%s*", path, section, name, section);
|
||||
snprintf (pathname, sizeof(pathname), "%s/cat%s/%s.%s*", path, section, name, section);
|
||||
else
|
||||
sprintf (pathname, "%s/man%s/%s.%s*", path, section, name, section);
|
||||
snprintf (pathname, sizeof(pathname), "%s/man%s/%s.%s*", path, section, name, section);
|
||||
|
||||
if (debug)
|
||||
fprintf (stderr, "globbing %s\n", pathname);
|
||||
@@ -603,18 +615,18 @@ glob_for_file (path, section, name, cat)
|
||||
if ((gf == (char **) -1 || *gf == NULL) && isdigit (*section))
|
||||
{
|
||||
if (cat)
|
||||
sprintf (pathname, "%s/cat%s/%s.%c*", path, section, name, *section);
|
||||
snprintf (pathname, sizeof(pathname), "%s/cat%s/%s.%c*", path, section, name, *section);
|
||||
else
|
||||
sprintf (pathname, "%s/man%s/%s.%c*", path, section, name, *section);
|
||||
snprintf (pathname, sizeof(pathname), "%s/man%s/%s.%c*", path, section, name, *section);
|
||||
|
||||
gf = glob_filename (pathname);
|
||||
}
|
||||
if ((gf == (char **) -1 || *gf == NULL) && isdigit (*section))
|
||||
{
|
||||
if (cat)
|
||||
sprintf (pathname, "%s/cat%s/%s.0*", path, section, name);
|
||||
snprintf (pathname, sizeof(pathname), "%s/cat%s/%s.0*", path, section, name);
|
||||
else
|
||||
sprintf (pathname, "%s/man%s/%s.0*", path, section, name);
|
||||
snprintf (pathname, sizeof(pathname), "%s/man%s/%s.0*", path, section, name);
|
||||
if (debug)
|
||||
fprintf (stderr, "globbing %s\n", pathname);
|
||||
gf = glob_filename (pathname);
|
||||
@@ -638,9 +650,9 @@ make_name (path, section, name, cat)
|
||||
char buf[FILENAME_MAX];
|
||||
|
||||
if (cat)
|
||||
sprintf (buf, "%s/cat%s/%s.%s", path, section, name, section);
|
||||
snprintf (buf, sizeof(buf), "%s/cat%s/%s.%s", path, section, name, section);
|
||||
else
|
||||
sprintf (buf, "%s/man%s/%s.%s", path, section, name, section);
|
||||
snprintf (buf, sizeof(buf), "%s/man%s/%s.%s", path, section, name, section);
|
||||
|
||||
if (access (buf, R_OK) == 0)
|
||||
names[i++] = strdup (buf);
|
||||
@@ -653,9 +665,9 @@ make_name (path, section, name, cat)
|
||||
if (section[1] != '\0')
|
||||
{
|
||||
if (cat)
|
||||
sprintf (buf, "%s/cat%c/%s.%s", path, section[0], name, section);
|
||||
snprintf (buf, sizeof(buf), "%s/cat%c/%s.%s", path, section[0], name, section);
|
||||
else
|
||||
sprintf (buf, "%s/man%c/%s.%s", path, section[0], name, section);
|
||||
snprintf (buf, sizeof(buf), "%s/man%c/%s.%s", path, section[0], name, section);
|
||||
|
||||
if (access (buf, R_OK) == 0)
|
||||
names[i++] = strdup (buf);
|
||||
@@ -708,9 +720,9 @@ display_cat_file (file)
|
||||
char *expander = get_expander (file);
|
||||
|
||||
if (expander != NULL)
|
||||
sprintf (command, "%s %s | %s", expander, file, pager);
|
||||
snprintf (command, sizeof(command), "%s %s | %s", expander, file, pager);
|
||||
else
|
||||
sprintf (command, "%s %s", pager, file);
|
||||
snprintf (command, sizeof(command), "%s %s", pager, file);
|
||||
|
||||
found = do_system_command (command);
|
||||
}
|
||||
@@ -737,18 +749,20 @@ ultimate_source (name, path)
|
||||
char *beg;
|
||||
char *end;
|
||||
|
||||
strcpy (ult, name);
|
||||
strcpy (buf, name);
|
||||
strncpy (ult, name, sizeof(ult)-1);
|
||||
ult[sizeof(ult)-1] = '\0';
|
||||
strncpy (buf, name, sizeof(buf)-1);
|
||||
ult[sizeof(buf)-1] = '\0';
|
||||
|
||||
next:
|
||||
|
||||
if ((fp = fopen (ult, "r")) == NULL)
|
||||
return buf;
|
||||
|
||||
if (fgets (buf, BUFSIZ, fp) == NULL)
|
||||
return ult;
|
||||
|
||||
if (strlen (buf) < 5)
|
||||
end = fgets (buf, BUFSIZ, fp);
|
||||
fclose(fp);
|
||||
|
||||
if (!end || strlen (buf) < 5)
|
||||
return ult;
|
||||
|
||||
beg = buf;
|
||||
@@ -763,11 +777,8 @@ ultimate_source (name, path)
|
||||
|
||||
*end = '\0';
|
||||
|
||||
strcpy (ult, path);
|
||||
strcat (ult, "/");
|
||||
strcat (ult, beg);
|
||||
|
||||
strcpy (buf, ult);
|
||||
snprintf(ult, sizeof(ult), "%s/%s", path, beg);
|
||||
snprintf(buf, sizeof(buf), "%s", ult);
|
||||
|
||||
goto next;
|
||||
}
|
||||
@@ -779,34 +790,34 @@ ultimate_source (name, path)
|
||||
}
|
||||
|
||||
void
|
||||
add_directive (first, d, file, buf)
|
||||
add_directive (first, d, file, buf, bufsize)
|
||||
int *first;
|
||||
char *d;
|
||||
char *file;
|
||||
char *buf;
|
||||
int bufsize;
|
||||
{
|
||||
if (strcmp (d, "") != 0)
|
||||
{
|
||||
if (*first)
|
||||
{
|
||||
*first = 0;
|
||||
strcpy (buf, d);
|
||||
strcat (buf, " ");
|
||||
strcat (buf, file);
|
||||
snprintf(buf, bufsize, "%s %s", d, file);
|
||||
}
|
||||
else
|
||||
{
|
||||
strcat (buf, " | ");
|
||||
strcat (buf, d);
|
||||
strncat (buf, " | ", bufsize-strlen(buf)-1);
|
||||
strncat (buf, d, bufsize-strlen(buf)-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
parse_roff_directive (cp, file, buf)
|
||||
parse_roff_directive (cp, file, buf, bufsize)
|
||||
char *cp;
|
||||
char *file;
|
||||
char *buf;
|
||||
int bufsize;
|
||||
{
|
||||
char c;
|
||||
int first = 1;
|
||||
@@ -822,9 +833,9 @@ parse_roff_directive (cp, file, buf)
|
||||
fprintf (stderr, "found eqn(1) directive\n");
|
||||
|
||||
if (troff)
|
||||
add_directive (&first, EQN, file, buf);
|
||||
add_directive (&first, EQN, file, buf, bufsize);
|
||||
else
|
||||
add_directive (&first, NEQN, file, buf);
|
||||
add_directive (&first, NEQN, file, buf, bufsize);
|
||||
|
||||
break;
|
||||
|
||||
@@ -833,7 +844,7 @@ parse_roff_directive (cp, file, buf)
|
||||
if (debug)
|
||||
fprintf (stderr, "found grap(1) directive\n");
|
||||
|
||||
add_directive (&first, GRAP, file, buf);
|
||||
add_directive (&first, GRAP, file, buf, bufsize);
|
||||
|
||||
break;
|
||||
|
||||
@@ -842,7 +853,7 @@ parse_roff_directive (cp, file, buf)
|
||||
if (debug)
|
||||
fprintf (stderr, "found pic(1) directive\n");
|
||||
|
||||
add_directive (&first, PIC, file, buf);
|
||||
add_directive (&first, PIC, file, buf, bufsize);
|
||||
|
||||
break;
|
||||
|
||||
@@ -852,7 +863,7 @@ parse_roff_directive (cp, file, buf)
|
||||
fprintf (stderr, "found tbl(1) directive\n");
|
||||
|
||||
tbl_found++;
|
||||
add_directive (&first, TBL, file, buf);
|
||||
add_directive (&first, TBL, file, buf, bufsize);
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
@@ -860,7 +871,7 @@ parse_roff_directive (cp, file, buf)
|
||||
if (debug)
|
||||
fprintf (stderr, "found vgrind(1) directive\n");
|
||||
|
||||
add_directive (&first, VGRIND, file, buf);
|
||||
add_directive (&first, VGRIND, file, buf, bufsize);
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
@@ -868,7 +879,7 @@ parse_roff_directive (cp, file, buf)
|
||||
if (debug)
|
||||
fprintf (stderr, "found refer(1) directive\n");
|
||||
|
||||
add_directive (&first, REFER, file, buf);
|
||||
add_directive (&first, REFER, file, buf, bufsize);
|
||||
break;
|
||||
|
||||
case ' ':
|
||||
@@ -891,19 +902,19 @@ parse_roff_directive (cp, file, buf)
|
||||
#ifdef HAS_TROFF
|
||||
if (troff)
|
||||
{
|
||||
strcat (buf, " | ");
|
||||
strcat (buf, TROFF);
|
||||
strncat (buf, " | ", bufsize-strlen(buf)-1);
|
||||
strncat (buf, TROFF, bufsize-strlen(buf)-1);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
strcat (buf, " | ");
|
||||
strcat (buf, NROFF);
|
||||
strncat (buf, " | ", bufsize-strlen(buf)-1);
|
||||
strncat (buf, NROFF, bufsize-strlen(buf)-1);
|
||||
}
|
||||
if (tbl_found && !troff && strcmp (COL, "") != 0)
|
||||
{
|
||||
strcat (buf, " | ");
|
||||
strcat (buf, COL);
|
||||
strncat (buf, " | ", bufsize-strlen(buf)-1);
|
||||
strncat (buf, COL, bufsize-strlen(buf)-1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -924,7 +935,7 @@ make_roff_command (file)
|
||||
if (debug)
|
||||
fprintf (stderr, "parsing directive from command line\n");
|
||||
|
||||
status = parse_roff_directive (roff_directive, file, buf);
|
||||
status = parse_roff_directive (roff_directive, file, buf, sizeof(buf));
|
||||
|
||||
if (status == 0)
|
||||
return buf;
|
||||
@@ -936,15 +947,14 @@ make_roff_command (file)
|
||||
if ((fp = fopen (file, "r")) != NULL)
|
||||
{
|
||||
cp = line;
|
||||
fgets (line, 100, fp);
|
||||
fgets (line, BUFSIZ, fp);
|
||||
fclose(fp);
|
||||
if (*cp++ == '\'' && *cp++ == '\\' && *cp++ == '"' && *cp++ == ' ')
|
||||
{
|
||||
if (debug)
|
||||
fprintf (stderr, "parsing directive from file\n");
|
||||
|
||||
status = parse_roff_directive (cp, file, buf);
|
||||
|
||||
fclose (fp);
|
||||
status = parse_roff_directive (cp, file, buf, sizeof(buf));
|
||||
|
||||
if (status == 0)
|
||||
return buf;
|
||||
@@ -968,7 +978,7 @@ make_roff_command (file)
|
||||
if (debug)
|
||||
fprintf (stderr, "parsing directive from environment\n");
|
||||
|
||||
status = parse_roff_directive (cp, file, buf);
|
||||
status = parse_roff_directive (cp, file, buf, sizeof(buf));
|
||||
|
||||
if (status == 0)
|
||||
return buf;
|
||||
@@ -981,20 +991,20 @@ make_roff_command (file)
|
||||
fprintf (stderr, "using default preprocessor sequence\n");
|
||||
|
||||
if ((cp = get_expander(file)) == NULL)
|
||||
cp = "cat";
|
||||
sprintf(buf, "%s %s | ", cp, file);
|
||||
cp = "/bin/cat";
|
||||
snprintf(buf, sizeof(buf), "%s %s | ", cp, file);
|
||||
#ifdef HAS_TROFF
|
||||
if (troff)
|
||||
{
|
||||
if (strcmp (TBL, "") != 0)
|
||||
{
|
||||
strcat (buf, TBL);
|
||||
strcat (buf, " | ");
|
||||
strcat (buf, TROFF);
|
||||
strncat(buf, TBL, sizeof(buf)-strlen(buf)-1);
|
||||
strncat(buf, " | ", sizeof(buf)-strlen(buf)-1);
|
||||
strncat(buf, TROFF, sizeof(buf)-strlen(buf)-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
strcat (buf, TROFF);
|
||||
strncat(buf, TROFF, sizeof(buf)-strlen(buf)-1);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1002,101 +1012,202 @@ make_roff_command (file)
|
||||
{
|
||||
if (strcmp (TBL, "") != 0)
|
||||
{
|
||||
strcat (buf, TBL);
|
||||
strcat (buf, " | ");
|
||||
strcat (buf, NROFF);
|
||||
strncat(buf, TBL, sizeof(buf)-strlen(buf)-1);
|
||||
strncat(buf, " | ", sizeof(buf)-strlen(buf)-1);
|
||||
strncat(buf, NROFF, sizeof(buf)-strlen(buf)-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy (buf, NROFF);
|
||||
strncpy (buf, NROFF, sizeof(buf));
|
||||
}
|
||||
|
||||
if (strcmp (COL, "") != 0)
|
||||
{
|
||||
strcat (buf, " | ");
|
||||
strcat (buf, COL);
|
||||
strncat (buf, " | ", sizeof(buf)-strlen(buf)-1);
|
||||
strncat (buf, COL, sizeof(buf)-strlen(buf)-1);
|
||||
}
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
sig_t ohup, oint, oquit, oterm;
|
||||
static char temp[FILENAME_MAX];
|
||||
|
||||
void cleantmp()
|
||||
{
|
||||
unlink(temp);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void
|
||||
set_sigs()
|
||||
{
|
||||
ohup = signal(SIGHUP, cleantmp);
|
||||
oint = signal(SIGINT, cleantmp);
|
||||
oquit = signal(SIGQUIT, cleantmp);
|
||||
oterm = signal(SIGTERM, cleantmp);
|
||||
}
|
||||
|
||||
void
|
||||
restore_sigs()
|
||||
{
|
||||
signal(SIGHUP, ohup);
|
||||
signal(SIGINT, oint);
|
||||
signal(SIGQUIT, oquit);
|
||||
signal(SIGTERM, oterm);
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to format the man page and create a new formatted file. Return
|
||||
* 1 for success and 0 for failure.
|
||||
*/
|
||||
int
|
||||
make_cat_file (path, man_file, cat_file)
|
||||
make_cat_file (path, man_file, cat_file, manid)
|
||||
register char *path;
|
||||
register char *man_file;
|
||||
register char *cat_file;
|
||||
{
|
||||
int status;
|
||||
int mode;
|
||||
FILE *fp;
|
||||
int s, f;
|
||||
FILE *fp, *pp;
|
||||
char *roff_command;
|
||||
char command[FILENAME_MAX];
|
||||
char temp[FILENAME_MAX];
|
||||
|
||||
sprintf(temp, "%s.tmp", cat_file);
|
||||
if ((fp = fopen (temp, "w")) != NULL)
|
||||
{
|
||||
fclose (fp);
|
||||
unlink (temp);
|
||||
|
||||
roff_command = make_roff_command (man_file);
|
||||
if (roff_command == NULL)
|
||||
return 0;
|
||||
else
|
||||
|
||||
snprintf(temp, sizeof(temp), "%s.tmpXXXXXX", cat_file);
|
||||
if ((f = mkstemp(temp)) >= 0 && (fp = fdopen(f, "w")) != NULL)
|
||||
{
|
||||
set_sigs();
|
||||
|
||||
if (fchmod (f, CATMODE) < 0) {
|
||||
perror("fchmod");
|
||||
unlink(temp);
|
||||
restore_sigs();
|
||||
fclose(fp);
|
||||
return 0;
|
||||
} else if (debug)
|
||||
fprintf (stderr, "mode of %s is now %o\n", temp, CATMODE);
|
||||
|
||||
#ifdef DO_COMPRESS
|
||||
sprintf (command, "(cd %s ; %s | %s > %s)", path,
|
||||
roff_command, COMPRESSOR, temp);
|
||||
snprintf (command, sizeof(command), "(cd %s ; %s | %s)", path,
|
||||
roff_command, COMPRESSOR);
|
||||
#else
|
||||
sprintf (command, "(cd %s ; %s > %s)", path,
|
||||
roff_command, temp);
|
||||
snprintf (command, sizeof(command), "(cd %s ; %s)", path,
|
||||
roff_command);
|
||||
#endif
|
||||
/*
|
||||
* Don't let the user interrupt the system () call and screw up
|
||||
* the formatted man page if we're not done yet.
|
||||
*/
|
||||
fprintf (stderr, "Formatting page, please wait...");
|
||||
fflush(stderr);
|
||||
|
||||
status = do_system_command (command);
|
||||
|
||||
if (status <= 0) {
|
||||
fprintf(stderr, "Failed.\n");
|
||||
unlink(temp);
|
||||
exit(1);
|
||||
}
|
||||
if (debug)
|
||||
fprintf (stderr, "\ntrying command: %s\n", command);
|
||||
else {
|
||||
if (rename(temp, cat_file) == -1) {
|
||||
/* FS might be sticky */
|
||||
sprintf(command, "cp %s %s", temp, cat_file);
|
||||
if (system(command))
|
||||
|
||||
#ifdef SETREUID
|
||||
if (manid) {
|
||||
setreuid(-1, ruid);
|
||||
setregid(-1, rgid);
|
||||
}
|
||||
#endif
|
||||
if ((pp = popen(command, "r")) == NULL) {
|
||||
s = errno;
|
||||
fprintf(stderr, "Failed.\n");
|
||||
errno = s;
|
||||
perror("popen");
|
||||
#ifdef SETREUID
|
||||
if (manid) {
|
||||
setreuid(-1, euid);
|
||||
setregid(-1, egid);
|
||||
}
|
||||
#endif
|
||||
unlink(temp);
|
||||
restore_sigs();
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
#ifdef SETREUID
|
||||
if (manid) {
|
||||
setreuid(-1, euid);
|
||||
setregid(-1, egid);
|
||||
}
|
||||
#endif
|
||||
|
||||
while ((s = getc(pp)) != EOF)
|
||||
putc(s, fp);
|
||||
|
||||
if ((s = pclose(pp)) == -1) {
|
||||
s = errno;
|
||||
fprintf(stderr, "Failed.\n");
|
||||
errno = s;
|
||||
perror("pclose");
|
||||
unlink(temp);
|
||||
restore_sigs();
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (s != 0) {
|
||||
fprintf(stderr, "Failed.\n");
|
||||
gripe_system_command(s);
|
||||
unlink(temp);
|
||||
restore_sigs();
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (debug)
|
||||
unlink(temp);
|
||||
else if (rename(temp, cat_file) == -1) {
|
||||
s = errno;
|
||||
fprintf(stderr,
|
||||
"\nHmm! Can't seem to rename %s to %s, check permissions on man dir!\n",
|
||||
temp, cat_file);
|
||||
errno = s;
|
||||
perror("rename");
|
||||
unlink(temp);
|
||||
restore_sigs();
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "Done.\n");
|
||||
if (status == 1)
|
||||
{
|
||||
mode = CATMODE;
|
||||
chmod (cat_file, mode);
|
||||
restore_sigs();
|
||||
|
||||
if (debug)
|
||||
fprintf (stderr, "mode of %s is now %o\n", cat_file, mode);
|
||||
if (fclose(fp)) {
|
||||
s = errno;
|
||||
if (!debug)
|
||||
unlink(cat_file);
|
||||
fprintf(stderr, "Failed.\n");
|
||||
errno = s;
|
||||
perror("fclose");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (debug) {
|
||||
fprintf(stderr, "No output, debug mode.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
fprintf(stderr, "Done.\n");
|
||||
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (debug)
|
||||
fprintf (stderr, "Couldn't open %s for writing.\n", cat_file);
|
||||
if (f >= 0) {
|
||||
s = errno;
|
||||
unlink(temp);
|
||||
errno = s;
|
||||
}
|
||||
if (debug) {
|
||||
s = errno;
|
||||
fprintf (stderr, "Couldn't open %s for writing.\n", temp);
|
||||
errno = s;
|
||||
}
|
||||
if (f >= 0) {
|
||||
perror("fdopen");
|
||||
close(f);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1132,7 +1243,7 @@ format_and_display (path, man_file, cat_file)
|
||||
if (roff_command == NULL)
|
||||
return 0;
|
||||
else
|
||||
sprintf (command, "(cd %s ; %s)", path, roff_command);
|
||||
snprintf (command, sizeof(command), "(cd %s ; %s)", path, roff_command);
|
||||
|
||||
found = do_system_command (command);
|
||||
}
|
||||
@@ -1158,10 +1269,10 @@ format_and_display (path, man_file, cat_file)
|
||||
#ifdef SETREUID
|
||||
setreuid(-1, euid);
|
||||
setregid(-1, egid);
|
||||
found = make_cat_file (path, man_file, cat_file, 1);
|
||||
#else
|
||||
found = make_cat_file (path, man_file, cat_file, 0);
|
||||
#endif
|
||||
|
||||
found = make_cat_file (path, man_file, cat_file);
|
||||
|
||||
#ifdef SETREUID
|
||||
setreuid(-1, ruid);
|
||||
setregid(-1, rgid);
|
||||
@@ -1173,7 +1284,7 @@ format_and_display (path, man_file, cat_file)
|
||||
effective group (user) ID == real group (user) ID
|
||||
except for the call above, I believe the problems
|
||||
of reading private man pages is avoided. */
|
||||
found = make_cat_file (path, man_file, cat_file);
|
||||
found = make_cat_file (path, man_file, cat_file, 0);
|
||||
}
|
||||
#endif
|
||||
#ifdef SECURE_MAN_UID
|
||||
@@ -1192,7 +1303,7 @@ format_and_display (path, man_file, cat_file)
|
||||
*/
|
||||
setuid (getuid ());
|
||||
|
||||
found = make_cat_file (path, man_file, cat_file);
|
||||
found = make_cat_file (path, man_file, cat_file, 0);
|
||||
}
|
||||
#endif
|
||||
if (found)
|
||||
@@ -1212,7 +1323,7 @@ format_and_display (path, man_file, cat_file)
|
||||
if (roff_command == NULL)
|
||||
return 0;
|
||||
else
|
||||
sprintf (command, "(cd %s ; %s | %s)", path,
|
||||
snprintf (command, sizeof(command), "(cd %s ; %s | %s)", path,
|
||||
roff_command, pager);
|
||||
|
||||
found = do_system_command (command);
|
||||
@@ -1401,7 +1512,8 @@ get_section_list ()
|
||||
int i;
|
||||
char *p;
|
||||
char *end;
|
||||
static char *tmp_section_list[100];
|
||||
#define TMP_SECTION_LIST_SIZE 100
|
||||
static char *tmp_section_list[TMP_SECTION_LIST_SIZE];
|
||||
|
||||
if (colon_sep_section_list == NULL)
|
||||
{
|
||||
@@ -1416,7 +1528,7 @@ get_section_list ()
|
||||
}
|
||||
|
||||
i = 0;
|
||||
for (p = colon_sep_section_list; ; p = end+1)
|
||||
for (p = colon_sep_section_list; i < TMP_SECTION_LIST_SIZE ; p = end+1)
|
||||
{
|
||||
if ((end = strchr (p, ':')) != NULL)
|
||||
*end = '\0';
|
||||
|
||||
@@ -17,7 +17,7 @@ beforeinstall:
|
||||
${DESTDIR}${BINDIR}
|
||||
|
||||
afterinstall:
|
||||
(DESTDIR=${DESTDIR}; cd ${DESTDIR}/usr/include; h2ph * sys/*)
|
||||
(DESTDIR=${DESTDIR}; cd ${DESTDIR}/usr/include; ${BINDIR}/h2ph * sys/*)
|
||||
|
||||
.include "../../Makefile.inc"
|
||||
.include <bsd.prog.mk>
|
||||
@@ -1135,7 +1135,7 @@ again:
|
||||
if (nlp->fake)
|
||||
{
|
||||
if (nlp->change_dir && chdir (nlp->change_dir))
|
||||
msg_perror ("Can't change to directory %d", nlp->change_dir);
|
||||
msg_perror ("Can't change to directory %s", nlp->change_dir);
|
||||
namelist = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -283,6 +283,7 @@ __END_DECLS
|
||||
*/
|
||||
#if !defined (_ANSI_SOURCE) && !defined(_POSIX_SOURCE)
|
||||
__BEGIN_DECLS
|
||||
int asprintf __P((char **, const char *, ...));
|
||||
char *fgetln __P((FILE *, size_t *));
|
||||
int fpurge __P((FILE *));
|
||||
int getw __P((FILE *));
|
||||
@@ -293,6 +294,7 @@ void setbuffer __P((FILE *, char *, int));
|
||||
int setlinebuf __P((FILE *));
|
||||
char *tempnam __P((const char *, const char *));
|
||||
int snprintf __P((char *, size_t, const char *, ...));
|
||||
int vasprintf __P((char **, const char *, _BSD_VA_LIST_));
|
||||
int vsnprintf __P((char *, size_t, const char *, _BSD_VA_LIST_));
|
||||
int vscanf __P((const char *, _BSD_VA_LIST_));
|
||||
int vsscanf __P((const char *, const char *, _BSD_VA_LIST_));
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ SUBDIR=csu/${MACHINE}
|
||||
SUBDIR+= libc libcompat libcom_err libcurses libedit \
|
||||
libdisk libf2c libftpio \
|
||||
libkvm libmd libmytinfo libncurses libpcap libresolv librpcsvc \
|
||||
libscsi libskey libss libtelnet libtermcap libutil liby
|
||||
libscsi libskey libss libtelnet libtermcap libutil liby libz
|
||||
|
||||
SUBDIR+= libcrypt
|
||||
.if exists(../secure) && !defined(NOSECURE) && !defined(NOCRYPT)
|
||||
|
||||
+1
-6
@@ -27,7 +27,7 @@
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $Id: crt0.c,v 1.16.4.2 1995/09/28 13:16:24 davidg Exp $
|
||||
* $Id: crt0.c,v 1.16.4.4 1996/06/05 02:45:01 jkh Exp $
|
||||
*/
|
||||
|
||||
|
||||
@@ -39,9 +39,7 @@ extern void exit();
|
||||
int _callmain();
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <locale.h>
|
||||
#include <stdlib.h>
|
||||
extern void _startup_setlocale __P((int, const char *));
|
||||
|
||||
#ifdef DYNAMIC
|
||||
#include <sys/types.h>
|
||||
@@ -179,9 +177,6 @@ asm("eprol:");
|
||||
monstartup(&eprol, &etext);
|
||||
#endif /* MCRT0 */
|
||||
|
||||
if (getenv("ENABLE_STARTUP_LOCALE") != NULL)
|
||||
_startup_setlocale(LC_ALL, "");
|
||||
|
||||
asm ("__callmain:"); /* Defined for the benefit of debuggers */
|
||||
exit(main(kfp->kargc, argv, environ));
|
||||
}
|
||||
|
||||
+49
-10
@@ -165,7 +165,7 @@ start_gr()
|
||||
_gr_yp_enabled = 0;
|
||||
while(line = fgetln(_gr_fp, &linelen)) {
|
||||
if(line[0] == '+') {
|
||||
if(line[1] && !_gr_yp_enabled) {
|
||||
if(line[1] && line[1] != ':' && !_gr_yp_enabled) {
|
||||
_gr_yp_enabled = 1;
|
||||
} else {
|
||||
_gr_yp_enabled = -1;
|
||||
@@ -218,9 +218,12 @@ grscan(search, gid, name)
|
||||
register char *cp, **m;
|
||||
char *bp;
|
||||
#ifdef YP
|
||||
int _ypfound = 0;
|
||||
int _ypfound;
|
||||
#endif;
|
||||
for (;;) {
|
||||
#ifdef YP
|
||||
_ypfound = 0;
|
||||
#endif
|
||||
if (!fgets(line, sizeof(line), _gr_fp))
|
||||
return(0);
|
||||
bp = line;
|
||||
@@ -251,11 +254,17 @@ grscan(search, gid, name)
|
||||
return(0);
|
||||
}
|
||||
} else {
|
||||
if (!_getypgroup(&_gr_group, &_gr_group.gr_name[1],
|
||||
cp = &_gr_group.gr_name[1];
|
||||
if (search && name != NULL)
|
||||
if (strcmp(cp, name))
|
||||
continue;
|
||||
if (!_getypgroup(&_gr_group, cp,
|
||||
"group.byname"))
|
||||
continue;
|
||||
if (search && name == NULL)
|
||||
if (gid != _gr_group.gr_gid)
|
||||
continue;
|
||||
/* We're going to override -- tell the world. */
|
||||
members[0] = NULL;
|
||||
_ypfound++;
|
||||
}
|
||||
}
|
||||
@@ -268,17 +277,47 @@ grscan(search, gid, name)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if ((_gr_group.gr_passwd = strsep(&bp, ":\n")) == NULL)
|
||||
break;;
|
||||
if (!(cp = strsep(&bp, ":\n")))
|
||||
continue;
|
||||
#ifdef YP
|
||||
if ((cp = strsep(&bp, ":\n")) == NULL)
|
||||
if (_ypfound)
|
||||
return(1);
|
||||
else
|
||||
break;
|
||||
if (strlen(cp) || !_ypfound)
|
||||
_gr_group.gr_passwd = cp;
|
||||
#else
|
||||
if ((_gr_group.gr_passwd = strsep(&bp, ":\n")) == NULL)
|
||||
break;
|
||||
#endif
|
||||
if (!(cp = strsep(&bp, ":\n")))
|
||||
if (_ypfound)
|
||||
return(1);
|
||||
else
|
||||
continue;
|
||||
#ifdef YP
|
||||
/*
|
||||
* Hurm. Should we be doing this? We allow UIDs to
|
||||
* be overridden -- what about GIDs?
|
||||
*/
|
||||
if (!_ypfound)
|
||||
#endif
|
||||
_gr_group.gr_gid = atoi(cp);
|
||||
if (search && name == NULL && _gr_group.gr_gid != gid)
|
||||
continue;
|
||||
cp = NULL;
|
||||
if (bp == NULL) /* !!! Must check for this! */
|
||||
break;
|
||||
#ifdef YP
|
||||
if ((cp = strsep(&bp, ":\n")) == NULL)
|
||||
break;
|
||||
|
||||
if (!strlen(cp) && _ypfound)
|
||||
return(1);
|
||||
else
|
||||
members[0] = NULL;
|
||||
bp = cp;
|
||||
cp = NULL;
|
||||
#endif
|
||||
for (m = _gr_group.gr_mem = members;; bp++) {
|
||||
if (m == &members[MAXGRP - 1])
|
||||
break;
|
||||
@@ -375,8 +414,8 @@ _getypgroup(struct group *gr, const char *name, char *map)
|
||||
if(s) *s = '\0';
|
||||
|
||||
if(resultlen >= sizeof resultbuf) return 0;
|
||||
strcpy(resultbuf, result);
|
||||
result = resultbuf;
|
||||
strncpy(resultbuf, result, resultlen);
|
||||
free(result);
|
||||
return(_gr_breakout_yp(gr, resultbuf));
|
||||
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ getvfsent(void)
|
||||
}
|
||||
|
||||
do {
|
||||
if(_vfs_index > _vfslistlen) {
|
||||
if(_vfs_index >= _vfslistlen) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: collate.c,v 1.4 1995/05/30 05:40:40 rgrimes Exp $
|
||||
* $Id: collate.c,v 1.4.4.2 1996/06/05 02:47:55 jkh Exp $
|
||||
*/
|
||||
|
||||
#include <rune.h>
|
||||
@@ -64,7 +64,7 @@ __collate_load_tables(encoding)
|
||||
__collate_load_error = 1;
|
||||
if (!encoding)
|
||||
return -1;
|
||||
if (!path_locale && !(path_locale = getenv("PATH_LOCALE")))
|
||||
if (!path_locale)
|
||||
path_locale = _PATH_LOCALE;
|
||||
strcpy(buf, path_locale);
|
||||
strcat(buf, "/");
|
||||
|
||||
@@ -71,7 +71,7 @@ setrunelocale(encoding)
|
||||
return(0);
|
||||
}
|
||||
|
||||
if (!PathLocale && !(PathLocale = getenv("PATH_LOCALE")))
|
||||
if (!PathLocale)
|
||||
PathLocale = _PATH_LOCALE;
|
||||
|
||||
(void) strcpy(name, PathLocale);
|
||||
|
||||
@@ -58,7 +58,7 @@ setlocale(category, locale)
|
||||
int found, i, len;
|
||||
char *env, *r;
|
||||
|
||||
if (!PathLocale && !(PathLocale = getenv("PATH_LOCALE")))
|
||||
if (!PathLocale)
|
||||
PathLocale = _PATH_LOCALE;
|
||||
|
||||
if (category < 0 || category >= _LC_LAST)
|
||||
|
||||
@@ -23,7 +23,7 @@ _startup_setlocale(category, locale)
|
||||
int found, i, len;
|
||||
char *env, *r;
|
||||
|
||||
if (!PathLocale && !(PathLocale = getenv("PATH_LOCALE")))
|
||||
if (!PathLocale)
|
||||
PathLocale = _PATH_LOCALE;
|
||||
|
||||
if (category < 0 || category >= _LC_LAST)
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static char sccsid[] = "@(#)gethostnamadr.c 8.1 (Berkeley) 6/4/93";
|
||||
static char rcsid[] = "$Id: gethostbydns.c,v 1.8 1996/01/13 09:03:40 peter Exp $";
|
||||
static char rcsid[] = "$Id: gethostbydns.c,v 1.4.4.5 1996/11/20 18:36:37 pst Exp $";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
@@ -305,12 +305,11 @@ gethostanswer(answer, anslen, qname, qclass, qtype)
|
||||
cp += n;
|
||||
continue; /* XXX - had_error++ ? */
|
||||
}
|
||||
if (haveanswer) {
|
||||
if (n != host.h_length) {
|
||||
cp += n;
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if (n != host.h_length) {
|
||||
cp += n;
|
||||
continue;
|
||||
}
|
||||
if (!haveanswer) {
|
||||
register int nn;
|
||||
|
||||
host.h_length = n;
|
||||
@@ -393,6 +392,8 @@ _gethostbydnsname(name)
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
host.h_length = INT32SZ;
|
||||
|
||||
/*
|
||||
* if there aren't any dots, it could be a user-level alias.
|
||||
* this is also done in res_query() since we are not the only
|
||||
|
||||
@@ -44,16 +44,16 @@
|
||||
.Nd get network host entry
|
||||
.Sh SYNOPSIS
|
||||
.Fd #include <netdb.h>
|
||||
.Fd extern struct h_errno;
|
||||
.Fd extern int h_errno;
|
||||
.Ft struct hostent *
|
||||
.Fn gethostbyname "char *name"
|
||||
.Fn gethostbyname "const char *name"
|
||||
.Ft struct hostent *
|
||||
.Fn gethostbyaddr "char *addr" "int len" "int type"
|
||||
.Fn gethostbyaddr "const char *addr" "int len" "int type"
|
||||
.Ft struct hostent *
|
||||
.Fn gethostent void
|
||||
.Fn sethostent "int stayopen"
|
||||
.Fn endhostent void
|
||||
.Fn herror "char *string"
|
||||
.Fn herror "const char *string"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Fn gethostbyname
|
||||
|
||||
+2
-2
@@ -99,7 +99,7 @@ rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
|
||||
}
|
||||
fcntl(s, F_SETOWN, pid);
|
||||
sin.sin_family = hp->h_addrtype;
|
||||
bcopy(hp->h_addr_list[0], &sin.sin_addr, hp->h_length);
|
||||
bcopy(hp->h_addr_list[0], &sin.sin_addr, MIN(hp->h_length,sizeof(sin.sin_addr)));
|
||||
sin.sin_port = rport;
|
||||
if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0)
|
||||
break;
|
||||
@@ -121,7 +121,7 @@ rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
|
||||
errno = oerrno;
|
||||
perror(0);
|
||||
hp->h_addr_list++;
|
||||
bcopy(hp->h_addr_list[0], &sin.sin_addr, hp->h_length);
|
||||
bcopy(hp->h_addr_list[0], &sin.sin_addr, MIN(hp->h_length, sizeof sin.sin_addr));
|
||||
(void)fprintf(stderr, "Trying %s...\n",
|
||||
inet_ntoa(sin.sin_addr));
|
||||
continue;
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
# @(#)Makefile.inc 8.3 (Berkeley) 4/17/94
|
||||
# $Id: Makefile.inc,v 1.6 1996/05/29 05:00:12 jkh Exp $
|
||||
|
||||
# stdio sources
|
||||
.PATH: ${.CURDIR}/stdio
|
||||
|
||||
SRCS+= clrerr.c fclose.c fdopen.c feof.c ferror.c fflush.c fgetc.c \
|
||||
fgetln.c fgetpos.c fgets.c fileno.c findfp.c flags.c fopen.c \
|
||||
SRCS+= asprintf.c clrerr.c fclose.c fdopen.c feof.c ferror.c fflush.c \
|
||||
fgetc.c fgetln.c fgetpos.c fgets.c fileno.c findfp.c flags.c fopen.c \
|
||||
fprintf.c fpurge.c fputc.c fputs.c fread.c freopen.c fscanf.c \
|
||||
fseek.c fsetpos.c ftell.c funopen.c fvwrite.c fwalk.c fwrite.c \
|
||||
getc.c getchar.c gets.c getw.c makebuf.c mktemp.c perror.c \
|
||||
printf.c putc.c putchar.c puts.c putw.c refill.c remove.c rewind.c \
|
||||
rget.c scanf.c setbuf.c setbuffer.c setvbuf.c snprintf.c sprintf.c \
|
||||
sscanf.c stdio.c tempnam.c tmpfile.c tmpnam.c ungetc.c vfprintf.c \
|
||||
vfscanf.c vprintf.c vscanf.c vsnprintf.c vsprintf.c vsscanf.c \
|
||||
wbuf.c wsetup.c
|
||||
sscanf.c stdio.c tempnam.c tmpfile.c tmpnam.c ungetc.c vasprintf.c \
|
||||
vfprintf.c vfscanf.c vprintf.c vscanf.c vsnprintf.c vsprintf.c \
|
||||
vsscanf.c wbuf.c wsetup.c
|
||||
|
||||
MAN3+= stdio/fclose.3 stdio/ferror.3 stdio/fflush.3 stdio/fgetln.3 \
|
||||
stdio/fgets.3 stdio/fopen.3 stdio/fputs.3 stdio/fread.3 stdio/fseek.3 \
|
||||
@@ -32,7 +33,7 @@ MLINKS+=getc.3 fgetc.3 getc.3 getchar.3 getc.3 getw.3
|
||||
MLINKS+=mktemp.3 mkstemp.3
|
||||
MLINKS+=printf.3 fprintf.3 printf.3 snprintf.3 printf.3 sprintf.3 \
|
||||
printf.3 vfprintf.3 printf.3 vprintf.3 printf.3 vsnprintf.3 \
|
||||
printf.3 vsprintf.3
|
||||
printf.3 vsprintf.3 printf.3 asprintf.3 printf.3 vasprintf.3
|
||||
MLINKS+=putc.3 fputc.3 putc.3 putchar.3 putc.3 putw.3
|
||||
MLINKS+=scanf.3 fscanf.3 scanf.3 sscanf.3 scanf.3 vfscanf.3 scanf.3 vscanf.3 \
|
||||
scanf.3 vsscanf.3
|
||||
|
||||
+48
-34
@@ -43,10 +43,12 @@
|
||||
.Nm fprintf ,
|
||||
.Nm sprintf ,
|
||||
.Nm snprintf ,
|
||||
.Nm asprintf ,
|
||||
.Nm vprintf ,
|
||||
.Nm vfprintf,
|
||||
.Nm vsprintf ,
|
||||
.Nm vsnprintf
|
||||
.Nm vsnprintf ,
|
||||
.Nm vasprintf
|
||||
.Nd formatted output conversion
|
||||
.Sh SYNOPSIS
|
||||
.Fd #include <stdio.h>
|
||||
@@ -58,8 +60,8 @@
|
||||
.Fn sprintf "char *str" "const char *format" ...
|
||||
.Ft int
|
||||
.Fn snprintf "char *str" "size_t size" "const char *format" ...
|
||||
.\" .Ft int
|
||||
.\" .Fn smprintf "const char *format" ...
|
||||
.Ft int
|
||||
.Fn asprintf "char **ret" "const char *format" ...
|
||||
.Fd #include <stdarg.h>
|
||||
.Ft int
|
||||
.Fn vprintf "const char *format" "va_list ap"
|
||||
@@ -69,8 +71,8 @@
|
||||
.Fn vsprintf "char *str" "char *format" "va_list ap"
|
||||
.Ft int
|
||||
.Fn vsnprintf "char *str" "size_t size" "const char *format" "va_list ap"
|
||||
.\" .Ft int
|
||||
.\" .Fn vsmprintf "const char *format" "va_list ap"
|
||||
.Ft int
|
||||
.Fn vasprintf "char **ret" "const char *format" "va_list ap"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Fn printf
|
||||
@@ -94,45 +96,47 @@ write output to the given output
|
||||
and
|
||||
.Fn vsnprintf
|
||||
write to the character string
|
||||
.Fa str .
|
||||
.\" .IR str ;
|
||||
.\" and
|
||||
.\" .I smprintf
|
||||
.\" and
|
||||
.\" .I vsmprintf
|
||||
.\" dynamically allocate a new string with
|
||||
.\" .IR malloc .
|
||||
.Fa str ;
|
||||
and
|
||||
.Fn asprintf
|
||||
and
|
||||
.Fn vasprintf
|
||||
dynamically allocate a new string with
|
||||
.Xr malloc 3
|
||||
/
|
||||
.Xr realloc 3 .
|
||||
.Pp
|
||||
These functions write the output under the control of a
|
||||
.Fa format
|
||||
string that specifies how subsequent arguments
|
||||
(or arguments accessed via the variable-length argument facilities of
|
||||
.Xr stdarg 3 )
|
||||
are converted for output.
|
||||
.\" Except for
|
||||
.\" .I smprintf
|
||||
.\" and
|
||||
.\" .IR vsmprintf ,
|
||||
.\" all of these functions return
|
||||
.Pp
|
||||
These functions return
|
||||
the number of characters printed
|
||||
(not including the trailing
|
||||
.Ql \e0
|
||||
used to end output to strings).
|
||||
.\" .I Smprintf
|
||||
.\" and
|
||||
.\" .I vsmprintf
|
||||
.\" return a pointer to a string of an appropriate length;
|
||||
.\" this pointer should be passed to
|
||||
.\" .I free
|
||||
.\" to release the associated storage
|
||||
.\" when it is no longer needed.
|
||||
.\" If sufficient space is not avaliable,
|
||||
.\" .I smprintf
|
||||
.\" and
|
||||
.\" .I vsmprintf
|
||||
.\" will return
|
||||
.\" .SM
|
||||
.\" .BR
|
||||
.Pp
|
||||
.Fn Asprintf
|
||||
and
|
||||
.Fn vasprintf
|
||||
return a pointer to a buffer sufficiently large to hold the
|
||||
string in the
|
||||
.Fa ret
|
||||
argument;
|
||||
This pointer should be passed to
|
||||
.Xr free 3
|
||||
to release the allocated storage when it is no longer needed.
|
||||
If sufficient space cannot be allocated,
|
||||
.Fn asprintf
|
||||
and
|
||||
.Fn vasprintf
|
||||
will return -1 and set
|
||||
.Fa ret
|
||||
to be a NULL pointer.
|
||||
.Pp
|
||||
.Fn Snprintf
|
||||
and
|
||||
.Fn vsnprintf
|
||||
@@ -147,6 +151,7 @@ if the return value is greater than or equal to the
|
||||
.Fa size
|
||||
argument, the string was too short
|
||||
and some of the printed characters were discarded.
|
||||
.Pp
|
||||
.Fn Sprintf
|
||||
and
|
||||
.Fn vsprintf
|
||||
@@ -600,6 +605,15 @@ The functions
|
||||
and
|
||||
.Fn vsnprintf
|
||||
are new to this release.
|
||||
.Pp
|
||||
The functions
|
||||
.Fn asprintf
|
||||
and
|
||||
.Fn vasprintf
|
||||
first appeared in the GNU C library. This implementation is thought
|
||||
to be compatable but is not derived from the GNU code. This implementation
|
||||
was written by Peter Wemm <[email protected]> and first appeared in
|
||||
.Fx 2.2 .
|
||||
.Sh BUGS
|
||||
The conversion formats
|
||||
.Cm \&%D ,
|
||||
@@ -631,7 +645,7 @@ and
|
||||
.Fn vsprintf
|
||||
assume an infinitely long string,
|
||||
callers must be careful not to overflow the actual space;
|
||||
this is often impossible to assure.
|
||||
this is often hard to assure.
|
||||
For safety, programmers should use the
|
||||
.Fn snprintf
|
||||
interface instead.
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
/*-
|
||||
* Copyright (c) 1996 Peter Wemm <peter@freebsd.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_RCS) && !defined(lint)
|
||||
static char rcsid[] = "$Id: vasprintf.c,v 1.2 1996/06/22 10:34:01 jraynard Exp $";
|
||||
#endif /* LIBC_RCS and not lint */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#if __STDC__
|
||||
#include <stdarg.h>
|
||||
#else
|
||||
#include <varargs.h>
|
||||
#endif
|
||||
|
||||
#define CHUNK_SPARE 128 /* how much spare to allocate to avoid realloc calls */
|
||||
|
||||
struct bufcookie {
|
||||
char *base; /* start of buffer */
|
||||
size_t size;
|
||||
size_t left;
|
||||
};
|
||||
|
||||
static int writehook __P((void *cookie, const char *, int));
|
||||
|
||||
static int
|
||||
writehook(cookie, buf, len)
|
||||
void *cookie;
|
||||
const char *buf;
|
||||
int len;
|
||||
{
|
||||
struct bufcookie *h = (struct bufcookie *)cookie;
|
||||
char *newbuf;
|
||||
|
||||
if (len == 0)
|
||||
return 0;
|
||||
|
||||
if (len > h->left) {
|
||||
/* grow malloc region */
|
||||
/*
|
||||
* XXX this is linearly expanded, which is slow for obscenely
|
||||
* large strings.
|
||||
*/
|
||||
h->left = h->left + len + CHUNK_SPARE;
|
||||
h->size = h->size + len + CHUNK_SPARE;
|
||||
newbuf = realloc(h->base, h->size);
|
||||
if (newbuf == NULL) {
|
||||
free(h->base);
|
||||
h->base = NULL;
|
||||
return (-1);
|
||||
} else
|
||||
h->base = newbuf;
|
||||
}
|
||||
/* "write" it */
|
||||
(void)memcpy(h->base + h->size - h->left, buf, (size_t)len);
|
||||
h->left -= len;
|
||||
return (len);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
vasprintf(str, fmt, ap)
|
||||
char **str;
|
||||
const char *fmt;
|
||||
va_list ap;
|
||||
{
|
||||
int ret;
|
||||
FILE *f;
|
||||
struct bufcookie h;
|
||||
|
||||
h.base = malloc(CHUNK_SPARE);
|
||||
if (h.base == NULL)
|
||||
return (-1);
|
||||
h.size = CHUNK_SPARE;
|
||||
h.left = CHUNK_SPARE;
|
||||
|
||||
f = funopen(&h, NULL, writehook, NULL, NULL);
|
||||
if (f == NULL) {
|
||||
free(h.base);
|
||||
return (-1);
|
||||
}
|
||||
ret = vfprintf(f, fmt, ap);
|
||||
fclose(f);
|
||||
if (ret < 0) {
|
||||
free(h.base);
|
||||
return (-1);
|
||||
}
|
||||
if (h.base == NULL) /* failed to realloc in writehook */
|
||||
return (-1);
|
||||
|
||||
h.base[h.size - h.left] = '\0';
|
||||
*str = realloc(h.base, (size_t)(h.size - h.left + 1));
|
||||
if (*str == NULL) /* failed to realloc it to actual size */
|
||||
*str = h.base; /* return oversize buffer */
|
||||
return (ret);
|
||||
}
|
||||
+16
-2
@@ -28,7 +28,7 @@
|
||||
*/
|
||||
|
||||
#ifndef LINT
|
||||
static char *rcsid = "$Id: yplib.c,v 1.10.4.5 1996/06/05 02:52:10 jkh Exp $";
|
||||
static char *rcsid = "$Id: yplib.c,v 1.10.4.6 1996/06/25 17:53:33 wpaul Exp $";
|
||||
#endif
|
||||
|
||||
#include <sys/param.h>
|
||||
@@ -373,7 +373,8 @@ static void
|
||||
_yp_unbind(ypb)
|
||||
struct dom_binding *ypb;
|
||||
{
|
||||
clnt_destroy(ypb->dom_client);
|
||||
if (ypb->dom_client != NULL)
|
||||
clnt_destroy(ypb->dom_client);
|
||||
ypb->dom_client = NULL;
|
||||
ypb->dom_socket = -1;
|
||||
}
|
||||
@@ -692,6 +693,17 @@ again:
|
||||
|
||||
r = clnt_call(ysd->dom_client, YPPROC_ORDER,
|
||||
xdr_ypreq_nokey, &yprnk, xdr_ypresp_order, &ypro, tv);
|
||||
|
||||
/*
|
||||
* NIS+ in YP compat mode doesn't support the YPPROC_ORDER
|
||||
* procedure.
|
||||
*/
|
||||
|
||||
if (r == RPC_PROCUNAVAIL) {
|
||||
return(YPERR_YPERR);
|
||||
goto bail;
|
||||
}
|
||||
|
||||
if(r != RPC_SUCCESS) {
|
||||
clnt_perror(ysd->dom_client, "yp_order: clnt_call");
|
||||
ysd->dom_vers = -1;
|
||||
@@ -700,6 +712,8 @@ again:
|
||||
|
||||
*outorder = ypro.ordernum;
|
||||
xdr_free(xdr_ypresp_order, (char *)&ypro);
|
||||
|
||||
bail:
|
||||
_yp_unbind(ysd);
|
||||
return ypprot_err(ypro.status);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# $Id: Makefile,v 1.11.4.6 1996/06/05 02:52:27 jkh Exp $
|
||||
# $Id: Makefile,v 1.11.4.7 1996/07/09 12:18:58 jkh Exp $
|
||||
|
||||
LIB= disk
|
||||
SRCS= blocks.c disklabel.c dkcksum.c chunk.c disk.c change.c \
|
||||
@@ -37,7 +37,8 @@ MLINKS+= libdisk.3 Open_Disk.3 \
|
||||
libdisk.3 MakeDev.3 \
|
||||
libdisk.3 MakeDevDisk.3 \
|
||||
libdisk.3 ShowChunkFlags.3 \
|
||||
libdisk.3 ChunkCanBeRoot.3
|
||||
libdisk.3 ChunkCanBeRoot.3 \
|
||||
libdisk.3 slice_type_name.3
|
||||
|
||||
.include <bsd.lib.mk>
|
||||
|
||||
|
||||
+40
-20
@@ -6,7 +6,7 @@
|
||||
* this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* $Id: change.c,v 1.10 1995/12/07 10:33:18 peter Exp $
|
||||
* $Id: change.c,v 1.9.2.2 1996/05/28 22:51:09 jkh Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -19,23 +19,6 @@
|
||||
#include <sys/types.h>
|
||||
#include "libdisk.h"
|
||||
|
||||
#if 0
|
||||
struct disk *
|
||||
Set_Phys_Geom(struct disk *disk, u_long cyl, u_long hd, u_long sect)
|
||||
{
|
||||
struct disk *d = Int_Open_Disk(disk->name,cyl*hd*sect);
|
||||
d->real_cyl = cyl;
|
||||
d->real_hd = hd;
|
||||
d->real_sect = sect;
|
||||
d->bios_cyl = disk->bios_cyl;
|
||||
d->bios_hd = disk->bios_hd;
|
||||
d->bios_sect = disk->bios_sect;
|
||||
d->flags = disk->flags;
|
||||
Free_Disk(disk);
|
||||
return d;
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
Set_Bios_Geom(struct disk *disk, u_long cyl, u_long hd, u_long sect)
|
||||
{
|
||||
@@ -45,6 +28,38 @@ Set_Bios_Geom(struct disk *disk, u_long cyl, u_long hd, u_long sect)
|
||||
Bios_Limit_Chunk(disk->chunks,1024*hd*sect);
|
||||
}
|
||||
|
||||
void
|
||||
Sanitize_Bios_Geom(struct disk *disk)
|
||||
{
|
||||
int sane = 1;
|
||||
|
||||
if (disk->bios_cyl > 1024)
|
||||
sane = 0;
|
||||
if (disk->bios_hd > 16)
|
||||
sane = 0;
|
||||
if (disk->bios_sect > 63)
|
||||
sane = 0;
|
||||
if (disk->bios_cyl*disk->bios_hd*disk->bios_sect !=
|
||||
disk->chunks->size)
|
||||
sane = 0;
|
||||
if (sane)
|
||||
return;
|
||||
|
||||
/* First try something that IDE can handle */
|
||||
disk->bios_sect = 63;
|
||||
disk->bios_hd = 16;
|
||||
disk->bios_cyl = disk->chunks->size/(disk->bios_sect*disk->bios_hd);
|
||||
|
||||
if (disk->bios_cyl < 1024)
|
||||
return;
|
||||
|
||||
/* Hmm, try harder... */
|
||||
disk->bios_hd = 255;
|
||||
disk->bios_cyl = disk->chunks->size/(disk->bios_sect*disk->bios_hd);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
All_FreeBSD(struct disk *d, int force_all)
|
||||
{
|
||||
@@ -57,6 +72,11 @@ All_FreeBSD(struct disk *d, int force_all)
|
||||
goto again;
|
||||
}
|
||||
c=d->chunks;
|
||||
Create_Chunk(d,c->offset,c->size,freebsd,0xa5,
|
||||
force_all? CHUNK_FORCE_ALL: 0);
|
||||
if (force_all) {
|
||||
Sanitize_Bios_Geom(d);
|
||||
Create_Chunk(d,c->offset,c->size,freebsd,0xa5,
|
||||
CHUNK_FORCE_ALL);
|
||||
} else {
|
||||
Create_Chunk(d,c->offset,c->size,freebsd,0xa5, 0);
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@
|
||||
* this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* $Id: create_chunk.c,v 1.24 1996/04/29 05:03:01 jkh Exp $
|
||||
* $Id: create_chunk.c,v 1.21.2.8 1996/05/28 22:51:12 jkh Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -257,6 +257,8 @@ MakeDev(struct chunk *c1, const char *path)
|
||||
bmaj = 0, cmaj = 3;
|
||||
else if (!strncmp(p, "sd", 2))
|
||||
bmaj = 4, cmaj = 13;
|
||||
else if (!strncmp(p, "od", 2))
|
||||
bmaj = 20, cmaj = 70;
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
+42
-3
@@ -6,7 +6,7 @@
|
||||
* this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* $Id: disk.c,v 1.22 1996/04/29 05:03:02 jkh Exp $
|
||||
* $Id: disk.c,v 1.20.2.2 1996/05/28 22:51:14 jkh Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -231,7 +231,9 @@ Debug_Disk(struct disk *d)
|
||||
#if 0
|
||||
printf(" real_geom=%lu/%lu/%lu",d->real_cyl,d->real_hd,d->real_sect);
|
||||
#endif
|
||||
printf(" bios_geom=%lu/%lu/%lu\n",d->bios_cyl,d->bios_hd,d->bios_sect);
|
||||
printf(" bios_geom=%lu/%lu/%lu = %lu\n",
|
||||
d->bios_cyl,d->bios_hd,d->bios_sect,
|
||||
d->bios_cyl*d->bios_hd*d->bios_sect);
|
||||
printf(" boot1=%p, boot2=%p, bootmgr=%p\n",
|
||||
d->boot1,d->boot2,d->bootmgr);
|
||||
Debug_Chunk(d->chunks);
|
||||
@@ -283,7 +285,7 @@ Collapse_Disk(struct disk *d)
|
||||
}
|
||||
#endif
|
||||
|
||||
static char * device_list[] = {"wd","sd",0};
|
||||
static char * device_list[] = {"wd","sd","od",0};
|
||||
|
||||
char **
|
||||
Disk_Names()
|
||||
@@ -345,3 +347,40 @@ Set_Boot_Blocks(struct disk *d, const u_char *b1, const u_char *b2)
|
||||
if(!d->boot2) err(1,"malloc failed");
|
||||
memcpy(d->boot2,b2,15*512);
|
||||
}
|
||||
|
||||
const char *
|
||||
slice_type_name( int type, int subtype )
|
||||
{
|
||||
switch (type) {
|
||||
case 0: return "whole";
|
||||
case 1: switch (subtype) {
|
||||
case 1: return "fat (12-bit)";
|
||||
case 2: return "XENIX /";
|
||||
case 3: return "XENIX /usr";
|
||||
case 4: return "fat (16-bit)";
|
||||
case 5: return "extended DOS";
|
||||
case 6: return "fat (>32Mb)";
|
||||
case 7: return "NTFS/HPFS";
|
||||
case 10: return "OS/2 bootmgr";
|
||||
case 84: return "OnTrack diskmgr";
|
||||
case 100: return "Netware 2.x";
|
||||
case 101: return "Netware 3.x";
|
||||
case 128: return "Minix 1.1";
|
||||
case 129: return "Minix 1.5";
|
||||
case 130: return "linux_swap";
|
||||
case 131: return "ext2fs";
|
||||
case 183: return "bsd/os";
|
||||
case 184: return "bsd/os swap";
|
||||
default: return "unknown";
|
||||
}
|
||||
case 2: return "fat";
|
||||
case 3: switch (subtype) {
|
||||
case 165: return "freebsd";
|
||||
default: return "unknown";
|
||||
}
|
||||
case 4: return "extended";
|
||||
case 5: return "part";
|
||||
case 6: return "unused";
|
||||
default: return "unknown";
|
||||
}
|
||||
}
|
||||
+20
-1
@@ -25,7 +25,7 @@
|
||||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
.\"
|
||||
.\" $Id: libdisk.3,v 1.2 1996/03/24 18:55:38 joerg Exp $
|
||||
.\" $Id: libdisk.3,v 1.1.2.2 1996/05/28 22:51:15 jkh Exp $
|
||||
.\" "
|
||||
.Dd March 15, 1996
|
||||
.Dt LIBDISK 3
|
||||
@@ -57,11 +57,19 @@
|
||||
.Nm MakeDevDisk ,
|
||||
.Nm ShowChunkFlags ,
|
||||
.Nm ChunkCanBeRoot ,
|
||||
.Nm chunk_n ,
|
||||
.Nm slice_type_name
|
||||
.Nd library interface to slice and partition labels
|
||||
.Sh SYNOPSIS
|
||||
.Fd #include <sys/types.h>
|
||||
.Fd #include <libdisk.h>
|
||||
.Dv extern const u_char *boot1, boot2;
|
||||
.\" What is the correct way to cause a single line break ???
|
||||
.Bd -literal
|
||||
.Dv extern const char *chunk_n[];
|
||||
.Ed
|
||||
.Ft const char *
|
||||
.Fn slice_type_name "int type" "int subtype"
|
||||
.Ft struct disk *
|
||||
.Fn Open_Disk "const char *devname"
|
||||
.Ft struct disk *
|
||||
@@ -310,6 +318,17 @@ returns a string to show flags.
|
||||
.Pp
|
||||
.Fn ChunkCanBeRoot
|
||||
returns NULL if chunk can be
|
||||
.Pp
|
||||
Chunk name strings can be accessed directly using the external array
|
||||
.Va chunk_n .
|
||||
.Pp
|
||||
.Fn slice_type_name
|
||||
returns the name strings associated with the specified
|
||||
.Ql type .
|
||||
.Ql subtype .
|
||||
If
|
||||
.Fn slice_type_name
|
||||
returns "unknown" for slices it isn't familar with.
|
||||
.Ql / .
|
||||
.Sh AUTHOR
|
||||
.Nm Libdisk
|
||||
|
||||
+12
-15
@@ -6,7 +6,7 @@
|
||||
* this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* $Id: libdisk.h,v 1.22 1996/04/29 06:45:33 jkh Exp $
|
||||
* $Id: libdisk.h,v 1.19.2.4 1996/05/28 22:51:17 jkh Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -28,11 +28,6 @@ struct disk {
|
||||
char *name;
|
||||
u_long flags;
|
||||
# define DISK_ON_TRACK 1
|
||||
#if 0
|
||||
u_long real_cyl;
|
||||
u_long real_hd;
|
||||
u_long real_sect;
|
||||
#endif
|
||||
u_long bios_cyl;
|
||||
u_long bios_hd;
|
||||
u_long bios_sect;
|
||||
@@ -91,6 +86,11 @@ struct chunk {
|
||||
extern const char *chunk_n[];
|
||||
extern const u_char boot1[], boot2[];
|
||||
|
||||
const char *
|
||||
slice_type_name( int type, int subtype );
|
||||
/* "chunk_n" for subtypes too
|
||||
*/
|
||||
|
||||
struct disk *
|
||||
Open_Disk(const char *devname);
|
||||
/* Will open the named disk, and return populated tree.
|
||||
@@ -111,19 +111,16 @@ Debug_Disk(struct disk *disk);
|
||||
/* Print the content of the tree to stdout
|
||||
*/
|
||||
|
||||
#if 0
|
||||
struct disk *
|
||||
Set_Phys_Geom(struct disk *disk, u_long cyl, u_long heads, u_long sects);
|
||||
/* Use a different physical geometry. Makes sense for ST506 disks only.
|
||||
* The tree returned is read from the disk, using this geometry.
|
||||
*/
|
||||
#endif
|
||||
|
||||
void
|
||||
Set_Bios_Geom(struct disk *disk, u_long cyl, u_long heads, u_long sects);
|
||||
/* Set the geometry the bios uses.
|
||||
*/
|
||||
|
||||
void
|
||||
Sanitize_Bios_Geom(struct disk *disk);
|
||||
/* Set the bios geometry to something sane
|
||||
*/
|
||||
|
||||
int
|
||||
Delete_Chunk(struct disk *disk, struct chunk *);
|
||||
/* Free a chunk of disk_space
|
||||
@@ -278,7 +275,7 @@ __END_DECLS
|
||||
*
|
||||
*Sample output from tst01:
|
||||
*
|
||||
* Debug_Disk(wd0) flags=0 real_geom=0/0/0 bios_geom=0/0/0
|
||||
* Debug_Disk(wd0) flags=0 bios_geom=0/0/0
|
||||
* >> 0x3d040 0 1411200 1411199 wd0 0 whole 0 0
|
||||
* >>>> 0x3d080 0 960120 960119 wd0s1 3 freebsd 0 8
|
||||
* >>>>>> 0x3d100 0 40960 40959 wd0s1a 5 part 0 0
|
||||
|
||||
+5
-21
@@ -6,7 +6,7 @@
|
||||
* this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* $Id: tst01.c,v 1.15.2.3 1996/05/28 22:51:18 jkh Exp $
|
||||
* $Id: tst01.c,v 1.15.2.4 1996/07/09 12:19:03 jkh Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -196,6 +196,10 @@ main(int argc, char **argv)
|
||||
All_FreeBSD(d, 1);
|
||||
continue;
|
||||
}
|
||||
if (!strcasecmp(*cmds,"sanitize")) {
|
||||
Sanitize_Bios_Geom(d);
|
||||
continue;
|
||||
}
|
||||
if (!strcasecmp(*cmds,"bios") && ncmd == 4) {
|
||||
Set_Bios_Geom(d,
|
||||
strtol(cmds[1],0,0),
|
||||
@@ -203,26 +207,6 @@ main(int argc, char **argv)
|
||||
strtol(cmds[3],0,0));
|
||||
continue;
|
||||
}
|
||||
#if 0
|
||||
if (!strcasecmp(*cmds,"phys") && ncmd == 4) {
|
||||
d = Set_Phys_Geom(d,
|
||||
strtol(cmds[1],0,0),
|
||||
strtol(cmds[2],0,0),
|
||||
strtol(cmds[3],0,0));
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
#if 0
|
||||
if (!strcasecmp(*cmds,"collapse")) {
|
||||
if (cmds[1])
|
||||
while (Collapse_Chunk(d,
|
||||
(struct chunk *)strtol(cmds[1],0,0)))
|
||||
;
|
||||
else
|
||||
Collapse_Disk(d);
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
if (!strcasecmp(*cmds,"list")) {
|
||||
cp = Disk_Names();
|
||||
printf("Disks:");
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* $Id: write_disk.c,v 1.17 1996/04/29 05:03:02 jkh Exp $
|
||||
* $Id: write_disk.c,v 1.14.2.3 1996/05/28 22:51:19 jkh Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -80,15 +80,9 @@ Write_FreeBSD(int fd, struct disk *new, struct disk *old, struct chunk *c1)
|
||||
|
||||
dl->d_secsize = 512;
|
||||
dl->d_secperunit = new->chunks->size;
|
||||
#if 0
|
||||
dl->d_ncylinders = new->real_cyl ? new->real_cyl : new->bios_cyl;
|
||||
dl->d_ntracks = new->real_hd ? new->real_hd : new->bios_hd;
|
||||
dl->d_nsectors = new->real_sect ? new->real_sect : new->bios_sect;
|
||||
#else
|
||||
dl->d_ncylinders = new->bios_cyl;
|
||||
dl->d_ntracks = new->bios_hd;
|
||||
dl->d_nsectors = new->bios_sect;
|
||||
#endif
|
||||
dl->d_secpercyl = dl->d_ntracks * dl->d_nsectors;
|
||||
|
||||
dl->d_npartitions = MAXPARTITIONS;
|
||||
|
||||
+19
-1
@@ -1,10 +1,28 @@
|
||||
LIB= ftpio
|
||||
CFLAGS+= -I${.CURDIR} -Wall
|
||||
SRCS= ftpio.c
|
||||
SRCS= ftpio.c ftperr.c
|
||||
MAN3= ftpio.3
|
||||
CLEANFILES+= ftperr.c
|
||||
|
||||
SHLIB_MAJOR= 4
|
||||
SHLIB_MINOR= 0
|
||||
|
||||
beforeinstall:
|
||||
cd ${.CURDIR}; cmp -s ftpio.h ${DESTDIR}/usr/include/ftpio.h || \
|
||||
${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 444 ftpio.h ${DESTDIR}/usr/include
|
||||
|
||||
ftperr.c: ftp.errors
|
||||
@echo '#include <stdio.h>' > ${.TARGET}
|
||||
@echo '#include "ftpio.h"' >> ${.TARGET}
|
||||
@echo "struct ftperr ftpErrList[] = {" \ >> ${.TARGET}
|
||||
@cat ${.ALLSRC} \
|
||||
| grep -v ^# \
|
||||
| sort \
|
||||
| while read NUM STRING; do \
|
||||
echo " { $${NUM}, \"$${STRING}\" },"; \
|
||||
done >> ${.TARGET}
|
||||
@echo "};" >> ${.TARGET}
|
||||
@echo -n "int const ftpErrListLength = " >> ${.TARGET}
|
||||
@echo "sizeof(ftpErrList) / sizeof(*ftpErrList);" >> ${.TARGET}
|
||||
|
||||
.include <bsd.lib.mk>
|
||||
@@ -0,0 +1,44 @@
|
||||
# $FreeBSD$
|
||||
#
|
||||
# This list is taken from RFC 959.
|
||||
# It probably needs a going over.
|
||||
#
|
||||
110 Restart marker reply
|
||||
120 Service ready in a few minutes
|
||||
125 Data connection already open; transfer starting
|
||||
150 File status okay; about to open data connection
|
||||
200 Command okay
|
||||
202 Command not implemented, superfluous at this site
|
||||
211 System status, or system help reply
|
||||
212 Directory status
|
||||
213 File status
|
||||
214 Help message
|
||||
215 Set system type
|
||||
220 Service ready for new user
|
||||
221 Service closing control connection
|
||||
225 Data connection open; no transfer in progress
|
||||
226 Requested file action successful
|
||||
227 Entering Passive Mode
|
||||
230 User logged in, proceed
|
||||
250 Requested file action okay, completed
|
||||
257 File/directory created
|
||||
331 User name okay, need password
|
||||
332 Need account for login
|
||||
350 Requested file action pending further information
|
||||
421 Service not available, closing control connection
|
||||
425 Can't open data connection
|
||||
426 Connection closed; transfer aborted
|
||||
450 File unavailable (e.g., file busy)
|
||||
451 Requested action aborted: local error in processing
|
||||
452 Insufficient storage space in system
|
||||
500 Syntax error, command unrecognized
|
||||
501 Syntax error in parameters or arguments
|
||||
502 Command not implemented
|
||||
503 Bad sequence of commands
|
||||
504 Command not implemented for that parameter
|
||||
530 Not logged in
|
||||
532 Need account for storing files
|
||||
550 File unavailable (e.g., file not found, no access)
|
||||
551 Requested action aborted. Page type unknown
|
||||
552 Exceeded storage allocation
|
||||
553 File name not allowed
|
||||
@@ -1,257 +0,0 @@
|
||||
/*
|
||||
* Copyright (c)1995, 1996 Jordan Hubbard
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code may be used, modified, copied, distributed, and
|
||||
* sold, in both source and binary form provided that the above
|
||||
* copyright and these terms are retained, verbatim, as the first
|
||||
* lines of this file. Under no circumstances is the author
|
||||
* responsible for the proper functioning of the software nor does
|
||||
* the author assume any responsibility for damages incurred with
|
||||
* its use.
|
||||
*
|
||||
* $Id: ftp_pkg.c,v 1.1.1.1 1996/06/17 12:26:06 jkh Exp $
|
||||
*
|
||||
* TCL Interface code for functions provided by the ftp library.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <ftpio.h>
|
||||
#include "ftp_pkg.h"
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE (1)
|
||||
#define FALSE (0)
|
||||
#endif
|
||||
|
||||
#define CHECK_ARGS(cnt, myname, str) \
|
||||
if (argc <= (cnt)) { sprintf(interp->result, "usage: %s %s", myname, str); return TCL_ERROR; }
|
||||
|
||||
#define USAGE(myname, msg) \
|
||||
{ fprintf(stderr, "%s: %s\n", myname, msg); return TCL_ERROR; }
|
||||
|
||||
|
||||
/* Registration function */
|
||||
int
|
||||
Ftp_Init(Tcl_Interp *interp)
|
||||
{
|
||||
Tcl_CreateCommand (interp, "ftp_login", Ftp_login, NULL, NULL);
|
||||
Tcl_CreateCommand (interp, "ftp_chdir", Ftp_chdir, NULL, NULL);
|
||||
Tcl_CreateCommand (interp, "ftp_getsize", Ftp_getsize, NULL, NULL);
|
||||
Tcl_CreateCommand (interp, "ftp_get", Ftp_get, NULL, NULL);
|
||||
Tcl_CreateCommand (interp, "ftp_put", Ftp_put, NULL, NULL);
|
||||
Tcl_CreateCommand (interp, "ftp_binary", Ftp_binary, NULL, NULL);
|
||||
Tcl_CreateCommand (interp, "ftp_passive", Ftp_passive, NULL, NULL);
|
||||
Tcl_CreateCommand (interp, "ftp_get_url", Ftp_get_url, NULL, NULL);
|
||||
Tcl_CreateCommand (interp, "ftp_put_url", Ftp_put_url, NULL, NULL);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* ftp_login host user passwd port
|
||||
* -- returns new fileId
|
||||
*
|
||||
*/
|
||||
int
|
||||
Ftp_login(ClientData clientData, Tcl_Interp *interp, int argc, char **argv)
|
||||
{
|
||||
FILE *fp;
|
||||
char *user, *pass;
|
||||
int port;
|
||||
|
||||
CHECK_ARGS(1, argv[0], "host [user] [passwd] [port]");
|
||||
|
||||
user = (argc > 2) ? argv[2] : "ftp";
|
||||
pass = (argc > 3) ? argv[3] : "setup@";
|
||||
port = (argc > 4) ? atoi(argv[4]) : 21;
|
||||
/* Debug("ftp_pkg: attempt login to host %s using %s/%s (port %d)", argv[1], user, pass, port); */
|
||||
fp = ftpLogin(argv[1], user, pass, port);
|
||||
if (fp) {
|
||||
/* Debug("ftp_pkg: logged successfully into host %s", argv[1]); */
|
||||
Tcl_EnterFile(interp, fp, TCL_FILE_READABLE | TCL_FILE_WRITABLE);
|
||||
return TCL_OK;
|
||||
}
|
||||
/* Debug("ftp_pkg: login operation failed for host %s", argv[1]); */
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* ftp_chdir file-handle newdir
|
||||
* -- returns status
|
||||
*/
|
||||
int
|
||||
Ftp_chdir(ClientData clientData, Tcl_Interp *interp, int argc, char **argv)
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
CHECK_ARGS(2, argv[0], "fileId directory");
|
||||
if (Tcl_GetOpenFile(interp, argv[1], TRUE, TRUE, &fp) != TCL_OK)
|
||||
return TCL_ERROR;
|
||||
/* Debug("ftp_pkg: attempt chdir to dir %s", argv[2]); */
|
||||
if (!ftpChdir(fp, argv[2])) {
|
||||
/* Debug("ftp_pkg: chdir successful"); */
|
||||
return TCL_OK;
|
||||
}
|
||||
/* Debug("ftp_pkg: chdir failed"); */
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* ftp_getsize file-handle filename
|
||||
* -- returns size
|
||||
*/
|
||||
int
|
||||
Ftp_getsize(ClientData clientData, Tcl_Interp *interp, int argc, char **argv)
|
||||
{
|
||||
FILE *fp;
|
||||
int sz;
|
||||
|
||||
CHECK_ARGS(2, argv[0], "fileId filename");
|
||||
if (Tcl_GetOpenFile(interp, argv[1], TRUE, TRUE, &fp) != TCL_OK)
|
||||
return TCL_ERROR;
|
||||
/* Debug("ftp_pkg: attempt to get size of %s", argv[2]); */
|
||||
if ((sz = ftpGetSize(fp, argv[2])) >= 0) {
|
||||
/* Debug("ftp_pkg: getsize successful (%d)", sz); */
|
||||
sprintf(interp->result, "%d", sz);
|
||||
return TCL_OK;
|
||||
}
|
||||
/* Debug("ftp_pkg: chdir failed"); */
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* ftp_get fileId filename
|
||||
* -- returns new fileId for filename
|
||||
*
|
||||
*/
|
||||
int
|
||||
Ftp_get(ClientData clientData, Tcl_Interp *interp, int argc, char **argv)
|
||||
{
|
||||
FILE *fp, *fp2;
|
||||
|
||||
CHECK_ARGS(2, argv[0], "fileId filename");
|
||||
if (Tcl_GetOpenFile(interp, argv[1], TRUE, TRUE, &fp) != TCL_OK)
|
||||
return TCL_ERROR;
|
||||
/* Debug("ftp_pkg: attempt to get file %s", argv[2]); */
|
||||
fp2 = ftpGet(fp, argv[2]);
|
||||
if (fp2) {
|
||||
/* Debug("ftp_pkg: get operation successful for: %s", argv[2]); */
|
||||
Tcl_EnterFile(interp, fp2, TCL_FILE_READABLE);
|
||||
return TCL_OK;
|
||||
}
|
||||
/* Debug("ftp_pkg: get operation failed for file %s", argv[2]); */
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* ftp_put fileId filename
|
||||
* -- returns new fileId for filename
|
||||
*
|
||||
*/
|
||||
int
|
||||
Ftp_put(ClientData clientData, Tcl_Interp *interp, int argc, char **argv)
|
||||
{
|
||||
FILE *fp, *fp2;
|
||||
|
||||
CHECK_ARGS(2, argv[0], "fileId filename");
|
||||
if (Tcl_GetOpenFile(interp, argv[1], TRUE, TRUE, &fp) != TCL_OK)
|
||||
return TCL_ERROR;
|
||||
/* Debug("ftp_pkg: attempt to put file %s", argv[2]); */
|
||||
fp2 = ftpPut(fp, argv[2]);
|
||||
if (fp2) {
|
||||
/* Debug("ftp_pkg: put operation successful for: %s", argv[2]); */
|
||||
Tcl_EnterFile(interp, fp2, TCL_FILE_READABLE);
|
||||
return TCL_OK;
|
||||
}
|
||||
/* Debug("ftp_pkg: put operation failed for file %s", argv[2]); */
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* ftp_binary fileId value
|
||||
* -- Set binary mode to truth value for FTP session represented by fileId
|
||||
*
|
||||
*/
|
||||
int
|
||||
Ftp_binary(ClientData clientData, Tcl_Interp *interp, int argc, char **argv)
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
CHECK_ARGS(1, argv[0], "fileId");
|
||||
if (Tcl_GetOpenFile(interp, argv[1], TRUE, TRUE, &fp) != TCL_OK)
|
||||
return TCL_ERROR;
|
||||
/* Debug("ftp_pkg: set binary mode"); */
|
||||
ftpBinary(fp);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* ftp_passive fileId value
|
||||
* -- Set passive mode to truth value for FTP session represented by fileId
|
||||
*
|
||||
*/
|
||||
int
|
||||
Ftp_passive(ClientData clientData, Tcl_Interp *interp, int argc, char **argv)
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
CHECK_ARGS(2, argv[0], "fileId bool");
|
||||
if (Tcl_GetOpenFile(interp, argv[1], TRUE, TRUE, &fp) != TCL_OK)
|
||||
return TCL_ERROR;
|
||||
/* Debug("ftp_pkg: set passive mode to %d", atoi(argv[2])); */
|
||||
ftpPassive(fp, atoi(argv[2]));
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* ftp_get_url URL user pass
|
||||
* -- Return new fileId for open URL (using user and pass to log in)
|
||||
*
|
||||
*/
|
||||
int
|
||||
Ftp_get_url(ClientData clientData, Tcl_Interp *interp, int argc, char **argv)
|
||||
{
|
||||
FILE *fp;
|
||||
char *user, *pass;
|
||||
|
||||
CHECK_ARGS(1, argv[0], "URL [username] [password]");
|
||||
user = (argc > 2) ? argv[2] : "ftp";
|
||||
pass = (argc > 3) ? argv[3] : "setup@";
|
||||
/* Debug("ftp_pkg: attempt to get URL %s as %s/%s", argv[1], user, pass); */
|
||||
fp = ftpGetURL(argv[1], user, pass);
|
||||
if (fp) {
|
||||
/* Debug("ftp_pkg: get URL successful"); */
|
||||
Tcl_EnterFile(interp, fp, TCL_FILE_READABLE);
|
||||
return TCL_OK;
|
||||
}
|
||||
/* Debug("ftp_pkg: get URL failed"); */
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* ftp_put_url URL user pass
|
||||
* -- Return new fileId for open url (using user and pass to log in)
|
||||
*
|
||||
*/
|
||||
int
|
||||
Ftp_put_url(ClientData clientData, Tcl_Interp *interp, int argc, char **argv)
|
||||
{
|
||||
FILE *fp;
|
||||
char *user, *pass;
|
||||
|
||||
CHECK_ARGS(1, argv[0], "URL [username] [password]");
|
||||
user = (argc > 2) ? argv[2] : "ftp";
|
||||
pass = (argc > 3) ? argv[3] : "setup@";
|
||||
/* Debug("ftp_pkg: attempt to put URL %s as %s/%s", argv[1], user, pass); */
|
||||
fp = ftpPutURL(argv[1], user, pass);
|
||||
if (fp) {
|
||||
/* Debug("ftp_pkg: put URL successful"); */
|
||||
Tcl_EnterFile(interp, fp, TCL_FILE_READABLE);
|
||||
return TCL_OK;
|
||||
}
|
||||
/* Debug("ftp_pkg: put URL failed"); */
|
||||
return TCL_ERROR;
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
#ifndef _FTP_PKG_H
|
||||
#define _FTP_PKG_H
|
||||
|
||||
/*
|
||||
* Copyright (c)1995, 1996 Jordan Hubbard
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code may be used, modified, copied, distributed, and
|
||||
* sold, in both source and binary form provided that the above
|
||||
* copyright and these terms are retained, verbatim, as the first
|
||||
* lines of this file. Under no circumstances is the author
|
||||
* responsible for the proper functioning of the software nor does
|
||||
* the author assume any responsibility for damages incurred with
|
||||
* its use.
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* TCL Interface code for functions provided by the ftp library.
|
||||
*/
|
||||
|
||||
#include <tcl.h>
|
||||
#include <ftpio.h>
|
||||
|
||||
extern int Ftp_login (ClientData clientData, Tcl_Interp *interp, int argc, char **argv);
|
||||
extern int Ftp_chdir (ClientData clientData, Tcl_Interp *interp, int argc, char **argv);
|
||||
extern int Ftp_getsize (ClientData clientData, Tcl_Interp *interp, int argc, char **argv);
|
||||
extern int Ftp_get (ClientData clientData, Tcl_Interp *interp, int argc, char **argv);
|
||||
extern int Ftp_put (ClientData clientData, Tcl_Interp *interp, int argc, char **argv);
|
||||
extern int Ftp_binary (ClientData clientData, Tcl_Interp *interp, int argc, char **argv);
|
||||
extern int Ftp_passive (ClientData clientData, Tcl_Interp *interp, int argc, char **argv);
|
||||
extern int Ftp_get_url (ClientData clientData, Tcl_Interp *interp, int argc, char **argv);
|
||||
extern int Ftp_put_url (ClientData clientData, Tcl_Interp *interp, int argc, char **argv);
|
||||
|
||||
#endif /* _FTP_PKG_H */
|
||||
+19
-14
@@ -22,6 +22,7 @@
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" $Id$
|
||||
.\"
|
||||
.Dd June 17, 1996
|
||||
.Dt ftpio 3
|
||||
@@ -43,11 +44,13 @@
|
||||
.Sh SYNOPSIS
|
||||
.Fd #include <ftpio.h>
|
||||
.Ft FILE *
|
||||
.Fn ftpLogin "char *host, char *user, char *passwd, int ftp_port"
|
||||
.Fn ftpLogin "char *host" "char *user" "char *passwd" "int ftp_port" "int verbose" "int *retcode"
|
||||
.Ft int
|
||||
.Fn ftpChdir "FILE *stream, char *dirname"
|
||||
.Ft int
|
||||
.Fn ftpErrno "FILE *stream"
|
||||
.Ft const char *
|
||||
.Fn ftpErrString "int errno"
|
||||
.Ft time_t
|
||||
.Fn ftpGetModtime "FILE *stream, char *file"
|
||||
.Ft size_t
|
||||
@@ -65,9 +68,9 @@
|
||||
.Ft void
|
||||
.Fn ftpVerbose "FILE *stream, int status"
|
||||
.Ft FILE *
|
||||
.Fn ftpGetURL "char *url, char *user, char *passwd"
|
||||
.Fn ftpGetURL "char *url, char *user, char *passwd, int *retcode"
|
||||
.Ft FILE *
|
||||
.Fn ftpPutURL "char *url, char *user, char *passwd"
|
||||
.Fn ftpPutURL "char *url, char *user, char *passwd, int *retcode"
|
||||
|
||||
.Sh DESCRIPTION
|
||||
These functions implement a high-level library for managing FTP connections.
|
||||
@@ -75,25 +78,28 @@ These functions implement a high-level library for managing FTP connections.
|
||||
.Fn ftpLogin
|
||||
attempts to log in using the supplied
|
||||
.Fa user ,
|
||||
.Fa passwd
|
||||
and
|
||||
.Fa passwd,
|
||||
.Fa ftp_port
|
||||
fields (if passed as 0,
|
||||
(if passed as 0,
|
||||
.Fa ftp_port
|
||||
defaults to the standard ftp port of 21). If it is successful, a
|
||||
defaults to the standard ftp port of 21) and
|
||||
.Fa verbose
|
||||
fields. If it is successful, a
|
||||
standard stream descriptor is returned which should be passed to
|
||||
subsequent FTP operations. On failure, NULL is returned and
|
||||
.Fn ftpErrno
|
||||
will return the error code returned by the foreign server.
|
||||
.Fa retcode
|
||||
will have the error code returned by the foreign server.
|
||||
.Pp
|
||||
.Fn ftpChdir
|
||||
attempts to issue a server CD command to the the directory named in
|
||||
attempts to issue a server CD command to the directory named in
|
||||
.Fa dir.
|
||||
On success, zero is returned. On failure, the error code from the server.
|
||||
.Pp
|
||||
.Fn ftpErrno
|
||||
returns the server failure code for the last operation (useful for seeing
|
||||
more about what happened if you're familiar with FTP error codes).
|
||||
.Fn ftpErrString
|
||||
returns a human readable version of the supplied server failure code.
|
||||
.Pp
|
||||
.Fn ftpGet
|
||||
attempts to retreive the file named by the
|
||||
@@ -108,7 +114,7 @@ as a restart point for the file, that is to say that the stream
|
||||
returned will point
|
||||
.Fa *seekto
|
||||
bytes into the file gotten (this is handy for restarting failed
|
||||
transfers efficiently). If the seek operation succeeds, the value
|
||||
transfers efficiently). If the seek operation fails, the value
|
||||
of
|
||||
.Fa *seekto
|
||||
will be zero'd.
|
||||
@@ -186,8 +192,7 @@ all my tests.
|
||||
.Sh HISTORY
|
||||
Started life as Poul-Henning Kamp's ftp driver for the system installation
|
||||
utility, later significantly mutated into a more general form as an
|
||||
extension of stdio and given a TCL interface (not enabled by default)
|
||||
by Jordan Hubbard. Also incorporates some ideas and extensions from
|
||||
Jean-Marc Zucconi.
|
||||
extension of stdio by Jordan Hubbard. Also incorporates some ideas and
|
||||
extensions from Jean-Marc Zucconi.
|
||||
.Sh AUTHORS
|
||||
Jordan Hubbard, Poul-Henning Kamp and Jean-Marc Zucconi
|
||||
+209
-81
@@ -14,26 +14,27 @@
|
||||
* Turned inside out. Now returns xfers as new file ids, not as a special
|
||||
* `state' of FTP_t
|
||||
*
|
||||
* $Id: ftpio.c,v 1.4.2.2 1996/06/24 02:30:36 jkh Exp $
|
||||
* $Id: ftpio.c,v 1.4.2.3 1996/07/04 05:47:30 jkh Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <netdb.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/signal.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <ftpio.h>
|
||||
#include <netdb.h>
|
||||
#include <signal.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define SUCCESS 0
|
||||
#define FAILURE -1
|
||||
@@ -44,7 +45,7 @@
|
||||
#endif
|
||||
|
||||
/* How to see by a given code whether or not the connection has timed out */
|
||||
#define FTP_TIMEOUT(code) (code == 421)
|
||||
#define FTP_TIMEOUT(code) (FtpTimedOut || code == FTP_TIMED_OUT)
|
||||
|
||||
/* Internal routines - deal only with internal FTP_t type */
|
||||
static FTP_t ftp_new(void);
|
||||
@@ -57,23 +58,32 @@ static __inline char *get_a_line(FTP_t ftp);
|
||||
static int get_a_number(FTP_t ftp, char **q);
|
||||
static int botch(char *func, char *botch_state);
|
||||
static int cmd(FTP_t ftp, const char *fmt, ...);
|
||||
static int ftp_login_session(FTP_t ftp, char *host, char *user, char *passwd, int port);
|
||||
static int ftp_file_op(FTP_t ftp, char *operation, char *file, FILE **fp, char *mode, int *seekto);
|
||||
static int ftp_login_session(FTP_t ftp, char *host, char *user, char *passwd, int port, int verbose);
|
||||
static int ftp_file_op(FTP_t ftp, char *operation, char *file, FILE **fp, char *mode, off_t *seekto);
|
||||
static int ftp_close(FTP_t ftp);
|
||||
static int get_url_info(char *url_in, char *host_ret, int *port_ret, char *name_ret);
|
||||
static void ftp_timeout(int sig);
|
||||
static void ftp_set_timeout(void);
|
||||
static void ftp_clear_timeout(void);
|
||||
|
||||
|
||||
/* Global status variable - ick */
|
||||
int FtpTimedOut;
|
||||
|
||||
/* FTP status codes */
|
||||
#define FTP_ASCII_HAPPY 200
|
||||
#define FTP_BINARY_HAPPY 200
|
||||
#define FTP_PORT_HAPPY 200
|
||||
/* FTP happy status codes */
|
||||
#define FTP_GENERALLY_HAPPY 200
|
||||
#define FTP_ASCII_HAPPY FTP_GENERALLY_HAPPY
|
||||
#define FTP_BINARY_HAPPY FTP_GENERALLY_HAPPY
|
||||
#define FTP_PORT_HAPPY FTP_GENERALLY_HAPPY
|
||||
#define FTP_HAPPY_COMMENT 220
|
||||
#define FTP_QUIT_HAPPY 221
|
||||
#define FTP_TRANSFER_HAPPY 226
|
||||
#define FTP_PASSIVE_HAPPY 227
|
||||
#define FTP_CHDIR_HAPPY 250
|
||||
|
||||
/* FTP unhappy status codes */
|
||||
#define FTP_TIMED_OUT 421
|
||||
|
||||
/*
|
||||
* XXX
|
||||
* gross! evil! bad! We really need an access primitive for cookie in stdio itself.
|
||||
@@ -97,11 +107,11 @@ check_code(FTP_t ftp, int var, int preferred)
|
||||
while (1) {
|
||||
if (var == preferred)
|
||||
return 0;
|
||||
else if (var == 226) /* last operation succeeded */
|
||||
else if (var == FTP_TRANSFER_HAPPY) /* last operation succeeded */
|
||||
var = get_a_number(ftp, NULL);
|
||||
else if (var == 220) /* chit-chat */
|
||||
else if (var == FTP_HAPPY_COMMENT) /* chit-chat */
|
||||
var = get_a_number(ftp, NULL);
|
||||
else if (var == 200) /* success codes */
|
||||
else if (var == FTP_GENERALLY_HAPPY) /* general success code */
|
||||
var = get_a_number(ftp, NULL);
|
||||
else {
|
||||
ftp->errno = var;
|
||||
@@ -165,22 +175,42 @@ ftpErrno(FILE *fp)
|
||||
return ftp->errno;
|
||||
}
|
||||
|
||||
size_t
|
||||
const char *
|
||||
ftpErrString(int errno)
|
||||
{
|
||||
int k;
|
||||
|
||||
if (errno == -1)
|
||||
return("connection in wrong state");
|
||||
for (k = 0; k < ftpErrListLength; k++)
|
||||
if (ftpErrList[k].num == errno)
|
||||
return(ftpErrList[k].string);
|
||||
return("Unknown error");
|
||||
}
|
||||
|
||||
off_t
|
||||
ftpGetSize(FILE *fp, char *name)
|
||||
{
|
||||
int i;
|
||||
char p[BUFSIZ], *cp;
|
||||
char p[BUFSIZ], *cp, *ep;
|
||||
FTP_t ftp = fcookie(fp);
|
||||
off_t size;
|
||||
|
||||
check_passive(fp);
|
||||
sprintf(p, "SIZE %s\r\n", name);
|
||||
i = writes(ftp->fd_ctrl, p);
|
||||
if (i)
|
||||
return (size_t)-1;
|
||||
if (ftp->is_verbose)
|
||||
fprintf(stderr, "Sending %s", p);
|
||||
if (writes(ftp->fd_ctrl, p))
|
||||
return (off_t)-1;
|
||||
i = get_a_number(ftp, &cp);
|
||||
if (check_code(ftp, i, 213))
|
||||
return (size_t)-1;
|
||||
return (size_t)atoi(cp);
|
||||
return (off_t)-1;
|
||||
|
||||
errno = 0; /* to check for ERANGE */
|
||||
size = (off_t)strtoq(cp, &ep, 10);
|
||||
if (*ep != '\0' || errno == ERANGE)
|
||||
return (off_t)-1;
|
||||
return size;
|
||||
}
|
||||
|
||||
time_t
|
||||
@@ -194,8 +224,9 @@ ftpGetModtime(FILE *fp, char *name)
|
||||
|
||||
check_passive(fp);
|
||||
sprintf(p, "MDTM %s\r\n", name);
|
||||
i = writes(ftp->fd_ctrl, p);
|
||||
if (i)
|
||||
if (ftp->is_verbose)
|
||||
fprintf(stderr, "Sending %s", p);
|
||||
if (writes(ftp->fd_ctrl, p))
|
||||
return (time_t)0;
|
||||
i = get_a_number(ftp, &cp);
|
||||
if (check_code(ftp, i, 213))
|
||||
@@ -215,7 +246,7 @@ ftpGetModtime(FILE *fp, char *name)
|
||||
}
|
||||
|
||||
FILE *
|
||||
ftpGet(FILE *fp, char *file, int *seekto)
|
||||
ftpGet(FILE *fp, char *file, off_t *seekto)
|
||||
{
|
||||
FILE *fp2;
|
||||
FTP_t ftp = fcookie(fp);
|
||||
@@ -231,20 +262,40 @@ ftpGet(FILE *fp, char *file, int *seekto)
|
||||
|
||||
/* Returns a standard FILE pointer type representing an open control connection */
|
||||
FILE *
|
||||
ftpLogin(char *host, char *user, char *passwd, int port)
|
||||
ftpLogin(char *host, char *user, char *passwd, int port, int verbose, int *retcode)
|
||||
{
|
||||
FTP_t n;
|
||||
FILE *fp;
|
||||
|
||||
if (retcode)
|
||||
*retcode = 0;
|
||||
if (networkInit() != SUCCESS)
|
||||
return NULL;
|
||||
|
||||
n = ftp_new();
|
||||
fp = NULL;
|
||||
if (n && ftp_login_session(n, host, user, passwd, port) == SUCCESS) {
|
||||
if (n && ftp_login_session(n, host, user, passwd, port, verbose) == SUCCESS) {
|
||||
fp = funopen(n, ftp_read_method, ftp_write_method, NULL, ftp_close_method); /* BSD 4.4 function! */
|
||||
fp->_file = n->fd_ctrl;
|
||||
}
|
||||
if (retcode) {
|
||||
if (!n)
|
||||
*retcode = (FtpTimedOut ? FTP_TIMED_OUT : -1);
|
||||
/* Poor attempt at mapping real errnos to FTP error codes */
|
||||
else switch(n->errno) {
|
||||
case EADDRNOTAVAIL:
|
||||
*retcode = FTP_TIMED_OUT; /* Actually no such host, but we have no way of saying that. :-( */
|
||||
break;
|
||||
|
||||
case ETIMEDOUT:
|
||||
*retcode = FTP_TIMED_OUT;
|
||||
break;
|
||||
|
||||
default:
|
||||
*retcode = n->errno;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return fp;
|
||||
}
|
||||
|
||||
@@ -269,7 +320,7 @@ ftpPassive(FILE *fp, int st)
|
||||
|
||||
if (ftp->is_passive == st)
|
||||
return SUCCESS;
|
||||
i = cmd(ftp, "PASSIVE");
|
||||
i = cmd(ftp, "PASV");
|
||||
if (i < 0)
|
||||
return i;
|
||||
ftp->is_passive = !ftp->is_passive;
|
||||
@@ -277,21 +328,49 @@ ftpPassive(FILE *fp, int st)
|
||||
}
|
||||
|
||||
FILE *
|
||||
ftpGetURL(char *url, char *user, char *passwd)
|
||||
ftpGetURL(char *url, char *user, char *passwd, int *retcode)
|
||||
{
|
||||
char host[255], name[255];
|
||||
int port;
|
||||
static FILE *fp = NULL;
|
||||
FILE *fp2;
|
||||
static FILE *fp = NULL;
|
||||
static char *prev_host;
|
||||
|
||||
if (fp) { /* Close previous managed connection */
|
||||
fclose(fp);
|
||||
fp = NULL;
|
||||
}
|
||||
if (retcode)
|
||||
*retcode = 0;
|
||||
if (get_url_info(url, host, &port, name) == SUCCESS) {
|
||||
fp = ftpLogin(host, user, passwd, port);
|
||||
if (fp && prev_host) {
|
||||
if (!strcmp(prev_host, host)) {
|
||||
/* Try to use cached connection */
|
||||
fp2 = ftpGet(fp, name, NULL);
|
||||
if (!fp2) {
|
||||
/* Connection timed out or was no longer valid */
|
||||
fclose(fp);
|
||||
free(prev_host);
|
||||
prev_host = NULL;
|
||||
}
|
||||
else
|
||||
return fp2;
|
||||
}
|
||||
else {
|
||||
/* It's a different host now, flush old */
|
||||
fclose(fp);
|
||||
free(prev_host);
|
||||
prev_host = NULL;
|
||||
}
|
||||
}
|
||||
fp = ftpLogin(host, user, passwd, port, 0, retcode);
|
||||
if (fp) {
|
||||
fp2 = ftpGet(fp, name, NULL);
|
||||
if (!fp2) {
|
||||
/* Connection timed out or was no longer valid */
|
||||
if (retcode)
|
||||
*retcode = ftpErrno(fp);
|
||||
fclose(fp);
|
||||
fp = NULL;
|
||||
}
|
||||
else
|
||||
prev_host = strdup(host);
|
||||
return fp2;
|
||||
}
|
||||
}
|
||||
@@ -299,21 +378,29 @@ ftpGetURL(char *url, char *user, char *passwd)
|
||||
}
|
||||
|
||||
FILE *
|
||||
ftpPutURL(char *url, char *user, char *passwd)
|
||||
ftpPutURL(char *url, char *user, char *passwd, int *retcode)
|
||||
{
|
||||
char host[255], name[255];
|
||||
int port;
|
||||
static FILE *fp = NULL;
|
||||
FILE *fp2;
|
||||
|
||||
if (retcode)
|
||||
*retcode = 0;
|
||||
if (fp) { /* Close previous managed connection */
|
||||
fclose(fp);
|
||||
fp = NULL;
|
||||
}
|
||||
if (get_url_info(url, host, &port, name) == SUCCESS) {
|
||||
fp = ftpLogin(host, user, passwd, port);
|
||||
fp = ftpLogin(host, user, passwd, port, 0, retcode);
|
||||
if (fp) {
|
||||
fp2 = ftpPut(fp, name);
|
||||
if (!fp2) {
|
||||
if (retcode)
|
||||
*retcode = ftpErrno(fp);
|
||||
fclose(fp);
|
||||
fp = NULL;
|
||||
}
|
||||
return fp2;
|
||||
}
|
||||
}
|
||||
@@ -411,27 +498,48 @@ check_passive(FILE *fp)
|
||||
}
|
||||
|
||||
static void
|
||||
ftp_timeout()
|
||||
ftp_timeout(int sig)
|
||||
{
|
||||
FtpTimedOut = TRUE;
|
||||
/* Debug("ftp_pkg: ftp_timeout called - operation timed out"); */
|
||||
}
|
||||
|
||||
static struct sigaction new;
|
||||
|
||||
static void
|
||||
ftp_set_timeout(void)
|
||||
{
|
||||
char *cp;
|
||||
int ival;
|
||||
|
||||
FtpTimedOut = FALSE;
|
||||
new.sa_handler = ftp_timeout;
|
||||
sigaction(SIGALRM, &new, NULL);
|
||||
cp = getenv("FTP_TIMEOUT");
|
||||
if (!cp || !(ival = atoi(cp)))
|
||||
ival = 120;
|
||||
alarm(ival);
|
||||
}
|
||||
|
||||
static void
|
||||
ftp_clear_timeout(void)
|
||||
{
|
||||
alarm(0);
|
||||
new.sa_handler = SIG_DFL;
|
||||
sigaction(SIGALRM, &new, NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
writes(int fd, char *s)
|
||||
{
|
||||
int n, i = strlen(s);
|
||||
|
||||
/* Set the timer */
|
||||
FtpTimedOut = FALSE;
|
||||
signal(SIGALRM, ftp_timeout);
|
||||
alarm(120);
|
||||
/* Debug("ftp_pkg: writing \"%s\" to ftp connection %d", s, fd); */
|
||||
ftp_set_timeout();
|
||||
n = write(fd, s, i);
|
||||
alarm(0);
|
||||
if (i != n)
|
||||
return FAILURE;
|
||||
return SUCCESS;
|
||||
ftp_clear_timeout();
|
||||
if (FtpTimedOut || i != n)
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static __inline char *
|
||||
@@ -440,23 +548,19 @@ get_a_line(FTP_t ftp)
|
||||
static char buf[BUFSIZ];
|
||||
int i,j;
|
||||
|
||||
/* Set the timer */
|
||||
FtpTimedOut = FALSE;
|
||||
signal(SIGALRM, ftp_timeout);
|
||||
|
||||
/* Debug("ftp_pkg: trying to read a line from %d", ftp->fd_ctrl); */
|
||||
for(i = 0; i < BUFSIZ;) {
|
||||
alarm(120);
|
||||
ftp_set_timeout();
|
||||
j = read(ftp->fd_ctrl, buf + i, 1);
|
||||
alarm(0);
|
||||
if (j != 1)
|
||||
ftp_clear_timeout();
|
||||
if (FtpTimedOut || j != 1)
|
||||
return NULL;
|
||||
if (buf[i] == '\r' || buf[i] == '\n') {
|
||||
if (!i)
|
||||
continue;
|
||||
buf[i] = '\0';
|
||||
if (ftp->is_verbose == TRUE)
|
||||
printf("%s\n",buf+4);
|
||||
fprintf(stderr, "%s\n",buf+4);
|
||||
return buf;
|
||||
}
|
||||
i++;
|
||||
@@ -475,6 +579,8 @@ get_a_number(FTP_t ftp, char **q)
|
||||
p = get_a_line(ftp);
|
||||
if (!p) {
|
||||
ftp_close(ftp);
|
||||
if (FtpTimedOut)
|
||||
return FTP_TIMED_OUT;
|
||||
return FAILURE;
|
||||
}
|
||||
if (!(isdigit(p[0]) && isdigit(p[1]) && isdigit(p[2])))
|
||||
@@ -504,11 +610,14 @@ ftp_close(FTP_t ftp)
|
||||
int i;
|
||||
|
||||
if (ftp->con_state == isopen) {
|
||||
/* Debug("ftp_pkg: in ftp_close(), sending QUIT"); */
|
||||
i = cmd(ftp, "QUIT");
|
||||
ftp->con_state = quit;
|
||||
/* If last operation timed out, don't try to quit - just close */
|
||||
if (ftp->errno != FTP_TIMED_OUT)
|
||||
i = cmd(ftp, "QUIT");
|
||||
else
|
||||
i = FTP_QUIT_HAPPY;
|
||||
close(ftp->fd_ctrl);
|
||||
ftp->fd_ctrl = -1;
|
||||
ftp->con_state = init;
|
||||
if (check_code(ftp, i, FTP_QUIT_HAPPY)) {
|
||||
ftp->errno = i;
|
||||
return FAILURE;
|
||||
@@ -538,19 +647,23 @@ cmd(FTP_t ftp, const char *fmt, ...)
|
||||
(void)vsnprintf(p, sizeof p, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (ftp->con_state != isopen)
|
||||
if (ftp->con_state == init)
|
||||
return botch("cmd", "open");
|
||||
|
||||
strcat(p, "\r\n");
|
||||
i = writes(ftp->fd_ctrl, p);
|
||||
if (i)
|
||||
if (ftp->is_verbose)
|
||||
fprintf(stderr, "Sending: %s", p);
|
||||
if (writes(ftp->fd_ctrl, p)) {
|
||||
if (FtpTimedOut)
|
||||
return FTP_TIMED_OUT;
|
||||
return FAILURE;
|
||||
while ((i = get_a_number(ftp, NULL)) == 220);
|
||||
}
|
||||
while ((i = get_a_number(ftp, NULL)) == FTP_HAPPY_COMMENT);
|
||||
return i;
|
||||
}
|
||||
|
||||
static int
|
||||
ftp_login_session(FTP_t ftp, char *host, char *user, char *passwd, int port)
|
||||
ftp_login_session(FTP_t ftp, char *host, char *user, char *passwd, int port, int verbose)
|
||||
{
|
||||
struct hostent *he = NULL;
|
||||
struct sockaddr_in sin;
|
||||
@@ -563,6 +676,7 @@ ftp_login_session(FTP_t ftp, char *host, char *user, char *passwd, int port)
|
||||
|
||||
if (ftp->con_state != init) {
|
||||
ftp_close(ftp);
|
||||
ftp->errno = -1;
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
@@ -582,37 +696,45 @@ ftp_login_session(FTP_t ftp, char *host, char *user, char *passwd, int port)
|
||||
}
|
||||
else {
|
||||
he = gethostbyname(host);
|
||||
if (!he)
|
||||
if (!he) {
|
||||
ftp->errno = 0;
|
||||
return FAILURE;
|
||||
}
|
||||
ftp->addrtype = sin.sin_family = he->h_addrtype;
|
||||
bcopy(he->h_addr, (char *)&sin.sin_addr, he->h_length);
|
||||
}
|
||||
|
||||
sin.sin_port = htons(port);
|
||||
|
||||
if ((s = socket(ftp->addrtype, SOCK_STREAM, 0)) < 0)
|
||||
if ((s = socket(ftp->addrtype, SOCK_STREAM, 0)) < 0) {
|
||||
ftp->errno = -1;
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
|
||||
(void)close(s);
|
||||
ftp->errno = errno;
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
ftp->fd_ctrl = s;
|
||||
ftp->con_state = isopen;
|
||||
ftp->is_verbose = verbose;
|
||||
|
||||
i = cmd(ftp, "USER %s", user);
|
||||
if (i >= 300 && i < 400)
|
||||
i = cmd(ftp, "PASS %s", passwd);
|
||||
if (i >= 299 || i < 0) {
|
||||
ftp_close(ftp);
|
||||
if (i > 0)
|
||||
ftp->errno = i;
|
||||
return FAILURE;
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
static int
|
||||
ftp_file_op(FTP_t ftp, char *operation, char *file, FILE **fp, char *mode, int *seekto)
|
||||
ftp_file_op(FTP_t ftp, char *operation, char *file, FILE **fp, char *mode, off_t *seekto)
|
||||
{
|
||||
int i,s;
|
||||
char *q;
|
||||
@@ -627,13 +749,19 @@ ftp_file_op(FTP_t ftp, char *operation, char *file, FILE **fp, char *mode, int *
|
||||
if (ftp->con_state != isopen)
|
||||
return botch("ftp_file_op", "open");
|
||||
|
||||
if ((s = socket(ftp->addrtype, SOCK_STREAM, 0)) < 0)
|
||||
if ((s = socket(ftp->addrtype, SOCK_STREAM, 0)) < 0) {
|
||||
ftp->errno = errno;
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
if (ftp->is_passive) {
|
||||
if (ftp->is_verbose)
|
||||
fprintf(stderr, "Sending PASV\n");
|
||||
if (writes(ftp->fd_ctrl, "PASV\r\n")) {
|
||||
ftp_close(ftp);
|
||||
return FAILURE;
|
||||
if (FtpTimedOut)
|
||||
ftp->errno = FTP_TIMED_OUT;
|
||||
return FTP_TIMED_OUT;
|
||||
}
|
||||
i = get_a_number(ftp, &q);
|
||||
if (check_code(ftp, i, FTP_PASSIVE_HAPPY)) {
|
||||
@@ -659,15 +787,15 @@ ftp_file_op(FTP_t ftp, char *operation, char *file, FILE **fp, char *mode, int *
|
||||
(void)close(s);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
if (seekto && *seekto) {
|
||||
i = cmd(ftp, "RETR %d", *seekto);
|
||||
i = cmd(ftp, "REST %d", *seekto);
|
||||
if (i < 0 || FTP_TIMEOUT(i)) {
|
||||
close(s);
|
||||
ftp->errno = i;
|
||||
*seekto = (off_t)0;
|
||||
return i;
|
||||
}
|
||||
else if (i != 350)
|
||||
*seekto = 0;
|
||||
}
|
||||
i = cmd(ftp, "%s %s", operation, file);
|
||||
if (i < 0 || i > 299) {
|
||||
@@ -685,7 +813,7 @@ ftp_file_op(FTP_t ftp, char *operation, char *file, FILE **fp, char *mode, int *
|
||||
sin.sin_port = 0;
|
||||
i = sizeof sin;
|
||||
if (bind(s, (struct sockaddr *)&sin, i) < 0) {
|
||||
close (s);
|
||||
close(s);
|
||||
return FAILURE;
|
||||
}
|
||||
getsockname(s,(struct sockaddr *)&sin,&i);
|
||||
@@ -706,14 +834,14 @@ ftp_file_op(FTP_t ftp, char *operation, char *file, FILE **fp, char *mode, int *
|
||||
return i;
|
||||
}
|
||||
if (seekto && *seekto) {
|
||||
i = cmd(ftp, "RETR %d", *seekto);
|
||||
i = cmd(ftp, "REST %d", *seekto);
|
||||
if (i < 0 || FTP_TIMEOUT(i)) {
|
||||
close(s);
|
||||
ftp->errno = i;
|
||||
return i;
|
||||
}
|
||||
else if (i != 350)
|
||||
*seekto = 0;
|
||||
*seekto = (off_t)0;
|
||||
}
|
||||
i = cmd(ftp, "%s %s", operation, file);
|
||||
if (i < 0 || i > 299) {
|
||||
|
||||
+17
-7
@@ -2,6 +2,7 @@
|
||||
#define _FTP_H_INCLUDE
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
|
||||
/*
|
||||
@@ -20,12 +21,12 @@
|
||||
* Turned inside out. Now returns xfers as new file ids, not as a special
|
||||
* `state' of FTP_t
|
||||
*
|
||||
* $Id: ftpio.h,v 1.2.2.2 1996/06/26 20:33:57 gpalmer Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/* Internal housekeeping data structure for FTP sessions */
|
||||
typedef struct {
|
||||
enum { init, isopen } con_state;
|
||||
enum { init, isopen, quit } con_state;
|
||||
int fd_ctrl;
|
||||
int addrtype;
|
||||
char *host;
|
||||
@@ -36,19 +37,28 @@ typedef struct {
|
||||
int is_verbose;
|
||||
} *FTP_t;
|
||||
|
||||
/* Structure we use to match FTP error codes with readable strings */
|
||||
struct ftperr {
|
||||
const int num;
|
||||
const char *string;
|
||||
};
|
||||
extern struct ftperr ftpErrList[];
|
||||
extern int const ftpErrListLength;
|
||||
|
||||
/* Exported routines - deal only with FILE* type */
|
||||
extern FILE *ftpLogin(char *host, char *user, char *passwd, int port);
|
||||
extern FILE *ftpLogin(char *host, char *user, char *passwd, int port, int verbose, int *retcode);
|
||||
extern int ftpChdir(FILE *fp, char *dir);
|
||||
extern int ftpErrno(FILE *fp);
|
||||
extern size_t ftpGetSize(FILE *fp, char *file);
|
||||
extern FILE *ftpGet(FILE *fp, char *file, int *seekto);
|
||||
extern off_t ftpGetSize(FILE *fp, char *file);
|
||||
extern FILE *ftpGet(FILE *fp, char *file, off_t *seekto);
|
||||
extern FILE *ftpPut(FILE *fp, char *file);
|
||||
extern int ftpAscii(FILE *fp);
|
||||
extern int ftpBinary(FILE *fp);
|
||||
extern int ftpPassive(FILE *fp, int status);
|
||||
extern void ftpVerbose(FILE *fp, int status);
|
||||
extern FILE *ftpGetURL(char *url, char *user, char *passwd);
|
||||
extern FILE *ftpPutURL(char *url, char *user, char *passwd);
|
||||
extern FILE *ftpGetURL(char *url, char *user, char *passwd, int *retcode);
|
||||
extern FILE *ftpPutURL(char *url, char *user, char *passwd, int *retcode);
|
||||
extern time_t ftpGetModtime(FILE *fp, char *s);
|
||||
extern const char *ftpErrString(int errno);
|
||||
|
||||
#endif /* _FTP_H_INCLUDE */
|
||||
@@ -49,7 +49,6 @@ static char sccsid[] = "@(#)genget.c 8.1 (Berkeley) 6/4/93";
|
||||
isprefix(s1, s2)
|
||||
register char *s1, *s2;
|
||||
{
|
||||
register int n = 0;
|
||||
char *os1;
|
||||
register char c1, c2;
|
||||
|
||||
|
||||
@@ -35,9 +35,12 @@
|
||||
static char sccsid[] = "@(#)getent.c 8.2 (Berkeley) 12/15/93";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
static char *area;
|
||||
|
||||
/*ARGSUSED*/
|
||||
int
|
||||
getent(cp, name)
|
||||
char *cp, *name;
|
||||
{
|
||||
|
||||
@@ -35,6 +35,8 @@
|
||||
static char sccsid[] = "@(#)misc.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "misc.h"
|
||||
|
||||
char *RemoteHostName;
|
||||
|
||||
@@ -0,0 +1,239 @@
|
||||
|
||||
ChangeLog file for zlib
|
||||
|
||||
Changes in 1.0.4 (24 Jul 96)
|
||||
- In very rare conditions, deflate(s, Z_FINISH) could fail to produce an EOF
|
||||
bit, so the decompressor could decompress all the correct data but went
|
||||
on to attempt decompressing extra garbage data. This affected minigzip too.
|
||||
- zlibVersion and gzerror return const char* (needed for DLL)
|
||||
- port to RISCOS (no fdopen, no multiple dots, no unlink, no fileno)
|
||||
- use z_error only for DEBUG (avoid problem with DLLs)
|
||||
|
||||
Changes in 1.0.3 (2 Jul 96)
|
||||
- use z_streamp instead of z_stream *, which is now a far pointer in MSDOS
|
||||
small and medium models; this makes the library incompatible with previous
|
||||
versions for these models. (No effect in large model or on other systems.)
|
||||
- return OK instead of BUF_ERROR if previous deflate call returned with
|
||||
avail_out as zero but there is nothing to do
|
||||
- added memcmp for non STDC compilers
|
||||
- define NO_DUMMY_DECL for more Mac compilers (.h files merged incorrectly)
|
||||
- define __32BIT__ if __386__ or i386 is defined (pb. with Watcom and SCO)
|
||||
- better check for 16-bit mode MSC (avoids problem with Symantec)
|
||||
|
||||
Changes in 1.0.2 (23 May 96)
|
||||
- added Windows DLL support
|
||||
- added a function zlibVersion (for the DLL support)
|
||||
- fixed declarations using Bytef in infutil.c (pb with MSDOS medium model)
|
||||
- Bytef is define's instead of typedef'd only for Borland C
|
||||
- avoid reading uninitialized memory in example.c
|
||||
- mention in README that the zlib format is now RFC1950
|
||||
- updated Makefile.dj2
|
||||
- added algorithm.doc
|
||||
|
||||
Changes in 1.0.1 (20 May 96) [1.0 skipped to avoid confusion]
|
||||
- fix array overlay in deflate.c which sometimes caused bad compressed data
|
||||
- fix inflate bug with empty stored block
|
||||
- fix MSDOS medium model which was broken in 0.99
|
||||
- fix deflateParams() which could generated bad compressed data.
|
||||
- Bytef is define'd instead of typedef'ed (work around Borland bug)
|
||||
- added an INDEX file
|
||||
- new makefiles for DJGPP (Makefile.dj2), 32-bit Borland (Makefile.b32),
|
||||
Watcom (Makefile.wat), Amiga SAS/C (Makefile.sas)
|
||||
- speed up adler32 for modern machines without auto-increment
|
||||
- added -ansi for IRIX in configure
|
||||
- static_init_done in trees.c is an int
|
||||
- define unlink as delete for VMS
|
||||
- fix configure for QNX
|
||||
- add configure branch for SCO and HPUX
|
||||
- avoid many warnings (unused variables, dead assignments, etc...)
|
||||
- no fdopen for BeOS
|
||||
- fix the Watcom fix for 32 bit mode (define FAR as empty)
|
||||
- removed redefinition of Byte for MKWERKS
|
||||
- work around an MWKERKS bug (incorrect merge of all .h files)
|
||||
|
||||
Changes in 0.99 (27 Jan 96)
|
||||
- allow preset dictionary shared between compressor and decompressor
|
||||
- allow compression level 0 (no compression)
|
||||
- add deflateParams in zlib.h: allow dynamic change of compression level
|
||||
and compression strategy.
|
||||
- test large buffers and deflateParams in example.c
|
||||
- add optional "configure" to build zlib as a shared library
|
||||
- suppress Makefile.qnx, use configure instead
|
||||
- fixed deflate for 64-bit systems (detected on Cray)
|
||||
- fixed inflate_blocks for 64-bit systems (detected on Alpha)
|
||||
- declare Z_DEFLATED in zlib.h (possible parameter for deflateInit2)
|
||||
- always return Z_BUF_ERROR when deflate() has nothing to do
|
||||
- deflateInit and inflateInit are now macros to allow version checking
|
||||
- prefix all global functions and types with z_ with -DZ_PREFIX
|
||||
- make falloc completely reentrant (inftrees.c)
|
||||
- fixed very unlikely race condition in ct_static_init
|
||||
- free in reverse order of allocation to help memory manager
|
||||
- use zlib-1.0/* instead of zlib/* inside the tar.gz
|
||||
- make zlib warning-free with "gcc -O3 -Wall -Wwrite-strings -Wpointer-arith
|
||||
-Wconversion -Wstrict-prototypes -Wmissing-prototypes"
|
||||
- allow gzread on concatenated .gz files
|
||||
- deflateEnd now returns Z_DATA_ERROR if it was premature
|
||||
- deflate is finally (?) fully deterministic (no matches beyond end of input)
|
||||
- Document Z_SYNC_FLUSH
|
||||
- add uninstall in Makefile
|
||||
- Check for __cpluplus in zlib.h
|
||||
- Better test in ct_align for partial flush
|
||||
- avoid harmless warnings for Borland C++
|
||||
- initialize hash_head in deflate.c
|
||||
- avoid warning on fdopen (gzio.c) for HP cc -Aa
|
||||
- include stdlib.h for STDC compilers
|
||||
- include errno.h for Cray
|
||||
- ignore error if ranlib doesn't exist
|
||||
- call ranlib twice for NeXTSTEP
|
||||
- use exec_prefix instead of prefix for libz.a
|
||||
- renamed ct_* as _tr_* to avoid conflict with applications
|
||||
- clear z->msg in inflateInit2 before any error return
|
||||
- initialize opaque in example.c, gzio.c, deflate.c and inflate.c
|
||||
- fixed typo in zconf.h (_GNUC__ => __GNUC__)
|
||||
- check for WIN32 in zconf.h and zutil.c (avoid farmalloc in 32-bit mode)
|
||||
- fix typo in Make_vms.com (f$trnlnm -> f$getsyi)
|
||||
- in fcalloc, normalize pointer if size > 65520 bytes
|
||||
- don't use special fcalloc for 32 bit Borland C++
|
||||
- use STDC instead of __GO32__ to avoid redeclaring exit, calloc, etc...
|
||||
- use Z_BINARY instead of BINARY
|
||||
- document that gzclose after gzdopen will close the file
|
||||
- allow "a" as mode in gzopen.
|
||||
- fix error checking in gzread
|
||||
- allow skipping .gz extra-field on pipes
|
||||
- added reference to Perl interface in README
|
||||
- put the crc table in FAR data (I dislike more and more the medium model :)
|
||||
- added get_crc_table
|
||||
- added a dimension to all arrays (Borland C can't count).
|
||||
- workaround Borland C bug in declaration of inflate_codes_new & inflate_fast
|
||||
- guard against multiple inclusion of *.h (for precompiled header on Mac)
|
||||
- Watcom C pretends to be Microsoft C small model even in 32 bit mode.
|
||||
- don't use unsized arrays to avoid silly warnings by Visual C++:
|
||||
warning C4746: 'inflate_mask' : unsized array treated as '__far'
|
||||
(what's wrong with far data in far model?).
|
||||
- define enum out of inflate_blocks_state to allow compilation with C++
|
||||
|
||||
Changes in 0.95 (16 Aug 95)
|
||||
- fix MSDOS small and medium model (now easier to adapt to any compiler)
|
||||
- inlined send_bits
|
||||
- fix the final (:-) bug for deflate with flush (output was correct but
|
||||
not completely flushed in rare occasions).
|
||||
- default window size is same for compression and decompression
|
||||
(it's now sufficient to set MAX_WBITS in zconf.h).
|
||||
- voidp -> voidpf and voidnp -> voidp (for consistency with other
|
||||
typedefs and because voidnp was not near in large model).
|
||||
|
||||
Changes in 0.94 (13 Aug 95)
|
||||
- support MSDOS medium model
|
||||
- fix deflate with flush (could sometimes generate bad output)
|
||||
- fix deflateReset (zlib header was incorrectly suppressed)
|
||||
- added support for VMS
|
||||
- allow a compression level in gzopen()
|
||||
- gzflush now calls fflush
|
||||
- For deflate with flush, flush even if no more input is provided.
|
||||
- rename libgz.a as libz.a
|
||||
- avoid complex expression in infcodes.c triggering Turbo C bug
|
||||
- work around a problem with gcc on Alpha (in INSERT_STRING)
|
||||
- don't use inline functions (problem with some gcc versions)
|
||||
- allow renaming of Byte, uInt, etc... with #define.
|
||||
- avoid warning about (unused) pointer before start of array in deflate.c
|
||||
- avoid various warnings in gzio.c, example.c, infblock.c, adler32.c, zutil.c
|
||||
- avoid reserved word 'new' in trees.c
|
||||
|
||||
Changes in 0.93 (25 June 95)
|
||||
- temporarily disable inline functions
|
||||
- make deflate deterministic
|
||||
- give enough lookahead for PARTIAL_FLUSH
|
||||
- Set binary mode for stdin/stdout in minigzip.c for OS/2
|
||||
- don't even use signed char in inflate (not portable enough)
|
||||
- fix inflate memory leak for segmented architectures
|
||||
|
||||
Changes in 0.92 (3 May 95)
|
||||
- don't assume that char is signed (problem on SGI)
|
||||
- Clear bit buffer when starting a stored block
|
||||
- no memcpy on Pyramid
|
||||
- suppressed inftest.c
|
||||
- optimized fill_window, put longest_match inline for gcc
|
||||
- optimized inflate on stored blocks.
|
||||
- untabify all sources to simplify patches
|
||||
|
||||
Changes in 0.91 (2 May 95)
|
||||
- Default MEM_LEVEL is 8 (not 9 for Unix) as documented in zlib.h
|
||||
- Document the memory requirements in zconf.h
|
||||
- added "make install"
|
||||
- fix sync search logic in inflateSync
|
||||
- deflate(Z_FULL_FLUSH) now works even if output buffer too short
|
||||
- after inflateSync, don't scare people with just "lo world"
|
||||
- added support for DJGPP
|
||||
|
||||
Changes in 0.9 (1 May 95)
|
||||
- don't assume that zalloc clears the allocated memory (the TurboC bug
|
||||
was Mark's bug after all :)
|
||||
- let again gzread copy uncompressed data unchanged (was working in 0.71)
|
||||
- deflate(Z_FULL_FLUSH), inflateReset and inflateSync are now fully implemented
|
||||
- added a test of inflateSync in example.c
|
||||
- moved MAX_WBITS to zconf.h because users might want to change that.
|
||||
- document explicitly that zalloc(64K) on MSDOS must return a normalized
|
||||
pointer (zero offset)
|
||||
- added Makefiles for Microsoft C, Turbo C, Borland C++
|
||||
- faster crc32()
|
||||
|
||||
Changes in 0.8 (29 April 95)
|
||||
- added fast inflate (inffast.c)
|
||||
- deflate(Z_FINISH) now returns Z_STREAM_END when done. Warning: this
|
||||
is incompatible with previous versions of zlib which returned Z_OK.
|
||||
- work around a TurboC compiler bug (bad code for b << 0, see infutil.h)
|
||||
(actually that was not a compiler bug, see 0.81 above)
|
||||
- gzread no longer reads one extra byte in certain cases
|
||||
- In gzio destroy(), don't reference a freed structure
|
||||
- avoid many warnings for MSDOS
|
||||
- avoid the ERROR symbol which is used by MS Windows
|
||||
|
||||
Changes in 0.71 (14 April 95)
|
||||
- Fixed more MSDOS compilation problems :( There is still a bug with
|
||||
TurboC large model.
|
||||
|
||||
Changes in 0.7 (14 April 95)
|
||||
- Added full inflate support.
|
||||
- Simplified the crc32() interface. The pre- and post-conditioning
|
||||
(one's complement) is now done inside crc32(). WARNING: this is
|
||||
incompatible with previous versions; see zlib.h for the new usage.
|
||||
|
||||
Changes in 0.61 (12 April 95)
|
||||
- workaround for a bug in TurboC. example and minigzip now work on MSDOS.
|
||||
|
||||
Changes in 0.6 (11 April 95)
|
||||
- added minigzip.c
|
||||
- added gzdopen to reopen a file descriptor as gzFile
|
||||
- added transparent reading of non-gziped files in gzread.
|
||||
- fixed bug in gzread (don't read crc as data)
|
||||
- fixed bug in destroy (gzio.c) (don't return Z_STREAM_END for gzclose).
|
||||
- don't allocate big arrays in the stack (for MSDOS)
|
||||
- fix some MSDOS compilation problems
|
||||
|
||||
Changes in 0.5:
|
||||
- do real compression in deflate.c. Z_PARTIAL_FLUSH is supported but
|
||||
not yet Z_FULL_FLUSH.
|
||||
- support decompression but only in a single step (forced Z_FINISH)
|
||||
- added opaque object for zalloc and zfree.
|
||||
- added deflateReset and inflateReset
|
||||
- added a variable zlib_version for consistency checking.
|
||||
- renamed the 'filter' parameter of deflateInit2 as 'strategy'.
|
||||
Added Z_FILTERED and Z_HUFFMAN_ONLY constants.
|
||||
|
||||
Changes in 0.4:
|
||||
- avoid "zip" everywhere, use zlib instead of ziplib.
|
||||
- suppress Z_BLOCK_FLUSH, interpret Z_PARTIAL_FLUSH as block flush
|
||||
if compression method == 8.
|
||||
- added adler32 and crc32
|
||||
- renamed deflateOptions as deflateInit2, call one or the other but not both
|
||||
- added the method parameter for deflateInit2.
|
||||
- added inflateInit2
|
||||
- simplied considerably deflateInit and inflateInit by not supporting
|
||||
user-provided history buffer. This is supported only in deflateInit2
|
||||
and inflateInit2.
|
||||
|
||||
Changes in 0.3:
|
||||
- prefix all macro names with Z_
|
||||
- use Z_FINISH instead of deflateEnd to finish compression.
|
||||
- added Z_HUFFMAN_ONLY
|
||||
- added gzerror()
|
||||
@@ -0,0 +1,36 @@
|
||||
#
|
||||
# $Id: Makefile,v 1.2 1996/08/18 23:52:20 peter Exp $
|
||||
#
|
||||
|
||||
MAINTAINER=[email protected]
|
||||
|
||||
LIB= z
|
||||
|
||||
#CFLAGS+= -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7
|
||||
#CFLAGS+= -g -DDEBUG
|
||||
#CFLAGS+= -Wall -Wwrite-strings -Wpointer-arith -Wconversion \
|
||||
# -Wstrict-prototypes -Wmissing-prototypes
|
||||
|
||||
CLEANFILES+= example.o example minigzip.o minigzip
|
||||
|
||||
SRCS = adler32.c compress.c crc32.c gzio.c uncompr.c deflate.c trees.c \
|
||||
zutil.c inflate.c infblock.c inftrees.c infcodes.c infutil.c inffast.c
|
||||
|
||||
beforeinstall:
|
||||
.for hdr in zconf.h zlib.h
|
||||
${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 ${.CURDIR}/${hdr} \
|
||||
${DESTDIR}/usr/include
|
||||
.endfor
|
||||
|
||||
minigzip: all minigzip.o
|
||||
$(CC) -o minigzip minigzip.o -L. -lz
|
||||
|
||||
example: all example.o
|
||||
$(CC) -o example example.o -L. -lz
|
||||
|
||||
test: example minigzip
|
||||
(export LD_LIBRARY_PATH=. ; ./example )
|
||||
(export LD_LIBRARY_PATH=. ; \
|
||||
echo hello world | ./minigzip | ./minigzip -d )
|
||||
|
||||
.include <bsd.lib.mk>
|
||||
@@ -0,0 +1,99 @@
|
||||
zlib 1.0.4 is a general purpose data compression library. All the code
|
||||
is reentrant (thread safe). The data format used by the zlib library
|
||||
is described by RFCs (Request for Comments) 1950 to 1952 in the files
|
||||
ftp://ds.internic.net/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate
|
||||
format) and rfc1952.txt (gzip format). These documents are also available in
|
||||
other formats from ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html
|
||||
|
||||
All functions of the compression library are documented in the file
|
||||
zlib.h. A usage example of the library is given in the file example.c
|
||||
which also tests that the library is working correctly. Another
|
||||
example is given in the file minigzip.c. The compression library itself
|
||||
is composed of all source files except example.c and minigzip.c.
|
||||
|
||||
To compile all files and run the test program, follow the instructions
|
||||
given at the top of Makefile. In short "make test; make install"
|
||||
should work for most machines. For MSDOS, use one of the special
|
||||
makefiles such as Makefile.msc; for VMS, use Make_vms.com or descrip.mms.
|
||||
|
||||
Questions about zlib should be sent to <[email protected]> or,
|
||||
if this fails, to the addresses given below in the Copyright section.
|
||||
The zlib home page is http://quest.jpl.nasa.gov/zlib/
|
||||
|
||||
The changes made in version 1.0.4 are documented in the file ChangeLog.
|
||||
The main changes since 1.0.3 are:
|
||||
|
||||
- In very rare conditions, deflate(s, Z_FINISH) could fail to produce an EOF
|
||||
bit, so the decompressor could decompress all the correct data but went
|
||||
on to attempt decompressing extra garbage data. This affected minigzip too.
|
||||
- zlibVersion and gzerror return const char* (needed for DLL)
|
||||
- port to RISCOS (no fdopen, no multiple dots, no unlink, no fileno)
|
||||
|
||||
|
||||
A Perl interface to zlib written by Paul Marquess <[email protected]>
|
||||
is in the CPAN (Comprehensive Perl Archive Network) sites, such as:
|
||||
ftp://ftp.cis.ufl.edu/pub/perl/CPAN/modules/by-module/Compress/Compress-Zlib*
|
||||
|
||||
|
||||
Notes for some targets:
|
||||
|
||||
- For Turbo C the small model is supported only with reduced performance to
|
||||
avoid any far allocation; it was tested with -DMAX_WBITS=11 -DMAX_MEM_LEVEL=3
|
||||
|
||||
- For 64-bit Iris, deflate.c must be compiled without any optimization.
|
||||
With -O, one libpng test fails. The test works in 32 bit mode (with
|
||||
the -32 compiler flag). The compiler bug has been reported to SGI.
|
||||
|
||||
- zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1
|
||||
it works when compiled with cc.
|
||||
|
||||
- zlib doesn't work on HP-UX 9.05 with one cc compiler (the one not
|
||||
accepting the -O option). It works with the other cc compiler.
|
||||
|
||||
- To build a Windows DLL version, include in a DLL project zlib.def, zlib.rc
|
||||
and all .c files except example.c and minigzip.c; compile with -DZLIB_DLL
|
||||
For help on building a zlib DLL, contact Alessandro Iacopetti
|
||||
<[email protected]> http://lisa.unial.it/iaco ,
|
||||
or contact Brad Clarke <[email protected]>.
|
||||
|
||||
- gzdopen is not supported on RISCOS
|
||||
|
||||
|
||||
Acknowledgments:
|
||||
|
||||
The deflate format used by zlib was defined by Phil Katz. The deflate
|
||||
and zlib specifications were written by Peter Deutsch. Thanks to all the
|
||||
people who reported problems and suggested various improvements in zlib;
|
||||
they are too numerous to cite here.
|
||||
|
||||
Copyright notice:
|
||||
|
||||
(C) 1995-1996 Jean-loup Gailly and Mark Adler
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
Jean-loup Gailly Mark Adler
|
||||
[email protected] [email protected]
|
||||
|
||||
If you use the zlib library in a product, we would appreciate *not*
|
||||
receiving lengthy legal documents to sign. The sources are provided
|
||||
for free but without warranty of any kind. The library has been
|
||||
entirely written by Jean-loup Gailly and Mark Adler; it does not
|
||||
include third-party code.
|
||||
|
||||
If you redistribute modified sources, we would appreciate that you include
|
||||
in the file ChangeLog history information documenting your changes.
|
||||
@@ -0,0 +1,48 @@
|
||||
/* adler32.c -- compute the Adler-32 checksum of a data stream
|
||||
* Copyright (C) 1995-1996 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* $Id: adler32.c,v 1.10 1996/05/22 11:52:18 me Exp $ */
|
||||
|
||||
#include "zlib.h"
|
||||
|
||||
#define BASE 65521L /* largest prime smaller than 65536 */
|
||||
#define NMAX 5552
|
||||
/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
|
||||
|
||||
#define DO1(buf,i) {s1 += buf[i]; s2 += s1;}
|
||||
#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
|
||||
#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
|
||||
#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
|
||||
#define DO16(buf) DO8(buf,0); DO8(buf,8);
|
||||
|
||||
/* ========================================================================= */
|
||||
uLong adler32(adler, buf, len)
|
||||
uLong adler;
|
||||
const Bytef *buf;
|
||||
uInt len;
|
||||
{
|
||||
unsigned long s1 = adler & 0xffff;
|
||||
unsigned long s2 = (adler >> 16) & 0xffff;
|
||||
int k;
|
||||
|
||||
if (buf == Z_NULL) return 1L;
|
||||
|
||||
while (len > 0) {
|
||||
k = len < NMAX ? len : NMAX;
|
||||
len -= k;
|
||||
while (k >= 16) {
|
||||
DO16(buf);
|
||||
buf += 16;
|
||||
k -= 16;
|
||||
}
|
||||
if (k != 0) do {
|
||||
s1 += *buf++;
|
||||
s2 += s1;
|
||||
} while (--k);
|
||||
s1 %= BASE;
|
||||
s2 %= BASE;
|
||||
}
|
||||
return (s2 << 16) | s1;
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
1. Compression algorithm (deflate)
|
||||
|
||||
The deflation algorithm used by zlib (also zip and gzip) is a variation of
|
||||
LZ77 (Lempel-Ziv 1977, see reference below). It finds duplicated strings in
|
||||
the input data. The second occurrence of a string is replaced by a
|
||||
pointer to the previous string, in the form of a pair (distance,
|
||||
length). Distances are limited to 32K bytes, and lengths are limited
|
||||
to 258 bytes. When a string does not occur anywhere in the previous
|
||||
32K bytes, it is emitted as a sequence of literal bytes. (In this
|
||||
description, `string' must be taken as an arbitrary sequence of bytes,
|
||||
and is not restricted to printable characters.)
|
||||
|
||||
Literals or match lengths are compressed with one Huffman tree, and
|
||||
match distances are compressed with another tree. The trees are stored
|
||||
in a compact form at the start of each block. The blocks can have any
|
||||
size (except that the compressed data for one block must fit in
|
||||
available memory). A block is terminated when deflate() determines that
|
||||
it would be useful to start another block with fresh trees. (This is
|
||||
somewhat similar to the behavior of LZW-based _compress_.)
|
||||
|
||||
Duplicated strings are found using a hash table. All input strings of
|
||||
length 3 are inserted in the hash table. A hash index is computed for
|
||||
the next 3 bytes. If the hash chain for this index is not empty, all
|
||||
strings in the chain are compared with the current input string, and
|
||||
the longest match is selected.
|
||||
|
||||
The hash chains are searched starting with the most recent strings, to
|
||||
favor small distances and thus take advantage of the Huffman encoding.
|
||||
The hash chains are singly linked. There are no deletions from the
|
||||
hash chains, the algorithm simply discards matches that are too old.
|
||||
|
||||
To avoid a worst-case situation, very long hash chains are arbitrarily
|
||||
truncated at a certain length, determined by a runtime option (level
|
||||
parameter of deflateInit). So deflate() does not always find the longest
|
||||
possible match but generally finds a match which is long enough.
|
||||
|
||||
deflate() also defers the selection of matches with a lazy evaluation
|
||||
mechanism. After a match of length N has been found, deflate() searches for a
|
||||
longer match at the next input byte. If a longer match is found, the
|
||||
previous match is truncated to a length of one (thus producing a single
|
||||
literal byte) and the longer match is emitted afterwards. Otherwise,
|
||||
the original match is kept, and the next match search is attempted only
|
||||
N steps later.
|
||||
|
||||
The lazy match evaluation is also subject to a runtime parameter. If
|
||||
the current match is long enough, deflate() reduces the search for a longer
|
||||
match, thus speeding up the whole process. If compression ratio is more
|
||||
important than speed, deflate() attempts a complete second search even if
|
||||
the first match is already long enough.
|
||||
|
||||
The lazy match evaluation is not performed for the fastest compression
|
||||
modes (level parameter 1 to 3). For these fast modes, new strings
|
||||
are inserted in the hash table only when no match was found, or
|
||||
when the match is not too long. This degrades the compression ratio
|
||||
but saves time since there are both fewer insertions and fewer searches.
|
||||
|
||||
|
||||
2. Decompression algorithm (inflate)
|
||||
|
||||
The real question is, given a Huffman tree, how to decode fast. The most
|
||||
important realization is that shorter codes are much more common than
|
||||
longer codes, so pay attention to decoding the short codes fast, and let
|
||||
the long codes take longer to decode.
|
||||
|
||||
inflate() sets up a first level table that covers some number of bits of
|
||||
input less than the length of longest code. It gets that many bits from the
|
||||
stream, and looks it up in the table. The table will tell if the next
|
||||
code is that many bits or less and how many, and if it is, it will tell
|
||||
the value, else it will point to the next level table for which inflate()
|
||||
grabs more bits and tries to decode a longer code.
|
||||
|
||||
How many bits to make the first lookup is a tradeoff between the time it
|
||||
takes to decode and the time it takes to build the table. If building the
|
||||
table took no time (and if you had infinite memory), then there would only
|
||||
be a first level table to cover all the way to the longest code. However,
|
||||
building the table ends up taking a lot longer for more bits since short
|
||||
codes are replicated many times in such a table. What inflate() does is
|
||||
simply to make the number of bits in the first table a variable, and set it
|
||||
for the maximum speed.
|
||||
|
||||
inflate() sends new trees relatively often, so it is possibly set for a
|
||||
smaller first level table than an application that has only one tree for
|
||||
all the data. For inflate, which has 286 possible codes for the
|
||||
literal/length tree, the size of the first table is nine bits. Also the
|
||||
distance trees have 30 possible values, and the size of the first table is
|
||||
six bits. Note that for each of those cases, the table ended up one bit
|
||||
longer than the ``average'' code length, i.e. the code length of an
|
||||
approximately flat code which would be a little more than eight bits for
|
||||
286 symbols and a little less than five bits for 30 symbols. It would be
|
||||
interesting to see if optimizing the first level table for other
|
||||
applications gave values within a bit or two of the flat code size.
|
||||
|
||||
|
||||
Jean-loup Gailly Mark Adler
|
||||
[email protected] [email protected]
|
||||
|
||||
|
||||
References:
|
||||
|
||||
[LZ77] Ziv J., Lempel A., ``A Universal Algorithm for Sequential Data
|
||||
Compression,'' IEEE Transactions on Information Theory, Vol. 23, No. 3,
|
||||
pp. 337-343.
|
||||
|
||||
``DEFLATE Compressed Data Format Specification'' available in
|
||||
ftp://ds.internic.net/rfc/rfc1951.txt
|
||||
@@ -0,0 +1,57 @@
|
||||
/* compress.c -- compress a memory buffer
|
||||
* Copyright (C) 1995-1996 Jean-loup Gailly.
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* $Id: compress.c,v 1.10 1996/05/23 16:51:12 me Exp $ */
|
||||
|
||||
#include "zlib.h"
|
||||
|
||||
/* ===========================================================================
|
||||
Compresses the source buffer into the destination buffer. sourceLen is
|
||||
the byte length of the source buffer. Upon entry, destLen is the total
|
||||
size of the destination buffer, which must be at least 0.1% larger than
|
||||
sourceLen plus 8 bytes. Upon exit, destLen is the actual size of the
|
||||
compressed buffer.
|
||||
This function can be used to compress a whole file at once if the
|
||||
input file is mmap'ed.
|
||||
compress returns Z_OK if success, Z_MEM_ERROR if there was not
|
||||
enough memory, Z_BUF_ERROR if there was not enough room in the output
|
||||
buffer.
|
||||
*/
|
||||
int compress (dest, destLen, source, sourceLen)
|
||||
Bytef *dest;
|
||||
uLongf *destLen;
|
||||
const Bytef *source;
|
||||
uLong sourceLen;
|
||||
{
|
||||
z_stream stream;
|
||||
int err;
|
||||
|
||||
stream.next_in = (Bytef*)source;
|
||||
stream.avail_in = (uInt)sourceLen;
|
||||
#ifdef MAXSEG_64K
|
||||
/* Check for source > 64K on 16-bit machine: */
|
||||
if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
|
||||
#endif
|
||||
stream.next_out = dest;
|
||||
stream.avail_out = (uInt)*destLen;
|
||||
if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
|
||||
|
||||
stream.zalloc = (alloc_func)0;
|
||||
stream.zfree = (free_func)0;
|
||||
stream.opaque = (voidpf)0;
|
||||
|
||||
err = deflateInit(&stream, Z_DEFAULT_COMPRESSION);
|
||||
if (err != Z_OK) return err;
|
||||
|
||||
err = deflate(&stream, Z_FINISH);
|
||||
if (err != Z_STREAM_END) {
|
||||
deflateEnd(&stream);
|
||||
return err == Z_OK ? Z_BUF_ERROR : err;
|
||||
}
|
||||
*destLen = stream.total_out;
|
||||
|
||||
err = deflateEnd(&stream);
|
||||
return err;
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
/* crc32.c -- compute the CRC-32 of a data stream
|
||||
* Copyright (C) 1995-1996 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* $Id: crc32.c,v 1.8 1996/01/30 21:59:10 me Exp $ */
|
||||
|
||||
#include "zlib.h"
|
||||
|
||||
#define local static
|
||||
|
||||
#ifdef DYNAMIC_CRC_TABLE
|
||||
|
||||
local int crc_table_empty = 1;
|
||||
local uLongf crc_table[256];
|
||||
local void make_crc_table OF((void));
|
||||
|
||||
/*
|
||||
Generate a table for a byte-wise 32-bit CRC calculation on the polynomial:
|
||||
x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.
|
||||
|
||||
Polynomials over GF(2) are represented in binary, one bit per coefficient,
|
||||
with the lowest powers in the most significant bit. Then adding polynomials
|
||||
is just exclusive-or, and multiplying a polynomial by x is a right shift by
|
||||
one. If we call the above polynomial p, and represent a byte as the
|
||||
polynomial q, also with the lowest power in the most significant bit (so the
|
||||
byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,
|
||||
where a mod b means the remainder after dividing a by b.
|
||||
|
||||
This calculation is done using the shift-register method of multiplying and
|
||||
taking the remainder. The register is initialized to zero, and for each
|
||||
incoming bit, x^32 is added mod p to the register if the bit is a one (where
|
||||
x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by
|
||||
x (which is shifting right by one and adding x^32 mod p if the bit shifted
|
||||
out is a one). We start with the highest power (least significant bit) of
|
||||
q and repeat for all eight bits of q.
|
||||
|
||||
The table is simply the CRC of all possible eight bit values. This is all
|
||||
the information needed to generate CRC's on data a byte at a time for all
|
||||
combinations of CRC register values and incoming bytes.
|
||||
*/
|
||||
local void make_crc_table()
|
||||
{
|
||||
uLong c;
|
||||
int n, k;
|
||||
uLong poly; /* polynomial exclusive-or pattern */
|
||||
/* terms of polynomial defining this crc (except x^32): */
|
||||
static Byte p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
|
||||
|
||||
/* make exclusive-or pattern from polynomial (0xedb88320L) */
|
||||
poly = 0L;
|
||||
for (n = 0; n < sizeof(p)/sizeof(Byte); n++)
|
||||
poly |= 1L << (31 - p[n]);
|
||||
|
||||
for (n = 0; n < 256; n++)
|
||||
{
|
||||
c = (uLong)n;
|
||||
for (k = 0; k < 8; k++)
|
||||
c = c & 1 ? poly ^ (c >> 1) : c >> 1;
|
||||
crc_table[n] = c;
|
||||
}
|
||||
crc_table_empty = 0;
|
||||
}
|
||||
#else
|
||||
/* ========================================================================
|
||||
* Table of CRC-32's of all single-byte values (made by make_crc_table)
|
||||
*/
|
||||
local uLongf crc_table[256] = {
|
||||
0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
|
||||
0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
|
||||
0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
|
||||
0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
|
||||
0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
|
||||
0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
|
||||
0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
|
||||
0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
|
||||
0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
|
||||
0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
|
||||
0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
|
||||
0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
|
||||
0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
|
||||
0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
|
||||
0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
|
||||
0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
|
||||
0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
|
||||
0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
|
||||
0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
|
||||
0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
|
||||
0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
|
||||
0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
|
||||
0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
|
||||
0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
|
||||
0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
|
||||
0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
|
||||
0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
|
||||
0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
|
||||
0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
|
||||
0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
|
||||
0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
|
||||
0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
|
||||
0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
|
||||
0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
|
||||
0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
|
||||
0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
|
||||
0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
|
||||
0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
|
||||
0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
|
||||
0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
|
||||
0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
|
||||
0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
|
||||
0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
|
||||
0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
|
||||
0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
|
||||
0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
|
||||
0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
|
||||
0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
|
||||
0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
|
||||
0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
|
||||
0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
|
||||
0x2d02ef8dL
|
||||
};
|
||||
#endif
|
||||
|
||||
/* =========================================================================
|
||||
* This function can be used by asm versions of crc32()
|
||||
*/
|
||||
uLongf *get_crc_table()
|
||||
{
|
||||
#ifdef DYNAMIC_CRC_TABLE
|
||||
if (crc_table_empty) make_crc_table();
|
||||
#endif
|
||||
return (uLongf *)crc_table;
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
#define DO1(buf) crc = crc_table[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8);
|
||||
#define DO2(buf) DO1(buf); DO1(buf);
|
||||
#define DO4(buf) DO2(buf); DO2(buf);
|
||||
#define DO8(buf) DO4(buf); DO4(buf);
|
||||
|
||||
/* ========================================================================= */
|
||||
uLong crc32(crc, buf, len)
|
||||
uLong crc;
|
||||
const Bytef *buf;
|
||||
uInt len;
|
||||
{
|
||||
if (buf == Z_NULL) return 0L;
|
||||
#ifdef DYNAMIC_CRC_TABLE
|
||||
if (crc_table_empty)
|
||||
make_crc_table();
|
||||
#endif
|
||||
crc = crc ^ 0xffffffffL;
|
||||
while (len >= 8)
|
||||
{
|
||||
DO8(buf);
|
||||
len -= 8;
|
||||
}
|
||||
if (len) do {
|
||||
DO1(buf);
|
||||
} while (--len);
|
||||
return crc ^ 0xffffffffL;
|
||||
}
|
||||
+1207
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,275 @@
|
||||
/* deflate.h -- internal compression state
|
||||
* Copyright (C) 1995-1996 Jean-loup Gailly
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* WARNING: this file should *not* be used by applications. It is
|
||||
part of the implementation of the compression library and is
|
||||
subject to change. Applications should only use zlib.h.
|
||||
*/
|
||||
|
||||
/* $Id: deflate.h,v 1.10 1996/07/02 12:41:00 me Exp $ */
|
||||
|
||||
#ifndef _DEFLATE_H
|
||||
#define _DEFLATE_H
|
||||
|
||||
#include "zutil.h"
|
||||
|
||||
/* ===========================================================================
|
||||
* Internal compression state.
|
||||
*/
|
||||
|
||||
#define LENGTH_CODES 29
|
||||
/* number of length codes, not counting the special END_BLOCK code */
|
||||
|
||||
#define LITERALS 256
|
||||
/* number of literal bytes 0..255 */
|
||||
|
||||
#define L_CODES (LITERALS+1+LENGTH_CODES)
|
||||
/* number of Literal or Length codes, including the END_BLOCK code */
|
||||
|
||||
#define D_CODES 30
|
||||
/* number of distance codes */
|
||||
|
||||
#define BL_CODES 19
|
||||
/* number of codes used to transfer the bit lengths */
|
||||
|
||||
#define HEAP_SIZE (2*L_CODES+1)
|
||||
/* maximum heap size */
|
||||
|
||||
#define MAX_BITS 15
|
||||
/* All codes must not exceed MAX_BITS bits */
|
||||
|
||||
#define INIT_STATE 42
|
||||
#define BUSY_STATE 113
|
||||
#define FINISH_STATE 666
|
||||
/* Stream status */
|
||||
|
||||
|
||||
/* Data structure describing a single value and its code string. */
|
||||
typedef struct ct_data_s {
|
||||
union {
|
||||
ush freq; /* frequency count */
|
||||
ush code; /* bit string */
|
||||
} fc;
|
||||
union {
|
||||
ush dad; /* father node in Huffman tree */
|
||||
ush len; /* length of bit string */
|
||||
} dl;
|
||||
} FAR ct_data;
|
||||
|
||||
#define Freq fc.freq
|
||||
#define Code fc.code
|
||||
#define Dad dl.dad
|
||||
#define Len dl.len
|
||||
|
||||
typedef struct static_tree_desc_s static_tree_desc;
|
||||
|
||||
typedef struct tree_desc_s {
|
||||
ct_data *dyn_tree; /* the dynamic tree */
|
||||
int max_code; /* largest code with non zero frequency */
|
||||
static_tree_desc *stat_desc; /* the corresponding static tree */
|
||||
} FAR tree_desc;
|
||||
|
||||
typedef ush Pos;
|
||||
typedef Pos FAR Posf;
|
||||
typedef unsigned IPos;
|
||||
|
||||
/* A Pos is an index in the character window. We use short instead of int to
|
||||
* save space in the various tables. IPos is used only for parameter passing.
|
||||
*/
|
||||
|
||||
typedef struct internal_state {
|
||||
z_streamp strm; /* pointer back to this zlib stream */
|
||||
int status; /* as the name implies */
|
||||
Bytef *pending_buf; /* output still pending */
|
||||
Bytef *pending_out; /* next pending byte to output to the stream */
|
||||
int pending; /* nb of bytes in the pending buffer */
|
||||
int noheader; /* suppress zlib header and adler32 */
|
||||
Byte data_type; /* UNKNOWN, BINARY or ASCII */
|
||||
Byte method; /* STORED (for zip only) or DEFLATED */
|
||||
int last_flush; /* value of flush param for previous deflate call */
|
||||
|
||||
/* used by deflate.c: */
|
||||
|
||||
uInt w_size; /* LZ77 window size (32K by default) */
|
||||
uInt w_bits; /* log2(w_size) (8..16) */
|
||||
uInt w_mask; /* w_size - 1 */
|
||||
|
||||
Bytef *window;
|
||||
/* Sliding window. Input bytes are read into the second half of the window,
|
||||
* and move to the first half later to keep a dictionary of at least wSize
|
||||
* bytes. With this organization, matches are limited to a distance of
|
||||
* wSize-MAX_MATCH bytes, but this ensures that IO is always
|
||||
* performed with a length multiple of the block size. Also, it limits
|
||||
* the window size to 64K, which is quite useful on MSDOS.
|
||||
* To do: use the user input buffer as sliding window.
|
||||
*/
|
||||
|
||||
ulg window_size;
|
||||
/* Actual size of window: 2*wSize, except when the user input buffer
|
||||
* is directly used as sliding window.
|
||||
*/
|
||||
|
||||
Posf *prev;
|
||||
/* Link to older string with same hash index. To limit the size of this
|
||||
* array to 64K, this link is maintained only for the last 32K strings.
|
||||
* An index in this array is thus a window index modulo 32K.
|
||||
*/
|
||||
|
||||
Posf *head; /* Heads of the hash chains or NIL. */
|
||||
|
||||
uInt ins_h; /* hash index of string to be inserted */
|
||||
uInt hash_size; /* number of elements in hash table */
|
||||
uInt hash_bits; /* log2(hash_size) */
|
||||
uInt hash_mask; /* hash_size-1 */
|
||||
|
||||
uInt hash_shift;
|
||||
/* Number of bits by which ins_h must be shifted at each input
|
||||
* step. It must be such that after MIN_MATCH steps, the oldest
|
||||
* byte no longer takes part in the hash key, that is:
|
||||
* hash_shift * MIN_MATCH >= hash_bits
|
||||
*/
|
||||
|
||||
long block_start;
|
||||
/* Window position at the beginning of the current output block. Gets
|
||||
* negative when the window is moved backwards.
|
||||
*/
|
||||
|
||||
uInt match_length; /* length of best match */
|
||||
IPos prev_match; /* previous match */
|
||||
int match_available; /* set if previous match exists */
|
||||
uInt strstart; /* start of string to insert */
|
||||
uInt match_start; /* start of matching string */
|
||||
uInt lookahead; /* number of valid bytes ahead in window */
|
||||
|
||||
uInt prev_length;
|
||||
/* Length of the best match at previous step. Matches not greater than this
|
||||
* are discarded. This is used in the lazy match evaluation.
|
||||
*/
|
||||
|
||||
uInt max_chain_length;
|
||||
/* To speed up deflation, hash chains are never searched beyond this
|
||||
* length. A higher limit improves compression ratio but degrades the
|
||||
* speed.
|
||||
*/
|
||||
|
||||
uInt max_lazy_match;
|
||||
/* Attempt to find a better match only when the current match is strictly
|
||||
* smaller than this value. This mechanism is used only for compression
|
||||
* levels >= 4.
|
||||
*/
|
||||
# define max_insert_length max_lazy_match
|
||||
/* Insert new strings in the hash table only if the match length is not
|
||||
* greater than this length. This saves time but degrades compression.
|
||||
* max_insert_length is used only for compression levels <= 3.
|
||||
*/
|
||||
|
||||
int level; /* compression level (1..9) */
|
||||
int strategy; /* favor or force Huffman coding*/
|
||||
|
||||
uInt good_match;
|
||||
/* Use a faster search when the previous match is longer than this */
|
||||
|
||||
int nice_match; /* Stop searching when current match exceeds this */
|
||||
|
||||
/* used by trees.c: */
|
||||
/* Didn't use ct_data typedef below to supress compiler warning */
|
||||
struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */
|
||||
struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */
|
||||
struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */
|
||||
|
||||
struct tree_desc_s l_desc; /* desc. for literal tree */
|
||||
struct tree_desc_s d_desc; /* desc. for distance tree */
|
||||
struct tree_desc_s bl_desc; /* desc. for bit length tree */
|
||||
|
||||
ush bl_count[MAX_BITS+1];
|
||||
/* number of codes at each bit length for an optimal tree */
|
||||
|
||||
int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */
|
||||
int heap_len; /* number of elements in the heap */
|
||||
int heap_max; /* element of largest frequency */
|
||||
/* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
|
||||
* The same heap array is used to build all trees.
|
||||
*/
|
||||
|
||||
uch depth[2*L_CODES+1];
|
||||
/* Depth of each subtree used as tie breaker for trees of equal frequency
|
||||
*/
|
||||
|
||||
uchf *l_buf; /* buffer for literals or lengths */
|
||||
|
||||
uInt lit_bufsize;
|
||||
/* Size of match buffer for literals/lengths. There are 4 reasons for
|
||||
* limiting lit_bufsize to 64K:
|
||||
* - frequencies can be kept in 16 bit counters
|
||||
* - if compression is not successful for the first block, all input
|
||||
* data is still in the window so we can still emit a stored block even
|
||||
* when input comes from standard input. (This can also be done for
|
||||
* all blocks if lit_bufsize is not greater than 32K.)
|
||||
* - if compression is not successful for a file smaller than 64K, we can
|
||||
* even emit a stored file instead of a stored block (saving 5 bytes).
|
||||
* This is applicable only for zip (not gzip or zlib).
|
||||
* - creating new Huffman trees less frequently may not provide fast
|
||||
* adaptation to changes in the input data statistics. (Take for
|
||||
* example a binary file with poorly compressible code followed by
|
||||
* a highly compressible string table.) Smaller buffer sizes give
|
||||
* fast adaptation but have of course the overhead of transmitting
|
||||
* trees more frequently.
|
||||
* - I can't count above 4
|
||||
*/
|
||||
|
||||
uInt last_lit; /* running index in l_buf */
|
||||
|
||||
ushf *d_buf;
|
||||
/* Buffer for distances. To simplify the code, d_buf and l_buf have
|
||||
* the same number of elements. To use different lengths, an extra flag
|
||||
* array would be necessary.
|
||||
*/
|
||||
|
||||
ulg opt_len; /* bit length of current block with optimal trees */
|
||||
ulg static_len; /* bit length of current block with static trees */
|
||||
ulg compressed_len; /* total bit length of compressed file */
|
||||
uInt matches; /* number of string matches in current block */
|
||||
int last_eob_len; /* bit length of EOB code for last block */
|
||||
|
||||
#ifdef DEBUG
|
||||
ulg bits_sent; /* bit length of the compressed data */
|
||||
#endif
|
||||
|
||||
ush bi_buf;
|
||||
/* Output buffer. bits are inserted starting at the bottom (least
|
||||
* significant bits).
|
||||
*/
|
||||
int bi_valid;
|
||||
/* Number of valid bits in bi_buf. All bits above the last valid bit
|
||||
* are always zero.
|
||||
*/
|
||||
|
||||
} FAR deflate_state;
|
||||
|
||||
/* Output a byte on the stream.
|
||||
* IN assertion: there is enough room in pending_buf.
|
||||
*/
|
||||
#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);}
|
||||
|
||||
|
||||
#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
|
||||
/* Minimum amount of lookahead, except at the end of the input file.
|
||||
* See deflate.c for comments about the MIN_MATCH+1.
|
||||
*/
|
||||
|
||||
#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD)
|
||||
/* In order to simplify the code, particularly on 16 bit machines, match
|
||||
* distances are limited to MAX_DIST instead of WSIZE.
|
||||
*/
|
||||
|
||||
/* in trees.c */
|
||||
void _tr_init OF((deflate_state *s));
|
||||
int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc));
|
||||
ulg _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len,
|
||||
int eof));
|
||||
void _tr_align OF((deflate_state *s));
|
||||
void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len,
|
||||
int eof));
|
||||
#endif
|
||||
@@ -0,0 +1,503 @@
|
||||
/* example.c -- usage example of the zlib compression library
|
||||
* Copyright (C) 1995-1996 Jean-loup Gailly.
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* $Id: example.c,v 1.16 1996/05/23 17:11:28 me Exp $ */
|
||||
|
||||
#include <stdio.h>
|
||||
#include "zlib.h"
|
||||
|
||||
#ifdef STDC
|
||||
# include <string.h>
|
||||
# include <stdlib.h>
|
||||
#else
|
||||
extern void exit OF((int));
|
||||
#endif
|
||||
|
||||
#define CHECK_ERR(err, msg) { \
|
||||
if (err != Z_OK) { \
|
||||
fprintf(stderr, "%s error: %d\n", msg, err); \
|
||||
exit(1); \
|
||||
} \
|
||||
}
|
||||
|
||||
const char hello[] = "hello, hello!";
|
||||
/* "hello world" would be more standard, but the repeated "hello"
|
||||
* stresses the compression code better, sorry...
|
||||
*/
|
||||
|
||||
const char dictionary[] = "hello";
|
||||
uLong dictId; /* Adler32 value of the dictionary */
|
||||
|
||||
void test_compress OF((Byte *compr, uLong comprLen,
|
||||
Byte *uncompr, uLong uncomprLen));
|
||||
void test_gzio OF((const char *out, const char *in,
|
||||
Byte *uncompr, int uncomprLen));
|
||||
void test_deflate OF((Byte *compr, uLong comprLen));
|
||||
void test_inflate OF((Byte *compr, uLong comprLen,
|
||||
Byte *uncompr, uLong uncomprLen));
|
||||
void test_large_deflate OF((Byte *compr, uLong comprLen,
|
||||
Byte *uncompr, uLong uncomprLen));
|
||||
void test_large_inflate OF((Byte *compr, uLong comprLen,
|
||||
Byte *uncompr, uLong uncomprLen));
|
||||
void test_flush OF((Byte *compr, uLong comprLen));
|
||||
void test_sync OF((Byte *compr, uLong comprLen,
|
||||
Byte *uncompr, uLong uncomprLen));
|
||||
void test_dict_deflate OF((Byte *compr, uLong comprLen));
|
||||
void test_dict_inflate OF((Byte *compr, uLong comprLen,
|
||||
Byte *uncompr, uLong uncomprLen));
|
||||
int main OF((int argc, char *argv[]));
|
||||
|
||||
/* ===========================================================================
|
||||
* Test compress() and uncompress()
|
||||
*/
|
||||
void test_compress(compr, comprLen, uncompr, uncomprLen)
|
||||
Byte *compr, *uncompr;
|
||||
uLong comprLen, uncomprLen;
|
||||
{
|
||||
int err;
|
||||
uLong len = strlen(hello)+1;
|
||||
|
||||
err = compress(compr, &comprLen, (const Bytef*)hello, len);
|
||||
CHECK_ERR(err, "compress");
|
||||
|
||||
strcpy((char*)uncompr, "garbage");
|
||||
|
||||
err = uncompress(uncompr, &uncomprLen, compr, comprLen);
|
||||
CHECK_ERR(err, "uncompress");
|
||||
|
||||
if (strcmp((char*)uncompr, hello)) {
|
||||
fprintf(stderr, "bad uncompress\n");
|
||||
} else {
|
||||
printf("uncompress(): %s\n", uncompr);
|
||||
}
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
* Test read/write of .gz files
|
||||
*/
|
||||
void test_gzio(out, in, uncompr, uncomprLen)
|
||||
const char *out; /* output file */
|
||||
const char *in; /* input file */
|
||||
Byte *uncompr;
|
||||
int uncomprLen;
|
||||
{
|
||||
int err;
|
||||
int len = strlen(hello)+1;
|
||||
gzFile file;
|
||||
|
||||
file = gzopen(out, "wb");
|
||||
if (file == NULL) {
|
||||
fprintf(stderr, "gzopen error\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (gzwrite(file, (const voidp)hello, (unsigned)len) != len) {
|
||||
fprintf(stderr, "gzwrite err: %s\n", gzerror(file, &err));
|
||||
}
|
||||
gzclose(file);
|
||||
|
||||
file = gzopen(in, "rb");
|
||||
if (file == NULL) {
|
||||
fprintf(stderr, "gzopen error\n");
|
||||
}
|
||||
strcpy((char*)uncompr, "garbage");
|
||||
|
||||
uncomprLen = gzread(file, uncompr, (unsigned)uncomprLen);
|
||||
if (uncomprLen != len) {
|
||||
fprintf(stderr, "gzread err: %s\n", gzerror(file, &err));
|
||||
}
|
||||
gzclose(file);
|
||||
|
||||
if (strcmp((char*)uncompr, hello)) {
|
||||
fprintf(stderr, "bad gzread\n");
|
||||
} else {
|
||||
printf("gzread(): %s\n", uncompr);
|
||||
}
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
* Test deflate() with small buffers
|
||||
*/
|
||||
void test_deflate(compr, comprLen)
|
||||
Byte *compr;
|
||||
uLong comprLen;
|
||||
{
|
||||
z_stream c_stream; /* compression stream */
|
||||
int err;
|
||||
int len = strlen(hello)+1;
|
||||
|
||||
c_stream.zalloc = (alloc_func)0;
|
||||
c_stream.zfree = (free_func)0;
|
||||
c_stream.opaque = (voidpf)0;
|
||||
|
||||
err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION);
|
||||
CHECK_ERR(err, "deflateInit");
|
||||
|
||||
c_stream.next_in = (Bytef*)hello;
|
||||
c_stream.next_out = compr;
|
||||
|
||||
while (c_stream.total_in != (uLong)len && c_stream.total_out < comprLen) {
|
||||
c_stream.avail_in = c_stream.avail_out = 1; /* force small buffers */
|
||||
err = deflate(&c_stream, Z_NO_FLUSH);
|
||||
CHECK_ERR(err, "deflate");
|
||||
}
|
||||
/* Finish the stream, still forcing small buffers: */
|
||||
for (;;) {
|
||||
c_stream.avail_out = 1;
|
||||
err = deflate(&c_stream, Z_FINISH);
|
||||
if (err == Z_STREAM_END) break;
|
||||
CHECK_ERR(err, "deflate");
|
||||
}
|
||||
|
||||
err = deflateEnd(&c_stream);
|
||||
CHECK_ERR(err, "deflateEnd");
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
* Test inflate() with small buffers
|
||||
*/
|
||||
void test_inflate(compr, comprLen, uncompr, uncomprLen)
|
||||
Byte *compr, *uncompr;
|
||||
uLong comprLen, uncomprLen;
|
||||
{
|
||||
int err;
|
||||
z_stream d_stream; /* decompression stream */
|
||||
|
||||
strcpy((char*)uncompr, "garbage");
|
||||
|
||||
d_stream.zalloc = (alloc_func)0;
|
||||
d_stream.zfree = (free_func)0;
|
||||
d_stream.opaque = (voidpf)0;
|
||||
|
||||
err = inflateInit(&d_stream);
|
||||
CHECK_ERR(err, "inflateInit");
|
||||
|
||||
d_stream.next_in = compr;
|
||||
d_stream.next_out = uncompr;
|
||||
|
||||
while (d_stream.total_out < uncomprLen && d_stream.total_in < comprLen) {
|
||||
d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */
|
||||
err = inflate(&d_stream, Z_NO_FLUSH);
|
||||
if (err == Z_STREAM_END) break;
|
||||
CHECK_ERR(err, "inflate");
|
||||
}
|
||||
|
||||
err = inflateEnd(&d_stream);
|
||||
CHECK_ERR(err, "inflateEnd");
|
||||
|
||||
if (strcmp((char*)uncompr, hello)) {
|
||||
fprintf(stderr, "bad inflate\n");
|
||||
} else {
|
||||
printf("inflate(): %s\n", uncompr);
|
||||
}
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
* Test deflate() with large buffers and dynamic change of compression level
|
||||
*/
|
||||
void test_large_deflate(compr, comprLen, uncompr, uncomprLen)
|
||||
Byte *compr, *uncompr;
|
||||
uLong comprLen, uncomprLen;
|
||||
{
|
||||
z_stream c_stream; /* compression stream */
|
||||
int err;
|
||||
|
||||
c_stream.zalloc = (alloc_func)0;
|
||||
c_stream.zfree = (free_func)0;
|
||||
c_stream.opaque = (voidpf)0;
|
||||
|
||||
err = deflateInit(&c_stream, Z_BEST_SPEED);
|
||||
CHECK_ERR(err, "deflateInit");
|
||||
|
||||
c_stream.next_out = compr;
|
||||
c_stream.avail_out = (uInt)comprLen;
|
||||
|
||||
/* At this point, uncompr is still mostly zeroes, so it should compress
|
||||
* very well:
|
||||
*/
|
||||
c_stream.next_in = uncompr;
|
||||
c_stream.avail_in = (uInt)uncomprLen;
|
||||
err = deflate(&c_stream, Z_NO_FLUSH);
|
||||
CHECK_ERR(err, "deflate");
|
||||
if (c_stream.avail_in != 0) {
|
||||
fprintf(stderr, "deflate not greedy\n");
|
||||
}
|
||||
|
||||
/* Feed in already compressed data and switch to no compression: */
|
||||
deflateParams(&c_stream, Z_NO_COMPRESSION, Z_DEFAULT_STRATEGY);
|
||||
c_stream.next_in = compr;
|
||||
c_stream.avail_in = (uInt)comprLen/2;
|
||||
err = deflate(&c_stream, Z_NO_FLUSH);
|
||||
CHECK_ERR(err, "deflate");
|
||||
|
||||
/* Switch back to compressing mode: */
|
||||
deflateParams(&c_stream, Z_BEST_COMPRESSION, Z_FILTERED);
|
||||
c_stream.next_in = uncompr;
|
||||
c_stream.avail_in = (uInt)uncomprLen;
|
||||
err = deflate(&c_stream, Z_NO_FLUSH);
|
||||
CHECK_ERR(err, "deflate");
|
||||
|
||||
err = deflate(&c_stream, Z_FINISH);
|
||||
if (err != Z_STREAM_END) {
|
||||
fprintf(stderr, "deflate should report Z_STREAM_END\n");
|
||||
}
|
||||
err = deflateEnd(&c_stream);
|
||||
CHECK_ERR(err, "deflateEnd");
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
* Test inflate() with large buffers
|
||||
*/
|
||||
void test_large_inflate(compr, comprLen, uncompr, uncomprLen)
|
||||
Byte *compr, *uncompr;
|
||||
uLong comprLen, uncomprLen;
|
||||
{
|
||||
int err;
|
||||
z_stream d_stream; /* decompression stream */
|
||||
|
||||
strcpy((char*)uncompr, "garbage");
|
||||
|
||||
d_stream.zalloc = (alloc_func)0;
|
||||
d_stream.zfree = (free_func)0;
|
||||
d_stream.opaque = (voidpf)0;
|
||||
|
||||
err = inflateInit(&d_stream);
|
||||
CHECK_ERR(err, "inflateInit");
|
||||
|
||||
d_stream.next_in = compr;
|
||||
d_stream.avail_in = (uInt)comprLen;
|
||||
|
||||
for (;;) {
|
||||
d_stream.next_out = uncompr; /* discard the output */
|
||||
d_stream.avail_out = (uInt)uncomprLen;
|
||||
err = inflate(&d_stream, Z_NO_FLUSH);
|
||||
if (err == Z_STREAM_END) break;
|
||||
CHECK_ERR(err, "large inflate");
|
||||
}
|
||||
|
||||
err = inflateEnd(&d_stream);
|
||||
CHECK_ERR(err, "inflateEnd");
|
||||
|
||||
if (d_stream.total_out != 2*uncomprLen + comprLen/2) {
|
||||
fprintf(stderr, "bad large inflate: %ld\n", d_stream.total_out);
|
||||
} else {
|
||||
printf("large_inflate(): OK\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
* Test deflate() with full flush
|
||||
*/
|
||||
void test_flush(compr, comprLen)
|
||||
Byte *compr;
|
||||
uLong comprLen;
|
||||
{
|
||||
z_stream c_stream; /* compression stream */
|
||||
int err;
|
||||
int len = strlen(hello)+1;
|
||||
|
||||
c_stream.zalloc = (alloc_func)0;
|
||||
c_stream.zfree = (free_func)0;
|
||||
c_stream.opaque = (voidpf)0;
|
||||
|
||||
err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION);
|
||||
CHECK_ERR(err, "deflateInit");
|
||||
|
||||
c_stream.next_in = (Bytef*)hello;
|
||||
c_stream.next_out = compr;
|
||||
c_stream.avail_in = 3;
|
||||
c_stream.avail_out = (uInt)comprLen;
|
||||
err = deflate(&c_stream, Z_FULL_FLUSH);
|
||||
CHECK_ERR(err, "deflate");
|
||||
|
||||
compr[3]++; /* force an error in first compressed block */
|
||||
c_stream.avail_in = len - 3;
|
||||
|
||||
err = deflate(&c_stream, Z_FINISH);
|
||||
if (err != Z_STREAM_END) {
|
||||
CHECK_ERR(err, "deflate");
|
||||
}
|
||||
err = deflateEnd(&c_stream);
|
||||
CHECK_ERR(err, "deflateEnd");
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
* Test inflateSync()
|
||||
*/
|
||||
void test_sync(compr, comprLen, uncompr, uncomprLen)
|
||||
Byte *compr, *uncompr;
|
||||
uLong comprLen, uncomprLen;
|
||||
{
|
||||
int err;
|
||||
z_stream d_stream; /* decompression stream */
|
||||
|
||||
strcpy((char*)uncompr, "garbage");
|
||||
|
||||
d_stream.zalloc = (alloc_func)0;
|
||||
d_stream.zfree = (free_func)0;
|
||||
d_stream.opaque = (voidpf)0;
|
||||
|
||||
err = inflateInit(&d_stream);
|
||||
CHECK_ERR(err, "inflateInit");
|
||||
|
||||
d_stream.next_in = compr;
|
||||
d_stream.next_out = uncompr;
|
||||
d_stream.avail_in = 2; /* just read the zlib header */
|
||||
d_stream.avail_out = (uInt)uncomprLen;
|
||||
|
||||
inflate(&d_stream, Z_NO_FLUSH);
|
||||
CHECK_ERR(err, "inflate");
|
||||
|
||||
d_stream.avail_in = (uInt)comprLen-2; /* read all compressed data */
|
||||
err = inflateSync(&d_stream); /* but skip the damaged part */
|
||||
CHECK_ERR(err, "inflateSync");
|
||||
|
||||
err = inflate(&d_stream, Z_FINISH);
|
||||
if (err != Z_DATA_ERROR) {
|
||||
fprintf(stderr, "inflate should report DATA_ERROR\n");
|
||||
/* Because of incorrect adler32 */
|
||||
}
|
||||
err = inflateEnd(&d_stream);
|
||||
CHECK_ERR(err, "inflateEnd");
|
||||
|
||||
printf("after inflateSync(): hel%s\n", uncompr);
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
* Test deflate() with preset dictionary
|
||||
*/
|
||||
void test_dict_deflate(compr, comprLen)
|
||||
Byte *compr;
|
||||
uLong comprLen;
|
||||
{
|
||||
z_stream c_stream; /* compression stream */
|
||||
int err;
|
||||
|
||||
c_stream.zalloc = (alloc_func)0;
|
||||
c_stream.zfree = (free_func)0;
|
||||
c_stream.opaque = (voidpf)0;
|
||||
|
||||
err = deflateInit(&c_stream, Z_BEST_COMPRESSION);
|
||||
CHECK_ERR(err, "deflateInit");
|
||||
|
||||
err = deflateSetDictionary(&c_stream,
|
||||
(const Bytef*)dictionary, sizeof(dictionary));
|
||||
CHECK_ERR(err, "deflateSetDictionary");
|
||||
|
||||
dictId = c_stream.adler;
|
||||
c_stream.next_out = compr;
|
||||
c_stream.avail_out = (uInt)comprLen;
|
||||
|
||||
c_stream.next_in = (Bytef*)hello;
|
||||
c_stream.avail_in = (uInt)strlen(hello)+1;
|
||||
|
||||
err = deflate(&c_stream, Z_FINISH);
|
||||
if (err != Z_STREAM_END) {
|
||||
fprintf(stderr, "deflate should report Z_STREAM_END\n");
|
||||
}
|
||||
err = deflateEnd(&c_stream);
|
||||
CHECK_ERR(err, "deflateEnd");
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
* Test inflate() with a preset dictionary
|
||||
*/
|
||||
void test_dict_inflate(compr, comprLen, uncompr, uncomprLen)
|
||||
Byte *compr, *uncompr;
|
||||
uLong comprLen, uncomprLen;
|
||||
{
|
||||
int err;
|
||||
z_stream d_stream; /* decompression stream */
|
||||
|
||||
strcpy((char*)uncompr, "garbage");
|
||||
|
||||
d_stream.zalloc = (alloc_func)0;
|
||||
d_stream.zfree = (free_func)0;
|
||||
d_stream.opaque = (voidpf)0;
|
||||
|
||||
err = inflateInit(&d_stream);
|
||||
CHECK_ERR(err, "inflateInit");
|
||||
|
||||
d_stream.next_in = compr;
|
||||
d_stream.avail_in = (uInt)comprLen;
|
||||
|
||||
d_stream.next_out = uncompr;
|
||||
d_stream.avail_out = (uInt)uncomprLen;
|
||||
|
||||
for (;;) {
|
||||
err = inflate(&d_stream, Z_NO_FLUSH);
|
||||
if (err == Z_STREAM_END) break;
|
||||
if (err == Z_NEED_DICT) {
|
||||
if (d_stream.adler != dictId) {
|
||||
fprintf(stderr, "unexpected dictionary");
|
||||
exit(1);
|
||||
}
|
||||
err = inflateSetDictionary(&d_stream, (const Bytef*)dictionary,
|
||||
sizeof(dictionary));
|
||||
}
|
||||
CHECK_ERR(err, "inflate with dict");
|
||||
}
|
||||
|
||||
err = inflateEnd(&d_stream);
|
||||
CHECK_ERR(err, "inflateEnd");
|
||||
|
||||
if (strcmp((char*)uncompr, hello)) {
|
||||
fprintf(stderr, "bad inflate with dict\n");
|
||||
} else {
|
||||
printf("inflate with dictionary: %s\n", uncompr);
|
||||
}
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
* Usage: example [output.gz [input.gz]]
|
||||
*/
|
||||
|
||||
int main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
Byte *compr, *uncompr;
|
||||
uLong comprLen = 10000*sizeof(int); /* don't overflow on MSDOS */
|
||||
uLong uncomprLen = comprLen;
|
||||
|
||||
if (zlibVersion()[0] != ZLIB_VERSION[0]) {
|
||||
fprintf(stderr, "incompatible zlib version\n");
|
||||
exit(1);
|
||||
|
||||
} else if (strcmp(zlibVersion(), ZLIB_VERSION) != 0) {
|
||||
fprintf(stderr, "warning: different zlib version\n");
|
||||
}
|
||||
|
||||
compr = (Byte*)calloc((uInt)comprLen, 1);
|
||||
uncompr = (Byte*)calloc((uInt)uncomprLen, 1);
|
||||
/* compr and uncompr are cleared to avoid reading uninitialized
|
||||
* data and to ensure that uncompr compresses well.
|
||||
*/
|
||||
if (compr == Z_NULL || uncompr == Z_NULL) {
|
||||
printf("out of memory\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
test_compress(compr, comprLen, uncompr, uncomprLen);
|
||||
|
||||
test_gzio((argc > 1 ? argv[1] : "foo.gz"),
|
||||
(argc > 2 ? argv[2] : "foo.gz"),
|
||||
uncompr, (int)uncomprLen);
|
||||
|
||||
test_deflate(compr, comprLen);
|
||||
test_inflate(compr, comprLen, uncompr, uncomprLen);
|
||||
|
||||
test_large_deflate(compr, comprLen, uncompr, uncomprLen);
|
||||
test_large_inflate(compr, comprLen, uncompr, uncomprLen);
|
||||
|
||||
test_flush(compr, comprLen);
|
||||
test_sync(compr, comprLen, uncompr, uncomprLen);
|
||||
|
||||
test_dict_deflate(compr, comprLen);
|
||||
test_dict_inflate(compr, comprLen, uncompr, uncomprLen);
|
||||
|
||||
exit(0);
|
||||
return 0; /* to avoid warning */
|
||||
}
|
||||
+523
@@ -0,0 +1,523 @@
|
||||
/* gzio.c -- IO on .gz files
|
||||
* Copyright (C) 1995-1996 Jean-loup Gailly.
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* $Id: gzio.c,v 1.14 1996/07/24 13:41:01 me Exp $ */
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "zutil.h"
|
||||
|
||||
struct internal_state {int dummy;}; /* for buggy compilers */
|
||||
|
||||
#define Z_BUFSIZE 4096
|
||||
|
||||
#define ALLOC(size) malloc(size)
|
||||
#define TRYFREE(p) {if (p) free(p);}
|
||||
|
||||
static int gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */
|
||||
|
||||
/* gzip flag byte */
|
||||
#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
|
||||
#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */
|
||||
#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
|
||||
#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
|
||||
#define COMMENT 0x10 /* bit 4 set: file comment present */
|
||||
#define RESERVED 0xE0 /* bits 5..7: reserved */
|
||||
|
||||
typedef struct gz_stream {
|
||||
z_stream stream;
|
||||
int z_err; /* error code for last stream operation */
|
||||
int z_eof; /* set if end of input file */
|
||||
FILE *file; /* .gz file */
|
||||
Byte *inbuf; /* input buffer */
|
||||
Byte *outbuf; /* output buffer */
|
||||
uLong crc; /* crc32 of uncompressed data */
|
||||
char *msg; /* error message */
|
||||
char *path; /* path name for debugging only */
|
||||
int transparent; /* 1 if input file is not a .gz file */
|
||||
char mode; /* 'w' or 'r' */
|
||||
} gz_stream;
|
||||
|
||||
|
||||
local gzFile gz_open OF((const char *path, const char *mode, int fd));
|
||||
local int get_byte OF((gz_stream *s));
|
||||
local void check_header OF((gz_stream *s));
|
||||
local int destroy OF((gz_stream *s));
|
||||
local void putLong OF((FILE *file, uLong x));
|
||||
local uLong getLong OF((gz_stream *s));
|
||||
|
||||
/* ===========================================================================
|
||||
Opens a gzip (.gz) file for reading or writing. The mode parameter
|
||||
is as in fopen ("rb" or "wb"). The file is given either by file descriptor
|
||||
or path name (if fd == -1).
|
||||
gz_open return NULL if the file could not be opened or if there was
|
||||
insufficient memory to allocate the (de)compression state; errno
|
||||
can be checked to distinguish the two cases (if errno is zero, the
|
||||
zlib error is Z_MEM_ERROR).
|
||||
*/
|
||||
local gzFile gz_open (path, mode, fd)
|
||||
const char *path;
|
||||
const char *mode;
|
||||
int fd;
|
||||
{
|
||||
int err;
|
||||
int level = Z_DEFAULT_COMPRESSION; /* compression level */
|
||||
char *p = (char*)mode;
|
||||
gz_stream *s;
|
||||
char fmode[80]; /* copy of mode, without the compression level */
|
||||
char *m = fmode;
|
||||
|
||||
if (!path || !mode) return Z_NULL;
|
||||
|
||||
s = (gz_stream *)ALLOC(sizeof(gz_stream));
|
||||
if (!s) return Z_NULL;
|
||||
|
||||
s->stream.zalloc = (alloc_func)0;
|
||||
s->stream.zfree = (free_func)0;
|
||||
s->stream.opaque = (voidpf)0;
|
||||
s->stream.next_in = s->inbuf = Z_NULL;
|
||||
s->stream.next_out = s->outbuf = Z_NULL;
|
||||
s->stream.avail_in = s->stream.avail_out = 0;
|
||||
s->file = NULL;
|
||||
s->z_err = Z_OK;
|
||||
s->z_eof = 0;
|
||||
s->crc = crc32(0L, Z_NULL, 0);
|
||||
s->msg = NULL;
|
||||
s->transparent = 0;
|
||||
|
||||
s->path = (char*)ALLOC(strlen(path)+1);
|
||||
if (s->path == NULL) {
|
||||
return destroy(s), (gzFile)Z_NULL;
|
||||
}
|
||||
strcpy(s->path, path); /* do this early for debugging */
|
||||
|
||||
s->mode = '\0';
|
||||
do {
|
||||
if (*p == 'r') s->mode = 'r';
|
||||
if (*p == 'w' || *p == 'a') s->mode = 'w';
|
||||
if (*p >= '0' && *p <= '9') {
|
||||
level = *p - '0';
|
||||
} else {
|
||||
*m++ = *p; /* copy the mode */
|
||||
}
|
||||
} while (*p++ && m != fmode + sizeof(fmode));
|
||||
if (s->mode == '\0') return destroy(s), (gzFile)Z_NULL;
|
||||
|
||||
if (s->mode == 'w') {
|
||||
err = deflateInit2(&(s->stream), level,
|
||||
Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, 0);
|
||||
/* windowBits is passed < 0 to suppress zlib header */
|
||||
|
||||
s->stream.next_out = s->outbuf = (Byte*)ALLOC(Z_BUFSIZE);
|
||||
|
||||
if (err != Z_OK || s->outbuf == Z_NULL) {
|
||||
return destroy(s), (gzFile)Z_NULL;
|
||||
}
|
||||
} else {
|
||||
err = inflateInit2(&(s->stream), -MAX_WBITS);
|
||||
s->stream.next_in = s->inbuf = (Byte*)ALLOC(Z_BUFSIZE);
|
||||
|
||||
if (err != Z_OK || s->inbuf == Z_NULL) {
|
||||
return destroy(s), (gzFile)Z_NULL;
|
||||
}
|
||||
}
|
||||
s->stream.avail_out = Z_BUFSIZE;
|
||||
|
||||
errno = 0;
|
||||
s->file = fd < 0 ? FOPEN(path, fmode) : (FILE*)fdopen(fd, fmode);
|
||||
|
||||
if (s->file == NULL) {
|
||||
return destroy(s), (gzFile)Z_NULL;
|
||||
}
|
||||
if (s->mode == 'w') {
|
||||
/* Write a very simple .gz header:
|
||||
*/
|
||||
fprintf(s->file, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1],
|
||||
Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE);
|
||||
} else {
|
||||
check_header(s); /* skip the .gz header */
|
||||
}
|
||||
return (gzFile)s;
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
Opens a gzip (.gz) file for reading or writing.
|
||||
*/
|
||||
gzFile gzopen (path, mode)
|
||||
const char *path;
|
||||
const char *mode;
|
||||
{
|
||||
return gz_open (path, mode, -1);
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
Associate a gzFile with the file descriptor fd. fd is not dup'ed here
|
||||
to mimic the behavio(u)r of fdopen.
|
||||
*/
|
||||
gzFile gzdopen (fd, mode)
|
||||
int fd;
|
||||
const char *mode;
|
||||
{
|
||||
char name[20];
|
||||
|
||||
if (fd < 0) return (gzFile)Z_NULL;
|
||||
sprintf(name, "<fd:%d>", fd); /* for debugging */
|
||||
|
||||
return gz_open (name, mode, fd);
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
Read a byte from a gz_stream; update next_in and avail_in. Return EOF
|
||||
for end of file.
|
||||
IN assertion: the stream s has been sucessfully opened for reading.
|
||||
*/
|
||||
local int get_byte(s)
|
||||
gz_stream *s;
|
||||
{
|
||||
if (s->z_eof) return EOF;
|
||||
if (s->stream.avail_in == 0) {
|
||||
errno = 0;
|
||||
s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file);
|
||||
if (s->stream.avail_in == 0) {
|
||||
s->z_eof = 1;
|
||||
if (ferror(s->file)) s->z_err = Z_ERRNO;
|
||||
return EOF;
|
||||
}
|
||||
s->stream.next_in = s->inbuf;
|
||||
}
|
||||
s->stream.avail_in--;
|
||||
return *(s->stream.next_in)++;
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
Check the gzip header of a gz_stream opened for reading. Set the stream
|
||||
mode to transparent if the gzip magic header is not present; set s->err
|
||||
to Z_DATA_ERROR if the magic header is present but the rest of the header
|
||||
is incorrect.
|
||||
IN assertion: the stream s has already been created sucessfully;
|
||||
s->stream.avail_in is zero for the first time, but may be non-zero
|
||||
for concatenated .gz files.
|
||||
*/
|
||||
local void check_header(s)
|
||||
gz_stream *s;
|
||||
{
|
||||
int method; /* method byte */
|
||||
int flags; /* flags byte */
|
||||
uInt len;
|
||||
int c;
|
||||
|
||||
/* Check the gzip magic header */
|
||||
for (len = 0; len < 2; len++) {
|
||||
c = get_byte(s);
|
||||
if (c != gz_magic[len]) {
|
||||
s->transparent = 1;
|
||||
if (c != EOF) s->stream.avail_in++, s->stream.next_in--;
|
||||
s->z_err = s->stream.avail_in != 0 ? Z_OK : Z_STREAM_END;
|
||||
return;
|
||||
}
|
||||
}
|
||||
method = get_byte(s);
|
||||
flags = get_byte(s);
|
||||
if (method != Z_DEFLATED || (flags & RESERVED) != 0) {
|
||||
s->z_err = Z_DATA_ERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Discard time, xflags and OS code: */
|
||||
for (len = 0; len < 6; len++) (void)get_byte(s);
|
||||
|
||||
if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */
|
||||
len = (uInt)get_byte(s);
|
||||
len += ((uInt)get_byte(s))<<8;
|
||||
/* len is garbage if EOF but the loop below will quit anyway */
|
||||
while (len-- != 0 && get_byte(s) != EOF) ;
|
||||
}
|
||||
if ((flags & ORIG_NAME) != 0) { /* skip the original file name */
|
||||
while ((c = get_byte(s)) != 0 && c != EOF) ;
|
||||
}
|
||||
if ((flags & COMMENT) != 0) { /* skip the .gz file comment */
|
||||
while ((c = get_byte(s)) != 0 && c != EOF) ;
|
||||
}
|
||||
if ((flags & HEAD_CRC) != 0) { /* skip the header crc */
|
||||
for (len = 0; len < 2; len++) (void)get_byte(s);
|
||||
}
|
||||
s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK;
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
* Cleanup then free the given gz_stream. Return a zlib error code.
|
||||
Try freeing in the reverse order of allocations.
|
||||
*/
|
||||
local int destroy (s)
|
||||
gz_stream *s;
|
||||
{
|
||||
int err = Z_OK;
|
||||
|
||||
if (!s) return Z_STREAM_ERROR;
|
||||
|
||||
TRYFREE(s->msg);
|
||||
|
||||
if (s->stream.state != NULL) {
|
||||
if (s->mode == 'w') {
|
||||
err = deflateEnd(&(s->stream));
|
||||
} else if (s->mode == 'r') {
|
||||
err = inflateEnd(&(s->stream));
|
||||
}
|
||||
}
|
||||
if (s->file != NULL && fclose(s->file)) {
|
||||
err = Z_ERRNO;
|
||||
}
|
||||
if (s->z_err < 0) err = s->z_err;
|
||||
|
||||
TRYFREE(s->inbuf);
|
||||
TRYFREE(s->outbuf);
|
||||
TRYFREE(s->path);
|
||||
TRYFREE(s);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
Reads the given number of uncompressed bytes from the compressed file.
|
||||
gzread returns the number of bytes actually read (0 for end of file).
|
||||
*/
|
||||
int gzread (file, buf, len)
|
||||
gzFile file;
|
||||
voidp buf;
|
||||
unsigned len;
|
||||
{
|
||||
gz_stream *s = (gz_stream*)file;
|
||||
Bytef *start = buf; /* starting point for crc computation */
|
||||
Byte *next_out; /* == stream.next_out but not forced far (for MSDOS) */
|
||||
|
||||
if (s == NULL || s->mode != 'r') return Z_STREAM_ERROR;
|
||||
|
||||
if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO) return -1;
|
||||
if (s->z_err == Z_STREAM_END) return 0; /* EOF */
|
||||
|
||||
s->stream.next_out = next_out = buf;
|
||||
s->stream.avail_out = len;
|
||||
|
||||
while (s->stream.avail_out != 0) {
|
||||
|
||||
if (s->transparent) {
|
||||
/* Copy first the lookahead bytes: */
|
||||
uInt n = s->stream.avail_in;
|
||||
if (n > s->stream.avail_out) n = s->stream.avail_out;
|
||||
if (n > 0) {
|
||||
zmemcpy(s->stream.next_out, s->stream.next_in, n);
|
||||
next_out += n;
|
||||
s->stream.next_out = next_out;
|
||||
s->stream.next_in += n;
|
||||
s->stream.avail_out -= n;
|
||||
s->stream.avail_in -= n;
|
||||
}
|
||||
if (s->stream.avail_out > 0) {
|
||||
s->stream.avail_out -= fread(next_out, 1, s->stream.avail_out,
|
||||
s->file);
|
||||
}
|
||||
return (int)(len - s->stream.avail_out);
|
||||
}
|
||||
if (s->stream.avail_in == 0 && !s->z_eof) {
|
||||
|
||||
errno = 0;
|
||||
s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file);
|
||||
if (s->stream.avail_in == 0) {
|
||||
s->z_eof = 1;
|
||||
if (ferror(s->file)) {
|
||||
s->z_err = Z_ERRNO;
|
||||
break;
|
||||
}
|
||||
}
|
||||
s->stream.next_in = s->inbuf;
|
||||
}
|
||||
s->z_err = inflate(&(s->stream), Z_NO_FLUSH);
|
||||
|
||||
if (s->z_err == Z_STREAM_END) {
|
||||
/* Check CRC and original size */
|
||||
s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start));
|
||||
start = s->stream.next_out;
|
||||
|
||||
if (getLong(s) != s->crc || getLong(s) != s->stream.total_out) {
|
||||
s->z_err = Z_DATA_ERROR;
|
||||
} else {
|
||||
/* Check for concatenated .gz files: */
|
||||
check_header(s);
|
||||
if (s->z_err == Z_OK) {
|
||||
inflateReset(&(s->stream));
|
||||
s->crc = crc32(0L, Z_NULL, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (s->z_err != Z_OK || s->z_eof) break;
|
||||
}
|
||||
s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start));
|
||||
|
||||
return (int)(len - s->stream.avail_out);
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
Writes the given number of uncompressed bytes into the compressed file.
|
||||
gzwrite returns the number of bytes actually written (0 in case of error).
|
||||
*/
|
||||
int gzwrite (file, buf, len)
|
||||
gzFile file;
|
||||
const voidp buf;
|
||||
unsigned len;
|
||||
{
|
||||
gz_stream *s = (gz_stream*)file;
|
||||
|
||||
if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
|
||||
|
||||
s->stream.next_in = buf;
|
||||
s->stream.avail_in = len;
|
||||
|
||||
while (s->stream.avail_in != 0) {
|
||||
|
||||
if (s->stream.avail_out == 0) {
|
||||
|
||||
s->stream.next_out = s->outbuf;
|
||||
if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) {
|
||||
s->z_err = Z_ERRNO;
|
||||
break;
|
||||
}
|
||||
s->stream.avail_out = Z_BUFSIZE;
|
||||
}
|
||||
s->z_err = deflate(&(s->stream), Z_NO_FLUSH);
|
||||
if (s->z_err != Z_OK) break;
|
||||
}
|
||||
s->crc = crc32(s->crc, buf, len);
|
||||
|
||||
return (int)(len - s->stream.avail_in);
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
Flushes all pending output into the compressed file. The parameter
|
||||
flush is as in the deflate() function.
|
||||
gzflush should be called only when strictly necessary because it can
|
||||
degrade compression.
|
||||
*/
|
||||
int gzflush (file, flush)
|
||||
gzFile file;
|
||||
int flush;
|
||||
{
|
||||
uInt len;
|
||||
int done = 0;
|
||||
gz_stream *s = (gz_stream*)file;
|
||||
|
||||
if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
|
||||
|
||||
s->stream.avail_in = 0; /* should be zero already anyway */
|
||||
|
||||
for (;;) {
|
||||
len = Z_BUFSIZE - s->stream.avail_out;
|
||||
|
||||
if (len != 0) {
|
||||
if ((uInt)fwrite(s->outbuf, 1, len, s->file) != len) {
|
||||
s->z_err = Z_ERRNO;
|
||||
return Z_ERRNO;
|
||||
}
|
||||
s->stream.next_out = s->outbuf;
|
||||
s->stream.avail_out = Z_BUFSIZE;
|
||||
}
|
||||
if (done) break;
|
||||
s->z_err = deflate(&(s->stream), flush);
|
||||
|
||||
/* deflate has finished flushing only when it hasn't used up
|
||||
* all the available space in the output buffer:
|
||||
*/
|
||||
done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END);
|
||||
|
||||
if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) break;
|
||||
}
|
||||
fflush(s->file);
|
||||
return s->z_err == Z_STREAM_END ? Z_OK : s->z_err;
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
Outputs a long in LSB order to the given file
|
||||
*/
|
||||
local void putLong (file, x)
|
||||
FILE *file;
|
||||
uLong x;
|
||||
{
|
||||
int n;
|
||||
for (n = 0; n < 4; n++) {
|
||||
fputc((int)(x & 0xff), file);
|
||||
x >>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
Reads a long in LSB order from the given gz_stream. Sets
|
||||
*/
|
||||
local uLong getLong (s)
|
||||
gz_stream *s;
|
||||
{
|
||||
uLong x = (uLong)get_byte(s);
|
||||
int c;
|
||||
|
||||
x += ((uLong)get_byte(s))<<8;
|
||||
x += ((uLong)get_byte(s))<<16;
|
||||
c = get_byte(s);
|
||||
if (c == EOF) s->z_err = Z_DATA_ERROR;
|
||||
x += ((uLong)c)<<24;
|
||||
return x;
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
Flushes all pending output if necessary, closes the compressed file
|
||||
and deallocates all the (de)compression state.
|
||||
*/
|
||||
int gzclose (file)
|
||||
gzFile file;
|
||||
{
|
||||
int err;
|
||||
gz_stream *s = (gz_stream*)file;
|
||||
|
||||
if (s == NULL) return Z_STREAM_ERROR;
|
||||
|
||||
if (s->mode == 'w') {
|
||||
err = gzflush (file, Z_FINISH);
|
||||
if (err != Z_OK) return destroy(file);
|
||||
|
||||
putLong (s->file, s->crc);
|
||||
putLong (s->file, s->stream.total_in);
|
||||
|
||||
}
|
||||
return destroy(file);
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
Returns the error message for the last error which occured on the
|
||||
given compressed file. errnum is set to zlib error number. If an
|
||||
error occured in the file system and not in the compression library,
|
||||
errnum is set to Z_ERRNO and the application may consult errno
|
||||
to get the exact error code.
|
||||
*/
|
||||
const char* gzerror (file, errnum)
|
||||
gzFile file;
|
||||
int *errnum;
|
||||
{
|
||||
char *m;
|
||||
gz_stream *s = (gz_stream*)file;
|
||||
|
||||
if (s == NULL) {
|
||||
*errnum = Z_STREAM_ERROR;
|
||||
return (const char*)ERR_MSG(Z_STREAM_ERROR);
|
||||
}
|
||||
*errnum = s->z_err;
|
||||
if (*errnum == Z_OK) return (const char*)"";
|
||||
|
||||
m = (char*)(*errnum == Z_ERRNO ? zstrerror(errno) : s->stream.msg);
|
||||
|
||||
if (m == NULL || *m == '\0') m = (char*)ERR_MSG(s->z_err);
|
||||
|
||||
TRYFREE(s->msg);
|
||||
s->msg = (char*)ALLOC(strlen(s->path) + strlen(m) + 3);
|
||||
strcpy(s->msg, s->path);
|
||||
strcat(s->msg, ": ");
|
||||
strcat(s->msg, m);
|
||||
return (const char*)s->msg;
|
||||
}
|
||||
@@ -0,0 +1,402 @@
|
||||
/* infblock.c -- interpret and process block types to last block
|
||||
* Copyright (C) 1995-1996 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#include "zutil.h"
|
||||
#include "infblock.h"
|
||||
#include "inftrees.h"
|
||||
#include "infcodes.h"
|
||||
#include "infutil.h"
|
||||
|
||||
struct inflate_codes_state {int dummy;}; /* for buggy compilers */
|
||||
|
||||
/* Table for deflate from PKZIP's appnote.txt. */
|
||||
local uInt border[] = { /* Order of the bit length code lengths */
|
||||
16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
|
||||
|
||||
/*
|
||||
Notes beyond the 1.93a appnote.txt:
|
||||
|
||||
1. Distance pointers never point before the beginning of the output
|
||||
stream.
|
||||
2. Distance pointers can point back across blocks, up to 32k away.
|
||||
3. There is an implied maximum of 7 bits for the bit length table and
|
||||
15 bits for the actual data.
|
||||
4. If only one code exists, then it is encoded using one bit. (Zero
|
||||
would be more efficient, but perhaps a little confusing.) If two
|
||||
codes exist, they are coded using one bit each (0 and 1).
|
||||
5. There is no way of sending zero distance codes--a dummy must be
|
||||
sent if there are none. (History: a pre 2.0 version of PKZIP would
|
||||
store blocks with no distance codes, but this was discovered to be
|
||||
too harsh a criterion.) Valid only for 1.93a. 2.04c does allow
|
||||
zero distance codes, which is sent as one code of zero bits in
|
||||
length.
|
||||
6. There are up to 286 literal/length codes. Code 256 represents the
|
||||
end-of-block. Note however that the static length tree defines
|
||||
288 codes just to fill out the Huffman codes. Codes 286 and 287
|
||||
cannot be used though, since there is no length base or extra bits
|
||||
defined for them. Similarily, there are up to 30 distance codes.
|
||||
However, static trees define 32 codes (all 5 bits) to fill out the
|
||||
Huffman codes, but the last two had better not show up in the data.
|
||||
7. Unzip can check dynamic Huffman blocks for complete code sets.
|
||||
The exception is that a single code would not be complete (see #4).
|
||||
8. The five bits following the block type is really the number of
|
||||
literal codes sent minus 257.
|
||||
9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits
|
||||
(1+6+6). Therefore, to output three times the length, you output
|
||||
three codes (1+1+1), whereas to output four times the same length,
|
||||
you only need two codes (1+3). Hmm.
|
||||
10. In the tree reconstruction algorithm, Code = Code + Increment
|
||||
only if BitLength(i) is not zero. (Pretty obvious.)
|
||||
11. Correction: 4 Bits: # of Bit Length codes - 4 (4 - 19)
|
||||
12. Note: length code 284 can represent 227-258, but length code 285
|
||||
really is 258. The last length deserves its own, short code
|
||||
since it gets used a lot in very redundant files. The length
|
||||
258 is special since 258 - 3 (the min match length) is 255.
|
||||
13. The literal/length and distance code bit lengths are read as a
|
||||
single stream of lengths. It is possible (and advantageous) for
|
||||
a repeat code (16, 17, or 18) to go across the boundary between
|
||||
the two sets of lengths.
|
||||
*/
|
||||
|
||||
|
||||
void inflate_blocks_reset(s, z, c)
|
||||
inflate_blocks_statef *s;
|
||||
z_streamp z;
|
||||
uLongf *c;
|
||||
{
|
||||
if (s->checkfn != Z_NULL)
|
||||
*c = s->check;
|
||||
if (s->mode == BTREE || s->mode == DTREE)
|
||||
ZFREE(z, s->sub.trees.blens);
|
||||
if (s->mode == CODES)
|
||||
{
|
||||
inflate_codes_free(s->sub.decode.codes, z);
|
||||
inflate_trees_free(s->sub.decode.td, z);
|
||||
inflate_trees_free(s->sub.decode.tl, z);
|
||||
}
|
||||
s->mode = TYPE;
|
||||
s->bitk = 0;
|
||||
s->bitb = 0;
|
||||
s->read = s->write = s->window;
|
||||
if (s->checkfn != Z_NULL)
|
||||
z->adler = s->check = (*s->checkfn)(0L, Z_NULL, 0);
|
||||
Trace((stderr, "inflate: blocks reset\n"));
|
||||
}
|
||||
|
||||
|
||||
inflate_blocks_statef *inflate_blocks_new(z, c, w)
|
||||
z_streamp z;
|
||||
check_func c;
|
||||
uInt w;
|
||||
{
|
||||
inflate_blocks_statef *s;
|
||||
|
||||
if ((s = (inflate_blocks_statef *)ZALLOC
|
||||
(z,1,sizeof(struct inflate_blocks_state))) == Z_NULL)
|
||||
return s;
|
||||
if ((s->window = (Bytef *)ZALLOC(z, 1, w)) == Z_NULL)
|
||||
{
|
||||
ZFREE(z, s);
|
||||
return Z_NULL;
|
||||
}
|
||||
s->end = s->window + w;
|
||||
s->checkfn = c;
|
||||
s->mode = TYPE;
|
||||
Trace((stderr, "inflate: blocks allocated\n"));
|
||||
inflate_blocks_reset(s, z, &s->check);
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
extern uInt inflate_hufts;
|
||||
#endif
|
||||
int inflate_blocks(s, z, r)
|
||||
inflate_blocks_statef *s;
|
||||
z_streamp z;
|
||||
int r;
|
||||
{
|
||||
uInt t; /* temporary storage */
|
||||
uLong b; /* bit buffer */
|
||||
uInt k; /* bits in bit buffer */
|
||||
Bytef *p; /* input data pointer */
|
||||
uInt n; /* bytes available there */
|
||||
Bytef *q; /* output window write pointer */
|
||||
uInt m; /* bytes to end of window or read pointer */
|
||||
|
||||
/* copy input/output information to locals (UPDATE macro restores) */
|
||||
LOAD
|
||||
|
||||
/* process input based on current state */
|
||||
while (1) switch (s->mode)
|
||||
{
|
||||
case TYPE:
|
||||
NEEDBITS(3)
|
||||
t = (uInt)b & 7;
|
||||
s->last = t & 1;
|
||||
switch (t >> 1)
|
||||
{
|
||||
case 0: /* stored */
|
||||
Trace((stderr, "inflate: stored block%s\n",
|
||||
s->last ? " (last)" : ""));
|
||||
DUMPBITS(3)
|
||||
t = k & 7; /* go to byte boundary */
|
||||
DUMPBITS(t)
|
||||
s->mode = LENS; /* get length of stored block */
|
||||
break;
|
||||
case 1: /* fixed */
|
||||
Trace((stderr, "inflate: fixed codes block%s\n",
|
||||
s->last ? " (last)" : ""));
|
||||
{
|
||||
uInt bl, bd;
|
||||
inflate_huft *tl, *td;
|
||||
|
||||
inflate_trees_fixed(&bl, &bd, &tl, &td);
|
||||
s->sub.decode.codes = inflate_codes_new(bl, bd, tl, td, z);
|
||||
if (s->sub.decode.codes == Z_NULL)
|
||||
{
|
||||
r = Z_MEM_ERROR;
|
||||
LEAVE
|
||||
}
|
||||
s->sub.decode.tl = Z_NULL; /* don't try to free these */
|
||||
s->sub.decode.td = Z_NULL;
|
||||
}
|
||||
DUMPBITS(3)
|
||||
s->mode = CODES;
|
||||
break;
|
||||
case 2: /* dynamic */
|
||||
Trace((stderr, "inflate: dynamic codes block%s\n",
|
||||
s->last ? " (last)" : ""));
|
||||
DUMPBITS(3)
|
||||
s->mode = TABLE;
|
||||
break;
|
||||
case 3: /* illegal */
|
||||
DUMPBITS(3)
|
||||
s->mode = BAD;
|
||||
z->msg = (char*)"invalid block type";
|
||||
r = Z_DATA_ERROR;
|
||||
LEAVE
|
||||
}
|
||||
break;
|
||||
case LENS:
|
||||
NEEDBITS(32)
|
||||
if ((((~b) >> 16) & 0xffff) != (b & 0xffff))
|
||||
{
|
||||
s->mode = BAD;
|
||||
z->msg = (char*)"invalid stored block lengths";
|
||||
r = Z_DATA_ERROR;
|
||||
LEAVE
|
||||
}
|
||||
s->sub.left = (uInt)b & 0xffff;
|
||||
b = k = 0; /* dump bits */
|
||||
Tracev((stderr, "inflate: stored length %u\n", s->sub.left));
|
||||
s->mode = s->sub.left ? STORED : (s->last ? DRY : TYPE);
|
||||
break;
|
||||
case STORED:
|
||||
if (n == 0)
|
||||
LEAVE
|
||||
NEEDOUT
|
||||
t = s->sub.left;
|
||||
if (t > n) t = n;
|
||||
if (t > m) t = m;
|
||||
zmemcpy(q, p, t);
|
||||
p += t; n -= t;
|
||||
q += t; m -= t;
|
||||
if ((s->sub.left -= t) != 0)
|
||||
break;
|
||||
Tracev((stderr, "inflate: stored end, %lu total out\n",
|
||||
z->total_out + (q >= s->read ? q - s->read :
|
||||
(s->end - s->read) + (q - s->window))));
|
||||
s->mode = s->last ? DRY : TYPE;
|
||||
break;
|
||||
case TABLE:
|
||||
NEEDBITS(14)
|
||||
s->sub.trees.table = t = (uInt)b & 0x3fff;
|
||||
#ifndef PKZIP_BUG_WORKAROUND
|
||||
if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29)
|
||||
{
|
||||
s->mode = BAD;
|
||||
z->msg = (char*)"too many length or distance symbols";
|
||||
r = Z_DATA_ERROR;
|
||||
LEAVE
|
||||
}
|
||||
#endif
|
||||
t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f);
|
||||
if (t < 19)
|
||||
t = 19;
|
||||
if ((s->sub.trees.blens = (uIntf*)ZALLOC(z, t, sizeof(uInt))) == Z_NULL)
|
||||
{
|
||||
r = Z_MEM_ERROR;
|
||||
LEAVE
|
||||
}
|
||||
DUMPBITS(14)
|
||||
s->sub.trees.index = 0;
|
||||
Tracev((stderr, "inflate: table sizes ok\n"));
|
||||
s->mode = BTREE;
|
||||
case BTREE:
|
||||
while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10))
|
||||
{
|
||||
NEEDBITS(3)
|
||||
s->sub.trees.blens[border[s->sub.trees.index++]] = (uInt)b & 7;
|
||||
DUMPBITS(3)
|
||||
}
|
||||
while (s->sub.trees.index < 19)
|
||||
s->sub.trees.blens[border[s->sub.trees.index++]] = 0;
|
||||
s->sub.trees.bb = 7;
|
||||
t = inflate_trees_bits(s->sub.trees.blens, &s->sub.trees.bb,
|
||||
&s->sub.trees.tb, z);
|
||||
if (t != Z_OK)
|
||||
{
|
||||
r = t;
|
||||
if (r == Z_DATA_ERROR)
|
||||
s->mode = BAD;
|
||||
LEAVE
|
||||
}
|
||||
s->sub.trees.index = 0;
|
||||
Tracev((stderr, "inflate: bits tree ok\n"));
|
||||
s->mode = DTREE;
|
||||
case DTREE:
|
||||
while (t = s->sub.trees.table,
|
||||
s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f))
|
||||
{
|
||||
inflate_huft *h;
|
||||
uInt i, j, c;
|
||||
|
||||
t = s->sub.trees.bb;
|
||||
NEEDBITS(t)
|
||||
h = s->sub.trees.tb + ((uInt)b & inflate_mask[t]);
|
||||
t = h->word.what.Bits;
|
||||
c = h->more.Base;
|
||||
if (c < 16)
|
||||
{
|
||||
DUMPBITS(t)
|
||||
s->sub.trees.blens[s->sub.trees.index++] = c;
|
||||
}
|
||||
else /* c == 16..18 */
|
||||
{
|
||||
i = c == 18 ? 7 : c - 14;
|
||||
j = c == 18 ? 11 : 3;
|
||||
NEEDBITS(t + i)
|
||||
DUMPBITS(t)
|
||||
j += (uInt)b & inflate_mask[i];
|
||||
DUMPBITS(i)
|
||||
i = s->sub.trees.index;
|
||||
t = s->sub.trees.table;
|
||||
if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) ||
|
||||
(c == 16 && i < 1))
|
||||
{
|
||||
s->mode = BAD;
|
||||
z->msg = (char*)"invalid bit length repeat";
|
||||
r = Z_DATA_ERROR;
|
||||
LEAVE
|
||||
}
|
||||
c = c == 16 ? s->sub.trees.blens[i - 1] : 0;
|
||||
do {
|
||||
s->sub.trees.blens[i++] = c;
|
||||
} while (--j);
|
||||
s->sub.trees.index = i;
|
||||
}
|
||||
}
|
||||
inflate_trees_free(s->sub.trees.tb, z);
|
||||
s->sub.trees.tb = Z_NULL;
|
||||
{
|
||||
uInt bl, bd;
|
||||
inflate_huft *tl, *td;
|
||||
inflate_codes_statef *c;
|
||||
|
||||
bl = 9; /* must be <= 9 for lookahead assumptions */
|
||||
bd = 6; /* must be <= 9 for lookahead assumptions */
|
||||
t = s->sub.trees.table;
|
||||
#ifdef DEBUG
|
||||
inflate_hufts = 0;
|
||||
#endif
|
||||
t = inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f),
|
||||
s->sub.trees.blens, &bl, &bd, &tl, &td, z);
|
||||
if (t != Z_OK)
|
||||
{
|
||||
if (t == (uInt)Z_DATA_ERROR)
|
||||
s->mode = BAD;
|
||||
r = t;
|
||||
LEAVE
|
||||
}
|
||||
Tracev((stderr, "inflate: trees ok, %d * %d bytes used\n",
|
||||
inflate_hufts, sizeof(inflate_huft)));
|
||||
if ((c = inflate_codes_new(bl, bd, tl, td, z)) == Z_NULL)
|
||||
{
|
||||
inflate_trees_free(td, z);
|
||||
inflate_trees_free(tl, z);
|
||||
r = Z_MEM_ERROR;
|
||||
LEAVE
|
||||
}
|
||||
ZFREE(z, s->sub.trees.blens);
|
||||
s->sub.decode.codes = c;
|
||||
s->sub.decode.tl = tl;
|
||||
s->sub.decode.td = td;
|
||||
}
|
||||
s->mode = CODES;
|
||||
case CODES:
|
||||
UPDATE
|
||||
if ((r = inflate_codes(s, z, r)) != Z_STREAM_END)
|
||||
return inflate_flush(s, z, r);
|
||||
r = Z_OK;
|
||||
inflate_codes_free(s->sub.decode.codes, z);
|
||||
inflate_trees_free(s->sub.decode.td, z);
|
||||
inflate_trees_free(s->sub.decode.tl, z);
|
||||
LOAD
|
||||
Tracev((stderr, "inflate: codes end, %lu total out\n",
|
||||
z->total_out + (q >= s->read ? q - s->read :
|
||||
(s->end - s->read) + (q - s->window))));
|
||||
if (!s->last)
|
||||
{
|
||||
s->mode = TYPE;
|
||||
break;
|
||||
}
|
||||
if (k > 7) /* return unused byte, if any */
|
||||
{
|
||||
Assert(k < 16, "inflate_codes grabbed too many bytes")
|
||||
k -= 8;
|
||||
n++;
|
||||
p--; /* can always return one */
|
||||
}
|
||||
s->mode = DRY;
|
||||
case DRY:
|
||||
FLUSH
|
||||
if (s->read != s->write)
|
||||
LEAVE
|
||||
s->mode = DONE;
|
||||
case DONE:
|
||||
r = Z_STREAM_END;
|
||||
LEAVE
|
||||
case BAD:
|
||||
r = Z_DATA_ERROR;
|
||||
LEAVE
|
||||
default:
|
||||
r = Z_STREAM_ERROR;
|
||||
LEAVE
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int inflate_blocks_free(s, z, c)
|
||||
inflate_blocks_statef *s;
|
||||
z_streamp z;
|
||||
uLongf *c;
|
||||
{
|
||||
inflate_blocks_reset(s, z, c);
|
||||
ZFREE(z, s->window);
|
||||
ZFREE(z, s);
|
||||
Trace((stderr, "inflate: blocks freed\n"));
|
||||
return Z_OK;
|
||||
}
|
||||
|
||||
|
||||
void inflate_set_dictionary(s, d, n)
|
||||
inflate_blocks_statef *s;
|
||||
const Bytef *d;
|
||||
uInt n;
|
||||
{
|
||||
zmemcpy((charf *)s->window, d, n);
|
||||
s->read = s->write = s->window + n;
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/* infblock.h -- header to use infblock.c
|
||||
* Copyright (C) 1995-1996 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* WARNING: this file should *not* be used by applications. It is
|
||||
part of the implementation of the compression library and is
|
||||
subject to change. Applications should only use zlib.h.
|
||||
*/
|
||||
|
||||
struct inflate_blocks_state;
|
||||
typedef struct inflate_blocks_state FAR inflate_blocks_statef;
|
||||
|
||||
extern inflate_blocks_statef * inflate_blocks_new OF((
|
||||
z_streamp z,
|
||||
check_func c, /* check function */
|
||||
uInt w)); /* window size */
|
||||
|
||||
extern int inflate_blocks OF((
|
||||
inflate_blocks_statef *,
|
||||
z_streamp ,
|
||||
int)); /* initial return code */
|
||||
|
||||
extern void inflate_blocks_reset OF((
|
||||
inflate_blocks_statef *,
|
||||
z_streamp ,
|
||||
uLongf *)); /* check value on output */
|
||||
|
||||
extern int inflate_blocks_free OF((
|
||||
inflate_blocks_statef *,
|
||||
z_streamp ,
|
||||
uLongf *)); /* check value on output */
|
||||
|
||||
extern void inflate_set_dictionary OF((
|
||||
inflate_blocks_statef *s,
|
||||
const Bytef *d, /* dictionary */
|
||||
uInt n)); /* dictionary length */
|
||||
@@ -0,0 +1,247 @@
|
||||
/* infcodes.c -- process literals and length/distance pairs
|
||||
* Copyright (C) 1995-1996 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#include "zutil.h"
|
||||
#include "inftrees.h"
|
||||
#include "infblock.h"
|
||||
#include "infcodes.h"
|
||||
#include "infutil.h"
|
||||
#include "inffast.h"
|
||||
|
||||
/* simplify the use of the inflate_huft type with some defines */
|
||||
#define base more.Base
|
||||
#define next more.Next
|
||||
#define exop word.what.Exop
|
||||
#define bits word.what.Bits
|
||||
|
||||
/* inflate codes private state */
|
||||
struct inflate_codes_state {
|
||||
|
||||
/* mode */
|
||||
enum { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
|
||||
START, /* x: set up for LEN */
|
||||
LEN, /* i: get length/literal/eob next */
|
||||
LENEXT, /* i: getting length extra (have base) */
|
||||
DIST, /* i: get distance next */
|
||||
DISTEXT, /* i: getting distance extra */
|
||||
COPY, /* o: copying bytes in window, waiting for space */
|
||||
LIT, /* o: got literal, waiting for output space */
|
||||
WASH, /* o: got eob, possibly still output waiting */
|
||||
END, /* x: got eob and all data flushed */
|
||||
BADCODE} /* x: got error */
|
||||
mode; /* current inflate_codes mode */
|
||||
|
||||
/* mode dependent information */
|
||||
uInt len;
|
||||
union {
|
||||
struct {
|
||||
inflate_huft *tree; /* pointer into tree */
|
||||
uInt need; /* bits needed */
|
||||
} code; /* if LEN or DIST, where in tree */
|
||||
uInt lit; /* if LIT, literal */
|
||||
struct {
|
||||
uInt get; /* bits to get for extra */
|
||||
uInt dist; /* distance back to copy from */
|
||||
} copy; /* if EXT or COPY, where and how much */
|
||||
} sub; /* submode */
|
||||
|
||||
/* mode independent information */
|
||||
Byte lbits; /* ltree bits decoded per branch */
|
||||
Byte dbits; /* dtree bits decoder per branch */
|
||||
inflate_huft *ltree; /* literal/length/eob tree */
|
||||
inflate_huft *dtree; /* distance tree */
|
||||
|
||||
};
|
||||
|
||||
|
||||
inflate_codes_statef *inflate_codes_new(bl, bd, tl, td, z)
|
||||
uInt bl, bd;
|
||||
inflate_huft *tl;
|
||||
inflate_huft *td; /* need separate declaration for Borland C++ */
|
||||
z_streamp z;
|
||||
{
|
||||
inflate_codes_statef *c;
|
||||
|
||||
if ((c = (inflate_codes_statef *)
|
||||
ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL)
|
||||
{
|
||||
c->mode = START;
|
||||
c->lbits = (Byte)bl;
|
||||
c->dbits = (Byte)bd;
|
||||
c->ltree = tl;
|
||||
c->dtree = td;
|
||||
Tracev((stderr, "inflate: codes new\n"));
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
int inflate_codes(s, z, r)
|
||||
inflate_blocks_statef *s;
|
||||
z_streamp z;
|
||||
int r;
|
||||
{
|
||||
uInt j; /* temporary storage */
|
||||
inflate_huft *t; /* temporary pointer */
|
||||
uInt e; /* extra bits or operation */
|
||||
uLong b; /* bit buffer */
|
||||
uInt k; /* bits in bit buffer */
|
||||
Bytef *p; /* input data pointer */
|
||||
uInt n; /* bytes available there */
|
||||
Bytef *q; /* output window write pointer */
|
||||
uInt m; /* bytes to end of window or read pointer */
|
||||
Bytef *f; /* pointer to copy strings from */
|
||||
inflate_codes_statef *c = s->sub.decode.codes; /* codes state */
|
||||
|
||||
/* copy input/output information to locals (UPDATE macro restores) */
|
||||
LOAD
|
||||
|
||||
/* process input and output based on current state */
|
||||
while (1) switch (c->mode)
|
||||
{ /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
|
||||
case START: /* x: set up for LEN */
|
||||
#ifndef SLOW
|
||||
if (m >= 258 && n >= 10)
|
||||
{
|
||||
UPDATE
|
||||
r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z);
|
||||
LOAD
|
||||
if (r != Z_OK)
|
||||
{
|
||||
c->mode = r == Z_STREAM_END ? WASH : BADCODE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif /* !SLOW */
|
||||
c->sub.code.need = c->lbits;
|
||||
c->sub.code.tree = c->ltree;
|
||||
c->mode = LEN;
|
||||
case LEN: /* i: get length/literal/eob next */
|
||||
j = c->sub.code.need;
|
||||
NEEDBITS(j)
|
||||
t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
|
||||
DUMPBITS(t->bits)
|
||||
e = (uInt)(t->exop);
|
||||
if (e == 0) /* literal */
|
||||
{
|
||||
c->sub.lit = t->base;
|
||||
Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
|
||||
"inflate: literal '%c'\n" :
|
||||
"inflate: literal 0x%02x\n", t->base));
|
||||
c->mode = LIT;
|
||||
break;
|
||||
}
|
||||
if (e & 16) /* length */
|
||||
{
|
||||
c->sub.copy.get = e & 15;
|
||||
c->len = t->base;
|
||||
c->mode = LENEXT;
|
||||
break;
|
||||
}
|
||||
if ((e & 64) == 0) /* next table */
|
||||
{
|
||||
c->sub.code.need = e;
|
||||
c->sub.code.tree = t->next;
|
||||
break;
|
||||
}
|
||||
if (e & 32) /* end of block */
|
||||
{
|
||||
Tracevv((stderr, "inflate: end of block\n"));
|
||||
c->mode = WASH;
|
||||
break;
|
||||
}
|
||||
c->mode = BADCODE; /* invalid code */
|
||||
z->msg = (char*)"invalid literal/length code";
|
||||
r = Z_DATA_ERROR;
|
||||
LEAVE
|
||||
case LENEXT: /* i: getting length extra (have base) */
|
||||
j = c->sub.copy.get;
|
||||
NEEDBITS(j)
|
||||
c->len += (uInt)b & inflate_mask[j];
|
||||
DUMPBITS(j)
|
||||
c->sub.code.need = c->dbits;
|
||||
c->sub.code.tree = c->dtree;
|
||||
Tracevv((stderr, "inflate: length %u\n", c->len));
|
||||
c->mode = DIST;
|
||||
case DIST: /* i: get distance next */
|
||||
j = c->sub.code.need;
|
||||
NEEDBITS(j)
|
||||
t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
|
||||
DUMPBITS(t->bits)
|
||||
e = (uInt)(t->exop);
|
||||
if (e & 16) /* distance */
|
||||
{
|
||||
c->sub.copy.get = e & 15;
|
||||
c->sub.copy.dist = t->base;
|
||||
c->mode = DISTEXT;
|
||||
break;
|
||||
}
|
||||
if ((e & 64) == 0) /* next table */
|
||||
{
|
||||
c->sub.code.need = e;
|
||||
c->sub.code.tree = t->next;
|
||||
break;
|
||||
}
|
||||
c->mode = BADCODE; /* invalid code */
|
||||
z->msg = (char*)"invalid distance code";
|
||||
r = Z_DATA_ERROR;
|
||||
LEAVE
|
||||
case DISTEXT: /* i: getting distance extra */
|
||||
j = c->sub.copy.get;
|
||||
NEEDBITS(j)
|
||||
c->sub.copy.dist += (uInt)b & inflate_mask[j];
|
||||
DUMPBITS(j)
|
||||
Tracevv((stderr, "inflate: distance %u\n", c->sub.copy.dist));
|
||||
c->mode = COPY;
|
||||
case COPY: /* o: copying bytes in window, waiting for space */
|
||||
#ifndef __TURBOC__ /* Turbo C bug for following expression */
|
||||
f = (uInt)(q - s->window) < c->sub.copy.dist ?
|
||||
s->end - (c->sub.copy.dist - (q - s->window)) :
|
||||
q - c->sub.copy.dist;
|
||||
#else
|
||||
f = q - c->sub.copy.dist;
|
||||
if ((uInt)(q - s->window) < c->sub.copy.dist)
|
||||
f = s->end - (c->sub.copy.dist - (uInt)(q - s->window));
|
||||
#endif
|
||||
while (c->len)
|
||||
{
|
||||
NEEDOUT
|
||||
OUTBYTE(*f++)
|
||||
if (f == s->end)
|
||||
f = s->window;
|
||||
c->len--;
|
||||
}
|
||||
c->mode = START;
|
||||
break;
|
||||
case LIT: /* o: got literal, waiting for output space */
|
||||
NEEDOUT
|
||||
OUTBYTE(c->sub.lit)
|
||||
c->mode = START;
|
||||
break;
|
||||
case WASH: /* o: got eob, possibly more output */
|
||||
FLUSH
|
||||
if (s->read != s->write)
|
||||
LEAVE
|
||||
c->mode = END;
|
||||
case END:
|
||||
r = Z_STREAM_END;
|
||||
LEAVE
|
||||
case BADCODE: /* x: got error */
|
||||
r = Z_DATA_ERROR;
|
||||
LEAVE
|
||||
default:
|
||||
r = Z_STREAM_ERROR;
|
||||
LEAVE
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void inflate_codes_free(c, z)
|
||||
inflate_codes_statef *c;
|
||||
z_streamp z;
|
||||
{
|
||||
ZFREE(z, c);
|
||||
Tracev((stderr, "inflate: codes free\n"));
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/* infcodes.h -- header to use infcodes.c
|
||||
* Copyright (C) 1995-1996 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* WARNING: this file should *not* be used by applications. It is
|
||||
part of the implementation of the compression library and is
|
||||
subject to change. Applications should only use zlib.h.
|
||||
*/
|
||||
|
||||
struct inflate_codes_state;
|
||||
typedef struct inflate_codes_state FAR inflate_codes_statef;
|
||||
|
||||
extern inflate_codes_statef *inflate_codes_new OF((
|
||||
uInt, uInt,
|
||||
inflate_huft *, inflate_huft *,
|
||||
z_streamp ));
|
||||
|
||||
extern int inflate_codes OF((
|
||||
inflate_blocks_statef *,
|
||||
z_streamp ,
|
||||
int));
|
||||
|
||||
extern void inflate_codes_free OF((
|
||||
inflate_codes_statef *,
|
||||
z_streamp ));
|
||||
|
||||
@@ -0,0 +1,168 @@
|
||||
/* inffast.c -- process literals and length/distance pairs fast
|
||||
* Copyright (C) 1995-1996 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#include "zutil.h"
|
||||
#include "inftrees.h"
|
||||
#include "infblock.h"
|
||||
#include "infcodes.h"
|
||||
#include "infutil.h"
|
||||
#include "inffast.h"
|
||||
|
||||
struct inflate_codes_state {int dummy;}; /* for buggy compilers */
|
||||
|
||||
/* simplify the use of the inflate_huft type with some defines */
|
||||
#define base more.Base
|
||||
#define next more.Next
|
||||
#define exop word.what.Exop
|
||||
#define bits word.what.Bits
|
||||
|
||||
/* macros for bit input with no checking and for returning unused bytes */
|
||||
#define GRABBITS(j) {while(k<(j)){b|=((uLong)NEXTBYTE)<<k;k+=8;}}
|
||||
#define UNGRAB {n+=(c=k>>3);p-=c;k&=7;}
|
||||
|
||||
/* Called with number of bytes left to write in window at least 258
|
||||
(the maximum string length) and number of input bytes available
|
||||
at least ten. The ten bytes are six bytes for the longest length/
|
||||
distance pair plus four bytes for overloading the bit buffer. */
|
||||
|
||||
int inflate_fast(bl, bd, tl, td, s, z)
|
||||
uInt bl, bd;
|
||||
inflate_huft *tl;
|
||||
inflate_huft *td; /* need separate declaration for Borland C++ */
|
||||
inflate_blocks_statef *s;
|
||||
z_streamp z;
|
||||
{
|
||||
inflate_huft *t; /* temporary pointer */
|
||||
uInt e; /* extra bits or operation */
|
||||
uLong b; /* bit buffer */
|
||||
uInt k; /* bits in bit buffer */
|
||||
Bytef *p; /* input data pointer */
|
||||
uInt n; /* bytes available there */
|
||||
Bytef *q; /* output window write pointer */
|
||||
uInt m; /* bytes to end of window or read pointer */
|
||||
uInt ml; /* mask for literal/length tree */
|
||||
uInt md; /* mask for distance tree */
|
||||
uInt c; /* bytes to copy */
|
||||
uInt d; /* distance back to copy from */
|
||||
Bytef *r; /* copy source pointer */
|
||||
|
||||
/* load input, output, bit values */
|
||||
LOAD
|
||||
|
||||
/* initialize masks */
|
||||
ml = inflate_mask[bl];
|
||||
md = inflate_mask[bd];
|
||||
|
||||
/* do until not enough input or output space for fast loop */
|
||||
do { /* assume called with m >= 258 && n >= 10 */
|
||||
/* get literal/length code */
|
||||
GRABBITS(20) /* max bits for literal/length code */
|
||||
if ((e = (t = tl + ((uInt)b & ml))->exop) == 0)
|
||||
{
|
||||
DUMPBITS(t->bits)
|
||||
Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
|
||||
"inflate: * literal '%c'\n" :
|
||||
"inflate: * literal 0x%02x\n", t->base));
|
||||
*q++ = (Byte)t->base;
|
||||
m--;
|
||||
continue;
|
||||
}
|
||||
do {
|
||||
DUMPBITS(t->bits)
|
||||
if (e & 16)
|
||||
{
|
||||
/* get extra bits for length */
|
||||
e &= 15;
|
||||
c = t->base + ((uInt)b & inflate_mask[e]);
|
||||
DUMPBITS(e)
|
||||
Tracevv((stderr, "inflate: * length %u\n", c));
|
||||
|
||||
/* decode distance base of block to copy */
|
||||
GRABBITS(15); /* max bits for distance code */
|
||||
e = (t = td + ((uInt)b & md))->exop;
|
||||
do {
|
||||
DUMPBITS(t->bits)
|
||||
if (e & 16)
|
||||
{
|
||||
/* get extra bits to add to distance base */
|
||||
e &= 15;
|
||||
GRABBITS(e) /* get extra bits (up to 13) */
|
||||
d = t->base + ((uInt)b & inflate_mask[e]);
|
||||
DUMPBITS(e)
|
||||
Tracevv((stderr, "inflate: * distance %u\n", d));
|
||||
|
||||
/* do the copy */
|
||||
m -= c;
|
||||
if ((uInt)(q - s->window) >= d) /* offset before dest */
|
||||
{ /* just copy */
|
||||
r = q - d;
|
||||
*q++ = *r++; c--; /* minimum count is three, */
|
||||
*q++ = *r++; c--; /* so unroll loop a little */
|
||||
}
|
||||
else /* else offset after destination */
|
||||
{
|
||||
e = d - (uInt)(q - s->window); /* bytes from offset to end */
|
||||
r = s->end - e; /* pointer to offset */
|
||||
if (c > e) /* if source crosses, */
|
||||
{
|
||||
c -= e; /* copy to end of window */
|
||||
do {
|
||||
*q++ = *r++;
|
||||
} while (--e);
|
||||
r = s->window; /* copy rest from start of window */
|
||||
}
|
||||
}
|
||||
do { /* copy all or what's left */
|
||||
*q++ = *r++;
|
||||
} while (--c);
|
||||
break;
|
||||
}
|
||||
else if ((e & 64) == 0)
|
||||
e = (t = t->next + ((uInt)b & inflate_mask[e]))->exop;
|
||||
else
|
||||
{
|
||||
z->msg = (char*)"invalid distance code";
|
||||
UNGRAB
|
||||
UPDATE
|
||||
return Z_DATA_ERROR;
|
||||
}
|
||||
} while (1);
|
||||
break;
|
||||
}
|
||||
if ((e & 64) == 0)
|
||||
{
|
||||
if ((e = (t = t->next + ((uInt)b & inflate_mask[e]))->exop) == 0)
|
||||
{
|
||||
DUMPBITS(t->bits)
|
||||
Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
|
||||
"inflate: * literal '%c'\n" :
|
||||
"inflate: * literal 0x%02x\n", t->base));
|
||||
*q++ = (Byte)t->base;
|
||||
m--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (e & 32)
|
||||
{
|
||||
Tracevv((stderr, "inflate: * end of block\n"));
|
||||
UNGRAB
|
||||
UPDATE
|
||||
return Z_STREAM_END;
|
||||
}
|
||||
else
|
||||
{
|
||||
z->msg = (char*)"invalid literal/length code";
|
||||
UNGRAB
|
||||
UPDATE
|
||||
return Z_DATA_ERROR;
|
||||
}
|
||||
} while (1);
|
||||
} while (m >= 258 && n >= 10);
|
||||
|
||||
/* not enough input or output--restore pointers and return */
|
||||
UNGRAB
|
||||
UPDATE
|
||||
return Z_OK;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
/* inffast.h -- header to use inffast.c
|
||||
* Copyright (C) 1995-1996 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* WARNING: this file should *not* be used by applications. It is
|
||||
part of the implementation of the compression library and is
|
||||
subject to change. Applications should only use zlib.h.
|
||||
*/
|
||||
|
||||
extern int inflate_fast OF((
|
||||
uInt,
|
||||
uInt,
|
||||
inflate_huft *,
|
||||
inflate_huft *,
|
||||
inflate_blocks_statef *,
|
||||
z_streamp ));
|
||||
@@ -0,0 +1,345 @@
|
||||
/* inflate.c -- zlib interface to inflate modules
|
||||
* Copyright (C) 1995-1996 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#include "zutil.h"
|
||||
#include "infblock.h"
|
||||
|
||||
struct inflate_blocks_state {int dummy;}; /* for buggy compilers */
|
||||
|
||||
/* inflate private state */
|
||||
struct internal_state {
|
||||
|
||||
/* mode */
|
||||
enum {
|
||||
METHOD, /* waiting for method byte */
|
||||
FLAG, /* waiting for flag byte */
|
||||
DICT4, /* four dictionary check bytes to go */
|
||||
DICT3, /* three dictionary check bytes to go */
|
||||
DICT2, /* two dictionary check bytes to go */
|
||||
DICT1, /* one dictionary check byte to go */
|
||||
DICT0, /* waiting for inflateSetDictionary */
|
||||
BLOCKS, /* decompressing blocks */
|
||||
CHECK4, /* four check bytes to go */
|
||||
CHECK3, /* three check bytes to go */
|
||||
CHECK2, /* two check bytes to go */
|
||||
CHECK1, /* one check byte to go */
|
||||
DONE, /* finished check, done */
|
||||
BAD} /* got an error--stay here */
|
||||
mode; /* current inflate mode */
|
||||
|
||||
/* mode dependent information */
|
||||
union {
|
||||
uInt method; /* if FLAGS, method byte */
|
||||
struct {
|
||||
uLong was; /* computed check value */
|
||||
uLong need; /* stream check value */
|
||||
} check; /* if CHECK, check values to compare */
|
||||
uInt marker; /* if BAD, inflateSync's marker bytes count */
|
||||
} sub; /* submode */
|
||||
|
||||
/* mode independent information */
|
||||
int nowrap; /* flag for no wrapper */
|
||||
uInt wbits; /* log2(window size) (8..15, defaults to 15) */
|
||||
inflate_blocks_statef
|
||||
*blocks; /* current inflate_blocks state */
|
||||
|
||||
};
|
||||
|
||||
|
||||
int inflateReset(z)
|
||||
z_streamp z;
|
||||
{
|
||||
uLong c;
|
||||
|
||||
if (z == Z_NULL || z->state == Z_NULL)
|
||||
return Z_STREAM_ERROR;
|
||||
z->total_in = z->total_out = 0;
|
||||
z->msg = Z_NULL;
|
||||
z->state->mode = z->state->nowrap ? BLOCKS : METHOD;
|
||||
inflate_blocks_reset(z->state->blocks, z, &c);
|
||||
Trace((stderr, "inflate: reset\n"));
|
||||
return Z_OK;
|
||||
}
|
||||
|
||||
|
||||
int inflateEnd(z)
|
||||
z_streamp z;
|
||||
{
|
||||
uLong c;
|
||||
|
||||
if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL)
|
||||
return Z_STREAM_ERROR;
|
||||
if (z->state->blocks != Z_NULL)
|
||||
inflate_blocks_free(z->state->blocks, z, &c);
|
||||
ZFREE(z, z->state);
|
||||
z->state = Z_NULL;
|
||||
Trace((stderr, "inflate: end\n"));
|
||||
return Z_OK;
|
||||
}
|
||||
|
||||
|
||||
int inflateInit2_(z, w, version, stream_size)
|
||||
z_streamp z;
|
||||
int w;
|
||||
const char *version;
|
||||
int stream_size;
|
||||
{
|
||||
if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
|
||||
stream_size != sizeof(z_stream))
|
||||
return Z_VERSION_ERROR;
|
||||
|
||||
/* initialize state */
|
||||
if (z == Z_NULL)
|
||||
return Z_STREAM_ERROR;
|
||||
z->msg = Z_NULL;
|
||||
if (z->zalloc == Z_NULL)
|
||||
{
|
||||
z->zalloc = zcalloc;
|
||||
z->opaque = (voidpf)0;
|
||||
}
|
||||
if (z->zfree == Z_NULL) z->zfree = zcfree;
|
||||
if ((z->state = (struct internal_state FAR *)
|
||||
ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL)
|
||||
return Z_MEM_ERROR;
|
||||
z->state->blocks = Z_NULL;
|
||||
|
||||
/* handle undocumented nowrap option (no zlib header or check) */
|
||||
z->state->nowrap = 0;
|
||||
if (w < 0)
|
||||
{
|
||||
w = - w;
|
||||
z->state->nowrap = 1;
|
||||
}
|
||||
|
||||
/* set window size */
|
||||
if (w < 8 || w > 15)
|
||||
{
|
||||
inflateEnd(z);
|
||||
return Z_STREAM_ERROR;
|
||||
}
|
||||
z->state->wbits = (uInt)w;
|
||||
|
||||
/* create inflate_blocks state */
|
||||
if ((z->state->blocks =
|
||||
inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, (uInt)1 << w))
|
||||
== Z_NULL)
|
||||
{
|
||||
inflateEnd(z);
|
||||
return Z_MEM_ERROR;
|
||||
}
|
||||
Trace((stderr, "inflate: allocated\n"));
|
||||
|
||||
/* reset state */
|
||||
inflateReset(z);
|
||||
return Z_OK;
|
||||
}
|
||||
|
||||
|
||||
int inflateInit_(z, version, stream_size)
|
||||
z_streamp z;
|
||||
const char *version;
|
||||
int stream_size;
|
||||
{
|
||||
return inflateInit2_(z, DEF_WBITS, version, stream_size);
|
||||
}
|
||||
|
||||
|
||||
#define NEEDBYTE {if(z->avail_in==0)return r;r=Z_OK;}
|
||||
#define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++)
|
||||
|
||||
int inflate(z, f)
|
||||
z_streamp z;
|
||||
int f;
|
||||
{
|
||||
int r;
|
||||
uInt b;
|
||||
|
||||
if (z == Z_NULL || z->state == Z_NULL || z->next_in == Z_NULL || f < 0)
|
||||
return Z_STREAM_ERROR;
|
||||
r = Z_BUF_ERROR;
|
||||
while (1) switch (z->state->mode)
|
||||
{
|
||||
case METHOD:
|
||||
NEEDBYTE
|
||||
if (((z->state->sub.method = NEXTBYTE) & 0xf) != Z_DEFLATED)
|
||||
{
|
||||
z->state->mode = BAD;
|
||||
z->msg = (char*)"unknown compression method";
|
||||
z->state->sub.marker = 5; /* can't try inflateSync */
|
||||
break;
|
||||
}
|
||||
if ((z->state->sub.method >> 4) + 8 > z->state->wbits)
|
||||
{
|
||||
z->state->mode = BAD;
|
||||
z->msg = (char*)"invalid window size";
|
||||
z->state->sub.marker = 5; /* can't try inflateSync */
|
||||
break;
|
||||
}
|
||||
z->state->mode = FLAG;
|
||||
case FLAG:
|
||||
NEEDBYTE
|
||||
b = NEXTBYTE;
|
||||
if (((z->state->sub.method << 8) + b) % 31)
|
||||
{
|
||||
z->state->mode = BAD;
|
||||
z->msg = (char*)"incorrect header check";
|
||||
z->state->sub.marker = 5; /* can't try inflateSync */
|
||||
break;
|
||||
}
|
||||
Trace((stderr, "inflate: zlib header ok\n"));
|
||||
if (!(b & PRESET_DICT))
|
||||
{
|
||||
z->state->mode = BLOCKS;
|
||||
break;
|
||||
}
|
||||
z->state->mode = DICT4;
|
||||
case DICT4:
|
||||
NEEDBYTE
|
||||
z->state->sub.check.need = (uLong)NEXTBYTE << 24;
|
||||
z->state->mode = DICT3;
|
||||
case DICT3:
|
||||
NEEDBYTE
|
||||
z->state->sub.check.need += (uLong)NEXTBYTE << 16;
|
||||
z->state->mode = DICT2;
|
||||
case DICT2:
|
||||
NEEDBYTE
|
||||
z->state->sub.check.need += (uLong)NEXTBYTE << 8;
|
||||
z->state->mode = DICT1;
|
||||
case DICT1:
|
||||
NEEDBYTE
|
||||
z->state->sub.check.need += (uLong)NEXTBYTE;
|
||||
z->adler = z->state->sub.check.need;
|
||||
z->state->mode = DICT0;
|
||||
return Z_NEED_DICT;
|
||||
case DICT0:
|
||||
z->state->mode = BAD;
|
||||
z->msg = (char*)"need dictionary";
|
||||
z->state->sub.marker = 0; /* can try inflateSync */
|
||||
return Z_STREAM_ERROR;
|
||||
case BLOCKS:
|
||||
r = inflate_blocks(z->state->blocks, z, r);
|
||||
if (r == Z_DATA_ERROR)
|
||||
{
|
||||
z->state->mode = BAD;
|
||||
z->state->sub.marker = 0; /* can try inflateSync */
|
||||
break;
|
||||
}
|
||||
if (r != Z_STREAM_END)
|
||||
return r;
|
||||
r = Z_OK;
|
||||
inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was);
|
||||
if (z->state->nowrap)
|
||||
{
|
||||
z->state->mode = DONE;
|
||||
break;
|
||||
}
|
||||
z->state->mode = CHECK4;
|
||||
case CHECK4:
|
||||
NEEDBYTE
|
||||
z->state->sub.check.need = (uLong)NEXTBYTE << 24;
|
||||
z->state->mode = CHECK3;
|
||||
case CHECK3:
|
||||
NEEDBYTE
|
||||
z->state->sub.check.need += (uLong)NEXTBYTE << 16;
|
||||
z->state->mode = CHECK2;
|
||||
case CHECK2:
|
||||
NEEDBYTE
|
||||
z->state->sub.check.need += (uLong)NEXTBYTE << 8;
|
||||
z->state->mode = CHECK1;
|
||||
case CHECK1:
|
||||
NEEDBYTE
|
||||
z->state->sub.check.need += (uLong)NEXTBYTE;
|
||||
|
||||
if (z->state->sub.check.was != z->state->sub.check.need)
|
||||
{
|
||||
z->state->mode = BAD;
|
||||
z->msg = (char*)"incorrect data check";
|
||||
z->state->sub.marker = 5; /* can't try inflateSync */
|
||||
break;
|
||||
}
|
||||
Trace((stderr, "inflate: zlib check ok\n"));
|
||||
z->state->mode = DONE;
|
||||
case DONE:
|
||||
return Z_STREAM_END;
|
||||
case BAD:
|
||||
return Z_DATA_ERROR;
|
||||
default:
|
||||
return Z_STREAM_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int inflateSetDictionary(z, dictionary, dictLength)
|
||||
z_streamp z;
|
||||
const Bytef *dictionary;
|
||||
uInt dictLength;
|
||||
{
|
||||
uInt length = dictLength;
|
||||
|
||||
if (z == Z_NULL || z->state == Z_NULL || z->state->mode != DICT0)
|
||||
return Z_STREAM_ERROR;
|
||||
|
||||
if (adler32(1L, dictionary, dictLength) != z->adler) return Z_DATA_ERROR;
|
||||
z->adler = 1L;
|
||||
|
||||
if (length >= ((uInt)1<<z->state->wbits))
|
||||
{
|
||||
length = (1<<z->state->wbits)-1;
|
||||
dictionary += dictLength - length;
|
||||
}
|
||||
inflate_set_dictionary(z->state->blocks, dictionary, length);
|
||||
z->state->mode = BLOCKS;
|
||||
return Z_OK;
|
||||
}
|
||||
|
||||
|
||||
int inflateSync(z)
|
||||
z_streamp z;
|
||||
{
|
||||
uInt n; /* number of bytes to look at */
|
||||
Bytef *p; /* pointer to bytes */
|
||||
uInt m; /* number of marker bytes found in a row */
|
||||
uLong r, w; /* temporaries to save total_in and total_out */
|
||||
|
||||
/* set up */
|
||||
if (z == Z_NULL || z->state == Z_NULL)
|
||||
return Z_STREAM_ERROR;
|
||||
if (z->state->mode != BAD)
|
||||
{
|
||||
z->state->mode = BAD;
|
||||
z->state->sub.marker = 0;
|
||||
}
|
||||
if ((n = z->avail_in) == 0)
|
||||
return Z_BUF_ERROR;
|
||||
p = z->next_in;
|
||||
m = z->state->sub.marker;
|
||||
|
||||
/* search */
|
||||
while (n && m < 4)
|
||||
{
|
||||
if (*p == (Byte)(m < 2 ? 0 : 0xff))
|
||||
m++;
|
||||
else if (*p)
|
||||
m = 0;
|
||||
else
|
||||
m = 4 - m;
|
||||
p++, n--;
|
||||
}
|
||||
|
||||
/* restore */
|
||||
z->total_in += p - z->next_in;
|
||||
z->next_in = p;
|
||||
z->avail_in = n;
|
||||
z->state->sub.marker = m;
|
||||
|
||||
/* return no joy or set up to restart on a new block */
|
||||
if (m != 4)
|
||||
return Z_DATA_ERROR;
|
||||
r = z->total_in; w = z->total_out;
|
||||
inflateReset(z);
|
||||
z->total_in = r; z->total_out = w;
|
||||
z->state->mode = BLOCKS;
|
||||
return Z_OK;
|
||||
}
|
||||
@@ -0,0 +1,470 @@
|
||||
/* inftrees.c -- generate Huffman trees for efficient decoding
|
||||
* Copyright (C) 1995-1996 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#include "zutil.h"
|
||||
#include "inftrees.h"
|
||||
|
||||
char inflate_copyright[] = " inflate 1.0.4 Copyright 1995-1996 Mark Adler ";
|
||||
/*
|
||||
If you use the zlib library in a product, an acknowledgment is welcome
|
||||
in the documentation of your product. If for some reason you cannot
|
||||
include such an acknowledgment, I would appreciate that you keep this
|
||||
copyright string in the executable of your product.
|
||||
*/
|
||||
struct internal_state {int dummy;}; /* for buggy compilers */
|
||||
|
||||
/* simplify the use of the inflate_huft type with some defines */
|
||||
#define base more.Base
|
||||
#define next more.Next
|
||||
#define exop word.what.Exop
|
||||
#define bits word.what.Bits
|
||||
|
||||
|
||||
local int huft_build OF((
|
||||
uIntf *, /* code lengths in bits */
|
||||
uInt, /* number of codes */
|
||||
uInt, /* number of "simple" codes */
|
||||
uIntf *, /* list of base values for non-simple codes */
|
||||
uIntf *, /* list of extra bits for non-simple codes */
|
||||
inflate_huft * FAR*,/* result: starting table */
|
||||
uIntf *, /* maximum lookup bits (returns actual) */
|
||||
z_streamp )); /* for zalloc function */
|
||||
|
||||
local voidpf falloc OF((
|
||||
voidpf, /* opaque pointer (not used) */
|
||||
uInt, /* number of items */
|
||||
uInt)); /* size of item */
|
||||
|
||||
/* Tables for deflate from PKZIP's appnote.txt. */
|
||||
local uInt cplens[31] = { /* Copy lengths for literal codes 257..285 */
|
||||
3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
|
||||
35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
|
||||
/* actually lengths - 2; also see note #13 above about 258 */
|
||||
local uInt cplext[31] = { /* Extra bits for literal codes 257..285 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
|
||||
3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 192, 192}; /* 192==invalid */
|
||||
local uInt cpdist[30] = { /* Copy offsets for distance codes 0..29 */
|
||||
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
|
||||
257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
|
||||
8193, 12289, 16385, 24577};
|
||||
local uInt cpdext[30] = { /* Extra bits for distance codes */
|
||||
0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
|
||||
7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
|
||||
12, 12, 13, 13};
|
||||
|
||||
/*
|
||||
Huffman code decoding is performed using a multi-level table lookup.
|
||||
The fastest way to decode is to simply build a lookup table whose
|
||||
size is determined by the longest code. However, the time it takes
|
||||
to build this table can also be a factor if the data being decoded
|
||||
is not very long. The most common codes are necessarily the
|
||||
shortest codes, so those codes dominate the decoding time, and hence
|
||||
the speed. The idea is you can have a shorter table that decodes the
|
||||
shorter, more probable codes, and then point to subsidiary tables for
|
||||
the longer codes. The time it costs to decode the longer codes is
|
||||
then traded against the time it takes to make longer tables.
|
||||
|
||||
This results of this trade are in the variables lbits and dbits
|
||||
below. lbits is the number of bits the first level table for literal/
|
||||
length codes can decode in one step, and dbits is the same thing for
|
||||
the distance codes. Subsequent tables are also less than or equal to
|
||||
those sizes. These values may be adjusted either when all of the
|
||||
codes are shorter than that, in which case the longest code length in
|
||||
bits is used, or when the shortest code is *longer* than the requested
|
||||
table size, in which case the length of the shortest code in bits is
|
||||
used.
|
||||
|
||||
There are two different values for the two tables, since they code a
|
||||
different number of possibilities each. The literal/length table
|
||||
codes 286 possible values, or in a flat code, a little over eight
|
||||
bits. The distance table codes 30 possible values, or a little less
|
||||
than five bits, flat. The optimum values for speed end up being
|
||||
about one bit more than those, so lbits is 8+1 and dbits is 5+1.
|
||||
The optimum values may differ though from machine to machine, and
|
||||
possibly even between compilers. Your mileage may vary.
|
||||
*/
|
||||
|
||||
|
||||
/* If BMAX needs to be larger than 16, then h and x[] should be uLong. */
|
||||
#define BMAX 15 /* maximum bit length of any code */
|
||||
#define N_MAX 288 /* maximum number of codes in any set */
|
||||
|
||||
#ifdef DEBUG
|
||||
uInt inflate_hufts;
|
||||
#endif
|
||||
|
||||
local int huft_build(b, n, s, d, e, t, m, zs)
|
||||
uIntf *b; /* code lengths in bits (all assumed <= BMAX) */
|
||||
uInt n; /* number of codes (assumed <= N_MAX) */
|
||||
uInt s; /* number of simple-valued codes (0..s-1) */
|
||||
uIntf *d; /* list of base values for non-simple codes */
|
||||
uIntf *e; /* list of extra bits for non-simple codes */
|
||||
inflate_huft * FAR *t; /* result: starting table */
|
||||
uIntf *m; /* maximum lookup bits, returns actual */
|
||||
z_streamp zs; /* for zalloc function */
|
||||
/* Given a list of code lengths and a maximum table size, make a set of
|
||||
tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR
|
||||
if the given code set is incomplete (the tables are still built in this
|
||||
case), Z_DATA_ERROR if the input is invalid (all zero length codes or an
|
||||
over-subscribed set of lengths), or Z_MEM_ERROR if not enough memory. */
|
||||
{
|
||||
|
||||
uInt a; /* counter for codes of length k */
|
||||
uInt c[BMAX+1]; /* bit length count table */
|
||||
uInt f; /* i repeats in table every f entries */
|
||||
int g; /* maximum code length */
|
||||
int h; /* table level */
|
||||
register uInt i; /* counter, current code */
|
||||
register uInt j; /* counter */
|
||||
register int k; /* number of bits in current code */
|
||||
int l; /* bits per table (returned in m) */
|
||||
register uIntf *p; /* pointer into c[], b[], or v[] */
|
||||
inflate_huft *q; /* points to current table */
|
||||
struct inflate_huft_s r; /* table entry for structure assignment */
|
||||
inflate_huft *u[BMAX]; /* table stack */
|
||||
uInt v[N_MAX]; /* values in order of bit length */
|
||||
register int w; /* bits before this table == (l * h) */
|
||||
uInt x[BMAX+1]; /* bit offsets, then code stack */
|
||||
uIntf *xp; /* pointer into x */
|
||||
int y; /* number of dummy codes added */
|
||||
uInt z; /* number of entries in current table */
|
||||
|
||||
|
||||
/* Generate counts for each bit length */
|
||||
p = c;
|
||||
#define C0 *p++ = 0;
|
||||
#define C2 C0 C0 C0 C0
|
||||
#define C4 C2 C2 C2 C2
|
||||
C4 /* clear c[]--assume BMAX+1 is 16 */
|
||||
p = b; i = n;
|
||||
do {
|
||||
c[*p++]++; /* assume all entries <= BMAX */
|
||||
} while (--i);
|
||||
if (c[0] == n) /* null input--all zero length codes */
|
||||
{
|
||||
*t = (inflate_huft *)Z_NULL;
|
||||
*m = 0;
|
||||
return Z_OK;
|
||||
}
|
||||
|
||||
|
||||
/* Find minimum and maximum length, bound *m by those */
|
||||
l = *m;
|
||||
for (j = 1; j <= BMAX; j++)
|
||||
if (c[j])
|
||||
break;
|
||||
k = j; /* minimum code length */
|
||||
if ((uInt)l < j)
|
||||
l = j;
|
||||
for (i = BMAX; i; i--)
|
||||
if (c[i])
|
||||
break;
|
||||
g = i; /* maximum code length */
|
||||
if ((uInt)l > i)
|
||||
l = i;
|
||||
*m = l;
|
||||
|
||||
|
||||
/* Adjust last length count to fill out codes, if needed */
|
||||
for (y = 1 << j; j < i; j++, y <<= 1)
|
||||
if ((y -= c[j]) < 0)
|
||||
return Z_DATA_ERROR;
|
||||
if ((y -= c[i]) < 0)
|
||||
return Z_DATA_ERROR;
|
||||
c[i] += y;
|
||||
|
||||
|
||||
/* Generate starting offsets into the value table for each length */
|
||||
x[1] = j = 0;
|
||||
p = c + 1; xp = x + 2;
|
||||
while (--i) { /* note that i == g from above */
|
||||
*xp++ = (j += *p++);
|
||||
}
|
||||
|
||||
|
||||
/* Make a table of values in order of bit lengths */
|
||||
p = b; i = 0;
|
||||
do {
|
||||
if ((j = *p++) != 0)
|
||||
v[x[j]++] = i;
|
||||
} while (++i < n);
|
||||
|
||||
|
||||
/* Generate the Huffman codes and for each, make the table entries */
|
||||
x[0] = i = 0; /* first Huffman code is zero */
|
||||
p = v; /* grab values in bit order */
|
||||
h = -1; /* no tables yet--level -1 */
|
||||
w = -l; /* bits decoded == (l * h) */
|
||||
u[0] = (inflate_huft *)Z_NULL; /* just to keep compilers happy */
|
||||
q = (inflate_huft *)Z_NULL; /* ditto */
|
||||
z = 0; /* ditto */
|
||||
|
||||
/* go through the bit lengths (k already is bits in shortest code) */
|
||||
for (; k <= g; k++)
|
||||
{
|
||||
a = c[k];
|
||||
while (a--)
|
||||
{
|
||||
/* here i is the Huffman code of length k bits for value *p */
|
||||
/* make tables up to required level */
|
||||
while (k > w + l)
|
||||
{
|
||||
h++;
|
||||
w += l; /* previous table always l bits */
|
||||
|
||||
/* compute minimum size table less than or equal to l bits */
|
||||
z = g - w;
|
||||
z = z > (uInt)l ? l : z; /* table size upper limit */
|
||||
if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */
|
||||
{ /* too few codes for k-w bit table */
|
||||
f -= a + 1; /* deduct codes from patterns left */
|
||||
xp = c + k;
|
||||
if (j < z)
|
||||
while (++j < z) /* try smaller tables up to z bits */
|
||||
{
|
||||
if ((f <<= 1) <= *++xp)
|
||||
break; /* enough codes to use up j bits */
|
||||
f -= *xp; /* else deduct codes from patterns */
|
||||
}
|
||||
}
|
||||
z = 1 << j; /* table entries for j-bit table */
|
||||
|
||||
/* allocate and link in new table */
|
||||
if ((q = (inflate_huft *)ZALLOC
|
||||
(zs,z + 1,sizeof(inflate_huft))) == Z_NULL)
|
||||
{
|
||||
if (h)
|
||||
inflate_trees_free(u[0], zs);
|
||||
return Z_MEM_ERROR; /* not enough memory */
|
||||
}
|
||||
#ifdef DEBUG
|
||||
inflate_hufts += z + 1;
|
||||
#endif
|
||||
*t = q + 1; /* link to list for huft_free() */
|
||||
*(t = &(q->next)) = Z_NULL;
|
||||
u[h] = ++q; /* table starts after link */
|
||||
|
||||
/* connect to last table, if there is one */
|
||||
if (h)
|
||||
{
|
||||
x[h] = i; /* save pattern for backing up */
|
||||
r.bits = (Byte)l; /* bits to dump before this table */
|
||||
r.exop = (Byte)j; /* bits in this table */
|
||||
r.next = q; /* pointer to this table */
|
||||
j = i >> (w - l); /* (get around Turbo C bug) */
|
||||
u[h-1][j] = r; /* connect to last table */
|
||||
}
|
||||
}
|
||||
|
||||
/* set up table entry in r */
|
||||
r.bits = (Byte)(k - w);
|
||||
if (p >= v + n)
|
||||
r.exop = 128 + 64; /* out of values--invalid code */
|
||||
else if (*p < s)
|
||||
{
|
||||
r.exop = (Byte)(*p < 256 ? 0 : 32 + 64); /* 256 is end-of-block */
|
||||
r.base = *p++; /* simple code is just the value */
|
||||
}
|
||||
else
|
||||
{
|
||||
r.exop = (Byte)(e[*p - s] + 16 + 64);/* non-simple--look up in lists */
|
||||
r.base = d[*p++ - s];
|
||||
}
|
||||
|
||||
/* fill code-like entries with r */
|
||||
f = 1 << (k - w);
|
||||
for (j = i >> w; j < z; j += f)
|
||||
q[j] = r;
|
||||
|
||||
/* backwards increment the k-bit code i */
|
||||
for (j = 1 << (k - 1); i & j; j >>= 1)
|
||||
i ^= j;
|
||||
i ^= j;
|
||||
|
||||
/* backup over finished tables */
|
||||
while ((i & ((1 << w) - 1)) != x[h])
|
||||
{
|
||||
h--; /* don't need to update q */
|
||||
w -= l;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Return Z_BUF_ERROR if we were given an incomplete table */
|
||||
return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK;
|
||||
}
|
||||
|
||||
|
||||
int inflate_trees_bits(c, bb, tb, z)
|
||||
uIntf *c; /* 19 code lengths */
|
||||
uIntf *bb; /* bits tree desired/actual depth */
|
||||
inflate_huft * FAR *tb; /* bits tree result */
|
||||
z_streamp z; /* for zfree function */
|
||||
{
|
||||
int r;
|
||||
|
||||
r = huft_build(c, 19, 19, (uIntf*)Z_NULL, (uIntf*)Z_NULL, tb, bb, z);
|
||||
if (r == Z_DATA_ERROR)
|
||||
z->msg = (char*)"oversubscribed dynamic bit lengths tree";
|
||||
else if (r == Z_BUF_ERROR)
|
||||
{
|
||||
inflate_trees_free(*tb, z);
|
||||
z->msg = (char*)"incomplete dynamic bit lengths tree";
|
||||
r = Z_DATA_ERROR;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
int inflate_trees_dynamic(nl, nd, c, bl, bd, tl, td, z)
|
||||
uInt nl; /* number of literal/length codes */
|
||||
uInt nd; /* number of distance codes */
|
||||
uIntf *c; /* that many (total) code lengths */
|
||||
uIntf *bl; /* literal desired/actual bit depth */
|
||||
uIntf *bd; /* distance desired/actual bit depth */
|
||||
inflate_huft * FAR *tl; /* literal/length tree result */
|
||||
inflate_huft * FAR *td; /* distance tree result */
|
||||
z_streamp z; /* for zfree function */
|
||||
{
|
||||
int r;
|
||||
|
||||
/* build literal/length tree */
|
||||
if ((r = huft_build(c, nl, 257, cplens, cplext, tl, bl, z)) != Z_OK)
|
||||
{
|
||||
if (r == Z_DATA_ERROR)
|
||||
z->msg = (char*)"oversubscribed literal/length tree";
|
||||
else if (r == Z_BUF_ERROR)
|
||||
{
|
||||
inflate_trees_free(*tl, z);
|
||||
z->msg = (char*)"incomplete literal/length tree";
|
||||
r = Z_DATA_ERROR;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/* build distance tree */
|
||||
if ((r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, z)) != Z_OK)
|
||||
{
|
||||
if (r == Z_DATA_ERROR)
|
||||
z->msg = (char*)"oversubscribed literal/length tree";
|
||||
else if (r == Z_BUF_ERROR) {
|
||||
#ifdef PKZIP_BUG_WORKAROUND
|
||||
r = Z_OK;
|
||||
}
|
||||
#else
|
||||
inflate_trees_free(*td, z);
|
||||
z->msg = (char*)"incomplete literal/length tree";
|
||||
r = Z_DATA_ERROR;
|
||||
}
|
||||
inflate_trees_free(*tl, z);
|
||||
return r;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* done */
|
||||
return Z_OK;
|
||||
}
|
||||
|
||||
|
||||
/* build fixed tables only once--keep them here */
|
||||
local int fixed_built = 0;
|
||||
#define FIXEDH 530 /* number of hufts used by fixed tables */
|
||||
local inflate_huft fixed_mem[FIXEDH];
|
||||
local uInt fixed_bl;
|
||||
local uInt fixed_bd;
|
||||
local inflate_huft *fixed_tl;
|
||||
local inflate_huft *fixed_td;
|
||||
|
||||
|
||||
local voidpf falloc(q, n, s)
|
||||
voidpf q; /* opaque pointer */
|
||||
uInt n; /* number of items */
|
||||
uInt s; /* size of item */
|
||||
{
|
||||
Assert(s == sizeof(inflate_huft) && n <= *(intf *)q,
|
||||
"inflate_trees falloc overflow");
|
||||
*(intf *)q -= n+s-s; /* s-s to avoid warning */
|
||||
return (voidpf)(fixed_mem + *(intf *)q);
|
||||
}
|
||||
|
||||
|
||||
int inflate_trees_fixed(bl, bd, tl, td)
|
||||
uIntf *bl; /* literal desired/actual bit depth */
|
||||
uIntf *bd; /* distance desired/actual bit depth */
|
||||
inflate_huft * FAR *tl; /* literal/length tree result */
|
||||
inflate_huft * FAR *td; /* distance tree result */
|
||||
{
|
||||
/* build fixed tables if not already (multiple overlapped executions ok) */
|
||||
if (!fixed_built)
|
||||
{
|
||||
int k; /* temporary variable */
|
||||
unsigned c[288]; /* length list for huft_build */
|
||||
z_stream z; /* for falloc function */
|
||||
int f = FIXEDH; /* number of hufts left in fixed_mem */
|
||||
|
||||
/* set up fake z_stream for memory routines */
|
||||
z.zalloc = falloc;
|
||||
z.zfree = Z_NULL;
|
||||
z.opaque = (voidpf)&f;
|
||||
|
||||
/* literal table */
|
||||
for (k = 0; k < 144; k++)
|
||||
c[k] = 8;
|
||||
for (; k < 256; k++)
|
||||
c[k] = 9;
|
||||
for (; k < 280; k++)
|
||||
c[k] = 7;
|
||||
for (; k < 288; k++)
|
||||
c[k] = 8;
|
||||
fixed_bl = 7;
|
||||
huft_build(c, 288, 257, cplens, cplext, &fixed_tl, &fixed_bl, &z);
|
||||
|
||||
/* distance table */
|
||||
for (k = 0; k < 30; k++)
|
||||
c[k] = 5;
|
||||
fixed_bd = 5;
|
||||
huft_build(c, 30, 0, cpdist, cpdext, &fixed_td, &fixed_bd, &z);
|
||||
|
||||
/* done */
|
||||
Assert(f == 0, "invalid build of fixed tables");
|
||||
fixed_built = 1;
|
||||
}
|
||||
*bl = fixed_bl;
|
||||
*bd = fixed_bd;
|
||||
*tl = fixed_tl;
|
||||
*td = fixed_td;
|
||||
return Z_OK;
|
||||
}
|
||||
|
||||
|
||||
int inflate_trees_free(t, z)
|
||||
inflate_huft *t; /* table to free */
|
||||
z_streamp z; /* for zfree function */
|
||||
/* Free the malloc'ed tables built by huft_build(), which makes a linked
|
||||
list of the tables it made, with the links in a dummy first entry of
|
||||
each table. */
|
||||
{
|
||||
register inflate_huft *p, *q, *r;
|
||||
|
||||
/* Reverse linked list */
|
||||
p = Z_NULL;
|
||||
q = t;
|
||||
while (q != Z_NULL)
|
||||
{
|
||||
r = (q - 1)->next;
|
||||
(q - 1)->next = p;
|
||||
p = q;
|
||||
q = r;
|
||||
}
|
||||
/* Go through linked list, freeing from the malloced (t[-1]) address. */
|
||||
while (p != Z_NULL)
|
||||
{
|
||||
q = (--p)->next;
|
||||
ZFREE(z,p);
|
||||
p = q;
|
||||
}
|
||||
return Z_OK;
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/* inftrees.h -- header to use inftrees.c
|
||||
* Copyright (C) 1995-1996 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* WARNING: this file should *not* be used by applications. It is
|
||||
part of the implementation of the compression library and is
|
||||
subject to change. Applications should only use zlib.h.
|
||||
*/
|
||||
|
||||
/* Huffman code lookup table entry--this entry is four bytes for machines
|
||||
that have 16-bit pointers (e.g. PC's in the small or medium model). */
|
||||
|
||||
typedef struct inflate_huft_s FAR inflate_huft;
|
||||
|
||||
struct inflate_huft_s {
|
||||
union {
|
||||
struct {
|
||||
Byte Exop; /* number of extra bits or operation */
|
||||
Byte Bits; /* number of bits in this code or subcode */
|
||||
} what;
|
||||
Bytef *pad; /* pad structure to a power of 2 (4 bytes for */
|
||||
} word; /* 16-bit, 8 bytes for 32-bit machines) */
|
||||
union {
|
||||
uInt Base; /* literal, length base, or distance base */
|
||||
inflate_huft *Next; /* pointer to next level of table */
|
||||
} more;
|
||||
};
|
||||
|
||||
#ifdef DEBUG
|
||||
extern uInt inflate_hufts;
|
||||
#endif
|
||||
|
||||
extern int inflate_trees_bits OF((
|
||||
uIntf *, /* 19 code lengths */
|
||||
uIntf *, /* bits tree desired/actual depth */
|
||||
inflate_huft * FAR *, /* bits tree result */
|
||||
z_streamp )); /* for zalloc, zfree functions */
|
||||
|
||||
extern int inflate_trees_dynamic OF((
|
||||
uInt, /* number of literal/length codes */
|
||||
uInt, /* number of distance codes */
|
||||
uIntf *, /* that many (total) code lengths */
|
||||
uIntf *, /* literal desired/actual bit depth */
|
||||
uIntf *, /* distance desired/actual bit depth */
|
||||
inflate_huft * FAR *, /* literal/length tree result */
|
||||
inflate_huft * FAR *, /* distance tree result */
|
||||
z_streamp )); /* for zalloc, zfree functions */
|
||||
|
||||
extern int inflate_trees_fixed OF((
|
||||
uIntf *, /* literal desired/actual bit depth */
|
||||
uIntf *, /* distance desired/actual bit depth */
|
||||
inflate_huft * FAR *, /* literal/length tree result */
|
||||
inflate_huft * FAR *)); /* distance tree result */
|
||||
|
||||
extern int inflate_trees_free OF((
|
||||
inflate_huft *, /* tables to free */
|
||||
z_streamp )); /* for zfree function */
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
/* inflate_util.c -- data and routines common to blocks and codes
|
||||
* Copyright (C) 1995-1996 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#include "zutil.h"
|
||||
#include "infblock.h"
|
||||
#include "inftrees.h"
|
||||
#include "infcodes.h"
|
||||
#include "infutil.h"
|
||||
|
||||
struct inflate_codes_state {int dummy;}; /* for buggy compilers */
|
||||
|
||||
/* And'ing with mask[n] masks the lower n bits */
|
||||
uInt inflate_mask[17] = {
|
||||
0x0000,
|
||||
0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
|
||||
0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
|
||||
};
|
||||
|
||||
|
||||
/* copy as much as possible from the sliding window to the output area */
|
||||
int inflate_flush(s, z, r)
|
||||
inflate_blocks_statef *s;
|
||||
z_streamp z;
|
||||
int r;
|
||||
{
|
||||
uInt n;
|
||||
Bytef *p;
|
||||
Bytef *q;
|
||||
|
||||
/* local copies of source and destination pointers */
|
||||
p = z->next_out;
|
||||
q = s->read;
|
||||
|
||||
/* compute number of bytes to copy as far as end of window */
|
||||
n = (uInt)((q <= s->write ? s->write : s->end) - q);
|
||||
if (n > z->avail_out) n = z->avail_out;
|
||||
if (n && r == Z_BUF_ERROR) r = Z_OK;
|
||||
|
||||
/* update counters */
|
||||
z->avail_out -= n;
|
||||
z->total_out += n;
|
||||
|
||||
/* update check information */
|
||||
if (s->checkfn != Z_NULL)
|
||||
z->adler = s->check = (*s->checkfn)(s->check, q, n);
|
||||
|
||||
/* copy as far as end of window */
|
||||
zmemcpy(p, q, n);
|
||||
p += n;
|
||||
q += n;
|
||||
|
||||
/* see if more to copy at beginning of window */
|
||||
if (q == s->end)
|
||||
{
|
||||
/* wrap pointers */
|
||||
q = s->window;
|
||||
if (s->write == s->end)
|
||||
s->write = s->window;
|
||||
|
||||
/* compute bytes to copy */
|
||||
n = (uInt)(s->write - q);
|
||||
if (n > z->avail_out) n = z->avail_out;
|
||||
if (n && r == Z_BUF_ERROR) r = Z_OK;
|
||||
|
||||
/* update counters */
|
||||
z->avail_out -= n;
|
||||
z->total_out += n;
|
||||
|
||||
/* update check information */
|
||||
if (s->checkfn != Z_NULL)
|
||||
z->adler = s->check = (*s->checkfn)(s->check, q, n);
|
||||
|
||||
/* copy */
|
||||
zmemcpy(p, q, n);
|
||||
p += n;
|
||||
q += n;
|
||||
}
|
||||
|
||||
/* update pointers */
|
||||
z->next_out = p;
|
||||
s->read = q;
|
||||
|
||||
/* done */
|
||||
return r;
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
/* infutil.h -- types and macros common to blocks and codes
|
||||
* Copyright (C) 1995-1996 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* WARNING: this file should *not* be used by applications. It is
|
||||
part of the implementation of the compression library and is
|
||||
subject to change. Applications should only use zlib.h.
|
||||
*/
|
||||
|
||||
#ifndef _INFUTIL_H
|
||||
#define _INFUTIL_H
|
||||
|
||||
typedef enum {
|
||||
TYPE, /* get type bits (3, including end bit) */
|
||||
LENS, /* get lengths for stored */
|
||||
STORED, /* processing stored block */
|
||||
TABLE, /* get table lengths */
|
||||
BTREE, /* get bit lengths tree for a dynamic block */
|
||||
DTREE, /* get length, distance trees for a dynamic block */
|
||||
CODES, /* processing fixed or dynamic block */
|
||||
DRY, /* output remaining window bytes */
|
||||
DONE, /* finished last block, done */
|
||||
BAD} /* got a data error--stuck here */
|
||||
inflate_block_mode;
|
||||
|
||||
/* inflate blocks semi-private state */
|
||||
struct inflate_blocks_state {
|
||||
|
||||
/* mode */
|
||||
inflate_block_mode mode; /* current inflate_block mode */
|
||||
|
||||
/* mode dependent information */
|
||||
union {
|
||||
uInt left; /* if STORED, bytes left to copy */
|
||||
struct {
|
||||
uInt table; /* table lengths (14 bits) */
|
||||
uInt index; /* index into blens (or border) */
|
||||
uIntf *blens; /* bit lengths of codes */
|
||||
uInt bb; /* bit length tree depth */
|
||||
inflate_huft *tb; /* bit length decoding tree */
|
||||
} trees; /* if DTREE, decoding info for trees */
|
||||
struct {
|
||||
inflate_huft *tl;
|
||||
inflate_huft *td; /* trees to free */
|
||||
inflate_codes_statef
|
||||
*codes;
|
||||
} decode; /* if CODES, current state */
|
||||
} sub; /* submode */
|
||||
uInt last; /* true if this block is the last block */
|
||||
|
||||
/* mode independent information */
|
||||
uInt bitk; /* bits in bit buffer */
|
||||
uLong bitb; /* bit buffer */
|
||||
Bytef *window; /* sliding window */
|
||||
Bytef *end; /* one byte after sliding window */
|
||||
Bytef *read; /* window read pointer */
|
||||
Bytef *write; /* window write pointer */
|
||||
check_func checkfn; /* check function */
|
||||
uLong check; /* check on output */
|
||||
|
||||
};
|
||||
|
||||
|
||||
/* defines for inflate input/output */
|
||||
/* update pointers and return */
|
||||
#define UPDBITS {s->bitb=b;s->bitk=k;}
|
||||
#define UPDIN {z->avail_in=n;z->total_in+=p-z->next_in;z->next_in=p;}
|
||||
#define UPDOUT {s->write=q;}
|
||||
#define UPDATE {UPDBITS UPDIN UPDOUT}
|
||||
#define LEAVE {UPDATE return inflate_flush(s,z,r);}
|
||||
/* get bytes and bits */
|
||||
#define LOADIN {p=z->next_in;n=z->avail_in;b=s->bitb;k=s->bitk;}
|
||||
#define NEEDBYTE {if(n)r=Z_OK;else LEAVE}
|
||||
#define NEXTBYTE (n--,*p++)
|
||||
#define NEEDBITS(j) {while(k<(j)){NEEDBYTE;b|=((uLong)NEXTBYTE)<<k;k+=8;}}
|
||||
#define DUMPBITS(j) {b>>=(j);k-=(j);}
|
||||
/* output bytes */
|
||||
#define WAVAIL (uInt)(q<s->read?s->read-q-1:s->end-q)
|
||||
#define LOADOUT {q=s->write;m=(uInt)WAVAIL;}
|
||||
#define WRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=(uInt)WAVAIL;}}
|
||||
#define FLUSH {UPDOUT r=inflate_flush(s,z,r); LOADOUT}
|
||||
#define NEEDOUT {if(m==0){WRAP if(m==0){FLUSH WRAP if(m==0) LEAVE}}r=Z_OK;}
|
||||
#define OUTBYTE(a) {*q++=(Byte)(a);m--;}
|
||||
/* load local pointers */
|
||||
#define LOAD {LOADIN LOADOUT}
|
||||
|
||||
/* masks for lower bits (size given to avoid silly warnings with Visual C++) */
|
||||
extern uInt inflate_mask[17];
|
||||
|
||||
/* copy as much as possible from the sliding window to the output area */
|
||||
extern int inflate_flush OF((
|
||||
inflate_blocks_statef *,
|
||||
z_streamp ,
|
||||
int));
|
||||
|
||||
struct internal_state {int dummy;}; /* for buggy compilers */
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,246 @@
|
||||
/* minigzip.c -- simulate gzip using the zlib compression library
|
||||
* Copyright (C) 1995-1996 Jean-loup Gailly.
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/*
|
||||
* minigzip is a minimal implementation of the gzip utility. This is
|
||||
* only an example of using zlib and isn't meant to replace the
|
||||
* full-featured gzip. No attempt is made to deal with file systems
|
||||
* limiting names to 14 or 8+3 characters, etc... Error checking is
|
||||
* very limited. So use minigzip only for testing; use gzip for the
|
||||
* real thing. On MSDOS, use only on file names without extension
|
||||
* or in pipe mode.
|
||||
*/
|
||||
|
||||
/* $Id: minigzip.c,v 1.10 1996/07/24 13:41:04 me Exp $ */
|
||||
|
||||
#include <stdio.h>
|
||||
#include "zlib.h"
|
||||
|
||||
#ifdef STDC
|
||||
# include <string.h>
|
||||
# include <stdlib.h>
|
||||
#else
|
||||
extern void exit OF((int));
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(MSDOS) || defined(OS2) || defined(WIN32)
|
||||
# include <fcntl.h>
|
||||
# include <io.h>
|
||||
# define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
|
||||
#else
|
||||
# define SET_BINARY_MODE(file)
|
||||
#endif
|
||||
|
||||
#ifdef VMS
|
||||
# define unlink delete
|
||||
# define GZ_SUFFIX "-gz"
|
||||
#endif
|
||||
#ifdef RISCOS
|
||||
# define unlink remove
|
||||
# define GZ_SUFFIX "-gz"
|
||||
# define fileno(file) file->__file
|
||||
#endif
|
||||
|
||||
#ifndef GZ_SUFFIX
|
||||
# define GZ_SUFFIX ".gz"
|
||||
#endif
|
||||
#define SUFFIX_LEN sizeof(GZ_SUFFIX)
|
||||
|
||||
extern int unlink OF((const char *));
|
||||
|
||||
#define BUFLEN 4096
|
||||
#define MAX_NAME_LEN 1024
|
||||
|
||||
#define local static
|
||||
/* For MSDOS and other systems with limitation on stack size. For Unix,
|
||||
#define local
|
||||
works also.
|
||||
*/
|
||||
|
||||
char *prog;
|
||||
|
||||
void error OF((const char *msg));
|
||||
void gz_compress OF((FILE *in, gzFile out));
|
||||
void gz_uncompress OF((gzFile in, FILE *out));
|
||||
void file_compress OF((char *file));
|
||||
void file_uncompress OF((char *file));
|
||||
int main OF((int argc, char *argv[]));
|
||||
|
||||
/* ===========================================================================
|
||||
* Display error message and exit
|
||||
*/
|
||||
void error(msg)
|
||||
const char *msg;
|
||||
{
|
||||
fprintf(stderr, "%s: %s\n", prog, msg);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
* Compress input to output then close both files.
|
||||
*/
|
||||
void gz_compress(in, out)
|
||||
FILE *in;
|
||||
gzFile out;
|
||||
{
|
||||
local char buf[BUFLEN];
|
||||
int len;
|
||||
int err;
|
||||
|
||||
for (;;) {
|
||||
len = fread(buf, 1, sizeof(buf), in);
|
||||
if (ferror(in)) {
|
||||
perror("fread");
|
||||
exit(1);
|
||||
}
|
||||
if (len == 0) break;
|
||||
|
||||
if (gzwrite(out, buf, (unsigned)len) != len) error(gzerror(out, &err));
|
||||
}
|
||||
fclose(in);
|
||||
if (gzclose(out) != Z_OK) error("failed gzclose");
|
||||
}
|
||||
|
||||
/* ===========================================================================
|
||||
* Uncompress input to output then close both files.
|
||||
*/
|
||||
void gz_uncompress(in, out)
|
||||
gzFile in;
|
||||
FILE *out;
|
||||
{
|
||||
local char buf[BUFLEN];
|
||||
int len;
|
||||
int err;
|
||||
|
||||
for (;;) {
|
||||
len = gzread(in, buf, sizeof(buf));
|
||||
if (len < 0) error (gzerror(in, &err));
|
||||
if (len == 0) break;
|
||||
|
||||
if ((int)fwrite(buf, 1, (unsigned)len, out) != len) {
|
||||
error("failed fwrite");
|
||||
}
|
||||
}
|
||||
if (fclose(out)) error("failed fclose");
|
||||
|
||||
if (gzclose(in) != Z_OK) error("failed gzclose");
|
||||
}
|
||||
|
||||
|
||||
/* ===========================================================================
|
||||
* Compress the given file: create a corresponding .gz file and remove the
|
||||
* original.
|
||||
*/
|
||||
void file_compress(file)
|
||||
char *file;
|
||||
{
|
||||
local char outfile[MAX_NAME_LEN];
|
||||
FILE *in;
|
||||
gzFile out;
|
||||
|
||||
strcpy(outfile, file);
|
||||
strcat(outfile, GZ_SUFFIX);
|
||||
|
||||
in = fopen(file, "rb");
|
||||
if (in == NULL) {
|
||||
perror(file);
|
||||
exit(1);
|
||||
}
|
||||
out = gzopen(outfile, "wb"); /* use "wb9" for maximal compression */
|
||||
if (out == NULL) {
|
||||
fprintf(stderr, "%s: can't gzopen %s\n", prog, outfile);
|
||||
exit(1);
|
||||
}
|
||||
gz_compress(in, out);
|
||||
|
||||
unlink(file);
|
||||
}
|
||||
|
||||
|
||||
/* ===========================================================================
|
||||
* Uncompress the given file and remove the original.
|
||||
*/
|
||||
void file_uncompress(file)
|
||||
char *file;
|
||||
{
|
||||
local char buf[MAX_NAME_LEN];
|
||||
char *infile, *outfile;
|
||||
FILE *out;
|
||||
gzFile in;
|
||||
int len = strlen(file);
|
||||
|
||||
strcpy(buf, file);
|
||||
|
||||
if (len > SUFFIX_LEN && strcmp(file+len-SUFFIX_LEN, GZ_SUFFIX) == 0) {
|
||||
infile = file;
|
||||
outfile = buf;
|
||||
outfile[len-3] = '\0';
|
||||
} else {
|
||||
outfile = file;
|
||||
infile = buf;
|
||||
strcat(infile, GZ_SUFFIX);
|
||||
}
|
||||
in = gzopen(infile, "rb");
|
||||
if (in == NULL) {
|
||||
fprintf(stderr, "%s: can't gzopen %s\n", prog, infile);
|
||||
exit(1);
|
||||
}
|
||||
out = fopen(outfile, "wb");
|
||||
if (out == NULL) {
|
||||
perror(file);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
gz_uncompress(in, out);
|
||||
|
||||
unlink(infile);
|
||||
}
|
||||
|
||||
|
||||
/* ===========================================================================
|
||||
* Usage: minigzip [-d] [files...]
|
||||
*/
|
||||
|
||||
int main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
int uncompr = 0;
|
||||
gzFile file;
|
||||
|
||||
prog = argv[0];
|
||||
argc--, argv++;
|
||||
|
||||
if (argc > 0) {
|
||||
uncompr = (strcmp(*argv, "-d") == 0);
|
||||
if (uncompr) {
|
||||
argc--, argv++;
|
||||
}
|
||||
}
|
||||
if (argc == 0) {
|
||||
SET_BINARY_MODE(stdin);
|
||||
SET_BINARY_MODE(stdout);
|
||||
if (uncompr) {
|
||||
file = gzdopen(fileno(stdin), "rb");
|
||||
if (file == NULL) error("can't gzdopen stdin");
|
||||
gz_uncompress(file, stdout);
|
||||
} else {
|
||||
file = gzdopen(fileno(stdout), "wb"); /* "wb9" for max compr. */
|
||||
if (file == NULL) error("can't gzdopen stdout");
|
||||
gz_compress(stdin, file);
|
||||
}
|
||||
} else {
|
||||
do {
|
||||
if (uncompr) {
|
||||
file_uncompress(*argv);
|
||||
} else {
|
||||
file_compress(*argv);
|
||||
}
|
||||
} while (argv++, --argc);
|
||||
}
|
||||
exit(0);
|
||||
return 0; /* to avoid warning */
|
||||
}
|
||||
+1141
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,58 @@
|
||||
/* uncompr.c -- decompress a memory buffer
|
||||
* Copyright (C) 1995-1996 Jean-loup Gailly.
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
/* $Id: uncompr.c,v 1.8 1996/01/30 21:59:26 me Exp $ */
|
||||
|
||||
#include "zlib.h"
|
||||
|
||||
/* ===========================================================================
|
||||
Decompresses the source buffer into the destination buffer. sourceLen is
|
||||
the byte length of the source buffer. Upon entry, destLen is the total
|
||||
size of the destination buffer, which must be large enough to hold the
|
||||
entire uncompressed data. (The size of the uncompressed data must have
|
||||
been saved previously by the compressor and transmitted to the decompressor
|
||||
by some mechanism outside the scope of this compression library.)
|
||||
Upon exit, destLen is the actual size of the compressed buffer.
|
||||
This function can be used to decompress a whole file at once if the
|
||||
input file is mmap'ed.
|
||||
|
||||
uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
|
||||
enough memory, Z_BUF_ERROR if there was not enough room in the output
|
||||
buffer, or Z_DATA_ERROR if the input data was corrupted.
|
||||
*/
|
||||
int uncompress (dest, destLen, source, sourceLen)
|
||||
Bytef *dest;
|
||||
uLongf *destLen;
|
||||
const Bytef *source;
|
||||
uLong sourceLen;
|
||||
{
|
||||
z_stream stream;
|
||||
int err;
|
||||
|
||||
stream.next_in = (Bytef*)source;
|
||||
stream.avail_in = (uInt)sourceLen;
|
||||
/* Check for source > 64K on 16-bit machine: */
|
||||
if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
|
||||
|
||||
stream.next_out = dest;
|
||||
stream.avail_out = (uInt)*destLen;
|
||||
if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
|
||||
|
||||
stream.zalloc = (alloc_func)0;
|
||||
stream.zfree = (free_func)0;
|
||||
|
||||
err = inflateInit(&stream);
|
||||
if (err != Z_OK) return err;
|
||||
|
||||
err = inflate(&stream, Z_FINISH);
|
||||
if (err != Z_STREAM_END) {
|
||||
inflateEnd(&stream);
|
||||
return err;
|
||||
}
|
||||
*destLen = stream.total_out;
|
||||
|
||||
err = inflateEnd(&stream);
|
||||
return err;
|
||||
}
|
||||
Loaded 100 of 643 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user