Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8cf6236545 | ||
|
|
59a4400972 | ||
|
|
bcc76fa94e | ||
|
|
4e706a260a | ||
|
|
954d729e75 | ||
|
|
4c11340d63 | ||
|
|
272f315ea8 |
39
.gitignore
vendored
39
.gitignore
vendored
@@ -1,39 +0,0 @@
|
||||
cscope.*
|
||||
*.swap
|
||||
.*.sw[po]
|
||||
.sw[po]
|
||||
*~
|
||||
*.orig
|
||||
*.diff
|
||||
*.patch
|
||||
*.rej
|
||||
*.[1-9].gz
|
||||
*.o
|
||||
*.[psS]o
|
||||
*.a
|
||||
*.d
|
||||
.depend
|
||||
nbsdsrc/*
|
||||
tools/revision
|
||||
TAGS
|
||||
tags
|
||||
GPATH
|
||||
GRTAGS
|
||||
GSYMS
|
||||
GTAGS
|
||||
\#*#
|
||||
CVS
|
||||
!/.gitignore
|
||||
.gitignore
|
||||
.svn
|
||||
minix-port.patch
|
||||
*.worldstone.log
|
||||
.worldstone*
|
||||
usr.bin/mdocml/man/*.7
|
||||
etc/passwd
|
||||
etc/pwd.db
|
||||
etc/spwd.db
|
||||
tools/image
|
||||
tools/kernel
|
||||
share/zoneinfo/builddir
|
||||
lib/libc/compat__*
|
||||
106
Makefile
106
Makefile
@@ -1,7 +1,5 @@
|
||||
# Master Makefile to compile everything in /usr/src except the system.
|
||||
|
||||
.include <bsd.own.mk>
|
||||
|
||||
MAKE=make
|
||||
|
||||
usage:
|
||||
@@ -15,7 +13,10 @@ usage:
|
||||
@echo " make libraries # Compile and install libraries"
|
||||
@echo " make commands # Compile all, commands, but don't install"
|
||||
@echo " make install # Compile and install commands"
|
||||
@echo " make depend # Generate required .depend files"
|
||||
@echo " make gnu-includes # Install include files for GCC"
|
||||
@echo " make gnu-libraries # Compile and install libraries for GCC"
|
||||
@echo " make clang-libraries # Compile and install libraries for GCC with clang"
|
||||
@echo " make clean # Remove all compiler results"
|
||||
@echo ""
|
||||
@echo "Run 'make' in tools/ to create a new MINIX configuration."
|
||||
@@ -29,96 +30,73 @@ usage:
|
||||
# 'make install' target.
|
||||
#
|
||||
# etcfiles has to be done first.
|
||||
world: mkfiles etcfiles includes libraries dep-all install etcforce
|
||||
.if ${COMPILER_TYPE} == "ack"
|
||||
world: mkfiles includes depend libraries install etcforce
|
||||
.elif ${COMPILER_TYPE} == "gnu"
|
||||
world: mkfiles includes depend gnu-libraries install etcforce
|
||||
.endif
|
||||
|
||||
mkfiles:
|
||||
make -C share/mk install
|
||||
|
||||
includes:
|
||||
$(MAKE) -C include includes
|
||||
$(MAKE) -C lib includes NBSD_LIBC=yes
|
||||
|
||||
MKHEADERSS=/usr/pkg/gcc*/libexec/gcc/*/*/install-tools/mkheaders
|
||||
gnu-includes: includes
|
||||
SHELL=/bin/sh; for d in $(MKHEADERSS); do if [ -f $$d ] ; then sh -e $$d ; fi; done
|
||||
$(MAKE) -C lib includes
|
||||
|
||||
libraries: includes
|
||||
$(MAKE) -C lib dependall install
|
||||
$(MAKE) -C lib build_ack
|
||||
|
||||
MKHEADERS411=/usr/gnu/libexec/gcc/i386-pc-minix/4.1.1/install-tools/mkheaders
|
||||
MKHEADERS443=/usr/gnu/libexec/gcc/i686-pc-minix/4.4.3/install-tools/mkheaders
|
||||
MKHEADERS443_PKGSRC=/usr/pkg/gcc44/libexec/gcc/i686-pc-minix/4.4.3/install-tools/mkheaders
|
||||
gnu-includes: includes
|
||||
SHELL=/bin/sh; if [ -f $(MKHEADERS411) ] ; then sh -e $(MKHEADERS411) ; fi
|
||||
SHELL=/bin/sh; if [ -f $(MKHEADERS443) ] ; then sh -e $(MKHEADERS443) ; fi
|
||||
SHELL=/bin/sh; if [ -f $(MKHEADERS443_PKGSRC) ] ; then sh -e $(MKHEADERS443_PKGSRC) ; fi
|
||||
|
||||
gnu-libraries: gnu-includes
|
||||
$(MAKE) -C lib build_gnu
|
||||
|
||||
clang-libraries: includes
|
||||
$(MAKE) -C lib build_clang
|
||||
|
||||
commands: includes libraries
|
||||
$(MAKE) -C commands all
|
||||
$(MAKE) -C bin all
|
||||
$(MAKE) -C sbin all
|
||||
$(MAKE) -C usr.bin all
|
||||
$(MAKE) -C libexec all
|
||||
$(MAKE) -C usr.sbin all
|
||||
|
||||
dep-all:
|
||||
$(MAKE) -C sys dependall
|
||||
$(MAKE) -C commands dependall
|
||||
$(MAKE) -C bin dependall
|
||||
$(MAKE) -C sbin dependall
|
||||
$(MAKE) -C usr.bin dependall
|
||||
$(MAKE) -C libexec dependall
|
||||
$(MAKE) -C usr.sbin dependall
|
||||
$(MAKE) -C kernel dependall
|
||||
$(MAKE) -C servers dependall
|
||||
$(MAKE) -C drivers dependall
|
||||
depend::
|
||||
$(MAKE) -C boot depend
|
||||
$(MAKE) -C commands depend
|
||||
$(MAKE) -C kernel depend
|
||||
$(MAKE) -C servers depend
|
||||
$(MAKE) -C drivers depend
|
||||
|
||||
etcfiles:
|
||||
etcfiles::
|
||||
$(MAKE) -C etc install
|
||||
|
||||
etcforce:
|
||||
etcforce::
|
||||
$(MAKE) -C etc installforce
|
||||
|
||||
all:
|
||||
$(MAKE) -C sys all
|
||||
all::
|
||||
$(MAKE) -C boot all
|
||||
$(MAKE) -C commands all
|
||||
$(MAKE) -C bin all
|
||||
$(MAKE) -C sbin all
|
||||
$(MAKE) -C usr.bin all
|
||||
$(MAKE) -C libexec all
|
||||
$(MAKE) -C usr.sbin all
|
||||
$(MAKE) -C tools all
|
||||
|
||||
install:
|
||||
$(MAKE) -C sys install
|
||||
$(MAKE) -C libexec install
|
||||
install::
|
||||
$(MAKE) -C boot install
|
||||
$(MAKE) -C man install makedb
|
||||
$(MAKE) -C commands install
|
||||
$(MAKE) -C bin install
|
||||
$(MAKE) -C sbin install
|
||||
$(MAKE) -C usr.bin install
|
||||
$(MAKE) -C usr.sbin install
|
||||
$(MAKE) -C servers install
|
||||
$(MAKE) -C share install
|
||||
$(MAKE) -C tools install
|
||||
|
||||
clean: mkfiles
|
||||
$(MAKE) -C sys clean
|
||||
clean::
|
||||
$(MAKE) -C boot clean
|
||||
$(MAKE) -C commands clean
|
||||
$(MAKE) -C bin clean
|
||||
$(MAKE) -C sbin clean
|
||||
$(MAKE) -C usr.bin clean
|
||||
$(MAKE) -C libexec clean
|
||||
$(MAKE) -C usr.sbin clean
|
||||
$(MAKE) -C share clean
|
||||
$(MAKE) -C tools clean
|
||||
$(MAKE) -C lib clean
|
||||
$(MAKE) -C lib clean_gnu
|
||||
$(MAKE) -C lib clean_ack
|
||||
$(MAKE) -C test clean
|
||||
|
||||
cleandepend: mkfiles
|
||||
$(MAKE) -C lib cleandepend
|
||||
$(MAKE) -C sys cleandepend
|
||||
cleandepend::
|
||||
$(MAKE) -C boot cleandepend
|
||||
$(MAKE) -C commands cleandepend
|
||||
$(MAKE) -C bin cleandepend
|
||||
$(MAKE) -C sbin cleandepend
|
||||
$(MAKE) -C usr.bin cleandepend
|
||||
$(MAKE) -C libexec cleandepend
|
||||
$(MAKE) -C usr.sbin cleandepend
|
||||
$(MAKE) -C tools cleandepend
|
||||
|
||||
# Warn usage change
|
||||
elf-libraries:
|
||||
echo "That target is just libraries now."
|
||||
false
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/pkg/bin/perl -w
|
||||
#!/usr/bin/perl -w
|
||||
|
||||
use strict;
|
||||
|
||||
|
||||
@@ -932,9 +932,9 @@ SPDP dtime()
|
||||
return q;
|
||||
}
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/times.h>
|
||||
#include <minix/sysinfo.h>
|
||||
#include <time.h>
|
||||
|
||||
struct tms tms;
|
||||
@@ -945,7 +945,7 @@ SPDP dtime(void)
|
||||
int secs, msecs;
|
||||
u32_t system_hz;
|
||||
times(&tms);
|
||||
system_hz = (u32_t) sysconf(_SC_CLK_TCK);
|
||||
getsysinfo_up(PM_PROC_NR, SIU_SYSTEMHZ, sizeof(system_hz), &system_hz);
|
||||
secs = tms.tms_utime / system_hz;
|
||||
q = secs;
|
||||
tms.tms_utime -= secs * system_hz;
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
# Makefile for bin
|
||||
|
||||
.include <bsd.own.mk>
|
||||
|
||||
SUBDIR= mkdir rm rmdir date
|
||||
|
||||
.include <bsd.subdir.mk>
|
||||
@@ -1,4 +0,0 @@
|
||||
CPPFLAGS+= -D_NETBSD_SOURCE
|
||||
|
||||
BINDIR?=/bin
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
# $NetBSD: Makefile,v 1.15 2011/08/14 10:53:16 christos Exp $
|
||||
# @(#)Makefile 8.1 (Berkeley) 5/31/93
|
||||
|
||||
PROG= date
|
||||
SRCS= date.c netdate.c
|
||||
DPADD+= ${LIBUTIL}
|
||||
LDADD+= -lutil
|
||||
CPPFLAGS+=-I${.CURDIR}
|
||||
|
||||
TZDIR= /usr/share/zoneinfo
|
||||
CPPFLAGS+= -DHAVE_ADJTIME=0 -DTZDIR=\"$(TZDIR)\"
|
||||
|
||||
COPTS.date.c = -Wno-format-nonliteral
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
244
bin/date/date.1
244
bin/date/date.1
@@ -1,244 +0,0 @@
|
||||
.\" $NetBSD: date.1,v 1.41 2010/02/04 22:56:11 wiz Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1980, 1990, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" This code is derived from software contributed to Berkeley by
|
||||
.\" the Institute of Electrical and Electronics Engineers, Inc.
|
||||
.\"
|
||||
.\" 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.
|
||||
.\" 3. Neither the name of the University nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
.\"
|
||||
.\" @(#)date.1 8.3 (Berkeley) 4/28/95
|
||||
.\"
|
||||
.Dd November 15, 2006
|
||||
.Dt DATE 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm date
|
||||
.Nd display or set date and time
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl ajnu
|
||||
.Op Fl d Ar date
|
||||
.Op Fl r Ar seconds
|
||||
.Op Cm + Ns Ar format
|
||||
.Sm off
|
||||
.Oo Oo Oo Oo Oo Oo
|
||||
.Ar CC Oc
|
||||
.Ar yy Oc
|
||||
.Ar mm Oc
|
||||
.Ar dd Oc
|
||||
.Ar HH Oc Ar MM Oo
|
||||
.Li \&. Ar SS Oc Oc
|
||||
.Sm on
|
||||
.Sh DESCRIPTION
|
||||
.Nm
|
||||
displays the current date and time when invoked without arguments.
|
||||
Providing arguments will format the date and time in a user-defined
|
||||
way or set the date.
|
||||
Only the superuser may set the date.
|
||||
.Pp
|
||||
The options are as follows:
|
||||
.Bl -tag -width Ds
|
||||
.It Fl a
|
||||
Use
|
||||
.Xr adjtime 2
|
||||
to change the local system time slowly,
|
||||
maintaining it as a monotonically increasing function.
|
||||
.Fl a
|
||||
implies
|
||||
.Fl n .
|
||||
.It Fl d Ar date
|
||||
Parse the provided human-described date and time and display the result without
|
||||
actually changing the system clock.
|
||||
(See
|
||||
.Xr parsedate 3
|
||||
for examples.)
|
||||
.It Fl j
|
||||
Parse the provided canonical representation of date and time (described below)
|
||||
and display the result without actually changing the system clock.
|
||||
.It Fl n
|
||||
The utility
|
||||
.Xr timed 8
|
||||
is used to synchronize the clocks on groups of machines.
|
||||
By default, if
|
||||
timed
|
||||
is running,
|
||||
.Nm
|
||||
will set the time on all of the machines in the local group.
|
||||
The
|
||||
.Fl n
|
||||
option stops
|
||||
.Nm
|
||||
from setting the time for other than the current machine.
|
||||
.It Fl r Ar seconds
|
||||
Print out the date and time that is
|
||||
.Ar seconds
|
||||
from the Epoch.
|
||||
.It Fl u
|
||||
Display or set the date in
|
||||
.Tn UTC
|
||||
(universal) time.
|
||||
.El
|
||||
.Pp
|
||||
An operand with a leading plus
|
||||
.Pq Cm +
|
||||
sign signals a user-defined format
|
||||
string which specifies the format in which to display the date and time.
|
||||
The format string may contain any of the conversion specifications described
|
||||
in the
|
||||
.Xr strftime 3
|
||||
manual page, as well as any arbitrary text.
|
||||
A \*[Lt]newline\*[Gt] character is always output after the characters
|
||||
specified by the format string.
|
||||
The format string for the default display is:
|
||||
.Bd -literal -offset indent
|
||||
%a %b %e %H:%M:%S %Z %Y
|
||||
.Ed
|
||||
.Pp
|
||||
If an operand does not have a leading plus sign, it is interpreted as
|
||||
a value for setting the system's notion of the current date and time.
|
||||
The canonical representation for setting the date and time is:
|
||||
.Pp
|
||||
.Bl -tag -width Ds -compact -offset indent
|
||||
.It Ar CC
|
||||
The first two digits of the year (the century).
|
||||
.It Ar yy
|
||||
The second two digits of the year.
|
||||
If
|
||||
.Ar yy
|
||||
is specified, but
|
||||
.Ar CC
|
||||
is not, a value for
|
||||
.Ar yy
|
||||
between 69 and 99 results in a
|
||||
.Ar CC
|
||||
value of 19.
|
||||
Otherwise, a
|
||||
.Ar CC
|
||||
value of 20 is used.
|
||||
.It Ar mm
|
||||
The month of the year, from 01 to 12.
|
||||
.It Ar dd
|
||||
The day of the month, from 01 to 31.
|
||||
.It Ar HH
|
||||
The hour of the day, from 00 to 23.
|
||||
.It Ar MM
|
||||
The minute of the hour, from 00 to 59.
|
||||
.It Ar SS
|
||||
The second of the minute, from 00 to 61.
|
||||
.El
|
||||
.Pp
|
||||
Everything but the minutes is optional.
|
||||
.Pp
|
||||
Time changes for Daylight Saving and Standard time and leap seconds
|
||||
and years are handled automatically.
|
||||
.Sh ENVIRONMENT
|
||||
The following environment variables affect the execution of
|
||||
.Nm :
|
||||
.Bl -tag -width iTZ
|
||||
.It Ev TZ
|
||||
The timezone to use when displaying dates.
|
||||
See
|
||||
.Xr environ 7
|
||||
for more information.
|
||||
.El
|
||||
.Sh FILES
|
||||
.Bl -tag -width /var/log/messages -compact
|
||||
.It Pa /etc/localtime
|
||||
Symlink pointing to system's default timezone information file in
|
||||
.Pa /usr/share/zoneinfo
|
||||
directory.
|
||||
.It Pa /var/log/wtmp
|
||||
A record of date resets and time changes.
|
||||
.It Pa /var/log/messages
|
||||
A record of the user setting the time.
|
||||
.El
|
||||
.Sh EXAMPLES
|
||||
The command:
|
||||
.Bd -literal -offset indent
|
||||
date '+DATE: %m/%d/%y%nTIME: %H:%M:%S'
|
||||
.Ed
|
||||
.Pp
|
||||
will display:
|
||||
.Bd -literal -offset indent
|
||||
DATE: 11/21/87
|
||||
TIME: 13:36:16
|
||||
.Ed
|
||||
.Pp
|
||||
The command:
|
||||
.Bd -literal -offset indent
|
||||
date 8506131627
|
||||
.Ed
|
||||
.Pp
|
||||
sets the date to
|
||||
.Dq Li "June 13, 1985, 4:27 PM" .
|
||||
.Pp
|
||||
The command:
|
||||
.Bd -literal -offset indent
|
||||
date 1432
|
||||
.Ed
|
||||
.Pp
|
||||
sets the time to
|
||||
.Li "2:32 PM" ,
|
||||
without modifying the date.
|
||||
.Sh DIAGNOSTICS
|
||||
Exit status is 0 on success, 1 if unable to set the date, and 2
|
||||
if able to set the local date, but unable to set it globally.
|
||||
.Pp
|
||||
Occasionally, when
|
||||
.Xr timed 8
|
||||
synchronizes the time on many hosts, the setting of a new time value may
|
||||
require more than a few seconds.
|
||||
On these occasions,
|
||||
.Nm
|
||||
prints:
|
||||
.Ql Network time being set .
|
||||
The message
|
||||
.Ql Communication error with timed
|
||||
occurs when the communication
|
||||
between
|
||||
.Nm
|
||||
and
|
||||
timed
|
||||
fails.
|
||||
.Sh SEE ALSO
|
||||
.Xr adjtime 2 ,
|
||||
.Xr gettimeofday 2 ,
|
||||
.Xr settimeofday 2 ,
|
||||
.Xr parsedate 3 ,
|
||||
.Xr strftime 3 ,
|
||||
.Xr utmp 5 ,
|
||||
.Xr timed 8
|
||||
.Rs
|
||||
.%T "TSP: The Time Synchronization Protocol for UNIX 4.3BSD"
|
||||
.%A R. Gusella
|
||||
.%A S. Zatti
|
||||
.Re
|
||||
.Sh STANDARDS
|
||||
The
|
||||
.Nm
|
||||
utility is expected to be compatible with
|
||||
.St -p1003.2 .
|
||||
350
bin/date/date.c
350
bin/date/date.c
@@ -1,350 +0,0 @@
|
||||
/* $NetBSD: date.c,v 1.60 2011/08/27 12:55:09 joerg Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1985, 1987, 1988, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__COPYRIGHT(
|
||||
"@(#) Copyright (c) 1985, 1987, 1988, 1993\
|
||||
The Regents of the University of California. All rights reserved.");
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)date.c 8.2 (Berkeley) 4/28/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: date.c,v 1.60 2011/08/27 12:55:09 joerg Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <locale.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#include <time.h>
|
||||
#include <tzfile.h>
|
||||
#include <unistd.h>
|
||||
#include <util.h>
|
||||
|
||||
#include "extern.h"
|
||||
|
||||
static time_t tval;
|
||||
static int aflag, jflag, rflag, nflag;
|
||||
|
||||
__dead static void badformat(void);
|
||||
__dead static void badtime(void);
|
||||
__dead static void badvalue(const char *);
|
||||
static void setthetime(const char *);
|
||||
__dead static void usage(void);
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
char *buf;
|
||||
size_t bufsiz;
|
||||
const char *format;
|
||||
int ch;
|
||||
long long val;
|
||||
struct tm *tm;
|
||||
|
||||
setprogname(argv[0]);
|
||||
(void)setlocale(LC_ALL, "");
|
||||
|
||||
while ((ch = getopt(argc, argv, "ad:jnr:u")) != -1) {
|
||||
switch (ch) {
|
||||
case 'a': /* adjust time slowly */
|
||||
aflag = 1;
|
||||
nflag = 1;
|
||||
break;
|
||||
case 'd':
|
||||
#ifndef __minix
|
||||
rflag = 1;
|
||||
tval = parsedate(optarg, NULL, NULL);
|
||||
if (tval == -1)
|
||||
#endif
|
||||
badarg: errx(EXIT_FAILURE,
|
||||
"Cannot parse `%s'", optarg);
|
||||
break;
|
||||
case 'j': /* don't set time */
|
||||
jflag = 1;
|
||||
break;
|
||||
case 'n': /* don't set network */
|
||||
nflag = 1;
|
||||
break;
|
||||
case 'r': /* user specified seconds */
|
||||
errno = 0;
|
||||
val = strtoll(optarg, &buf, 0);
|
||||
if (optarg[0] == '\0' || *buf != '\0')
|
||||
goto badarg;
|
||||
if (errno == ERANGE && (val == LLONG_MAX ||
|
||||
val == LLONG_MIN))
|
||||
err(EXIT_FAILURE, "Bad number `%s'", optarg);
|
||||
rflag = 1;
|
||||
tval = (time_t)val;
|
||||
break;
|
||||
case 'u': /* do everything in UTC */
|
||||
(void)setenv("TZ", "UTC0", 1);
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (!rflag && time(&tval) == -1)
|
||||
err(EXIT_FAILURE, "time");
|
||||
|
||||
|
||||
/* allow the operands in any order */
|
||||
if (*argv && **argv == '+') {
|
||||
format = *argv;
|
||||
++argv;
|
||||
} else
|
||||
format = "+%a %b %e %H:%M:%S %Z %Y";
|
||||
|
||||
if (*argv) {
|
||||
setthetime(*argv);
|
||||
++argv;
|
||||
}
|
||||
|
||||
if (*argv && **argv == '+')
|
||||
format = *argv;
|
||||
|
||||
if ((buf = malloc(bufsiz = 1024)) == NULL)
|
||||
goto bad;
|
||||
|
||||
if ((tm = localtime(&tval)) == NULL)
|
||||
err(EXIT_FAILURE, "localtime %lld failed", (long long)tval);
|
||||
|
||||
while (strftime(buf, bufsiz, format, tm) == 0)
|
||||
if ((buf = realloc(buf, bufsiz <<= 1)) == NULL)
|
||||
goto bad;
|
||||
|
||||
(void)printf("%s\n", buf + 1);
|
||||
free(buf);
|
||||
return 0;
|
||||
bad:
|
||||
err(EXIT_FAILURE, "Cannot allocate format buffer");
|
||||
}
|
||||
|
||||
static void
|
||||
badformat(void)
|
||||
{
|
||||
warnx("illegal time format");
|
||||
usage();
|
||||
}
|
||||
|
||||
static void
|
||||
badtime(void)
|
||||
{
|
||||
errx(EXIT_FAILURE, "illegal time");
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
static void
|
||||
badvalue(const char *param)
|
||||
{
|
||||
warnx("invalid %s supplied", param);
|
||||
usage();
|
||||
}
|
||||
|
||||
#define ATOI2(s) ((s) += 2, ((s)[-2] - '0') * 10 + ((s)[-1] - '0'))
|
||||
|
||||
static void
|
||||
setthetime(const char *p)
|
||||
{
|
||||
struct timeval tv;
|
||||
time_t new_time;
|
||||
struct tm *lt;
|
||||
const char *dot, *t;
|
||||
size_t len;
|
||||
int yearset;
|
||||
|
||||
for (t = p, dot = NULL; *t; ++t) {
|
||||
if (isdigit((unsigned char)*t))
|
||||
continue;
|
||||
if (*t == '.' && dot == NULL) {
|
||||
dot = t;
|
||||
continue;
|
||||
}
|
||||
badformat();
|
||||
}
|
||||
|
||||
if ((lt = localtime(&tval)) == NULL)
|
||||
err(EXIT_FAILURE, "localtime %lld failed", (long long)tval);
|
||||
|
||||
lt->tm_isdst = -1; /* Divine correct DST */
|
||||
|
||||
if (dot != NULL) { /* .ss */
|
||||
len = strlen(dot);
|
||||
if (len != 3)
|
||||
badformat();
|
||||
++dot;
|
||||
lt->tm_sec = ATOI2(dot);
|
||||
if (lt->tm_sec > 61)
|
||||
badvalue("seconds");
|
||||
} else {
|
||||
len = 0;
|
||||
lt->tm_sec = 0;
|
||||
}
|
||||
|
||||
yearset = 0;
|
||||
switch (strlen(p) - len) {
|
||||
case 12: /* cc */
|
||||
lt->tm_year = ATOI2(p) * 100 - TM_YEAR_BASE;
|
||||
if (lt->tm_year < 0)
|
||||
badtime();
|
||||
yearset = 1;
|
||||
/* FALLTHROUGH */
|
||||
case 10: /* yy */
|
||||
if (yearset) {
|
||||
lt->tm_year += ATOI2(p);
|
||||
} else {
|
||||
yearset = ATOI2(p);
|
||||
if (yearset < 69)
|
||||
lt->tm_year = yearset + 2000 - TM_YEAR_BASE;
|
||||
else
|
||||
lt->tm_year = yearset + 1900 - TM_YEAR_BASE;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
case 8: /* mm */
|
||||
lt->tm_mon = ATOI2(p);
|
||||
if (lt->tm_mon > 12 || lt->tm_mon == 0)
|
||||
badvalue("month");
|
||||
--lt->tm_mon; /* time struct is 0 - 11 */
|
||||
/* FALLTHROUGH */
|
||||
case 6: /* dd */
|
||||
lt->tm_mday = ATOI2(p);
|
||||
switch (lt->tm_mon) {
|
||||
case 0:
|
||||
case 2:
|
||||
case 4:
|
||||
case 6:
|
||||
case 7:
|
||||
case 9:
|
||||
case 11:
|
||||
if (lt->tm_mday > 31 || lt->tm_mday == 0)
|
||||
badvalue("day of month");
|
||||
break;
|
||||
case 3:
|
||||
case 5:
|
||||
case 8:
|
||||
case 10:
|
||||
if (lt->tm_mday > 30 || lt->tm_mday == 0)
|
||||
badvalue("day of month");
|
||||
break;
|
||||
case 1:
|
||||
if (lt->tm_mday > 29 || lt->tm_mday == 0 ||
|
||||
(lt->tm_mday == 29 &&
|
||||
!isleap(lt->tm_year + TM_YEAR_BASE)))
|
||||
badvalue("day of month");
|
||||
break;
|
||||
default:
|
||||
badvalue("month");
|
||||
break;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
case 4: /* hh */
|
||||
lt->tm_hour = ATOI2(p);
|
||||
if (lt->tm_hour > 23)
|
||||
badvalue("hour");
|
||||
/* FALLTHROUGH */
|
||||
case 2: /* mm */
|
||||
lt->tm_min = ATOI2(p);
|
||||
if (lt->tm_min > 59)
|
||||
badvalue("minute");
|
||||
break;
|
||||
case 0: /* was just .sss */
|
||||
if (len != 0)
|
||||
break;
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
badformat();
|
||||
}
|
||||
|
||||
/* convert broken-down time to UTC clock time */
|
||||
if ((new_time = mktime(lt)) == -1)
|
||||
badtime();
|
||||
|
||||
/* if jflag is set, don't actually change the time, just return */
|
||||
if (jflag) {
|
||||
tval = new_time;
|
||||
return;
|
||||
}
|
||||
|
||||
/* set the time */
|
||||
if (nflag || netsettime(new_time)) {
|
||||
logwtmp("|", "date", "");
|
||||
#if HAVE_ADJTIME
|
||||
if (aflag) {
|
||||
tv.tv_sec = new_time - tval;
|
||||
tv.tv_usec = 0;
|
||||
if (adjtime(&tv, NULL))
|
||||
err(EXIT_FAILURE, "adjtime");
|
||||
}
|
||||
#else
|
||||
if (aflag) {
|
||||
err(EXIT_FAILURE, "no adjtime");
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
tval = new_time;
|
||||
tv.tv_sec = tval;
|
||||
tv.tv_usec = 0;
|
||||
if (settimeofday(&tv, NULL))
|
||||
err(EXIT_FAILURE, "settimeofday");
|
||||
}
|
||||
logwtmp("{", "date", "");
|
||||
}
|
||||
|
||||
if ((p = getlogin()) == NULL)
|
||||
p = "???";
|
||||
syslog(LOG_AUTH | LOG_NOTICE, "date set by %s", p);
|
||||
}
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
(void)fprintf(stderr,
|
||||
"Usage: %s [-ajnu] [-d date] [-r seconds] [+format]",
|
||||
getprogname());
|
||||
(void)fprintf(stderr, " [[[[[[CC]yy]mm]dd]HH]MM[.SS]]\n");
|
||||
exit(EXIT_FAILURE);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
/* $NetBSD: extern.h,v 1.8 2006/11/17 22:11:28 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*
|
||||
* @(#)extern.h 8.1 (Berkeley) 5/31/93
|
||||
*/
|
||||
|
||||
#ifndef _EXTERN_H_
|
||||
#define _EXTERN_H_
|
||||
|
||||
int netsettime(time_t);
|
||||
|
||||
#endif /* !_EXTERN_H_ */
|
||||
@@ -1,200 +0,0 @@
|
||||
/* $NetBSD: netdate.c,v 1.30 2011/01/29 02:16:52 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)netdate.c 8.2 (Berkeley) 4/28/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: netdate.c,v 1.30 2011/01/29 02:16:52 christos Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#define TSPTYPES
|
||||
#include <protocols/timed.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <poll.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "extern.h"
|
||||
|
||||
#define WAITACK 2000 /* milliseconds */
|
||||
#define WAITDATEACK 5000 /* milliseconds */
|
||||
|
||||
static const char *
|
||||
tsp_type_to_string(const struct tsp *msg)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
i = msg->tsp_type;
|
||||
return i < TSPTYPENUMBER ? tsptype[i] : "unknown";
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the date in the machines controlled by timedaemons by communicating the
|
||||
* new date to the local timedaemon. If the timedaemon is in the master state,
|
||||
* it performs the correction on all slaves. If it is in the slave state, it
|
||||
* notifies the master that a correction is needed.
|
||||
* Returns 0 on success. Returns > 0 on failure.
|
||||
*/
|
||||
int
|
||||
netsettime(time_t tval)
|
||||
{
|
||||
struct sockaddr_in dest;
|
||||
struct tsp msg;
|
||||
char hostname[MAXHOSTNAMELEN];
|
||||
struct servent *sp;
|
||||
struct pollfd ready;
|
||||
int found, s, timed_ack, waittime;
|
||||
|
||||
if ((sp = getservbyname("timed", "udp")) == NULL) {
|
||||
warnx("udp/timed: unknown service");
|
||||
return 2;
|
||||
}
|
||||
|
||||
(void)memset(&dest, 0, sizeof(dest));
|
||||
#ifdef BSD4_4
|
||||
dest.sin_len = sizeof(dest);
|
||||
#endif
|
||||
dest.sin_family = AF_INET;
|
||||
dest.sin_port = sp->s_port;
|
||||
dest.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
s = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (s == -1) {
|
||||
if (errno != EAFNOSUPPORT)
|
||||
warn("timed");
|
||||
return 2;
|
||||
}
|
||||
|
||||
#ifdef IP_PORTRANGE
|
||||
{
|
||||
static const int on = IP_PORTRANGE_LOW;
|
||||
|
||||
if (setsockopt(s, IPPROTO_IP, IP_PORTRANGE, &on,
|
||||
sizeof(on)) == -1) {
|
||||
warn("setsockopt");
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
msg.tsp_type = TSP_SETDATE;
|
||||
msg.tsp_vers = TSPVERSION;
|
||||
if (gethostname(hostname, sizeof(hostname)) == -1) {
|
||||
warn("gethostname");
|
||||
goto bad;
|
||||
}
|
||||
(void)strlcpy(msg.tsp_name, hostname, sizeof(msg.tsp_name));
|
||||
msg.tsp_seq = htons((in_port_t)0);
|
||||
msg.tsp_time.tv_sec = htonl((in_addr_t)tval); /* XXX: y2038 */
|
||||
msg.tsp_time.tv_usec = htonl((in_addr_t)0);
|
||||
if (connect(s, (const void *)&dest, sizeof(dest)) == -1) {
|
||||
warn("connect");
|
||||
goto bad;
|
||||
}
|
||||
if (send(s, &msg, sizeof(msg), 0) == -1) {
|
||||
if (errno != ECONNREFUSED)
|
||||
warn("send");
|
||||
goto bad;
|
||||
}
|
||||
|
||||
timed_ack = -1;
|
||||
waittime = WAITACK;
|
||||
ready.fd = s;
|
||||
ready.events = POLLIN;
|
||||
loop:
|
||||
found = poll(&ready, 1, waittime);
|
||||
|
||||
{
|
||||
socklen_t len;
|
||||
int error;
|
||||
|
||||
len = sizeof(error);
|
||||
if (getsockopt(s, SOL_SOCKET, SO_ERROR, &error, &len) == -1) {
|
||||
warn("getsockopt");
|
||||
goto bad;
|
||||
}
|
||||
if (error) {
|
||||
if (error != ECONNREFUSED) {
|
||||
errno = error;
|
||||
warn("send (delayed error)");
|
||||
}
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
|
||||
if (found > 0 && ready.revents & POLLIN) {
|
||||
ssize_t ret;
|
||||
|
||||
if ((ret = recv(s, &msg, sizeof(msg), 0)) == -1) {
|
||||
if (errno != ECONNREFUSED)
|
||||
warn("recv");
|
||||
goto bad;
|
||||
} else if ((size_t)ret < sizeof(msg)) {
|
||||
warnx("recv: incomplete packet");
|
||||
goto bad;
|
||||
}
|
||||
|
||||
msg.tsp_seq = ntohs(msg.tsp_seq);
|
||||
msg.tsp_time.tv_sec = ntohl(msg.tsp_time.tv_sec);
|
||||
msg.tsp_time.tv_usec = ntohl(msg.tsp_time.tv_usec);
|
||||
switch (msg.tsp_type) {
|
||||
case TSP_ACK:
|
||||
timed_ack = TSP_ACK;
|
||||
waittime = WAITDATEACK;
|
||||
goto loop;
|
||||
case TSP_DATEACK:
|
||||
(void)close(s);
|
||||
return 0;
|
||||
default:
|
||||
warnx("wrong ack received from timed: %s",
|
||||
tsp_type_to_string(&msg));
|
||||
timed_ack = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (timed_ack == -1)
|
||||
warnx("can't reach time daemon, time set locally");
|
||||
|
||||
bad:
|
||||
(void)close(s);
|
||||
return 2;
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
# $NetBSD: Makefile,v 1.8 1997/07/20 22:37:21 christos Exp $
|
||||
# @(#)Makefile 8.1 (Berkeley) 5/31/93
|
||||
|
||||
PROG= mkdir
|
||||
SYMLINKS= $(BINDIR)/$(PROG) /usr/bin/$(PROG)
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
@@ -1,94 +0,0 @@
|
||||
.\" $NetBSD: mkdir.1,v 1.16 2003/08/07 09:05:16 agc Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1989, 1990, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" This code is derived from software contributed to Berkeley by
|
||||
.\" the Institute of Electrical and Electronics Engineers, Inc.
|
||||
.\"
|
||||
.\" 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.
|
||||
.\" 3. Neither the name of the University nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
.\"
|
||||
.\" @(#)mkdir.1 8.2 (Berkeley) 1/25/94
|
||||
.\"
|
||||
.Dd January 25, 1994
|
||||
.Dt MKDIR 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm mkdir
|
||||
.Nd make directories
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl p
|
||||
.Op Fl m Ar mode
|
||||
.Ar directory_name ...
|
||||
.Sh DESCRIPTION
|
||||
.Nm
|
||||
creates the directories named as operands, in the order specified,
|
||||
using mode
|
||||
.Li rwxrwxrwx (\&0777)
|
||||
as modified by the current
|
||||
.Xr umask 2 .
|
||||
.Pp
|
||||
The options are as follows:
|
||||
.Pp
|
||||
.Bl -tag -width indent
|
||||
.It Fl m
|
||||
Set the file permission bits of the final created directory to
|
||||
the specified mode.
|
||||
The mode argument can be in any of the formats specified to the
|
||||
.Xr chmod 1
|
||||
utility.
|
||||
If a symbolic mode is specified, the operation characters
|
||||
.Dq +
|
||||
and
|
||||
.Dq -
|
||||
are interpreted relative to an initial mode of
|
||||
.Dq a=rwx .
|
||||
.It Fl p
|
||||
Create intermediate directories as required.
|
||||
If this option is not specified, the full path prefix of each
|
||||
operand must already exist.
|
||||
Intermediate directories are created with permission bits of
|
||||
.Li rwxrwxrwx (\&0777)
|
||||
as modified by the current umask, plus write and search
|
||||
permission for the owner.
|
||||
Do not consider it an error if the argument directory already exists.
|
||||
.El
|
||||
.Pp
|
||||
The user must have write permission in the parent directory.
|
||||
.Sh EXIT STATUS
|
||||
.Nm
|
||||
exits 0 if successful, and \*[Gt]0 if an error occurred.
|
||||
.Sh SEE ALSO
|
||||
.Xr chmod 1 ,
|
||||
.Xr rmdir 1 ,
|
||||
.Xr mkdir 2 ,
|
||||
.Xr umask 2
|
||||
.Sh STANDARDS
|
||||
The
|
||||
.Nm
|
||||
utility is expected to be
|
||||
.St -p1003.2
|
||||
compatible.
|
||||
@@ -1,224 +0,0 @@
|
||||
/* $NetBSD: mkdir.c,v 1.37 2008/07/20 00:52:40 lukem Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1983, 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__COPYRIGHT("@(#) Copyright (c) 1983, 1992, 1993\
|
||||
The Regents of the University of California. All rights reserved.");
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)mkdir.c 8.2 (Berkeley) 1/25/94";
|
||||
#else
|
||||
__RCSID("$NetBSD: mkdir.c,v 1.37 2008/07/20 00:52:40 lukem Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <locale.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int mkpath(char *, mode_t, mode_t);
|
||||
void usage(void);
|
||||
int main(int, char *[]);
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int ch, exitval, pflag;
|
||||
void *set;
|
||||
mode_t mode, dir_mode;
|
||||
|
||||
setprogname(argv[0]);
|
||||
(void)setlocale(LC_ALL, "");
|
||||
|
||||
/*
|
||||
* The default file mode is a=rwx (0777) with selected permissions
|
||||
* removed in accordance with the file mode creation mask. For
|
||||
* intermediate path name components, the mode is the default modified
|
||||
* by u+wx so that the subdirectories can always be created.
|
||||
*/
|
||||
mode = (S_IRWXU | S_IRWXG | S_IRWXO) & ~umask(0);
|
||||
dir_mode = mode | S_IWUSR | S_IXUSR;
|
||||
|
||||
pflag = 0;
|
||||
while ((ch = getopt(argc, argv, "m:p")) != -1)
|
||||
switch (ch) {
|
||||
case 'p':
|
||||
pflag = 1;
|
||||
break;
|
||||
case 'm':
|
||||
if ((set = setmode(optarg)) == NULL) {
|
||||
err(EXIT_FAILURE, "Cannot set file mode `%s'",
|
||||
optarg);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
mode = getmode(set, S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
free(set);
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
/* NOTREACHED */
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (*argv == NULL) {
|
||||
usage();
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
for (exitval = EXIT_SUCCESS; *argv != NULL; ++argv) {
|
||||
#ifdef notdef
|
||||
char *slash;
|
||||
|
||||
/* Kernel takes care of this */
|
||||
/* Remove trailing slashes, per POSIX. */
|
||||
slash = strrchr(*argv, '\0');
|
||||
while (--slash > *argv && *slash == '/')
|
||||
*slash = '\0';
|
||||
#endif
|
||||
|
||||
if (pflag) {
|
||||
if (mkpath(*argv, mode, dir_mode) < 0)
|
||||
exitval = EXIT_FAILURE;
|
||||
} else {
|
||||
if (mkdir(*argv, mode) < 0) {
|
||||
warn("%s", *argv);
|
||||
exitval = EXIT_FAILURE;
|
||||
} else {
|
||||
/*
|
||||
* The mkdir() and umask() calls both honor
|
||||
* only the file permission bits, so if you try
|
||||
* to set a mode including the sticky, setuid,
|
||||
* setgid bits you lose them. So chmod().
|
||||
*/
|
||||
if ((mode & ~(S_IRWXU|S_IRWXG|S_IRWXO)) != 0 &&
|
||||
chmod(*argv, mode) == -1) {
|
||||
warn("%s", *argv);
|
||||
exitval = EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
exit(exitval);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
/*
|
||||
* mkpath -- create directories.
|
||||
* path - path
|
||||
* mode - file mode of terminal directory
|
||||
* dir_mode - file mode of intermediate directories
|
||||
*/
|
||||
int
|
||||
mkpath(char *path, mode_t mode, mode_t dir_mode)
|
||||
{
|
||||
struct stat sb;
|
||||
char *slash;
|
||||
int done, rv;
|
||||
|
||||
done = 0;
|
||||
slash = path;
|
||||
|
||||
for (;;) {
|
||||
slash += strspn(slash, "/");
|
||||
slash += strcspn(slash, "/");
|
||||
|
||||
done = (*slash == '\0');
|
||||
*slash = '\0';
|
||||
|
||||
rv = mkdir(path, done ? mode : dir_mode);
|
||||
if (rv < 0) {
|
||||
/*
|
||||
* Can't create; path exists or no perms.
|
||||
* stat() path to determine what's there now.
|
||||
*/
|
||||
int sverrno;
|
||||
|
||||
sverrno = errno;
|
||||
if (stat(path, &sb) < 0) {
|
||||
/* Not there; use mkdir()s error */
|
||||
errno = sverrno;
|
||||
warn("%s", path);
|
||||
return -1;
|
||||
}
|
||||
if (!S_ISDIR(sb.st_mode)) {
|
||||
/* Is there, but isn't a directory */
|
||||
errno = ENOTDIR;
|
||||
warn("%s", path);
|
||||
return -1;
|
||||
}
|
||||
} else if (done) {
|
||||
/*
|
||||
* Created ok, and this is the last element
|
||||
*/
|
||||
/*
|
||||
* The mkdir() and umask() calls both honor only the
|
||||
* file permission bits, so if you try to set a mode
|
||||
* including the sticky, setuid, setgid bits you lose
|
||||
* them. So chmod().
|
||||
*/
|
||||
if ((mode & ~(S_IRWXU|S_IRWXG|S_IRWXO)) != 0 &&
|
||||
chmod(path, mode) == -1) {
|
||||
warn("%s", path);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (done) {
|
||||
break;
|
||||
}
|
||||
*slash = '/';
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
usage(void)
|
||||
{
|
||||
|
||||
(void)fprintf(stderr, "usage: %s [-p] [-m mode] dirname ...\n",
|
||||
getprogname());
|
||||
exit(EXIT_FAILURE);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
# $NetBSD: Makefile,v 1.9 1997/07/20 22:37:50 christos Exp $
|
||||
# @(#)Makefile 8.1 (Berkeley) 5/31/93
|
||||
|
||||
PROG= rm
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
207
bin/rm/rm.1
207
bin/rm/rm.1
@@ -1,207 +0,0 @@
|
||||
.\" $NetBSD: rm.1,v 1.24 2006/09/02 23:28:32 wiz Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1990, 1993, 1994, 2003
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" This code is derived from software contributed to Berkeley by
|
||||
.\" the Institute of Electrical and Electronics Engineers, Inc.
|
||||
.\"
|
||||
.\" 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.
|
||||
.\" 3. Neither the name of the University nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
.\"
|
||||
.\" @(#)rm.1 8.5 (Berkeley) 12/5/94
|
||||
.\"
|
||||
.Dd August 25, 2006
|
||||
.Dt RM 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm rm
|
||||
.Nd remove directory entries
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl f | Fl i
|
||||
.Op Fl dPRrvW
|
||||
.Ar
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
utility attempts to remove the non-directory type files specified on the
|
||||
command line.
|
||||
If the permissions of the file do not permit writing, and the standard
|
||||
input device is a terminal, the user is prompted (on the standard error
|
||||
output) for confirmation.
|
||||
.Pp
|
||||
The options are as follows:
|
||||
.Bl -tag -width flag
|
||||
.It Fl d
|
||||
Attempt to remove directories as well as other types of files.
|
||||
.It Fl f
|
||||
Attempt to remove the files without prompting for confirmation,
|
||||
regardless of the file's permissions.
|
||||
If the file does not exist, do not display a diagnostic message or modify
|
||||
the exit status to reflect an error.
|
||||
The
|
||||
.Fl f
|
||||
option overrides any previous
|
||||
.Fl i
|
||||
options.
|
||||
.It Fl i
|
||||
Request confirmation before attempting to remove each file, regardless of
|
||||
the file's permissions, or whether or not the standard input device is a
|
||||
terminal.
|
||||
The
|
||||
.Fl i
|
||||
option overrides any previous
|
||||
.Fl f
|
||||
options.
|
||||
.It Fl P
|
||||
Overwrite regular files before deleting them.
|
||||
Files are overwritten three times, first with the byte pattern 0xff,
|
||||
then 0x00, and then with random data, before they are deleted.
|
||||
Some care is taken to ensure that the data are actually written to
|
||||
disk, but this cannot be guaranteed, even on traditional filesystems;
|
||||
on log-structured filesystems or if any block-journaling scheme is
|
||||
in use, this option is completely useless.
|
||||
If the file cannot be
|
||||
overwritten, it will not be removed.
|
||||
.It Fl R
|
||||
Attempt to remove the file hierarchy rooted in each file argument.
|
||||
The
|
||||
.Fl R
|
||||
option implies the
|
||||
.Fl d
|
||||
option.
|
||||
If the
|
||||
.Fl i
|
||||
option is specified, the user is prompted for confirmation before
|
||||
each directory's contents are processed (as well as before the attempt
|
||||
is made to remove the directory).
|
||||
If the user does not respond affirmatively, the file hierarchy rooted in
|
||||
that directory is skipped.
|
||||
.Pp
|
||||
.It Fl r
|
||||
Equivalent to
|
||||
.Fl R .
|
||||
.It Fl v
|
||||
Cause
|
||||
.Nm
|
||||
to be verbose, showing files as they are processed.
|
||||
.It Fl W
|
||||
Attempts to undelete the named files.
|
||||
Currently, this option can only be used to recover
|
||||
files covered by whiteouts.
|
||||
.El
|
||||
.Pp
|
||||
The
|
||||
.Nm
|
||||
utility removes symbolic links, not the files referenced by the links.
|
||||
.Pp
|
||||
It is an error to attempt to remove the files ``.'' and ``..''.
|
||||
.Sh EXIT STATUS
|
||||
The
|
||||
.Nm
|
||||
utility exits 0 if all of the named files or file hierarchies were removed,
|
||||
or if the
|
||||
.Fl f
|
||||
option was specified and all of the existing files or file hierarchies were
|
||||
removed.
|
||||
If an error occurs,
|
||||
.Nm
|
||||
exits with a value \*[Gt]0.
|
||||
.Sh EXAMPLES
|
||||
.Nm
|
||||
uses
|
||||
.Xr getopt 3
|
||||
standard argument processing.
|
||||
Removing filenames that begin with a dash
|
||||
.Pq e.g., Ar -file
|
||||
in the current directory which might otherwise be taken as option flags to
|
||||
.Nm
|
||||
can be accomplished as follows:
|
||||
.Pp
|
||||
.Ic "rm -- -file"
|
||||
.Pp
|
||||
or
|
||||
.Pp
|
||||
.Ic "rm ./-file"
|
||||
.Sh SEE ALSO
|
||||
.Xr rmdir 1 ,
|
||||
.Xr undelete 2 ,
|
||||
.Xr unlink 2 ,
|
||||
.Xr fts 3 ,
|
||||
.Xr getopt 3 ,
|
||||
.Xr symlink 7
|
||||
.Sh BUGS
|
||||
The
|
||||
.Fl P
|
||||
option assumes that the underlying file system is a fixed-block file
|
||||
system.
|
||||
FFS is a fixed-block file system, LFS is not.
|
||||
In addition, only regular files are overwritten, other types of files
|
||||
are not.
|
||||
Recent research indicates that as many as 35 overwrite passes with
|
||||
carefully chosen data patterns may be necessary to actually prevent
|
||||
recovery of data from a magnetic disk.
|
||||
Thus the
|
||||
.Fl P
|
||||
option is likely both insufficient for its design purpose and far
|
||||
too costly for default operation.
|
||||
However, it will at least prevent the recovery of data from FFS
|
||||
volumes with
|
||||
.Xr fsdb 8 .
|
||||
.Sh COMPATIBILITY
|
||||
The
|
||||
.Nm
|
||||
utility differs from historical implementations in that the
|
||||
.Fl f
|
||||
option only masks attempts to remove non-existent files instead of
|
||||
masking a large variety of errors.
|
||||
.Pp
|
||||
Also, historical
|
||||
.Bx
|
||||
implementations prompted on the standard output,
|
||||
not the standard error output.
|
||||
.Sh STANDARDS
|
||||
The
|
||||
.Nm
|
||||
utility is expected to be
|
||||
.St -p1003.2
|
||||
compatible.
|
||||
The
|
||||
.Fl v
|
||||
option is an extension.
|
||||
.Pp
|
||||
The
|
||||
.Fl P
|
||||
option attempts to conform to U.S. DoD 5220-22.M, "National Industrial
|
||||
Security Program Operating Manual" ("NISPOM") as updated by Change
|
||||
2 and the July 23, 2003 "Clearing \*[Am] Sanitization Matrix".
|
||||
However, unlike earlier revisions of NISPOM, the 2003 matrix imposes
|
||||
requirements which make it clear that the standard does not and
|
||||
can not apply to the erasure of individual files, in particular
|
||||
requirements relating to spare sector management for an entire
|
||||
magnetic disk.
|
||||
.Em Because these requirements are not met, the
|
||||
.Fl P
|
||||
.Em option does not conform to the standard .
|
||||
605
bin/rm/rm.c
605
bin/rm/rm.c
@@ -1,605 +0,0 @@
|
||||
/* $NetBSD: rm.c,v 1.50 2011/08/29 14:48:46 joerg Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1990, 1993, 1994, 2003
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__COPYRIGHT("@(#) Copyright (c) 1990, 1993, 1994\
|
||||
The Regents of the University of California. All rights reserved.");
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)rm.c 8.8 (Berkeley) 4/27/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: rm.c,v 1.50 2011/08/29 14:48:46 joerg Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <fts.h>
|
||||
#include <grp.h>
|
||||
#include <locale.h>
|
||||
#include <pwd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static int dflag, eval, fflag, iflag, Pflag, stdin_ok, vflag, Wflag;
|
||||
|
||||
static int check(char *, char *, struct stat *);
|
||||
static void checkdot(char **);
|
||||
static void rm_file(char **);
|
||||
static int rm_overwrite(char *, struct stat *);
|
||||
static void rm_tree(char **);
|
||||
__dead static void usage(void);
|
||||
|
||||
#ifdef __minix
|
||||
# ifndef O_SYNC
|
||||
# define O_SYNC 0
|
||||
# endif
|
||||
# ifndef O_RSYNC
|
||||
# define O_RSYNC 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* For the sake of the `-f' flag, check whether an error number indicates the
|
||||
* failure of an operation due to an non-existent file, either per se (ENOENT)
|
||||
* or because its filename argument was illegal (ENAMETOOLONG, ENOTDIR).
|
||||
*/
|
||||
#define NONEXISTENT(x) \
|
||||
((x) == ENOENT || (x) == ENAMETOOLONG || (x) == ENOTDIR)
|
||||
|
||||
/*
|
||||
* rm --
|
||||
* This rm is different from historic rm's, but is expected to match
|
||||
* POSIX 1003.2 behavior. The most visible difference is that -f
|
||||
* has two specific effects now, ignore non-existent files and force
|
||||
* file removal.
|
||||
*/
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int ch, rflag;
|
||||
|
||||
setprogname(argv[0]);
|
||||
(void)setlocale(LC_ALL, "");
|
||||
|
||||
Pflag = rflag = 0;
|
||||
while ((ch = getopt(argc, argv, "dfiPRrvW")) != -1)
|
||||
switch (ch) {
|
||||
case 'd':
|
||||
dflag = 1;
|
||||
break;
|
||||
case 'f':
|
||||
fflag = 1;
|
||||
iflag = 0;
|
||||
break;
|
||||
case 'i':
|
||||
fflag = 0;
|
||||
iflag = 1;
|
||||
break;
|
||||
case 'P':
|
||||
Pflag = 1;
|
||||
break;
|
||||
case 'R':
|
||||
case 'r': /* Compatibility. */
|
||||
rflag = 1;
|
||||
break;
|
||||
case 'v':
|
||||
vflag = 1;
|
||||
break;
|
||||
case 'W':
|
||||
Wflag = 1;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc < 1) {
|
||||
if (fflag)
|
||||
return 0;
|
||||
usage();
|
||||
}
|
||||
|
||||
checkdot(argv);
|
||||
|
||||
if (*argv) {
|
||||
stdin_ok = isatty(STDIN_FILENO);
|
||||
|
||||
if (rflag)
|
||||
rm_tree(argv);
|
||||
else
|
||||
rm_file(argv);
|
||||
}
|
||||
|
||||
exit(eval);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
static void
|
||||
rm_tree(char **argv)
|
||||
{
|
||||
FTS *fts;
|
||||
FTSENT *p;
|
||||
int flags, needstat, rval;
|
||||
|
||||
/*
|
||||
* Remove a file hierarchy. If forcing removal (-f), or interactive
|
||||
* (-i) or can't ask anyway (stdin_ok), don't stat the file.
|
||||
*/
|
||||
needstat = !fflag && !iflag && stdin_ok;
|
||||
|
||||
/*
|
||||
* If the -i option is specified, the user can skip on the pre-order
|
||||
* visit. The fts_number field flags skipped directories.
|
||||
*/
|
||||
#define SKIPPED 1
|
||||
|
||||
flags = FTS_PHYSICAL;
|
||||
if (!needstat)
|
||||
flags |= FTS_NOSTAT;
|
||||
#ifndef __minix
|
||||
if (Wflag)
|
||||
flags |= FTS_WHITEOUT;
|
||||
#endif
|
||||
if ((fts = fts_open(argv, flags, NULL)) == NULL)
|
||||
err(1, "fts_open failed");
|
||||
while ((p = fts_read(fts)) != NULL) {
|
||||
|
||||
switch (p->fts_info) {
|
||||
case FTS_DNR:
|
||||
if (!fflag || p->fts_errno != ENOENT) {
|
||||
warnx("%s: %s", p->fts_path,
|
||||
strerror(p->fts_errno));
|
||||
eval = 1;
|
||||
}
|
||||
continue;
|
||||
case FTS_ERR:
|
||||
errx(EXIT_FAILURE, "%s: %s", p->fts_path,
|
||||
strerror(p->fts_errno));
|
||||
/* NOTREACHED */
|
||||
case FTS_NS:
|
||||
/*
|
||||
* FTS_NS: assume that if can't stat the file, it
|
||||
* can't be unlinked.
|
||||
*/
|
||||
if (fflag && NONEXISTENT(p->fts_errno))
|
||||
continue;
|
||||
if (needstat) {
|
||||
warnx("%s: %s", p->fts_path,
|
||||
strerror(p->fts_errno));
|
||||
eval = 1;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case FTS_D:
|
||||
/* Pre-order: give user chance to skip. */
|
||||
if (!fflag && !check(p->fts_path, p->fts_accpath,
|
||||
p->fts_statp)) {
|
||||
(void)fts_set(fts, p, FTS_SKIP);
|
||||
p->fts_number = SKIPPED;
|
||||
}
|
||||
continue;
|
||||
case FTS_DP:
|
||||
/* Post-order: see if user skipped. */
|
||||
if (p->fts_number == SKIPPED)
|
||||
continue;
|
||||
break;
|
||||
default:
|
||||
if (!fflag &&
|
||||
!check(p->fts_path, p->fts_accpath, p->fts_statp))
|
||||
continue;
|
||||
}
|
||||
|
||||
rval = 0;
|
||||
/*
|
||||
* If we can't read or search the directory, may still be
|
||||
* able to remove it. Don't print out the un{read,search}able
|
||||
* message unless the remove fails.
|
||||
*/
|
||||
switch (p->fts_info) {
|
||||
case FTS_DP:
|
||||
case FTS_DNR:
|
||||
rval = rmdir(p->fts_accpath);
|
||||
if (rval != 0 && fflag && errno == ENOENT)
|
||||
continue;
|
||||
break;
|
||||
|
||||
#ifndef __minix
|
||||
case FTS_W:
|
||||
rval = undelete(p->fts_accpath);
|
||||
if (rval != 0 && fflag && errno == ENOENT)
|
||||
continue;
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
if (Pflag) {
|
||||
if (rm_overwrite(p->fts_accpath, NULL))
|
||||
continue;
|
||||
}
|
||||
rval = unlink(p->fts_accpath);
|
||||
if (rval != 0 && fflag && NONEXISTENT(errno))
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
if (rval != 0) {
|
||||
warn("%s", p->fts_path);
|
||||
eval = 1;
|
||||
} else if (vflag)
|
||||
(void)printf("%s\n", p->fts_path);
|
||||
}
|
||||
if (errno)
|
||||
err(1, "fts_read");
|
||||
fts_close(fts);
|
||||
}
|
||||
|
||||
static void
|
||||
rm_file(char **argv)
|
||||
{
|
||||
struct stat sb;
|
||||
int rval;
|
||||
char *f;
|
||||
|
||||
/*
|
||||
* Remove a file. POSIX 1003.2 states that, by default, attempting
|
||||
* to remove a directory is an error, so must always stat the file.
|
||||
*/
|
||||
while ((f = *argv++) != NULL) {
|
||||
/* Assume if can't stat the file, can't unlink it. */
|
||||
if (lstat(f, &sb)) {
|
||||
if (Wflag) {
|
||||
#ifdef __minix
|
||||
sb.st_mode = S_IWUSR|S_IRUSR;
|
||||
#else
|
||||
sb.st_mode = S_IFWHT|S_IWUSR|S_IRUSR;
|
||||
#endif
|
||||
} else {
|
||||
if (!fflag || !NONEXISTENT(errno)) {
|
||||
warn("%s", f);
|
||||
eval = 1;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
} else if (Wflag) {
|
||||
warnx("%s: %s", f, strerror(EEXIST));
|
||||
eval = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (S_ISDIR(sb.st_mode) && !dflag) {
|
||||
warnx("%s: is a directory", f);
|
||||
eval = 1;
|
||||
continue;
|
||||
}
|
||||
#ifndef __minix
|
||||
if (!fflag && !S_ISWHT(sb.st_mode) && !check(f, f, &sb))
|
||||
#else
|
||||
if (!fflag && !check(f, f, &sb))
|
||||
#endif
|
||||
continue;
|
||||
#ifndef __minix
|
||||
if (S_ISWHT(sb.st_mode))
|
||||
rval = undelete(f);
|
||||
else
|
||||
#endif
|
||||
if (S_ISDIR(sb.st_mode))
|
||||
rval = rmdir(f);
|
||||
else {
|
||||
if (Pflag) {
|
||||
if (rm_overwrite(f, &sb))
|
||||
continue;
|
||||
}
|
||||
rval = unlink(f);
|
||||
}
|
||||
if (rval && (!fflag || !NONEXISTENT(errno))) {
|
||||
warn("%s", f);
|
||||
eval = 1;
|
||||
}
|
||||
if (vflag && rval == 0)
|
||||
(void)printf("%s\n", f);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* rm_overwrite --
|
||||
* Overwrite the file 3 times with varying bit patterns.
|
||||
*
|
||||
* This is an expensive way to keep people from recovering files from your
|
||||
* non-snapshotted FFS filesystems using fsdb(8). Really. No more. Only
|
||||
* regular files are deleted, directories (and therefore names) will remain.
|
||||
* Also, this assumes a fixed-block file system (like FFS, or a V7 or a
|
||||
* System V file system). In a logging file system, you'll have to have
|
||||
* kernel support.
|
||||
*
|
||||
* A note on standards: U.S. DoD 5220.22-M "National Industrial Security
|
||||
* Program Operating Manual" ("NISPOM") is often cited as a reference
|
||||
* for clearing and sanitizing magnetic media. In fact, a matrix of
|
||||
* "clearing" and "sanitization" methods for various media was given in
|
||||
* Chapter 8 of the original 1995 version of NISPOM. However, that
|
||||
* matrix was *removed from the document* when Chapter 8 was rewritten
|
||||
* in Change 2 to the document in 2001. Recently, the Defense Security
|
||||
* Service has made a revised clearing and sanitization matrix available
|
||||
* in Microsoft Word format on the DSS web site. The standardization
|
||||
* status of this matrix is unclear. Furthermore, one must be very
|
||||
* careful when referring to this matrix: it is intended for the "clearing"
|
||||
* prior to reuse or "sanitization" prior to disposal of *entire media*,
|
||||
* not individual files and the only non-physically-destructive method of
|
||||
* "sanitization" that is permitted for magnetic disks of any kind is
|
||||
* specifically noted to be prohibited for media that have contained
|
||||
* Top Secret data.
|
||||
*
|
||||
* It is impossible to actually conform to the exact procedure given in
|
||||
* the matrix if one is overwriting a file, not an entire disk, because
|
||||
* the procedure requires examination and comparison of the disk's defect
|
||||
* lists. Any program that claims to securely erase *files* while
|
||||
* conforming to the standard, then, is not correct. We do as much of
|
||||
* what the standard requires as can actually be done when erasing a
|
||||
* file, rather than an entire disk; but that does not make us conformant.
|
||||
*
|
||||
* Furthermore, the presence of track caches, disk and controller write
|
||||
* caches, and so forth make it extremely difficult to ensure that data
|
||||
* have actually been written to the disk, particularly when one tries
|
||||
* to repeatedly overwrite the same sectors in quick succession. We call
|
||||
* fsync(), but controllers with nonvolatile cache, as well as IDE disks
|
||||
* that just plain lie about the stable storage of data, will defeat this.
|
||||
*
|
||||
* Finally, widely respected research suggests that the given procedure
|
||||
* is nowhere near sufficient to prevent the recovery of data using special
|
||||
* forensic equipment and techniques that are well-known. This is
|
||||
* presumably one reason that the matrix requires physical media destruction,
|
||||
* rather than any technique of the sort attempted here, for secret data.
|
||||
*
|
||||
* Caveat Emptor.
|
||||
*
|
||||
* rm_overwrite will return 0 on success.
|
||||
*/
|
||||
|
||||
static int
|
||||
rm_overwrite(char *file, struct stat *sbp)
|
||||
{
|
||||
struct stat sb;
|
||||
int fd, randint;
|
||||
char randchar;
|
||||
|
||||
fd = -1;
|
||||
if (sbp == NULL) {
|
||||
if (lstat(file, &sb))
|
||||
goto err;
|
||||
sbp = &sb;
|
||||
}
|
||||
if (!S_ISREG(sbp->st_mode))
|
||||
return 0;
|
||||
|
||||
/* flags to try to defeat hidden caching by forcing seeks */
|
||||
if ((fd = open(file, O_RDWR|O_SYNC|O_RSYNC, 0)) == -1)
|
||||
goto err;
|
||||
|
||||
#define RAND_BYTES 1
|
||||
#define THIS_BYTE 0
|
||||
|
||||
#define WRITE_PASS(mode, byte) do { \
|
||||
off_t len; \
|
||||
size_t wlen, i; \
|
||||
char buf[8 * 1024]; \
|
||||
\
|
||||
if (fsync(fd) || lseek(fd, (off_t)0, SEEK_SET)) \
|
||||
goto err; \
|
||||
\
|
||||
if (mode == THIS_BYTE) \
|
||||
memset(buf, byte, sizeof(buf)); \
|
||||
for (len = sbp->st_size; len > 0; len -= wlen) { \
|
||||
if (mode == RAND_BYTES) { \
|
||||
for (i = 0; i < sizeof(buf); \
|
||||
i+= sizeof(u_int32_t)) \
|
||||
*(int *)(buf + i) = arc4random(); \
|
||||
} \
|
||||
wlen = len < (off_t)sizeof(buf) ? (size_t)len : sizeof(buf); \
|
||||
if ((size_t)write(fd, buf, wlen) != wlen) \
|
||||
goto err; \
|
||||
} \
|
||||
sync(); /* another poke at hidden caches */ \
|
||||
} while (/* CONSTCOND */ 0)
|
||||
|
||||
#define READ_PASS(byte) do { \
|
||||
off_t len; \
|
||||
size_t rlen; \
|
||||
char pattern[8 * 1024]; \
|
||||
char buf[8 * 1024]; \
|
||||
\
|
||||
if (fsync(fd) || lseek(fd, (off_t)0, SEEK_SET)) \
|
||||
goto err; \
|
||||
\
|
||||
memset(pattern, byte, sizeof(pattern)); \
|
||||
for(len = sbp->st_size; len > 0; len -= rlen) { \
|
||||
rlen = len < (off_t)sizeof(buf) ? (size_t)len : sizeof(buf); \
|
||||
if((size_t)read(fd, buf, rlen) != rlen) \
|
||||
goto err; \
|
||||
if(memcmp(buf, pattern, rlen)) \
|
||||
goto err; \
|
||||
} \
|
||||
sync(); /* another poke at hidden caches */ \
|
||||
} while (/* CONSTCOND */ 0)
|
||||
|
||||
/*
|
||||
* DSS sanitization matrix "clear" for magnetic disks:
|
||||
* option 'c' "Overwrite all addressable locations with a single
|
||||
* character."
|
||||
*/
|
||||
randint = arc4random();
|
||||
randchar = *(char *)&randint;
|
||||
WRITE_PASS(THIS_BYTE, randchar);
|
||||
|
||||
/*
|
||||
* DSS sanitization matrix "sanitize" for magnetic disks:
|
||||
* option 'd', sub 2 "Overwrite all addressable locations with a
|
||||
* character, then its complement. Verify "complement" character
|
||||
* was written successfully to all addressable locations, then
|
||||
* overwrite all addressable locations with random characters; or
|
||||
* verify third overwrite of random characters." The rest of the
|
||||
* text in d-sub-2 specifies requirements for overwriting spared
|
||||
* sectors; we cannot conform to it when erasing only a file, thus
|
||||
* we do not conform to the standard.
|
||||
*/
|
||||
|
||||
/* 1. "a character" */
|
||||
WRITE_PASS(THIS_BYTE, 0xff);
|
||||
|
||||
/* 2. "its complement" */
|
||||
WRITE_PASS(THIS_BYTE, 0x00);
|
||||
|
||||
/* 3. "Verify 'complement' character" */
|
||||
READ_PASS(0x00);
|
||||
|
||||
/* 4. "overwrite all addressable locations with random characters" */
|
||||
|
||||
WRITE_PASS(RAND_BYTES, 0x00);
|
||||
|
||||
/*
|
||||
* As the file might be huge, and we note that this revision of
|
||||
* the matrix says "random characters", not "a random character"
|
||||
* as the original did, we do not verify the random-character
|
||||
* write; the "or" in the standard allows this.
|
||||
*/
|
||||
|
||||
if (close(fd) == -1) {
|
||||
fd = -1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err: eval = 1;
|
||||
warn("%s", file);
|
||||
if (fd != -1)
|
||||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
check(char *path, char *name, struct stat *sp)
|
||||
{
|
||||
int ch, first;
|
||||
char modep[15];
|
||||
|
||||
/* Check -i first. */
|
||||
if (iflag)
|
||||
(void)fprintf(stderr, "remove '%s'? ", path);
|
||||
else {
|
||||
/*
|
||||
* If it's not a symbolic link and it's unwritable and we're
|
||||
* talking to a terminal, ask. Symbolic links are excluded
|
||||
* because their permissions are meaningless. Check stdin_ok
|
||||
* first because we may not have stat'ed the file.
|
||||
*/
|
||||
if (!stdin_ok || S_ISLNK(sp->st_mode) ||
|
||||
!(access(name, W_OK) && (errno != ETXTBSY)))
|
||||
return (1);
|
||||
strmode(sp->st_mode, modep);
|
||||
if (Pflag) {
|
||||
warnx(
|
||||
"%s: -P was specified but file could not"
|
||||
" be overwritten", path);
|
||||
return 0;
|
||||
}
|
||||
(void)fprintf(stderr, "override %s%s%s:%s for '%s'? ",
|
||||
modep + 1, modep[9] == ' ' ? "" : " ",
|
||||
user_from_uid(sp->st_uid, 0),
|
||||
group_from_gid(sp->st_gid, 0), path);
|
||||
}
|
||||
(void)fflush(stderr);
|
||||
|
||||
first = ch = getchar();
|
||||
while (ch != '\n' && ch != EOF)
|
||||
ch = getchar();
|
||||
return (first == 'y' || first == 'Y');
|
||||
}
|
||||
|
||||
/*
|
||||
* POSIX.2 requires that if "." or ".." are specified as the basename
|
||||
* portion of an operand, a diagnostic message be written to standard
|
||||
* error and nothing more be done with such operands.
|
||||
*
|
||||
* Since POSIX.2 defines basename as the final portion of a path after
|
||||
* trailing slashes have been removed, we'll remove them here.
|
||||
*/
|
||||
#define ISDOT(a) ((a)[0] == '.' && (!(a)[1] || ((a)[1] == '.' && !(a)[2])))
|
||||
static void
|
||||
checkdot(char **argv)
|
||||
{
|
||||
char *p, **save, **t;
|
||||
int complained;
|
||||
|
||||
complained = 0;
|
||||
for (t = argv; *t;) {
|
||||
/* strip trailing slashes */
|
||||
p = strrchr(*t, '\0');
|
||||
while (--p > *t && *p == '/')
|
||||
*p = '\0';
|
||||
|
||||
/* extract basename */
|
||||
if ((p = strrchr(*t, '/')) != NULL)
|
||||
++p;
|
||||
else
|
||||
p = *t;
|
||||
|
||||
if (ISDOT(p)) {
|
||||
if (!complained++)
|
||||
warnx("\".\" and \"..\" may not be removed");
|
||||
eval = 1;
|
||||
for (save = t; (t[0] = t[1]) != NULL; ++t)
|
||||
continue;
|
||||
t = save;
|
||||
} else
|
||||
++t;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
|
||||
(void)fprintf(stderr, "usage: %s [-f|-i] [-dPRrvW] file ...\n",
|
||||
getprogname());
|
||||
exit(1);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
# $NetBSD: Makefile,v 1.8 1997/07/20 22:37:52 christos Exp $
|
||||
# @(#)Makefile 8.1 (Berkeley) 5/31/93
|
||||
|
||||
PROG= rmdir
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
@@ -1,90 +0,0 @@
|
||||
.\" $NetBSD: rmdir.1,v 1.15 2003/08/07 09:05:29 agc Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1990, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" This code is derived from software contributed to Berkeley by
|
||||
.\" the Institute of Electrical and Electronics Engineers, Inc.
|
||||
.\"
|
||||
.\" 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.
|
||||
.\" 3. Neither the name of the University nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
.\"
|
||||
.\" @(#)rmdir.1 8.1 (Berkeley) 5/31/93
|
||||
.\"
|
||||
.Dd May 31, 1993
|
||||
.Dt RMDIR 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm rmdir
|
||||
.Nd remove directories
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl p
|
||||
.Ar directory ...
|
||||
.Sh DESCRIPTION
|
||||
The rmdir utility removes the directory entry specified by
|
||||
each
|
||||
.Ar directory
|
||||
argument, provided it is empty.
|
||||
.Pp
|
||||
Arguments are processed in the order given.
|
||||
In order to remove both a parent directory and a subdirectory
|
||||
of that parent, the subdirectory
|
||||
must be specified first so the parent directory
|
||||
is empty when
|
||||
.Nm
|
||||
tries to remove it.
|
||||
.Pp
|
||||
The following option is available:
|
||||
.Bl -tag -width Ds
|
||||
.It Fl p
|
||||
Each
|
||||
.Ar directory
|
||||
argument is treated as a pathname of which all
|
||||
components will be removed, if they are empty,
|
||||
starting with the last most component.
|
||||
(See
|
||||
.Xr rm 1
|
||||
for fully non-discriminant recursive removal.)
|
||||
.El
|
||||
.Sh EXIT STATUS
|
||||
The
|
||||
.Nm
|
||||
utility exits with one of the following values:
|
||||
.Bl -tag -width Ds
|
||||
.It Li \&0
|
||||
Each directory entry specified by a dir operand
|
||||
referred to an empty directory and was removed
|
||||
successfully.
|
||||
.It Li \&\*[Gt]\&0
|
||||
An error occurred.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr rm 1
|
||||
.Sh STANDARDS
|
||||
The
|
||||
.Nm
|
||||
utility is expected to be
|
||||
.St -p1003.2
|
||||
compatible.
|
||||
@@ -1,121 +0,0 @@
|
||||
/* $NetBSD: rmdir.c,v 1.26 2011/08/29 14:49:38 joerg Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1992, 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__COPYRIGHT("@(#) Copyright (c) 1992, 1993, 1994\
|
||||
The Regents of the University of California. All rights reserved.");
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)rmdir.c 8.3 (Berkeley) 4/2/94";
|
||||
#else
|
||||
__RCSID("$NetBSD: rmdir.c,v 1.26 2011/08/29 14:49:38 joerg Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <locale.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static int rm_path(char *);
|
||||
__dead static void usage(void);
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int ch, errors, pflag;
|
||||
|
||||
setprogname(argv[0]);
|
||||
(void)setlocale(LC_ALL, "");
|
||||
|
||||
pflag = 0;
|
||||
while ((ch = getopt(argc, argv, "p")) != -1)
|
||||
switch(ch) {
|
||||
case 'p':
|
||||
pflag = 1;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc == 0)
|
||||
usage();
|
||||
|
||||
for (errors = 0; *argv; argv++) {
|
||||
/* We rely on the kernel to ignore trailing '/' characters. */
|
||||
if (rmdir(*argv) < 0) {
|
||||
warn("%s", *argv);
|
||||
errors = 1;
|
||||
} else if (pflag)
|
||||
errors |= rm_path(*argv);
|
||||
}
|
||||
|
||||
exit(errors);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
static int
|
||||
rm_path(char *path)
|
||||
{
|
||||
char *p;
|
||||
|
||||
while ((p = strrchr(path, '/')) != NULL) {
|
||||
*p = 0;
|
||||
if (p[1] == 0)
|
||||
/* Ignore trailing '/' on deleted name */
|
||||
continue;
|
||||
|
||||
if (rmdir(path) < 0) {
|
||||
warn("%s", path);
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
(void)fprintf(stderr, "usage: %s [-p] directory ...\n", getprogname());
|
||||
exit(1);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
97
boot/Makefile
Normal file
97
boot/Makefile
Normal file
@@ -0,0 +1,97 @@
|
||||
# Makefile for the boot monitor package.
|
||||
|
||||
# XXX: Can only be built with ACK currently
|
||||
CC:=${CC:C/^gcc/cc/}
|
||||
COMPILER_TYPE:=ack
|
||||
|
||||
PROGS= bootblock cdbootblock boot masterboot \
|
||||
jumpboot installboot edparams dosboot mkfile
|
||||
|
||||
SRCS.bootblock= bootblock.s
|
||||
CPPFLAGS.bootblock.s= ${I86CPPFLAGS}
|
||||
LDFLAGS.bootblock= ${I86LDFLAGS}
|
||||
BINDIR.bootblock= /usr/mdec
|
||||
MAN.bootblock=
|
||||
|
||||
SRCS.cdbootblock= cdbootblock.s
|
||||
CPPFLAGS.cdbootblock.s= ${I86CPPFLAGS} -DCDBOOT
|
||||
LDFLAGS.cdbootblock= ${I86LDFLAGS}
|
||||
BINDIR.cdbootblock= /usr/mdec
|
||||
MAN.cdbootblock=
|
||||
|
||||
SRCS.boot= boothead.s boot.c bootimage.c rawfs86.c
|
||||
CPPFLAGS.boothead.s= ${I86CPPFLAGS}
|
||||
CPPFLAGS.boot.c= ${I86CPPFLAGS}
|
||||
CPPFLAGS.bootimage.c= ${I86CPPFLAGS}
|
||||
CPPFLAGS.rawfs86.c= ${I86CPPFLAGS}
|
||||
LDFLAGS.boot= ${I86LDFLAGS}
|
||||
DPADD.boot= ${LIBSYS}
|
||||
LDADD.boot= -lsys
|
||||
BINDIR.boot= /usr/mdec
|
||||
MAN.boot=
|
||||
|
||||
realall: .PHONY bootsize
|
||||
bootsize: boot
|
||||
${INSTALL} -S 22kb boot
|
||||
|
||||
SRCS.masterboot= masterboot.s
|
||||
CPPFLAGS.masterboot.s= ${I86CPPFLAGS}
|
||||
LDFLAGS.masterboot= ${I86LDFLAGS}
|
||||
BINDIR.masterboot= /usr/mdec
|
||||
MAN.masterboot=
|
||||
|
||||
SRCS.jumpboot= jumpboot.s
|
||||
CPPFLAGS.jumpboot.s= ${I86CPPFLAGS}
|
||||
LDFLAGS.jumpboot= ${I86LDFLAGS}
|
||||
BINDIR.jumpboot= /usr/mdec
|
||||
MAN.jumpboot=
|
||||
|
||||
SRCS.installboot= installboot.c rawfs.c
|
||||
BINDIR.installboot= /usr/bin
|
||||
MAN.installboot=
|
||||
|
||||
SRCS.edparams= edparams.c rawfs.c
|
||||
CPPFLAGS.edparams.c= -DUNIX
|
||||
BINDIR.edparams= /usr/bin
|
||||
MAN.edparams=
|
||||
|
||||
SRCS.dosboot= doshead.s dosboot.o bootimage.o rawfs86.o
|
||||
CPPFLAGS.dosboot.c= -DDOS $(I86CPPFLAGS)
|
||||
LDADD.dosboot= ${I86LDFLAGS} -lsys
|
||||
BINDIR.dosboot= /usr/mdec
|
||||
CPPFLAGS.doshead.s= -mi386
|
||||
MAN.dosboot=
|
||||
|
||||
SRCS.mkfile= mkfhead.s mkfile.c
|
||||
CPPFLAGS.mkfile.s= ${I86CPPFLAGS}
|
||||
LDADD.mkfile= ${I86LDFLAGS} -lsys
|
||||
BINDIR.mkfile= /usr/mdec
|
||||
MAN.mkfile=
|
||||
|
||||
rawfs86.c: rawfs.c
|
||||
ln -f rawfs.c rawfs86.c
|
||||
|
||||
edparams.c: boot.c
|
||||
ln -f boot.c edparams.c
|
||||
|
||||
dosboot.c: boot.c
|
||||
ln -f boot.c dosboot.c
|
||||
|
||||
cdbootblock.s: bootblock.s
|
||||
ln -f bootblock.s cdbootblock.s
|
||||
|
||||
mkfile.com: mkfile
|
||||
|
||||
boot.com: dosboot
|
||||
./a.out2com dosboot boot.com
|
||||
|
||||
CPPFLAGS= -I${MINIXSRCDIR}
|
||||
AFLAGS= -I${MINIXSRCDIR}
|
||||
I86CPPFLAGS= -mi86 -Was-ncc
|
||||
I86LDFLAGS= -mi86 -Was-ncc -.o -com
|
||||
|
||||
STRIPFLAG= -s
|
||||
|
||||
CLEANFILES+= rawfs86.c edparams.c cdbootblock.s dosboot.c
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
25
boot/a.out2com
Executable file
25
boot/a.out2com
Executable file
@@ -0,0 +1,25 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# a.out2com - Minix a.out to DOS .COM Author: Kees J. Bot
|
||||
# 17 Jun 1995
|
||||
# Transform a Minix a.out to the COM format of MS-DOS,
|
||||
# the executable must be common I&D with 256 scratch bytes at the start of
|
||||
# the text segment to make space for the Program Segment Prefix. The Minix
|
||||
# a.out header and these 256 bytes are removed to make a COM file.
|
||||
|
||||
case $# in
|
||||
2) aout="$1"
|
||||
com="$2"
|
||||
;;
|
||||
*) echo "Usage: $0 <a.out> <dos.com>" >&2
|
||||
exit 1
|
||||
esac
|
||||
|
||||
size "$aout" >/dev/null || exit
|
||||
set `size "$aout" | sed 1d`
|
||||
count=`expr \( $1 + $2 - 256 + 31 \) / 32`
|
||||
|
||||
exec dd if="$aout" of="$com" bs=32 skip=9 count=$count conv=silent
|
||||
|
||||
#
|
||||
# $PchId: a.out2com,v 1.3 1998/08/01 09:13:01 philip Exp $
|
||||
128
boot/addaout.c
Normal file
128
boot/addaout.c
Normal file
@@ -0,0 +1,128 @@
|
||||
/* A small utility to append an a.out header to an arbitrary file. This allows
|
||||
* inclusion of arbitrary data in the boot image, so that it is magically
|
||||
* loaded as a RAM disk. The a.out header is structured as follows:
|
||||
*
|
||||
* a_flags: A_IMG to indicate this is not an executable
|
||||
*
|
||||
* Created: April 2005, Jorrit N. Herder
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <a.out.h>
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define INPUT_FILE 1
|
||||
#define OUTPUT_FILE 2
|
||||
|
||||
/* Report problems. */
|
||||
static void report(const char *problem, const char *message)
|
||||
{
|
||||
fprintf(stderr, "%s:\n", problem);
|
||||
fprintf(stderr, " %s\n\n", message);
|
||||
}
|
||||
|
||||
|
||||
static int copy_data(int srcfd, int dstfd)
|
||||
{
|
||||
char buf[8192];
|
||||
ssize_t n;
|
||||
int total=0;
|
||||
|
||||
/** FIXME: handle error from read() */
|
||||
|
||||
/* Copy the little bytes themselves. (Source from cp.c). */
|
||||
while ((n= read(srcfd, buf, sizeof(buf))) > 0) {
|
||||
char *bp = buf;
|
||||
ssize_t r = 0;
|
||||
|
||||
/** FIXME: handle error from write() */
|
||||
while (n > 0 && (r= write(dstfd, bp, n)) > 0) {
|
||||
bp += r;
|
||||
n -= r;
|
||||
total += r;
|
||||
}
|
||||
if (r == 0) {
|
||||
fprintf(stderr, "Warning: EOF writing to output file.\n");
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
return(total);
|
||||
}
|
||||
|
||||
|
||||
/* Main program. */
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct exec aout;
|
||||
struct stat stin;
|
||||
int fdin, fdout;
|
||||
char * bp;
|
||||
int n,r;
|
||||
int total_size;
|
||||
|
||||
/* Check if command line arguments are present, or print usage. */
|
||||
if (argc!=3) {
|
||||
printf("Invalid arguments. Usage:\n");
|
||||
printf(" %s <input_file> <output_file>\n",argv[0]);
|
||||
return(1);
|
||||
}
|
||||
|
||||
/* Check if we can open the input and output file. */
|
||||
if (stat(argv[INPUT_FILE], &stin) != 0) {
|
||||
report("Couldn't get status of input file", strerror(errno));
|
||||
return(1);
|
||||
}
|
||||
if ((fdin = open(argv[INPUT_FILE], O_RDONLY)) < 0) {
|
||||
report("Couldn't open input file", strerror(errno));
|
||||
return(1);
|
||||
}
|
||||
if ((fdout = open(argv[OUTPUT_FILE], O_WRONLY|O_CREAT|O_TRUNC,
|
||||
stin.st_mode & 0777)) < 0) {
|
||||
report("Couldn't open output file", strerror(errno));
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
/* Copy input file to output file, but leave space for a.out header. */
|
||||
lseek(fdout, sizeof(aout), SEEK_SET);
|
||||
total_size = copy_data(fdin, fdout);
|
||||
if (total_size < 0) {
|
||||
report("Aborted", "Output file may be truncated.");
|
||||
return(1);
|
||||
} else if (total_size == 0) {
|
||||
report("Aborted without prepending header", "No data in input file.");
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
/* Build a.out header and write to output file. */
|
||||
memset(&aout, 0, sizeof(struct exec));
|
||||
aout.a_magic[0] = A_MAGIC0;
|
||||
aout.a_magic[1] = A_MAGIC1;
|
||||
aout.a_flags |= A_IMG;
|
||||
aout.a_hdrlen = sizeof(aout);
|
||||
aout.a_text = 0;
|
||||
aout.a_data = total_size;
|
||||
aout.a_bss = 0;
|
||||
aout.a_total = aout.a_hdrlen + aout.a_data;
|
||||
|
||||
bp = (char *) &aout;
|
||||
n = sizeof(aout);
|
||||
lseek(fdout, 0L, SEEK_SET);
|
||||
while (n > 0 && (r= write(fdout, bp, n)) > 0) {
|
||||
bp += r;
|
||||
n -= r;
|
||||
}
|
||||
|
||||
printf("Prepended data file (%d bytes) with a.out header (%u bytes).\n",
|
||||
total_size, sizeof(aout));
|
||||
printf("Done.\n");
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
2075
boot/boot.c
Normal file
2075
boot/boot.c
Normal file
File diff suppressed because it is too large
Load Diff
231
boot/boot.h
Normal file
231
boot/boot.h
Normal file
@@ -0,0 +1,231 @@
|
||||
/* boot.h - Info between different parts of boot. Author: Kees J. Bot
|
||||
*/
|
||||
|
||||
#ifndef DEBUG
|
||||
#define DEBUG 0
|
||||
#endif
|
||||
|
||||
/* Constants describing the metal: */
|
||||
|
||||
#define SECTOR_SIZE 512
|
||||
#define SECTOR_SHIFT 9
|
||||
#define RATIO(b) ((b) / SECTOR_SIZE)
|
||||
|
||||
#define PARAMSEC 1 /* Sector containing boot parameters. */
|
||||
|
||||
#define DSKBASE 0x1E /* Floppy disk parameter vector. */
|
||||
#define DSKPARSIZE 11 /* There are this many bytes of parameters. */
|
||||
|
||||
#define ESC '\33' /* Escape key. */
|
||||
|
||||
#define HEADERPOS 0x00600L /* Place for an array of struct exec's. */
|
||||
|
||||
#define FREEPOS 0x08000L /* Memory from FREEPOS to caddr is free to
|
||||
* play with.
|
||||
*/
|
||||
#if BIOS
|
||||
#define MSEC_PER_TICK 55 /* Clock does 18.2 ticks per second. */
|
||||
#define TICKS_PER_DAY 0x1800B0L /* After 24 hours it wraps. */
|
||||
#endif
|
||||
|
||||
#if UNIX
|
||||
#define MSEC_PER_TICK 1000 /* Clock does 18.2 ticks per second. */
|
||||
#define TICKS_PER_DAY 86400L /* Doesn't wrap, but that doesn't matter. */
|
||||
#endif
|
||||
|
||||
#define BOOTPOS 0x07C00L /* Bootstraps are loaded here. */
|
||||
#define SIGNATURE 0xAA55 /* Proper bootstraps have this signature. */
|
||||
#define SIGNATOFF 510 /* Offset within bootblock. */
|
||||
|
||||
/* BIOS video modes. */
|
||||
#define MONO_MODE 0x07 /* 80x25 monochrome. */
|
||||
#define COLOR_MODE 0x03 /* 80x25 color. */
|
||||
|
||||
|
||||
/* Variables shared with boothead.s: */
|
||||
#ifndef EXTERN
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
typedef struct vector { /* 8086 vector */
|
||||
u16_t offset;
|
||||
u16_t segment;
|
||||
} vector;
|
||||
|
||||
EXTERN vector rem_part; /* Boot partition table entry. */
|
||||
|
||||
EXTERN u32_t caddr, daddr; /* Code and data address of the boot program. */
|
||||
EXTERN u32_t runsize; /* Size of this program. */
|
||||
|
||||
EXTERN u16_t device; /* Drive being booted from. */
|
||||
EXTERN u16_t cddevice; /* Drive that is CD if known. */
|
||||
|
||||
#define CDNAME "cd" /* Name of the CD device. */
|
||||
|
||||
typedef struct { /* One chunk of free memory. */
|
||||
u32_t base; /* Start byte. */
|
||||
u32_t size; /* Number of bytes. */
|
||||
} memory;
|
||||
|
||||
typedef struct { /* One chunk of free memory. */
|
||||
u32_t base_lo; /* Start byte. */
|
||||
u32_t base_hi;
|
||||
u32_t size_lo; /* Number of bytes. */
|
||||
u32_t size_hi; /* Number of bytes. */
|
||||
u32_t type;
|
||||
u32_t acpi_attrs;
|
||||
} e820_memory;
|
||||
|
||||
EXTERN memory mem[3]; /* List of available memory. */
|
||||
EXTERN e820_memory emem[16]; /* List of available memory. */
|
||||
EXTERN int mem_entries;
|
||||
EXTERN int mon_return; /* Monitor stays in memory? */
|
||||
EXTERN int cdbooted; /* Did we boot from CD? (Set by boothead.s.) */
|
||||
|
||||
typedef struct bios_env
|
||||
{
|
||||
u16_t ax;
|
||||
u16_t bx;
|
||||
u16_t cx;
|
||||
u16_t flags;
|
||||
} bios_env_t;
|
||||
|
||||
#define FL_CARRY 0x0001 /* carry flag */
|
||||
|
||||
/* Functions defined by boothead.s: */
|
||||
|
||||
void exit(int code);
|
||||
/* Exit the monitor. */
|
||||
u32_t mon2abs(void *ptr);
|
||||
/* Local monitor address to absolute address. */
|
||||
u32_t vec2abs(vector *vec);
|
||||
/* Vector to absolute address. */
|
||||
void raw_copy(u32_t dstaddr, u32_t srcaddr, u32_t count);
|
||||
/* Copy bytes from anywhere to anywhere. */
|
||||
u16_t get_word(u32_t addr);
|
||||
/* Get a word from anywhere. */
|
||||
void put_word(u32_t addr, u16_t word);
|
||||
/* Put a word anywhere. */
|
||||
void relocate(void);
|
||||
/* Switch to a copy of this program. */
|
||||
int dev_open(void), dev_close(void);
|
||||
/* Open device and determine params / close device. */
|
||||
int dev_boundary(u32_t sector);
|
||||
/* True if sector is on a track boundary. */
|
||||
int readsectors(u32_t bufaddr, u32_t sector, u8_t count);
|
||||
/* Read 1 or more sectors from "device". */
|
||||
int writesectors(u32_t bufaddr, u32_t sector, u8_t count);
|
||||
/* Write 1 or more sectors to "device". */
|
||||
|
||||
int biosreadsectors(u32_t bufaddr, u32_t sector, u8_t count);
|
||||
|
||||
int getch(void);
|
||||
/* Read a keypress. */
|
||||
void scan_keyboard(void);
|
||||
/* Read keypress directly from kb controller. */
|
||||
void ungetch(int c);
|
||||
/* Undo a keypress. */
|
||||
int escape(void);
|
||||
/* True if escape typed. */
|
||||
void putch(int c);
|
||||
/* Send a character to the screen. */
|
||||
#if BIOS
|
||||
void pause(void);
|
||||
/* Wait for an interrupt. */
|
||||
void serial_init(int line);
|
||||
#endif /* Enable copying console I/O to a serial line. */
|
||||
|
||||
void set_mode(unsigned mode);
|
||||
void clear_screen(void);
|
||||
/* Set video mode / clear the screen. */
|
||||
|
||||
u16_t get_bus(void);
|
||||
/* System bus type, XT, AT, or MCA. */
|
||||
u16_t get_video(void);
|
||||
/* Display type, MDA to VGA. */
|
||||
u32_t get_tick(void);
|
||||
/* Current value of the clock tick counter. */
|
||||
|
||||
void bootstrap(int device, struct part_entry *entry);
|
||||
/* Execute a bootstrap routine for a different O.S. */
|
||||
void minix(u32_t koff, u32_t kcs, u32_t kds,
|
||||
char *bootparams, size_t paramsize, u32_t aout);
|
||||
/* Start Minix. */
|
||||
void int15(bios_env_t *);
|
||||
|
||||
|
||||
/* Shared between boot.c and bootimage.c: */
|
||||
|
||||
/* Sticky attributes. */
|
||||
#define E_SPECIAL 0x01 /* These are known to the program. */
|
||||
#define E_DEV 0x02 /* The value is a device name. */
|
||||
#define E_RESERVED 0x04 /* May not be set by user, e.g. 'boot' */
|
||||
#define E_STICKY 0x07 /* Don't go once set. */
|
||||
|
||||
/* Volatile attributes. */
|
||||
#define E_VAR 0x08 /* Variable */
|
||||
#define E_FUNCTION 0x10 /* Function definition. */
|
||||
|
||||
/* Variables, functions, and commands. */
|
||||
typedef struct environment {
|
||||
struct environment *next;
|
||||
char flags;
|
||||
char *name; /* name = value */
|
||||
char *arg; /* name(arg) {value} */
|
||||
char *value;
|
||||
char *defval; /* Safehouse for default values. */
|
||||
} environment;
|
||||
|
||||
EXTERN environment *env; /* Lists the environment. */
|
||||
|
||||
char *b_value(const char *name); /* Get/set the value of a variable. */
|
||||
int b_setvar(int flags, char *name, char *value);
|
||||
void b_unset(const char *name);
|
||||
|
||||
void parse_code(char *code); /* Parse boot monitor commands. */
|
||||
|
||||
extern int fsok; /* True if the boot device contains an FS. */
|
||||
EXTERN u32_t lowsec; /* Offset to the file system on the boot device. */
|
||||
|
||||
/* Called by boot.c: */
|
||||
|
||||
void bootminix(void); /* Load and start a Minix image. */
|
||||
|
||||
|
||||
/* Called by bootimage.c: */
|
||||
|
||||
void readerr(off_t sec, int err);
|
||||
/* Report a read error. */
|
||||
char *ul2a(u32_t n, unsigned b), *ul2a10(u32_t n);
|
||||
/* Transform u32_t to ASCII at base b or base 10. */
|
||||
long a2l(const char *a);
|
||||
/* Cheap atol(). */
|
||||
unsigned a2x(const char *a);
|
||||
/* ASCII to hex. */
|
||||
dev_t name2dev(char *name);
|
||||
/* Translate a device name to a device number. */
|
||||
int numprefix(char *s, char **ps);
|
||||
/* True for a numeric prefix. */
|
||||
int numeric(char *s);
|
||||
/* True for a numeric string. */
|
||||
char *unix_err(int err);
|
||||
/* Give a descriptive text for some UNIX errors. */
|
||||
int run_trailer(void);
|
||||
/* Run the trailer function. */
|
||||
|
||||
#if DOS
|
||||
/* The monitor runs under MS-DOS. */
|
||||
extern char PSP[256]; /* Program Segment Prefix. */
|
||||
EXTERN char *vdisk; /* Name of the virtual disk. */
|
||||
EXTERN char *drun; /* Initial command from DOS command line. */
|
||||
#else
|
||||
/* The monitor uses only the BIOS. */
|
||||
#define DOS 0
|
||||
#endif
|
||||
|
||||
void readblock(off_t, char *, int);
|
||||
void delay(const char *);
|
||||
|
||||
/*
|
||||
* $PchId: boot.h,v 1.12 2002/02/27 19:42:45 philip Exp $
|
||||
*/
|
||||
256
boot/bootblock.s
Normal file
256
boot/bootblock.s
Normal file
@@ -0,0 +1,256 @@
|
||||
#
|
||||
! Bootblock 1.5 - Minix boot block. Author: Kees J. Bot
|
||||
! 21 Dec 1991
|
||||
!
|
||||
! When the PC is powered on, it will try to read the first sector of floppy
|
||||
! disk 0 at address 0x7C00. If this fails due to the absence of flexible
|
||||
! magnetic media, it will read the master boot record from the first sector
|
||||
! of the hard disk. This sector not only contains executable code, but also
|
||||
! the partition table of the hard disk. When executed, it will select the
|
||||
! active partition and load the first sector of that at address 0x7C00.
|
||||
! This file contains the code that is eventually read from either the floppy
|
||||
! disk, or the hard disk partition. It is just smart enough to load /boot
|
||||
! from the boot device into memory at address 0x10000 and execute that. The
|
||||
! disk addresses for /boot are patched into this code by installboot as 24-bit
|
||||
! sector numbers and 8-bit sector counts above enddata upwards. /boot is in
|
||||
! turn smart enough to load the different parts of the Minix kernel into
|
||||
! memory and execute them to finally get Minix started.
|
||||
!
|
||||
|
||||
LOADOFF = 0x7C00 ! 0x0000:LOADOFF is where this code is loaded
|
||||
BOOTSEG = 0x1000 ! Secondary boot code segment.
|
||||
#ifdef CDBOOT
|
||||
BOOTOFF = 0x0050 ! Offset into /boot above header
|
||||
#else
|
||||
BOOTOFF = 0x0030 ! Offset into /boot above header
|
||||
#endif
|
||||
BUFFER = 0x0600 ! First free memory
|
||||
#ifndef CDBOOT /* just constants, but make no sense for CDs */
|
||||
LOWSEC = 8 ! Offset of logical first sector in partition
|
||||
! table
|
||||
|
||||
! Variables addressed using bp register
|
||||
lowsec = 2 ! Offset of boot partition within drive
|
||||
secpcyl = 6 ! Sectors per cylinder = heads * sectors
|
||||
#endif
|
||||
device = 0 ! The boot device
|
||||
|
||||
.text
|
||||
|
||||
! Start boot procedure.
|
||||
|
||||
boot:
|
||||
xor ax, ax ! ax = 0x0000, the vector segment
|
||||
mov ds, ax
|
||||
cli ! Ignore interrupts while setting stack
|
||||
mov ss, ax ! ss = ds = vector segment
|
||||
mov sp, #LOADOFF ! Usual place for a bootstrap stack
|
||||
sti
|
||||
|
||||
push ax
|
||||
push ax ! Push a zero lowsec(bp)
|
||||
|
||||
push dx ! Boot device in dl will be device(bp)
|
||||
mov bp, sp ! Using var(bp) is one byte cheaper then var.
|
||||
|
||||
push es
|
||||
push si ! es:si = partition table entry if hard disk
|
||||
|
||||
mov di, #LOADOFF+sectors ! char *di = sectors;
|
||||
|
||||
#ifndef CDBOOT
|
||||
testb dl, dl ! Winchester disks if dl >= 0x80
|
||||
jge floppy
|
||||
#endif
|
||||
|
||||
winchester:
|
||||
|
||||
#ifndef CDBOOT
|
||||
! Get the offset of the first sector of the boot partition from the partition
|
||||
! table. The table is found at es:si, the lowsec parameter at offset LOWSEC.
|
||||
|
||||
eseg
|
||||
les ax, LOWSEC(si) ! es:ax = LOWSEC+2(si):LOWSEC(si)
|
||||
mov lowsec+0(bp), ax ! Low 16 bits of partitions first sector
|
||||
mov lowsec+2(bp), es ! High 16 bits of partitions first sector
|
||||
|
||||
! Get the drive parameters, the number of sectors is bluntly written into the
|
||||
! floppy disk sectors/track array.
|
||||
|
||||
movb ah, #0x08 ! Code for drive parameters
|
||||
int 0x13 ! dl still contains drive
|
||||
andb cl, #0x3F ! cl = max sector number (1-origin)
|
||||
movb (di), cl ! Number of sectors per track
|
||||
incb dh ! dh = 1 + max head number (0-origin)
|
||||
#endif
|
||||
jmp loadboot
|
||||
|
||||
#ifndef CDBOOT
|
||||
! Floppy:
|
||||
! Execute three read tests to determine the drive type. Test for each floppy
|
||||
! type by reading the last sector on the first track. If it fails, try a type
|
||||
! that has less sectors. Therefore we start with 1.44M (18 sectors) then 1.2M
|
||||
! (15 sectors) ending with 720K/360K (both 9 sectors).
|
||||
|
||||
next: inc di ! Next number of sectors per track
|
||||
|
||||
floppy: xorb ah, ah ! Reset drive
|
||||
int 0x13
|
||||
|
||||
movb cl, (di) ! cl = number of last sector on track
|
||||
|
||||
cmpb cl, #9 ! No need to do the last 720K/360K test
|
||||
je success
|
||||
|
||||
! Try to read the last sector on track 0
|
||||
|
||||
mov es, lowsec(bp) ! es = vector segment (lowsec = 0)
|
||||
mov bx, #BUFFER ! es:bx buffer = 0x0000:0x0600
|
||||
mov ax, #0x0201 ! Read sector, #sectors = 1
|
||||
xorb ch, ch ! Track 0, last sector
|
||||
xorb dh, dh ! Drive dl, head 0
|
||||
int 0x13
|
||||
jc next ! Error, try the next floppy type
|
||||
|
||||
success:movb dh, #2 ! Load number of heads for multiply
|
||||
#endif
|
||||
|
||||
loadboot:
|
||||
! Load /boot from the boot device
|
||||
|
||||
#ifndef CDBOOT
|
||||
movb al, (di) ! al = (di) = sectors per track
|
||||
mulb dh ! dh = heads, ax = heads * sectors
|
||||
mov secpcyl(bp), ax ! Sectors per cylinder = heads * sectors
|
||||
#endif
|
||||
|
||||
mov ax, #BOOTSEG ! Segment to load /boot into
|
||||
mov es, ax
|
||||
xor bx, bx ! Load first sector at es:bx = BOOTSEG:0x0000
|
||||
mov si, #LOADOFF+addresses ! Start of the boot code addresses
|
||||
load:
|
||||
mov ax, 1(si) ! Get next sector number: low 16 bits
|
||||
movb dl, 3(si) ! Bits 16-23 for your up to 8GB partition
|
||||
xorb dh, dh ! dx:ax = sector within partition
|
||||
#ifndef CDBOOT
|
||||
add ax, lowsec+0(bp)
|
||||
adc dx, lowsec+2(bp)! dx:ax = sector within drive
|
||||
cmp dx, #[1024*255*63-255]>>16 ! Near 8G limit?
|
||||
jae bigdisk
|
||||
div secpcyl(bp) ! ax = cylinder, dx = sector within cylinder
|
||||
xchg ax, dx ! ax = sector within cylinder, dx = cylinder
|
||||
movb ch, dl ! ch = low 8 bits of cylinder
|
||||
divb (di) ! al = head, ah = sector (0-origin)
|
||||
xorb dl, dl ! About to shift bits 8-9 of cylinder into dl
|
||||
shr dx, #1
|
||||
shr dx, #1 ! dl[6..7] = high cylinder
|
||||
orb dl, ah ! dl[0..5] = sector (0-origin)
|
||||
movb cl, dl ! cl[0..5] = sector, cl[6..7] = high cyl
|
||||
incb cl ! cl[0..5] = sector (1-origin)
|
||||
movb dh, al ! dh = al = head
|
||||
movb dl, device(bp) ! dl = device to read
|
||||
movb al, (di) ! Sectors per track - Sector number (0-origin)
|
||||
subb al, ah ! = Sectors left on this track
|
||||
cmpb al, (si) ! Compare with # sectors to read
|
||||
jbe read ! Cant read past the end of a cylinder?
|
||||
movb al, (si) ! (si) < sectors left on this track
|
||||
read: push ax ! Save al = sectors to read
|
||||
movb ah, #0x02 ! Code for disk read (all registers in use now!)
|
||||
int 0x13 ! Call the BIOS for a read
|
||||
pop cx ! Restore al in cl
|
||||
jmp rdeval
|
||||
#endif
|
||||
bigdisk:
|
||||
movb cl, (si) ! Number of sectors to read
|
||||
push si ! Save si
|
||||
mov si, #LOADOFF+ext_rw ! si = extended read/write parameter packet
|
||||
movb 2(si), cl ! Fill in # blocks to transfer
|
||||
mov 4(si), bx ! Buffer address
|
||||
mov 8(si), ax ! Starting block number = dx:ax
|
||||
mov 10(si), dx
|
||||
movb dl, device(bp) ! dl = device to read
|
||||
movb ah, #0x42 ! Extended read
|
||||
int 0x13
|
||||
pop si ! Restore si to point to the addresses array
|
||||
!jmp rdeval
|
||||
rdeval:
|
||||
jc error ! Jump on disk read error
|
||||
movb al, cl ! Restore al = sectors read
|
||||
addb bh, al ! bx += 2 * al * 256 (add bytes read)
|
||||
addb bh, al ! es:bx = where next sector must be read
|
||||
#ifdef CDBOOT
|
||||
addb bh, al ! For CDs, a sector is 2048 bytes, so
|
||||
addb bh, al ! do this 6 more times to get byte count.
|
||||
addb bh, al
|
||||
addb bh, al
|
||||
addb bh, al
|
||||
addb bh, al
|
||||
#endif
|
||||
add 1(si), ax ! Update address by sectors read
|
||||
adcb 3(si), ah ! Don't forget bits 16-23 (add ah = 0)
|
||||
subb (si), al ! Decrement sector count by sectors read
|
||||
jnz load ! Not all sectors have been read
|
||||
add si, #4 ! Next (address, count) pair
|
||||
cmpb ah, (si) ! Done when no sectors to read
|
||||
jnz load ! Read next chunk of /boot
|
||||
|
||||
done:
|
||||
|
||||
! Call /boot, assuming a long a.out header (48 bytes). The a.out header is
|
||||
! usually short (32 bytes), but to be sure /boot has two entry points:
|
||||
! One at offset 0 for the long, and one at offset 16 for the short header.
|
||||
! Parameters passed in registers are:
|
||||
!
|
||||
! dl = Boot-device.
|
||||
! es:si = Partition table entry if hard disk.
|
||||
!
|
||||
pop si ! Restore es:si = partition table entry
|
||||
pop es ! dl is still loaded
|
||||
jmpf BOOTOFF, BOOTSEG ! jmp to sec. boot (skipping header).
|
||||
|
||||
! Read error: print message, hang forever
|
||||
error:
|
||||
mov si, #LOADOFF+errno+1
|
||||
prnum: movb al, ah ! Error number in ah
|
||||
andb al, #0x0F ! Low 4 bits
|
||||
cmpb al, #10 ! A-F?
|
||||
jb digit ! 0-9!
|
||||
addb al, #7 ! 'A' - ':'
|
||||
digit: addb (si), al ! Modify '0' in string
|
||||
dec si
|
||||
movb cl, #4 ! Next 4 bits
|
||||
shrb ah, cl
|
||||
jnz prnum ! Again if digit > 0
|
||||
|
||||
mov si, #LOADOFF+rderr ! String to print
|
||||
print: lodsb ! al = *si++ is char to be printed
|
||||
testb al, al ! Null byte marks end
|
||||
hang: jz hang ! Hang forever waiting for CTRL-ALT-DEL
|
||||
movb ah, #0x0E ! Print character in teletype mode
|
||||
mov bx, #0x0001 ! Page 0, foreground color
|
||||
int 0x10 ! Call BIOS VIDEO_IO
|
||||
jmp print
|
||||
|
||||
.data
|
||||
rderr: .ascii "Read error "
|
||||
errno: .ascii "00 \0"
|
||||
errend:
|
||||
|
||||
! Floppy disk sectors per track for the 1.44M, 1.2M and 360K/720K types:
|
||||
sectors:
|
||||
.data1 18, 15, 9
|
||||
|
||||
! Extended read/write commands require a parameter packet.
|
||||
ext_rw:
|
||||
.data1 0x10 ! Length of extended r/w packet
|
||||
.data1 0 ! Reserved
|
||||
.data2 0 ! Blocks to transfer (to be filled in)
|
||||
.data2 0 ! Buffer address offset (tbfi)
|
||||
.data2 BOOTSEG ! Buffer address segment
|
||||
.data4 0 ! Starting block number low 32 bits (tbfi)
|
||||
.data4 0 ! Starting block number high 32 bits
|
||||
|
||||
.align 2
|
||||
addresses:
|
||||
! The space below this is for disk addresses for a 38K /boot program (worst
|
||||
! case, i.e. file is completely fragmented). It should be enough.
|
||||
1619
boot/boothead.s
Normal file
1619
boot/boothead.s
Normal file
File diff suppressed because it is too large
Load Diff
857
boot/bootimage.c
Normal file
857
boot/bootimage.c
Normal file
@@ -0,0 +1,857 @@
|
||||
/* bootimage.c - Load an image and start it. Author: Kees J. Bot
|
||||
* 19 Jan 1992
|
||||
*/
|
||||
#define BIOS 1 /* Can only be used under the BIOS. */
|
||||
#define nil 0
|
||||
#define _POSIX_SOURCE 1
|
||||
#define _MINIX 1
|
||||
#include <stddef.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <a.out.h>
|
||||
#include <minix/config.h>
|
||||
#include <minix/const.h>
|
||||
#include <minix/type.h>
|
||||
#include <minix/syslib.h>
|
||||
#include <minix/tty.h>
|
||||
#include <sys/video.h>
|
||||
#include <kernel/const.h>
|
||||
#include <kernel/type.h>
|
||||
#include <machine/partition.h>
|
||||
#include "rawfs.h"
|
||||
#include "image.h"
|
||||
#include "boot.h"
|
||||
|
||||
static int block_size = 0;
|
||||
static int verboseboot = VERBOSEBOOT_QUIET;
|
||||
|
||||
#define DEBUG_PRINT(params, level) do { \
|
||||
if (verboseboot >= (level)) printf params; } while (0)
|
||||
#define DEBUGBASIC(params) DEBUG_PRINT(params, VERBOSEBOOT_BASIC)
|
||||
#define DEBUGEXTRA(params) DEBUG_PRINT(params, VERBOSEBOOT_EXTRA)
|
||||
#define DEBUGMAX(params) DEBUG_PRINT(params, VERBOSEBOOT_MAX)
|
||||
|
||||
extern int serial_line;
|
||||
extern u16_t vid_port; /* Video i/o port. */
|
||||
extern u32_t vid_mem_base; /* Video memory base address. */
|
||||
extern u32_t vid_mem_size; /* Video memory size. */
|
||||
|
||||
#define click_shift clck_shft /* 7 char clash with click_size. */
|
||||
|
||||
/* Some kernels have extra features: */
|
||||
#define K_I386 0x0001 /* Make the 386 transition before you call me. */
|
||||
#define K_CLAIM 0x0002 /* I will acquire my own bss pages, thank you. */
|
||||
#define K_CHMEM 0x0004 /* This kernel listens to chmem for its stack size. */
|
||||
#define K_HIGH 0x0008 /* Load mm, fs, etc. in extended memory. */
|
||||
#define K_HDR 0x0010 /* No need to patch sizes, kernel uses the headers. */
|
||||
#define K_RET 0x0020 /* Returns to the monitor on reboot. */
|
||||
#define K_INT86 0x0040 /* Requires generic INT support. */
|
||||
#define K_MEML 0x0080 /* Pass a list of free memory. */
|
||||
#define K_BRET 0x0100 /* New monitor code on shutdown in boot parameters. */
|
||||
#define K_KHIGH 0x0200 /* Load kernel in extended memory. */
|
||||
#define K_ALL 0x03FF /* All feature bits this monitor supports. */
|
||||
|
||||
|
||||
/* Data about the different processes. */
|
||||
|
||||
#define PROCESS_MAX 16 /* Must match the space in kernel/mpx.x */
|
||||
#define KERNEL_IDX 0 /* The first process is the kernel. */
|
||||
#define FS 2 /* The third must be fs. */
|
||||
|
||||
struct process { /* Per-process memory adresses. */
|
||||
u32_t entry; /* Entry point. */
|
||||
u32_t cs; /* Code segment. */
|
||||
u32_t ds; /* Data segment. */
|
||||
u32_t data; /* To access the data segment. */
|
||||
u32_t end; /* End of this process, size = (end - cs). */
|
||||
} process[PROCESS_MAX];
|
||||
int n_procs; /* Number of processes. */
|
||||
|
||||
/* Magic numbers in process' data space. */
|
||||
#define MAGIC_OFF 0 /* Offset of magic # in data seg. */
|
||||
#define CLICK_OFF 2 /* Offset in kernel text to click_shift. */
|
||||
#define FLAGS_OFF 4 /* Offset in kernel text to flags. */
|
||||
#define KERNEL_D_MAGIC 0x526F /* Kernel magic number. */
|
||||
|
||||
/* Offsets of sizes to be patched into kernel and fs. */
|
||||
#define P_SIZ_OFF 0 /* Process' sizes into kernel data. */
|
||||
#define P_INIT_OFF 4 /* Init cs & sizes into fs data. */
|
||||
|
||||
|
||||
#define between(a, c, z) ((unsigned) ((c) - (a)) <= ((z) - (a)))
|
||||
|
||||
void pretty_image(const char *image)
|
||||
/* Pretty print the name of the image to load. Translate '/' and '_' to
|
||||
* space, first letter goes uppercase. An 'r' before a digit prints as
|
||||
* 'revision'. E.g. 'minix/1.6.16r10' -> 'Minix 1.6.16 revision 10'.
|
||||
* The idea is that the part before the 'r' is the official Minix release
|
||||
* and after the 'r' you can put version numbers for your own changes.
|
||||
*/
|
||||
{
|
||||
int up= 0, c;
|
||||
|
||||
while ((c= *image++) != 0) {
|
||||
if (c == '/' || c == '_') c= ' ';
|
||||
|
||||
if (c == 'r' && between('0', *image, '9')) {
|
||||
printf(" revision ");
|
||||
continue;
|
||||
}
|
||||
if (!up && between('a', c, 'z')) c= c - 'a' + 'A';
|
||||
|
||||
if (between('A', c, 'Z')) up= 1;
|
||||
|
||||
putch(c);
|
||||
}
|
||||
}
|
||||
|
||||
#define RAW_ALIGN 16
|
||||
#define BUFSIZE_ZEROS 128
|
||||
|
||||
void raw_clear(u32_t addr, u32_t count)
|
||||
/* Clear "count" bytes at absolute address "addr". */
|
||||
{
|
||||
static char zerosdata[BUFSIZE_ZEROS + RAW_ALIGN];
|
||||
char *zeros = zerosdata + RAW_ALIGN - (unsigned) &zerosdata % RAW_ALIGN;
|
||||
u32_t dst;
|
||||
u32_t zct;
|
||||
|
||||
zct= BUFSIZE_ZEROS;
|
||||
if (zct > count) zct= count;
|
||||
raw_copy(addr, mon2abs(zeros), zct);
|
||||
count-= zct;
|
||||
|
||||
while (count > 0) {
|
||||
dst= addr + zct;
|
||||
if (zct > count) zct= count;
|
||||
raw_copy(dst, addr, zct);
|
||||
count-= zct;
|
||||
zct*= 2;
|
||||
}
|
||||
}
|
||||
|
||||
/* Align a to a multiple of n (a power of 2): */
|
||||
#define align(a, n) (((u32_t)(a) + ((u32_t)(n) - 1)) & ~((u32_t)(n) - 1))
|
||||
unsigned click_shift;
|
||||
unsigned click_size; /* click_size = Smallest kernel memory object. */
|
||||
unsigned k_flags; /* Not all kernels are created equal. */
|
||||
u32_t reboot_code; /* Obsolete reboot code return pointer. */
|
||||
|
||||
int params2params(char *params, size_t psize)
|
||||
/* Repackage the environment settings for the kernel. */
|
||||
{
|
||||
size_t i, n;
|
||||
environment *e;
|
||||
char *name, *value;
|
||||
dev_t dev;
|
||||
|
||||
i= 0;
|
||||
for (e= env; e != nil; e= e->next) {
|
||||
name= e->name;
|
||||
value= e->value;
|
||||
|
||||
if (!(e->flags & E_VAR)) continue;
|
||||
|
||||
if (e->flags & E_DEV) {
|
||||
if ((dev= name2dev(value)) == -1) return 0;
|
||||
value= ul2a10((u16_t) dev);
|
||||
}
|
||||
|
||||
n= i + strlen(name) + 1 + strlen(value) + 1;
|
||||
if (n < psize) {
|
||||
strcpy(params + i, name);
|
||||
strcat(params + i, "=");
|
||||
strcat(params + i, value);
|
||||
}
|
||||
i= n;
|
||||
}
|
||||
|
||||
if (!(k_flags & K_MEML)) {
|
||||
/* Require old memory size variables. */
|
||||
|
||||
value= ul2a10((mem[0].base + mem[0].size) / 1024);
|
||||
n= i + 7 + 1 + strlen(value) + 1;
|
||||
if (n < psize) {
|
||||
strcpy(params + i, "memsize=");
|
||||
strcat(params + i, value);
|
||||
}
|
||||
i= n;
|
||||
value= ul2a10(mem[1].size / 1024);
|
||||
n= i + 7 + 1 + strlen(value) + 1;
|
||||
if (n < psize) {
|
||||
strcpy(params + i, "emssize=");
|
||||
strcat(params + i, value);
|
||||
}
|
||||
i= n;
|
||||
}
|
||||
|
||||
if (i >= psize) {
|
||||
printf("Too many boot parameters\n");
|
||||
return 0;
|
||||
}
|
||||
params[i]= 0; /* End marked with empty string. */
|
||||
return 1;
|
||||
}
|
||||
|
||||
void patch_sizes(void)
|
||||
/* Patch sizes of each process into kernel data space, kernel ds into kernel
|
||||
* text space, and sizes of init into data space of fs. All the patched
|
||||
* numbers are based on the kernel click size, not hardware segments.
|
||||
*/
|
||||
{
|
||||
u16_t text_size, data_size;
|
||||
int i;
|
||||
struct process *procp, *initp;
|
||||
u32_t doff;
|
||||
|
||||
if (k_flags & K_HDR) return; /* Uses the headers. */
|
||||
|
||||
/* Patch text and data sizes of the processes into kernel data space.
|
||||
*/
|
||||
doff= process[KERNEL_IDX].data + P_SIZ_OFF;
|
||||
|
||||
for (i= 0; i < n_procs; i++) {
|
||||
procp= &process[i];
|
||||
text_size= (procp->ds - procp->cs) >> click_shift;
|
||||
data_size= (procp->end - procp->ds) >> click_shift;
|
||||
|
||||
/* Two words per process, the text and data size: */
|
||||
put_word(doff, text_size); doff+= 2;
|
||||
put_word(doff, data_size); doff+= 2;
|
||||
|
||||
initp= procp; /* The last process must be init. */
|
||||
}
|
||||
|
||||
if (k_flags & (K_HIGH|K_MEML)) return; /* Doesn't need FS patching. */
|
||||
|
||||
/* Patch cs and sizes of init into fs data. */
|
||||
put_word(process[FS].data + P_INIT_OFF+0, initp->cs >> click_shift);
|
||||
put_word(process[FS].data + P_INIT_OFF+2, text_size);
|
||||
put_word(process[FS].data + P_INIT_OFF+4, data_size);
|
||||
}
|
||||
|
||||
int selected(const char *name)
|
||||
/* True iff name has no label or the proper label. */
|
||||
{
|
||||
char *colon, *label;
|
||||
int cmp;
|
||||
|
||||
if ((colon= strchr(name, ':')) == nil) return 1;
|
||||
if ((label= b_value("label")) == nil) return 1;
|
||||
|
||||
*colon= 0;
|
||||
cmp= strcmp(label, name);
|
||||
*colon= ':';
|
||||
return cmp == 0;
|
||||
}
|
||||
|
||||
static u32_t proc_size(const struct image_header *hdr)
|
||||
/* Return the size of a process in sectors as found in an image. */
|
||||
{
|
||||
u32_t len= hdr->process.a_text;
|
||||
|
||||
if (hdr->process.a_flags & A_PAL) len+= hdr->process.a_hdrlen;
|
||||
if (hdr->process.a_flags & A_SEP) len= align(len, SECTOR_SIZE);
|
||||
len= align(len + hdr->process.a_data, SECTOR_SIZE);
|
||||
|
||||
return len >> SECTOR_SHIFT;
|
||||
}
|
||||
|
||||
off_t image_off, image_size;
|
||||
u32_t (*vir2sec)(u32_t vsec); /* Where is a sector on disk? */
|
||||
|
||||
u32_t file_vir2sec(u32_t vsec)
|
||||
/* Translate a virtual sector number to an absolute disk sector. */
|
||||
{
|
||||
off_t blk;
|
||||
|
||||
if(!block_size) { errno = 0; return -1; }
|
||||
|
||||
if ((blk= r_vir2abs(vsec / RATIO(block_size))) == -1) {
|
||||
errno= EIO;
|
||||
return -1;
|
||||
}
|
||||
return blk == 0 ? 0 : lowsec + blk * RATIO(block_size) + vsec % RATIO(block_size);
|
||||
}
|
||||
|
||||
u32_t flat_vir2sec(u32_t vsec)
|
||||
/* Simply add an absolute sector offset to vsec. */
|
||||
{
|
||||
return lowsec + image_off + vsec;
|
||||
}
|
||||
|
||||
char *get_sector(u32_t vsec)
|
||||
/* Read a sector "vsec" from the image into memory and return its address.
|
||||
* Return nil on error. (This routine tries to read an entire track, so
|
||||
* the next request is usually satisfied from the track buffer.)
|
||||
*/
|
||||
{
|
||||
u32_t sec;
|
||||
int r;
|
||||
#define SECBUFS 16
|
||||
static char bufdata[SECBUFS * SECTOR_SIZE + RAW_ALIGN];
|
||||
static size_t count; /* Number of sectors in the buffer. */
|
||||
static u32_t bufsec; /* First Sector now in the buffer. */
|
||||
char *buf = bufdata + RAW_ALIGN - (unsigned) &bufdata % RAW_ALIGN;
|
||||
|
||||
if (vsec == 0) count= 0; /* First sector; initialize. */
|
||||
|
||||
if ((sec= (*vir2sec)(vsec)) == -1) return nil;
|
||||
|
||||
if (sec == 0) {
|
||||
/* A hole. */
|
||||
count= 0;
|
||||
memset(buf, 0, SECTOR_SIZE);
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* Can we return a sector from the buffer? */
|
||||
if ((sec - bufsec) < count) {
|
||||
return buf + ((size_t) (sec - bufsec) << SECTOR_SHIFT);
|
||||
}
|
||||
|
||||
/* Not in the buffer. */
|
||||
count= 0;
|
||||
bufsec= sec;
|
||||
|
||||
/* Read a whole track if possible. */
|
||||
while (++count < SECBUFS && !dev_boundary(bufsec + count)) {
|
||||
vsec++;
|
||||
if ((sec= (*vir2sec)(vsec)) == -1) break;
|
||||
|
||||
/* Consecutive? */
|
||||
if (sec != bufsec + count) break;
|
||||
}
|
||||
|
||||
/* Actually read the sectors. */
|
||||
if ((r= readsectors(mon2abs(buf), bufsec, count)) != 0) {
|
||||
readerr(bufsec, r);
|
||||
count= 0;
|
||||
errno= 0;
|
||||
return nil;
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
int get_clickshift(u32_t ksec, struct image_header *hdr)
|
||||
/* Get the click shift and special flags from kernel text. */
|
||||
{
|
||||
char *textp;
|
||||
|
||||
if ((textp= get_sector(ksec)) == nil) return 0;
|
||||
|
||||
if (hdr->process.a_flags & A_PAL) textp+= hdr->process.a_hdrlen;
|
||||
click_shift= * (u16_t *) (textp + CLICK_OFF);
|
||||
k_flags= * (u16_t *) (textp + FLAGS_OFF);
|
||||
|
||||
if ((k_flags & ~K_ALL) != 0) {
|
||||
printf("%s requires features this monitor doesn't offer\n",
|
||||
hdr->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (click_shift < HCLICK_SHIFT || click_shift > 16) {
|
||||
printf("%s click size is bad\n", hdr->name);
|
||||
errno= 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
click_size= 1 << click_shift;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int get_segment(u32_t *vsec, long *size, u32_t *addr, u32_t limit)
|
||||
/* Read *size bytes starting at virtual sector *vsec to memory at *addr. */
|
||||
{
|
||||
char *buf;
|
||||
size_t cnt, n;
|
||||
|
||||
cnt= 0;
|
||||
while (*size > 0) {
|
||||
if (cnt == 0) {
|
||||
if ((buf= get_sector((*vsec)++)) == nil) return 0;
|
||||
cnt= SECTOR_SIZE;
|
||||
}
|
||||
if (*addr + click_size > limit)
|
||||
{
|
||||
DEBUGEXTRA(("get_segment: out of memory; "
|
||||
"addr=0x%lx; limit=0x%lx; size=%lx\n",
|
||||
*addr, limit, size));
|
||||
errno= ENOMEM;
|
||||
return 0;
|
||||
}
|
||||
n= click_size;
|
||||
if (n > cnt) n= cnt;
|
||||
DEBUGMAX(("raw_copy(0x%lx, 0x%lx/0x%x, 0x%lx)... ",
|
||||
*addr, mon2abs(buf), buf, n));
|
||||
raw_copy(*addr, mon2abs(buf), n);
|
||||
DEBUGMAX(("done\n"));
|
||||
*addr+= n;
|
||||
*size-= n;
|
||||
buf+= n;
|
||||
cnt-= n;
|
||||
}
|
||||
|
||||
/* Zero extend to a click. */
|
||||
n= align(*addr, click_size) - *addr;
|
||||
DEBUGMAX(("raw_clear(0x%lx, 0x%lx)... ", *addr, n));
|
||||
raw_clear(*addr, n);
|
||||
DEBUGMAX(("done\n"));
|
||||
*addr+= n;
|
||||
*size-= n;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void restore_screen(void)
|
||||
{
|
||||
struct boot_tty_info boot_tty_info;
|
||||
u32_t info_location;
|
||||
#define LINES 25
|
||||
#define CHARS 80
|
||||
static u16_t consolescreen[LINES][CHARS];
|
||||
|
||||
/* Try and find out what the main console was displaying
|
||||
* by looking into video memory.
|
||||
*/
|
||||
|
||||
info_location = vid_mem_base+vid_mem_size-sizeof(boot_tty_info);
|
||||
raw_copy(mon2abs(&boot_tty_info), info_location,
|
||||
sizeof(boot_tty_info));
|
||||
|
||||
if(boot_tty_info.magic == TTYMAGIC) {
|
||||
if((boot_tty_info.flags & (BTIF_CONSORIGIN|BTIF_CONSCURSOR)) ==
|
||||
(BTIF_CONSORIGIN|BTIF_CONSCURSOR)) {
|
||||
int line;
|
||||
raw_copy(mon2abs(consolescreen),
|
||||
vid_mem_base + boot_tty_info.consorigin,
|
||||
sizeof(consolescreen));
|
||||
clear_screen();
|
||||
for(line = 0; line < LINES; line++) {
|
||||
int ch;
|
||||
for(ch = 0; ch < CHARS; ch++) {
|
||||
u16_t newch = consolescreen[line][ch] & BYTE;
|
||||
if(newch < ' ') newch = ' ';
|
||||
putch(newch);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void exec_image(char *image)
|
||||
/* Get a Minix image into core, patch it up and execute. */
|
||||
{
|
||||
int i;
|
||||
struct image_header hdr;
|
||||
char *buf;
|
||||
u32_t vsec, addr, limit, aout, n, totalmem = 0;
|
||||
struct process *procp; /* Process under construction. */
|
||||
long a_text, a_data, a_bss, a_stack;
|
||||
int banner= 0;
|
||||
long processor= a2l(b_value("processor"));
|
||||
u16_t kmagic, mode;
|
||||
char *console;
|
||||
char params[SECTOR_SIZE];
|
||||
extern char *sbrk(int);
|
||||
char *verb;
|
||||
|
||||
/* The stack is pretty deep here, so check if heap and stack collide. */
|
||||
(void) sbrk(0);
|
||||
|
||||
if ((verb= b_value(VERBOSEBOOTVARNAME)) != nil)
|
||||
verboseboot = a2l(verb);
|
||||
|
||||
printf("\nLoading ");
|
||||
pretty_image(image);
|
||||
printf(".\n");
|
||||
|
||||
vsec= 0; /* Load this sector from image next. */
|
||||
addr= mem[0].base; /* Into this memory block. */
|
||||
limit= mem[0].base + mem[0].size;
|
||||
if (limit > caddr) limit= caddr;
|
||||
|
||||
/* Allocate and clear the area where the headers will be placed. */
|
||||
aout = (limit -= PROCESS_MAX * A_MINHDR);
|
||||
|
||||
/* Clear the area where the headers will be placed. */
|
||||
raw_clear(aout, PROCESS_MAX * A_MINHDR);
|
||||
|
||||
/* Read the many different processes: */
|
||||
for (i= 0; vsec < image_size; i++) {
|
||||
u32_t startaddr;
|
||||
startaddr = addr;
|
||||
if (i == PROCESS_MAX) {
|
||||
printf("There are more then %d programs in %s\n",
|
||||
PROCESS_MAX, image);
|
||||
errno= 0;
|
||||
return;
|
||||
}
|
||||
procp= &process[i];
|
||||
|
||||
/* Read header. */
|
||||
DEBUGEXTRA(("Reading header... "));
|
||||
for (;;) {
|
||||
if ((buf= get_sector(vsec++)) == nil) return;
|
||||
|
||||
memcpy(&hdr, buf, sizeof(hdr));
|
||||
|
||||
if (BADMAG(hdr.process)) { errno= ENOEXEC; return; }
|
||||
|
||||
/* Check the optional label on the process. */
|
||||
if (selected(hdr.name)) break;
|
||||
|
||||
/* Bad label, skip this process. */
|
||||
vsec+= proc_size(&hdr);
|
||||
}
|
||||
DEBUGEXTRA(("done\n"));
|
||||
|
||||
/* Sanity check: an 8086 can't run a 386 kernel. */
|
||||
if (hdr.process.a_cpu == A_I80386 && processor < 386) {
|
||||
printf("You can't run a 386 kernel on this 80%ld\n",
|
||||
processor);
|
||||
errno= 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get the click shift from the kernel text segment. */
|
||||
if (i == KERNEL_IDX) {
|
||||
if (!get_clickshift(vsec, &hdr)) return;
|
||||
addr= align(addr, click_size);
|
||||
|
||||
/* big kernels must be loaded into extended memory */
|
||||
if (k_flags & K_KHIGH) {
|
||||
addr= mem[1].base;
|
||||
limit= mem[1].base + mem[1].size;
|
||||
}
|
||||
}
|
||||
|
||||
/* Save a copy of the header for the kernel, with a_syms
|
||||
* misused as the address where the process is loaded at.
|
||||
*/
|
||||
DEBUGEXTRA(("raw_copy(0x%lx, 0x%lx, 0x%x)... ",
|
||||
aout + i * A_MINHDR, mon2abs(&hdr.process), A_MINHDR));
|
||||
hdr.process.a_syms= addr;
|
||||
raw_copy(aout + i * A_MINHDR, mon2abs(&hdr.process), A_MINHDR);
|
||||
DEBUGEXTRA(("done\n"));
|
||||
|
||||
if (!banner) {
|
||||
DEBUGBASIC((" cs ds text data bss"));
|
||||
if (k_flags & K_CHMEM) DEBUGBASIC((" stack"));
|
||||
DEBUGBASIC(("\n"));
|
||||
banner= 1;
|
||||
}
|
||||
|
||||
/* Segment sizes. */
|
||||
DEBUGEXTRA(("a_text=0x%lx; a_data=0x%lx; a_bss=0x%lx; a_flags=0x%x)\n",
|
||||
hdr.process.a_text, hdr.process.a_data,
|
||||
hdr.process.a_bss, hdr.process.a_flags));
|
||||
|
||||
a_text= hdr.process.a_text;
|
||||
a_data= hdr.process.a_data;
|
||||
a_bss= hdr.process.a_bss;
|
||||
if (k_flags & K_CHMEM) {
|
||||
a_stack= hdr.process.a_total - a_data - a_bss;
|
||||
if (!(hdr.process.a_flags & A_SEP)) a_stack-= a_text;
|
||||
} else {
|
||||
a_stack= 0;
|
||||
}
|
||||
|
||||
/* Collect info about the process to be. */
|
||||
procp->cs= addr;
|
||||
|
||||
/* Process may be page aligned so that the text segment contains
|
||||
* the header, or have an unmapped zero page against vaxisms.
|
||||
*/
|
||||
procp->entry= hdr.process.a_entry;
|
||||
if (hdr.process.a_flags & A_PAL) a_text+= hdr.process.a_hdrlen;
|
||||
if (hdr.process.a_flags & A_UZP) procp->cs-= click_size;
|
||||
|
||||
/* Separate I&D: two segments. Common I&D: only one. */
|
||||
if (hdr.process.a_flags & A_SEP) {
|
||||
/* Read the text segment. */
|
||||
DEBUGEXTRA(("get_segment(0x%lx, 0x%lx, 0x%lx, 0x%lx)\n",
|
||||
vsec, a_text, addr, limit));
|
||||
if (!get_segment(&vsec, &a_text, &addr, limit)) return;
|
||||
DEBUGEXTRA(("get_segment done vsec=0x%lx a_text=0x%lx "
|
||||
"addr=0x%lx\n",
|
||||
vsec, a_text, addr));
|
||||
|
||||
/* The data segment follows. */
|
||||
procp->ds= addr;
|
||||
if (hdr.process.a_flags & A_UZP) procp->ds-= click_size;
|
||||
procp->data= addr;
|
||||
} else {
|
||||
/* Add text to data to form one segment. */
|
||||
procp->data= addr + a_text;
|
||||
procp->ds= procp->cs;
|
||||
a_data+= a_text;
|
||||
}
|
||||
|
||||
/* Read the data segment. */
|
||||
DEBUGEXTRA(("get_segment(0x%lx, 0x%lx, 0x%lx, 0x%lx)\n",
|
||||
vsec, a_data, addr, limit));
|
||||
if (!get_segment(&vsec, &a_data, &addr, limit)) return;
|
||||
DEBUGEXTRA(("get_segment done vsec=0x%lx a_data=0x%lx "
|
||||
"addr=0x%lx\n",
|
||||
vsec, a_data, addr));
|
||||
|
||||
/* Make space for bss and stack unless... */
|
||||
if (i != KERNEL_IDX && (k_flags & K_CLAIM)) a_bss= a_stack= 0;
|
||||
|
||||
DEBUGBASIC(("%07lx %07lx %8ld %8ld %8ld",
|
||||
procp->cs, procp->ds, hdr.process.a_text,
|
||||
hdr.process.a_data, hdr.process.a_bss));
|
||||
if (k_flags & K_CHMEM) DEBUGBASIC((" %8ld", a_stack));
|
||||
|
||||
/* Note that a_data may be negative now, but we can look at it
|
||||
* as -a_data bss bytes.
|
||||
*/
|
||||
|
||||
/* Compute the number of bss clicks left. */
|
||||
a_bss+= a_data;
|
||||
n= align(a_bss, click_size);
|
||||
a_bss-= n;
|
||||
|
||||
/* Zero out bss. */
|
||||
DEBUGEXTRA(("\nraw_clear(0x%lx, 0x%lx); limit=0x%lx... ", addr, n, limit));
|
||||
if (addr + n > limit) { errno= ENOMEM; return; }
|
||||
raw_clear(addr, n);
|
||||
DEBUGEXTRA(("done\n"));
|
||||
addr+= n;
|
||||
|
||||
/* And the number of stack clicks. */
|
||||
a_stack+= a_bss;
|
||||
n= align(a_stack, click_size);
|
||||
a_stack-= n;
|
||||
|
||||
/* Add space for the stack. */
|
||||
addr+= n;
|
||||
|
||||
/* Process endpoint. */
|
||||
procp->end= addr;
|
||||
|
||||
if (verboseboot >= VERBOSEBOOT_BASIC)
|
||||
printf(" %s\n", hdr.name);
|
||||
else {
|
||||
u32_t mem;
|
||||
mem = addr-startaddr;
|
||||
printf("%s ", hdr.name);
|
||||
totalmem += mem;
|
||||
}
|
||||
|
||||
if (i == 0 && (k_flags & (K_HIGH | K_KHIGH)) == K_HIGH) {
|
||||
/* Load the rest in extended memory. */
|
||||
addr= mem[1].base;
|
||||
limit= mem[1].base + mem[1].size;
|
||||
}
|
||||
}
|
||||
|
||||
if (verboseboot < VERBOSEBOOT_BASIC)
|
||||
printf("(%luk)\n", totalmem/1024);
|
||||
|
||||
if ((n_procs= i) == 0) {
|
||||
printf("There are no programs in %s\n", image);
|
||||
errno= 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check the kernel magic number. */
|
||||
raw_copy(mon2abs(&kmagic),
|
||||
process[KERNEL_IDX].data + MAGIC_OFF, sizeof(kmagic));
|
||||
if (kmagic != KERNEL_D_MAGIC) {
|
||||
printf("Kernel magic number is incorrect (0x%x@0x%lx)\n",
|
||||
kmagic, process[KERNEL_IDX].data + MAGIC_OFF);
|
||||
errno= 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Patch sizes, etc. into kernel data. */
|
||||
DEBUGEXTRA(("patch_sizes()... "));
|
||||
patch_sizes();
|
||||
DEBUGEXTRA(("done\n"));
|
||||
|
||||
#if !DOS
|
||||
if (!(k_flags & K_MEML)) {
|
||||
/* Copy the a.out headers to the old place. */
|
||||
raw_copy(HEADERPOS, aout, PROCESS_MAX * A_MINHDR);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Run the trailer function just before starting Minix. */
|
||||
DEBUGEXTRA(("run_trailer()... "));
|
||||
if (!run_trailer()) { errno= 0; return; }
|
||||
DEBUGEXTRA(("done\n"));
|
||||
|
||||
/* Translate the boot parameters to what Minix likes best. */
|
||||
DEBUGEXTRA(("params2params(0x%x, 0x%x)... ", params, sizeof(params)));
|
||||
if (!params2params(params, sizeof(params))) { errno= 0; return; }
|
||||
DEBUGEXTRA(("done\n"));
|
||||
|
||||
/* Set the video to the required mode. */
|
||||
if ((console= b_value("console")) == nil || (mode= a2x(console)) == 0) {
|
||||
mode= strcmp(b_value("chrome"), "color") == 0 ? COLOR_MODE :
|
||||
MONO_MODE;
|
||||
}
|
||||
DEBUGEXTRA(("set_mode(%d)... ", mode));
|
||||
set_mode(mode);
|
||||
DEBUGEXTRA(("done\n"));
|
||||
|
||||
/* Close the disk. */
|
||||
DEBUGEXTRA(("dev_close()... "));
|
||||
(void) dev_close();
|
||||
DEBUGEXTRA(("done\n"));
|
||||
|
||||
/* Minix. */
|
||||
DEBUGEXTRA(("minix(0x%lx, 0x%lx, 0x%lx, 0x%x, 0x%x, 0x%lx)\n",
|
||||
process[KERNEL_IDX].entry, process[KERNEL_IDX].cs,
|
||||
process[KERNEL_IDX].ds, params, sizeof(params), aout));
|
||||
minix(process[KERNEL_IDX].entry, process[KERNEL_IDX].cs,
|
||||
process[KERNEL_IDX].ds, params, sizeof(params), aout);
|
||||
|
||||
if (!(k_flags & K_BRET)) {
|
||||
extern u32_t reboot_code;
|
||||
raw_copy(mon2abs(params), reboot_code, sizeof(params));
|
||||
}
|
||||
parse_code(params);
|
||||
|
||||
/* Return from Minix. Things may have changed, so assume nothing. */
|
||||
fsok= -1;
|
||||
errno= 0;
|
||||
|
||||
/* Read leftover character, if any. */
|
||||
scan_keyboard();
|
||||
|
||||
/* Restore screen contents. */
|
||||
restore_screen();
|
||||
}
|
||||
|
||||
|
||||
|
||||
ino_t latest_version(char *version, struct stat *stp)
|
||||
/* Recursively read the current directory, selecting the newest image on
|
||||
* the way up. (One can't use r_stat while reading a directory.)
|
||||
*/
|
||||
{
|
||||
char name[NAME_MAX + 1];
|
||||
ino_t ino, newest;
|
||||
time_t mtime;
|
||||
|
||||
if ((ino= r_readdir(name)) == 0) { stp->st_mtime= 0; return 0; }
|
||||
|
||||
newest= latest_version(version, stp);
|
||||
mtime= stp->st_mtime;
|
||||
r_stat(ino, stp);
|
||||
|
||||
if (S_ISREG(stp->st_mode) && stp->st_mtime > mtime) {
|
||||
newest= ino;
|
||||
strcpy(version, name);
|
||||
} else {
|
||||
stp->st_mtime= mtime;
|
||||
}
|
||||
return newest;
|
||||
}
|
||||
|
||||
char *select_image(char *image)
|
||||
/* Look image up on the filesystem, if it is a file then we're done, but
|
||||
* if its a directory then we want the newest file in that directory. If
|
||||
* it doesn't exist at all, then see if it is 'number:number' and get the
|
||||
* image from that absolute offset off the disk.
|
||||
*/
|
||||
{
|
||||
ino_t image_ino;
|
||||
struct stat st;
|
||||
|
||||
image= strcpy(malloc((strlen(image) + 1 + NAME_MAX + 1)
|
||||
* sizeof(char)), image);
|
||||
|
||||
fsok= r_super(&block_size) != 0;
|
||||
if (!fsok || (image_ino= r_lookup(ROOT_INO, image)) == 0) {
|
||||
char *size;
|
||||
|
||||
if (numprefix(image, &size) && *size++ == ':'
|
||||
&& numeric(size)) {
|
||||
vir2sec= flat_vir2sec;
|
||||
image_off= a2l(image);
|
||||
image_size= a2l(size);
|
||||
strcpy(image, "Minix");
|
||||
return image;
|
||||
}
|
||||
if (!fsok)
|
||||
printf("No image selected\n");
|
||||
else
|
||||
printf("Can't load %s: %s\n", image, unix_err(errno));
|
||||
goto bail_out;
|
||||
}
|
||||
|
||||
r_stat(image_ino, &st);
|
||||
if (!S_ISREG(st.st_mode)) {
|
||||
char *version= image + strlen(image);
|
||||
char dots[NAME_MAX + 1];
|
||||
|
||||
if (!S_ISDIR(st.st_mode)) {
|
||||
printf("%s: %s\n", image, unix_err(ENOTDIR));
|
||||
goto bail_out;
|
||||
}
|
||||
(void) r_readdir(dots);
|
||||
(void) r_readdir(dots); /* "." & ".." */
|
||||
*version++= '/';
|
||||
*version= 0;
|
||||
if ((image_ino= latest_version(version, &st)) == 0) {
|
||||
printf("There are no images in %s\n", image);
|
||||
goto bail_out;
|
||||
}
|
||||
r_stat(image_ino, &st);
|
||||
}
|
||||
vir2sec= file_vir2sec;
|
||||
image_size= (st.st_size + SECTOR_SIZE - 1) >> SECTOR_SHIFT;
|
||||
return image;
|
||||
bail_out:
|
||||
free(image);
|
||||
return nil;
|
||||
}
|
||||
|
||||
void bootminix(void)
|
||||
/* Load Minix and run it. (Given the size of this program it is surprising
|
||||
* that it ever gets to that.)
|
||||
*/
|
||||
{
|
||||
char *image;
|
||||
|
||||
if ((image= select_image(b_value("image"))) == nil) return;
|
||||
|
||||
if(serial_line >= 0) {
|
||||
char linename[2];
|
||||
linename[0] = serial_line + '0';
|
||||
linename[1] = '\0';
|
||||
b_setvar(E_VAR, SERVARNAME, linename);
|
||||
}
|
||||
|
||||
exec_image(image);
|
||||
|
||||
switch (errno) {
|
||||
case ENOEXEC:
|
||||
printf("%s contains a bad program header\n", image);
|
||||
break;
|
||||
case ENOMEM:
|
||||
printf("Not enough memory to load %s\n", image);
|
||||
break;
|
||||
case EIO:
|
||||
printf("Unexpected EOF on %s\n", image);
|
||||
case 0:
|
||||
/* No error or error already reported. */;
|
||||
}
|
||||
free(image);
|
||||
|
||||
if(serial_line >= 0)
|
||||
b_unset(SERVARNAME);
|
||||
}
|
||||
|
||||
/*
|
||||
* $PchId: bootimage.c,v 1.10 2002/02/27 19:39:09 philip Exp $
|
||||
*/
|
||||
1380
boot/doshead.s
Normal file
1380
boot/doshead.s
Normal file
File diff suppressed because it is too large
Load Diff
13
boot/image.h
Normal file
13
boot/image.h
Normal file
@@ -0,0 +1,13 @@
|
||||
/* image.h - Info between installboot and boot. Author: Kees J. Bot
|
||||
*/
|
||||
|
||||
#define IM_NAME_MAX 63
|
||||
|
||||
struct image_header {
|
||||
char name[IM_NAME_MAX + 1]; /* Null terminated. */
|
||||
struct exec process;
|
||||
};
|
||||
|
||||
/*
|
||||
* $PchId: image.h,v 1.4 1995/11/27 22:23:12 philip Exp $
|
||||
*/
|
||||
832
boot/installboot.c
Normal file
832
boot/installboot.c
Normal file
@@ -0,0 +1,832 @@
|
||||
/* installboot 3.0 - Make a device bootable Author: Kees J. Bot
|
||||
* 21 Dec 1991
|
||||
*
|
||||
* Either make a device bootable or make an image from kernel, mm, fs, etc.
|
||||
*/
|
||||
#define _POSIX_SOURCE 1
|
||||
#define _MINIX 1
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <dirent.h>
|
||||
#include <a.out.h>
|
||||
#include <minix/config.h>
|
||||
#include <minix/const.h>
|
||||
#include <minix/partition.h>
|
||||
#include <minix/u64.h>
|
||||
#include "rawfs.h"
|
||||
#include "image.h"
|
||||
|
||||
#define BOOTBLOCK 0 /* Of course */
|
||||
#define SECTOR_SIZE 512 /* Disk sector size. */
|
||||
#define RATIO(b) ((b)/SECTOR_SIZE)
|
||||
#define SIGNATURE 0xAA55 /* Boot block signature. */
|
||||
#define BOOT_MAX 64 /* Absolute maximum size of secondary boot */
|
||||
#define SIGPOS 510 /* Where to put signature word. */
|
||||
#define PARTPOS 446 /* Offset to the partition table in a master
|
||||
* boot block.
|
||||
*/
|
||||
|
||||
#define between(a, c, z) ((unsigned) ((c) - (a)) <= ((z) - (a)))
|
||||
#define control(c) between('\0', (c), '\37')
|
||||
|
||||
#define BOOT_BLOCK_SIZE 1024
|
||||
|
||||
static void report(const char *label)
|
||||
/* installboot: label: No such file or directory */
|
||||
{
|
||||
fprintf(stderr, "installboot: %s: %s\n", label, strerror(errno));
|
||||
}
|
||||
|
||||
static void fatal(const char *label)
|
||||
{
|
||||
report(label);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
char *basename(char *name)
|
||||
/* Return the last component of name, stripping trailing slashes from name.
|
||||
* Precondition: name != "/". If name is prefixed by a label, then the
|
||||
* label is copied to the basename too.
|
||||
*/
|
||||
{
|
||||
static char base[IM_NAME_MAX];
|
||||
char *p, *bp= base;
|
||||
|
||||
if ((p= strchr(name, ':')) != NULL) {
|
||||
while (name <= p && bp < base + IM_NAME_MAX - 1)
|
||||
*bp++ = *name++;
|
||||
}
|
||||
for (;;) {
|
||||
if ((p= strrchr(name, '/')) == NULL) { p= name; break; }
|
||||
if (*++p != 0) break;
|
||||
*--p= 0;
|
||||
}
|
||||
while (*p != 0 && bp < base + IM_NAME_MAX - 1) *bp++ = *p++;
|
||||
*bp= 0;
|
||||
return base;
|
||||
}
|
||||
|
||||
static void bread(FILE *f, char *name, void *buf, size_t len)
|
||||
/* Read len bytes. Don't dare return without them. */
|
||||
{
|
||||
if (len > 0 && fread(buf, len, 1, f) != 1) {
|
||||
if (ferror(f)) fatal(name);
|
||||
fprintf(stderr, "installboot: Unexpected EOF on %s\n", name);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
static void bwrite(FILE *f, const char *name, const void *buf, size_t len)
|
||||
{
|
||||
if (len > 0 && fwrite(buf, len, 1, f) != 1) fatal(name);
|
||||
}
|
||||
|
||||
long total_text= 0, total_data= 0, total_bss= 0;
|
||||
int making_image= 0;
|
||||
|
||||
void read_header(int talk, char *proc, FILE *procf, struct image_header *ihdr)
|
||||
/* Read the a.out header of a program and check it. If procf happens to be
|
||||
* NULL then the header is already in *image_hdr and need only be checked.
|
||||
*/
|
||||
{
|
||||
int n, big= 0;
|
||||
static int banner= 0;
|
||||
struct exec *phdr= &ihdr->process;
|
||||
|
||||
if (procf == NULL) {
|
||||
/* Header already present. */
|
||||
n= phdr->a_hdrlen;
|
||||
} else {
|
||||
memset(ihdr, 0, sizeof(*ihdr));
|
||||
|
||||
/* Put the basename of proc in the header. */
|
||||
strncpy(ihdr->name, basename(proc), IM_NAME_MAX);
|
||||
|
||||
/* Read the header. */
|
||||
n= fread(phdr, sizeof(char), A_MINHDR, procf);
|
||||
if (ferror(procf)) fatal(proc);
|
||||
}
|
||||
|
||||
if (n < A_MINHDR || BADMAG(*phdr)) {
|
||||
fprintf(stderr, "installboot: %s is not an executable\n", proc);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Get the rest of the exec header. */
|
||||
if (procf != NULL) {
|
||||
bread(procf, proc, ((char *) phdr) + A_MINHDR,
|
||||
phdr->a_hdrlen - A_MINHDR);
|
||||
}
|
||||
|
||||
if (talk && !banner) {
|
||||
printf(" text data bss size\n");
|
||||
banner= 1;
|
||||
}
|
||||
|
||||
if (talk) {
|
||||
printf(" %8ld %8ld %8ld %9ld %s\n",
|
||||
phdr->a_text, phdr->a_data, phdr->a_bss,
|
||||
phdr->a_text + phdr->a_data + phdr->a_bss, proc);
|
||||
}
|
||||
total_text+= phdr->a_text;
|
||||
total_data+= phdr->a_data;
|
||||
total_bss+= phdr->a_bss;
|
||||
|
||||
if (phdr->a_cpu == A_I8086) {
|
||||
long data= phdr->a_data + phdr->a_bss;
|
||||
|
||||
if (!(phdr->a_flags & A_SEP)) data+= phdr->a_text;
|
||||
|
||||
if (phdr->a_text >= 65536) big|= 1;
|
||||
if (data >= 65536) big|= 2;
|
||||
}
|
||||
if (big) {
|
||||
fprintf(stderr,
|
||||
"%s will crash, %s%s%s segment%s larger then 64K\n",
|
||||
proc,
|
||||
big & 1 ? "text" : "",
|
||||
big == 3 ? " and " : "",
|
||||
big & 2 ? "data" : "",
|
||||
big == 3 ? "s are" : " is");
|
||||
}
|
||||
}
|
||||
|
||||
void padimage(const char *image, FILE *imagef, int n)
|
||||
/* Add n zeros to image to pad it to a sector boundary. */
|
||||
{
|
||||
while (n > 0) {
|
||||
if (putc(0, imagef) == EOF) fatal(image);
|
||||
n--;
|
||||
}
|
||||
}
|
||||
|
||||
#define align(n) (((n) + ((SECTOR_SIZE) - 1)) & ~((SECTOR_SIZE) - 1))
|
||||
|
||||
void copyexec(char *proc, FILE *procf, char *image, FILE *imagef, long n)
|
||||
/* Copy n bytes from proc to image padded to fill a sector. */
|
||||
{
|
||||
int pad, c;
|
||||
|
||||
/* Compute number of padding bytes. */
|
||||
pad= align(n) - n;
|
||||
|
||||
while (n > 0) {
|
||||
if ((c= getc(procf)) == EOF) {
|
||||
if (ferror(procf)) fatal(proc);
|
||||
fprintf(stderr, "installboot: premature EOF on %s\n",
|
||||
proc);
|
||||
exit(1);
|
||||
}
|
||||
if (putc(c, imagef) == EOF) fatal(image);
|
||||
n--;
|
||||
}
|
||||
padimage(image, imagef, pad);
|
||||
}
|
||||
|
||||
void make_image(char *image, char **procv)
|
||||
/* Collect a set of files in an image, each "segment" is nicely padded out
|
||||
* to SECTOR_SIZE, so it may be read from disk into memory without trickery.
|
||||
*/
|
||||
{
|
||||
FILE *imagef, *procf;
|
||||
char *proc, *file;
|
||||
int procn;
|
||||
struct image_header ihdr;
|
||||
struct exec phdr;
|
||||
struct stat st;
|
||||
|
||||
making_image= 1;
|
||||
|
||||
if ((imagef= fopen(image, "w")) == NULL) fatal(image);
|
||||
|
||||
for (procn= 0; (proc= *procv++) != NULL; procn++) {
|
||||
/* Remove the label from the file name. */
|
||||
if ((file= strchr(proc, ':')) != NULL) file++; else file= proc;
|
||||
|
||||
/* Real files please, may need to seek. */
|
||||
if (stat(file, &st) < 0
|
||||
|| (errno= EISDIR, !S_ISREG(st.st_mode))
|
||||
|| (procf= fopen(file, "r")) == NULL
|
||||
) fatal(proc);
|
||||
|
||||
/* Read a.out header. */
|
||||
read_header(1, proc, procf, &ihdr);
|
||||
|
||||
/* Scratch. */
|
||||
phdr= ihdr.process;
|
||||
|
||||
/* The symbol table is always stripped off. */
|
||||
ihdr.process.a_syms= 0;
|
||||
ihdr.process.a_flags &= ~A_NSYM;
|
||||
|
||||
/* Write header padded to fill a sector */
|
||||
bwrite(imagef, image, &ihdr, sizeof(ihdr));
|
||||
|
||||
padimage(image, imagef, SECTOR_SIZE - sizeof(ihdr));
|
||||
|
||||
/* A page aligned executable needs the header in text. */
|
||||
if (phdr.a_flags & A_PAL) {
|
||||
rewind(procf);
|
||||
phdr.a_text+= phdr.a_hdrlen;
|
||||
}
|
||||
|
||||
/* Copy text and data of proc to image. */
|
||||
if (phdr.a_flags & A_SEP) {
|
||||
/* Separate I&D: pad text & data separately. */
|
||||
|
||||
copyexec(proc, procf, image, imagef, phdr.a_text);
|
||||
copyexec(proc, procf, image, imagef, phdr.a_data);
|
||||
} else {
|
||||
/* Common I&D: keep text and data together. */
|
||||
|
||||
copyexec(proc, procf, image, imagef,
|
||||
phdr.a_text + phdr.a_data);
|
||||
}
|
||||
|
||||
/* Done with proc. */
|
||||
(void) fclose(procf);
|
||||
}
|
||||
/* Done with image. */
|
||||
|
||||
if (fclose(imagef) == EOF) fatal(image);
|
||||
|
||||
printf(" ------ ------ ------ -------\n");
|
||||
printf(" %8ld %8ld %8ld %9ld total\n",
|
||||
total_text, total_data, total_bss,
|
||||
total_text + total_data + total_bss);
|
||||
}
|
||||
|
||||
void extractexec(FILE *imagef, char *image, FILE *procf, char *proc,
|
||||
long count, off_t *alen)
|
||||
/* Copy a segment of an executable. It is padded to a sector in image. */
|
||||
{
|
||||
char buf[SECTOR_SIZE];
|
||||
|
||||
while (count > 0) {
|
||||
bread(imagef, image, buf, sizeof(buf));
|
||||
*alen-= sizeof(buf);
|
||||
|
||||
bwrite(procf, proc, buf,
|
||||
count < sizeof(buf) ? (size_t) count : sizeof(buf));
|
||||
count-= sizeof(buf);
|
||||
}
|
||||
}
|
||||
|
||||
void extract_image(char *image)
|
||||
/* Extract the executables from an image. */
|
||||
{
|
||||
FILE *imagef, *procf;
|
||||
off_t len;
|
||||
struct stat st;
|
||||
struct image_header ihdr;
|
||||
struct exec phdr;
|
||||
char buf[SECTOR_SIZE];
|
||||
|
||||
if (stat(image, &st) < 0) fatal(image);
|
||||
|
||||
/* Size of the image. */
|
||||
len= S_ISREG(st.st_mode) ? st.st_size : -1;
|
||||
|
||||
if ((imagef= fopen(image, "r")) == NULL) fatal(image);
|
||||
|
||||
while (len != 0) {
|
||||
/* Extract a program, first sector is an extended header. */
|
||||
bread(imagef, image, buf, sizeof(buf));
|
||||
len-= sizeof(buf);
|
||||
|
||||
memcpy(&ihdr, buf, sizeof(ihdr));
|
||||
phdr= ihdr.process;
|
||||
|
||||
/* Check header. */
|
||||
read_header(1, ihdr.name, NULL, &ihdr);
|
||||
|
||||
if ((procf= fopen(ihdr.name, "w")) == NULL) fatal(ihdr.name);
|
||||
|
||||
if (phdr.a_flags & A_PAL) {
|
||||
/* A page aligned process contains a header in text. */
|
||||
phdr.a_text+= phdr.a_hdrlen;
|
||||
} else {
|
||||
bwrite(procf, ihdr.name, &ihdr.process, phdr.a_hdrlen);
|
||||
}
|
||||
|
||||
/* Extract text and data segments. */
|
||||
if (phdr.a_flags & A_SEP) {
|
||||
extractexec(imagef, image, procf, ihdr.name,
|
||||
phdr.a_text, &len);
|
||||
extractexec(imagef, image, procf, ihdr.name,
|
||||
phdr.a_data, &len);
|
||||
} else {
|
||||
extractexec(imagef, image, procf, ihdr.name,
|
||||
phdr.a_text + phdr.a_data, &len);
|
||||
}
|
||||
|
||||
if (fclose(procf) == EOF) fatal(ihdr.name);
|
||||
}
|
||||
}
|
||||
|
||||
static int rawfd; /* File descriptor to open device. */
|
||||
static const char *rawdev; /* Name of device. */
|
||||
|
||||
void readblock(off_t blk, char *buf, int block_size)
|
||||
/* For rawfs, so that it can read blocks. */
|
||||
{
|
||||
int n;
|
||||
|
||||
if (lseek(rawfd, blk * block_size, SEEK_SET) < 0
|
||||
|| (n= read(rawfd, buf, block_size)) < 0
|
||||
) fatal(rawdev);
|
||||
|
||||
if (n < block_size) {
|
||||
fprintf(stderr, "installboot: Unexpected EOF on %s\n", rawdev);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void writeblock(off_t blk, const char *buf, int block_size)
|
||||
/* Add a function to write blocks for local use. */
|
||||
{
|
||||
if (lseek(rawfd, blk * block_size, SEEK_SET) < 0
|
||||
|| write(rawfd, buf, block_size) < 0
|
||||
) fatal(rawdev);
|
||||
}
|
||||
|
||||
int raw_install(char *file, off_t *start, off_t *len, int block_size)
|
||||
/* Copy bootcode or an image to the boot device at the given absolute disk
|
||||
* block number. This "raw" installation is used to place bootcode and
|
||||
* image on a disk without a filesystem to make a simple boot disk. Useful
|
||||
* in automated scripts for J. Random User.
|
||||
* Note: *len == 0 when an image is read. It is set right afterwards.
|
||||
*/
|
||||
{
|
||||
static char buf[_MAX_BLOCK_SIZE]; /* Nonvolatile block buffer. */
|
||||
FILE *f;
|
||||
off_t sec;
|
||||
unsigned long devsize;
|
||||
static int banner= 0;
|
||||
struct partition entry;
|
||||
|
||||
/* See if the device has a maximum size. */
|
||||
devsize= -1;
|
||||
if (ioctl(rawfd, DIOCGETP, &entry) == 0) devsize= cv64ul(entry.size);
|
||||
|
||||
if ((f= fopen(file, "r")) == NULL) fatal(file);
|
||||
|
||||
/* Copy sectors from file onto the boot device. */
|
||||
sec= *start;
|
||||
do {
|
||||
int off= sec % RATIO(BOOT_BLOCK_SIZE);
|
||||
|
||||
if (fread(buf + off * SECTOR_SIZE, 1, SECTOR_SIZE, f) == 0)
|
||||
break;
|
||||
|
||||
if (sec >= devsize) {
|
||||
fprintf(stderr,
|
||||
"installboot: %s can't be attached to %s\n",
|
||||
file, rawdev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (off == RATIO(BOOT_BLOCK_SIZE) - 1) writeblock(sec / RATIO(BOOT_BLOCK_SIZE), buf, BOOT_BLOCK_SIZE);
|
||||
} while (++sec != *start + *len);
|
||||
|
||||
if (ferror(f)) fatal(file);
|
||||
(void) fclose(f);
|
||||
|
||||
/* Write a partial block, this may be the last image. */
|
||||
if (sec % RATIO(BOOT_BLOCK_SIZE) != 0) writeblock(sec / RATIO(BOOT_BLOCK_SIZE), buf, BOOT_BLOCK_SIZE);
|
||||
|
||||
if (!banner) {
|
||||
printf(" sector length\n");
|
||||
banner= 1;
|
||||
}
|
||||
*len= sec - *start;
|
||||
printf("%8ld%8ld %s\n", *start, *len, file);
|
||||
*start= sec;
|
||||
return 1;
|
||||
}
|
||||
|
||||
enum howto { FS, BOOT };
|
||||
|
||||
void make_bootable(enum howto how, char *device, char *bootblock,
|
||||
char *bootcode, char **imagev)
|
||||
/* Install bootblock on the bootsector of device with the disk addresses to
|
||||
* bootcode patched into the data segment of bootblock. "How" tells if there
|
||||
* should or shoudn't be a file system on the disk. The images in the imagev
|
||||
* vector are added to the end of the device.
|
||||
*/
|
||||
{
|
||||
char buf[_MAX_BLOCK_SIZE + 256], *adrp, *parmp;
|
||||
struct fileaddr {
|
||||
off_t address;
|
||||
int count;
|
||||
} bootaddr[BOOT_MAX + 1], *bap= bootaddr;
|
||||
struct exec boothdr;
|
||||
struct image_header dummy;
|
||||
struct stat st;
|
||||
ino_t ino;
|
||||
off_t sector, max_sector;
|
||||
FILE *bootf;
|
||||
off_t addr, fssize, pos, len;
|
||||
char *labels, *label, *image;
|
||||
int nolabel;
|
||||
int block_size = 0;
|
||||
|
||||
/* Open device and set variables for readblock. */
|
||||
if ((rawfd= open(rawdev= device, O_RDWR)) < 0) fatal(device);
|
||||
|
||||
/* Read and check the superblock. */
|
||||
fssize= r_super(&block_size);
|
||||
|
||||
switch (how) {
|
||||
case FS:
|
||||
if (fssize == 0) {
|
||||
fprintf(stderr,
|
||||
"installboot: %s is not a Minix file system\n",
|
||||
device);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case BOOT:
|
||||
if (fssize != 0) {
|
||||
int s;
|
||||
printf("%s contains a file system!\n", device);
|
||||
printf("Scribbling in 10 seconds");
|
||||
for (s= 0; s < 10; s++) {
|
||||
fputc('.', stdout);
|
||||
fflush(stdout);
|
||||
sleep(1);
|
||||
}
|
||||
fputc('\n', stdout);
|
||||
}
|
||||
fssize= 1; /* Just a boot block. */
|
||||
}
|
||||
|
||||
if (how == FS) {
|
||||
/* See if the boot code can be found on the file system. */
|
||||
if ((ino= r_lookup(ROOT_INO, bootcode)) == 0) {
|
||||
if (errno != ENOENT) fatal(bootcode);
|
||||
}
|
||||
} else {
|
||||
/* Boot code must be attached at the end. */
|
||||
ino= 0;
|
||||
}
|
||||
|
||||
if (ino == 0) {
|
||||
/* For a raw installation, we need to copy the boot code onto
|
||||
* the device, so we need to look at the file to be copied.
|
||||
*/
|
||||
if (stat(bootcode, &st) < 0) fatal(bootcode);
|
||||
|
||||
if ((bootf= fopen(bootcode, "r")) == NULL) fatal(bootcode);
|
||||
} else {
|
||||
/* Boot code is present in the file system. */
|
||||
r_stat(ino, &st);
|
||||
|
||||
/* Get the header from the first block. */
|
||||
if ((addr= r_vir2abs((off_t) 0)) == 0) {
|
||||
boothdr.a_magic[0]= !A_MAGIC0;
|
||||
} else {
|
||||
readblock(addr, buf, block_size);
|
||||
memcpy(&boothdr, buf, sizeof(struct exec));
|
||||
}
|
||||
bootf= NULL;
|
||||
dummy.process= boothdr;
|
||||
}
|
||||
/* See if it is an executable (read_header does the check). */
|
||||
read_header(0, bootcode, bootf, &dummy);
|
||||
boothdr= dummy.process;
|
||||
|
||||
if (bootf != NULL) fclose(bootf);
|
||||
|
||||
/* Get all the sector addresses of the secondary boot code. */
|
||||
max_sector= (boothdr.a_hdrlen + boothdr.a_text
|
||||
+ boothdr.a_data + SECTOR_SIZE - 1) / SECTOR_SIZE;
|
||||
|
||||
if (max_sector > BOOT_MAX * RATIO(block_size)) {
|
||||
fprintf(stderr, "installboot: %s is way too big\n", bootcode);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* Determine the addresses to the boot code to be patched into the
|
||||
* boot block.
|
||||
*/
|
||||
bap->count= 0; /* Trick to get the address recording going. */
|
||||
|
||||
for (sector= 0; sector < max_sector; sector++) {
|
||||
if (ino == 0) {
|
||||
addr= fssize + (sector / RATIO(block_size));
|
||||
} else
|
||||
if ((addr= r_vir2abs(sector / RATIO(block_size))) == 0) {
|
||||
fprintf(stderr, "installboot: %s has holes!\n",
|
||||
bootcode);
|
||||
exit(1);
|
||||
}
|
||||
addr= (addr * RATIO(block_size)) + (sector % RATIO(block_size));
|
||||
|
||||
/* First address of the addresses array? */
|
||||
if (bap->count == 0) bap->address= addr;
|
||||
|
||||
/* Paste sectors together in a multisector read. */
|
||||
if (bap->address + bap->count == addr)
|
||||
bap->count++;
|
||||
else {
|
||||
/* New address. */
|
||||
bap++;
|
||||
bap->address= addr;
|
||||
bap->count= 1;
|
||||
}
|
||||
}
|
||||
(++bap)->count= 0; /* No more. */
|
||||
|
||||
/* Get the boot block and patch the pieces in. */
|
||||
readblock(BOOTBLOCK, buf, BOOT_BLOCK_SIZE);
|
||||
|
||||
if ((bootf= fopen(bootblock, "r")) == NULL) fatal(bootblock);
|
||||
|
||||
read_header(0, bootblock, bootf, &dummy);
|
||||
boothdr= dummy.process;
|
||||
|
||||
if (boothdr.a_text + boothdr.a_data +
|
||||
4 * (bap - bootaddr) + 1 > PARTPOS) {
|
||||
fprintf(stderr,
|
||||
"installboot: %s + addresses to %s don't fit in the boot sector\n",
|
||||
bootblock, bootcode);
|
||||
fprintf(stderr,
|
||||
"You can try copying/reinstalling %s to defragment it\n",
|
||||
bootcode);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* All checks out right. Read bootblock into the boot block! */
|
||||
bread(bootf, bootblock, buf, boothdr.a_text + boothdr.a_data);
|
||||
(void) fclose(bootf);
|
||||
|
||||
/* Patch the addresses in. */
|
||||
adrp= buf + (int) (boothdr.a_text + boothdr.a_data);
|
||||
for (bap= bootaddr; bap->count != 0; bap++) {
|
||||
*adrp++= bap->count;
|
||||
*adrp++= (bap->address >> 0) & 0xFF;
|
||||
*adrp++= (bap->address >> 8) & 0xFF;
|
||||
*adrp++= (bap->address >> 16) & 0xFF;
|
||||
}
|
||||
/* Zero count stops bootblock's reading loop. */
|
||||
*adrp++= 0;
|
||||
|
||||
if (bap > bootaddr+1) {
|
||||
printf("%s and %d addresses to %s patched into %s\n",
|
||||
bootblock, (int)(bap - bootaddr), bootcode, device);
|
||||
}
|
||||
|
||||
/* Boot block signature. */
|
||||
buf[SIGPOS+0]= (SIGNATURE >> 0) & 0xFF;
|
||||
buf[SIGPOS+1]= (SIGNATURE >> 8) & 0xFF;
|
||||
|
||||
/* Sector 2 of the boot block is used for boot parameters, initially
|
||||
* filled with null commands (newlines). Initialize it only if
|
||||
* necessary.
|
||||
*/
|
||||
for (parmp= buf + SECTOR_SIZE; parmp < buf + 2*SECTOR_SIZE; parmp++) {
|
||||
if (*imagev != NULL || (control(*parmp) && *parmp != '\n')) {
|
||||
/* Param sector must be initialized. */
|
||||
memset(buf + SECTOR_SIZE, '\n', SECTOR_SIZE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Offset to the end of the file system to add boot code and images. */
|
||||
pos= fssize * RATIO(block_size);
|
||||
|
||||
if (ino == 0) {
|
||||
/* Place the boot code onto the boot device. */
|
||||
len= max_sector;
|
||||
if (!raw_install(bootcode, &pos, &len, block_size)) {
|
||||
if (how == FS) {
|
||||
fprintf(stderr,
|
||||
"\t(Isn't there a copy of %s on %s that can be used?)\n",
|
||||
bootcode, device);
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
parmp= buf + SECTOR_SIZE;
|
||||
nolabel= 0;
|
||||
|
||||
if (how == BOOT) {
|
||||
/* A boot only disk needs to have floppies swapped. */
|
||||
strcpy(parmp,
|
||||
"trailer()echo \\nInsert the root diskette then hit RETURN\\n\\w\\c\n");
|
||||
parmp+= strlen(parmp);
|
||||
}
|
||||
|
||||
while ((labels= *imagev++) != NULL) {
|
||||
/* Place each kernel image on the boot device. */
|
||||
|
||||
if ((image= strchr(labels, ':')) != NULL)
|
||||
*image++= 0;
|
||||
else {
|
||||
if (nolabel) {
|
||||
fprintf(stderr,
|
||||
"installboot: Only one image can be the default\n");
|
||||
exit(1);
|
||||
}
|
||||
nolabel= 1;
|
||||
image= labels;
|
||||
labels= NULL;
|
||||
}
|
||||
len= 0;
|
||||
if (!raw_install(image, &pos, &len, block_size)) exit(1);
|
||||
|
||||
if (labels == NULL) {
|
||||
/* Let this image be the default. */
|
||||
sprintf(parmp, "image=%ld:%ld\n", pos-len, len);
|
||||
parmp+= strlen(parmp);
|
||||
}
|
||||
|
||||
while (labels != NULL) {
|
||||
/* Image is prefixed by a comma separated list of
|
||||
* labels. Define functions to select label and image.
|
||||
*/
|
||||
label= labels;
|
||||
if ((labels= strchr(labels, ',')) != NULL) *labels++ = 0;
|
||||
|
||||
sprintf(parmp,
|
||||
"%s(%c){label=%s;image=%ld:%ld;echo %s kernel selected;menu}\n",
|
||||
label,
|
||||
between('A', label[0], 'Z')
|
||||
? label[0]-'A'+'a' : label[0],
|
||||
label, pos-len, len, label);
|
||||
parmp+= strlen(parmp);
|
||||
}
|
||||
|
||||
if (parmp > buf + block_size) {
|
||||
fprintf(stderr,
|
||||
"installboot: Out of parameter space, too many images\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
/* Install boot block. */
|
||||
writeblock((off_t) BOOTBLOCK, buf, 1024);
|
||||
|
||||
if (pos > fssize * RATIO(block_size)) {
|
||||
/* Tell the total size of the data on the device. */
|
||||
printf("%16ld (%ld kb) total\n", pos,
|
||||
(pos + RATIO(block_size) - 1) / RATIO(block_size));
|
||||
}
|
||||
}
|
||||
|
||||
static void install_master(const char *device, char *masterboot, char **guide)
|
||||
/* Booting a hard disk is a two stage process: The master bootstrap in sector
|
||||
* 0 loads the bootstrap from sector 0 of the active partition which in turn
|
||||
* starts the operating system. This code installs such a master bootstrap
|
||||
* on a hard disk. If guide[0] is non-null then the master bootstrap is
|
||||
* guided into booting a certain device.
|
||||
*/
|
||||
{
|
||||
FILE *masf;
|
||||
unsigned long size;
|
||||
struct stat st;
|
||||
static char buf[_MAX_BLOCK_SIZE];
|
||||
|
||||
/* Open device. */
|
||||
if ((rawfd= open(rawdev= device, O_RDWR)) < 0) fatal(device);
|
||||
|
||||
/* Open the master boot code. */
|
||||
if ((masf= fopen(masterboot, "r")) == NULL) fatal(masterboot);
|
||||
|
||||
/* See if the user is cloning a device. */
|
||||
if (fstat(fileno(masf), &st) >=0 && S_ISBLK(st.st_mode))
|
||||
size= PARTPOS;
|
||||
else {
|
||||
/* Read and check header otherwise. */
|
||||
struct image_header ihdr;
|
||||
|
||||
read_header(1, masterboot, masf, &ihdr);
|
||||
size= ihdr.process.a_text + ihdr.process.a_data;
|
||||
}
|
||||
if (size > PARTPOS) {
|
||||
fprintf(stderr, "installboot: %s is too big\n", masterboot);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Read the master boot block, patch it, write. */
|
||||
readblock(BOOTBLOCK, buf, BOOT_BLOCK_SIZE);
|
||||
|
||||
memset(buf, 0, PARTPOS);
|
||||
(void) bread(masf, masterboot, buf, size);
|
||||
|
||||
if (guide[0] != NULL) {
|
||||
/* Fixate partition to boot. */
|
||||
const char *keys= guide[0];
|
||||
const char *logical= guide[1];
|
||||
size_t i;
|
||||
int logfd;
|
||||
u32_t offset;
|
||||
struct partition geometry;
|
||||
|
||||
/* A string of digits to be seen as keystrokes. */
|
||||
i= 0;
|
||||
do {
|
||||
if (!between('0', keys[i], '9')) {
|
||||
fprintf(stderr,
|
||||
"installboot: bad guide keys '%s'\n",
|
||||
keys);
|
||||
exit(1);
|
||||
}
|
||||
} while (keys[++i] != 0);
|
||||
|
||||
if (size + i + 1 > PARTPOS) {
|
||||
fprintf(stderr,
|
||||
"installboot: not enough space after '%s' for '%s'\n",
|
||||
masterboot, keys);
|
||||
exit(1);
|
||||
}
|
||||
memcpy(buf + size, keys, i);
|
||||
size += i;
|
||||
buf[size]= '\r';
|
||||
|
||||
if (logical != NULL) {
|
||||
if ((logfd= open(logical, O_RDONLY)) < 0
|
||||
|| ioctl(logfd, DIOCGETP, &geometry) < 0
|
||||
) {
|
||||
fatal(logical);
|
||||
}
|
||||
offset= div64u(geometry.base, SECTOR_SIZE);
|
||||
if (size + 5 > PARTPOS) {
|
||||
fprintf(stderr,
|
||||
"installboot: not enough space "
|
||||
"after '%s' for '%s' and an offset "
|
||||
"to '%s'\n",
|
||||
masterboot, keys, logical);
|
||||
exit(1);
|
||||
}
|
||||
buf[size]= '#';
|
||||
memcpy(buf+size+1, &offset, 4);
|
||||
}
|
||||
}
|
||||
|
||||
/* Install signature. */
|
||||
buf[SIGPOS+0]= (SIGNATURE >> 0) & 0xFF;
|
||||
buf[SIGPOS+1]= (SIGNATURE >> 8) & 0xFF;
|
||||
|
||||
writeblock(BOOTBLOCK, buf, BOOT_BLOCK_SIZE);
|
||||
}
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Usage: installboot -i(mage) image kernel mm fs ... init\n"
|
||||
" installboot -(e)x(tract) image\n"
|
||||
" installboot -d(evice) device bootblock boot [image ...]\n"
|
||||
" installboot -b(oot) device bootblock boot image ...\n"
|
||||
" installboot -m(aster) device masterboot [keys [logical]]\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static int isoption(const char *option, const char *test)
|
||||
/* Check if the option argument is equals "test". Also accept -i as short
|
||||
* for -image, and the special case -x for -extract.
|
||||
*/
|
||||
{
|
||||
if (strcmp(option, test) == 0) return 1;
|
||||
if (option[0] != '-' && strlen(option) != 2) return 0;
|
||||
if (option[1] == test[1]) return 1;
|
||||
if (option[1] == 'x' && test[1] == 'e') return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc < 2) usage();
|
||||
|
||||
if (argc >= 4 && isoption(argv[1], "-image")) {
|
||||
make_image(argv[2], argv + 3);
|
||||
} else
|
||||
if (argc == 3 && isoption(argv[1], "-extract")) {
|
||||
extract_image(argv[2]);
|
||||
} else
|
||||
if (argc >= 5 && isoption(argv[1], "-device")) {
|
||||
make_bootable(FS, argv[2], argv[3], argv[4], argv + 5);
|
||||
} else
|
||||
if (argc >= 6 && isoption(argv[1], "-boot")) {
|
||||
make_bootable(BOOT, argv[2], argv[3], argv[4], argv + 5);
|
||||
} else
|
||||
if ((4 <= argc && argc <= 6) && isoption(argv[1], "-master")) {
|
||||
install_master(argv[2], argv[3], argv + 4);
|
||||
} else {
|
||||
usage();
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* $PchId: installboot.c,v 1.10 2000/08/13 22:07:50 philip Exp $
|
||||
*/
|
||||
261
boot/jumpboot.s
Normal file
261
boot/jumpboot.s
Normal file
@@ -0,0 +1,261 @@
|
||||
! jumpboot 1.0 - Jump to another bootstrap Author: Kees J. Bot
|
||||
! 14 Apr 1999
|
||||
!
|
||||
! This code may be placed into any free boot sector, like the first sector
|
||||
! of an extended partition, a file system partition other than the root,
|
||||
! or even the master bootstrap. It will load and run another bootstrap whose
|
||||
! disk, partition, and slice number (not necessarily all three) are patched
|
||||
! into this code by installboot. If the ALT key is held down when this code
|
||||
! is booted then you can type the disk, partition, and slice numbers manually.
|
||||
! The manual interface is default if no numbers are patched in by installboot.
|
||||
!
|
||||
|
||||
o32 = 0x66 ! This assembler doesn't know 386 extensions
|
||||
LOADOFF = 0x7C00 ! 0x0000:LOADOFF is where this code is loaded
|
||||
BUFFER = 0x0600 ! First free memory
|
||||
PART_TABLE = 446 ! Location of partition table within master
|
||||
PENTRYSIZE = 16 ! Size of one partition table entry
|
||||
MAGIC = 510 ! Location of the AA55 magic number
|
||||
|
||||
! <ibm/partition.h>:
|
||||
MINIX_PART = 0x81
|
||||
sysind = 4
|
||||
lowsec = 8
|
||||
|
||||
|
||||
.text
|
||||
|
||||
! Find and load another bootstrap and jump to it.
|
||||
jumpboot:
|
||||
xor ax, ax
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
cli
|
||||
mov ss, ax ! ds = es = ss = Vector segment
|
||||
mov sp, #LOADOFF
|
||||
sti
|
||||
|
||||
! Move this code to safety, then jump to it.
|
||||
mov si, sp ! si = start of this code
|
||||
mov di, #BUFFER ! di = Buffer area
|
||||
mov cx, #512/2 ! One sector
|
||||
cld
|
||||
rep movs
|
||||
jmpf BUFFER+migrate, 0 ! To safety
|
||||
migrate:
|
||||
|
||||
mov bp, #BUFFER+guide ! Patched guiding characters
|
||||
altkey:
|
||||
movb ah, #0x02 ! Keyboard shift status
|
||||
int 0x16
|
||||
testb al, #0x08 ! Bit 3 = ALT key
|
||||
jz noalt ! ALT key pressed?
|
||||
again:
|
||||
mov bp, #zero ! Ignore patched stuff
|
||||
noalt:
|
||||
|
||||
! Follow guide characters to find the boot partition.
|
||||
call print
|
||||
.ascii "d?\b\0" ! Initial greeting
|
||||
|
||||
! Disk number?
|
||||
disk:
|
||||
movb dl, #0x80 - 0x30 ! Prepare to add an ASCII digit
|
||||
call getch ! Get number to tell which disk
|
||||
addb dl, al ! dl = 0x80 + (al - '0')
|
||||
jns n0nboot ! Result should be >= 0x80
|
||||
mov si, #BUFFER+zero-lowsec ! si = where lowsec(si) is zero
|
||||
cmpb (bp), #0x23 ! Next guide character is '#'?
|
||||
jne notlogical
|
||||
lea si, 1-lowsec(bp) ! Logical sector offset follows '#'
|
||||
notlogical:
|
||||
call load ! Load chosen sector of chosen disk
|
||||
cmpb (bp), #0x23
|
||||
je boot ! Run bootstrap if a logical is chosen
|
||||
|
||||
call print ! Intro to partition number
|
||||
.ascii "p?\b\0"
|
||||
|
||||
part:
|
||||
call getch ! Get character to tell partition
|
||||
call gettable ! Get partition table
|
||||
call sort ! Sort partition table
|
||||
call choose_load ! Compute chosen entry and load
|
||||
|
||||
cmpb sysind(si), #MINIX_PART ! Minix subpartition table possible?
|
||||
jne waitboot
|
||||
|
||||
call print ! Intro to slice number
|
||||
.ascii "s?\b\0"
|
||||
|
||||
slice:
|
||||
call getch ! Get character to tell slice
|
||||
call gettable ! Get partition table
|
||||
call choose_load ! Compute chosen entry and load
|
||||
|
||||
waitboot:
|
||||
call print ! Intro to nothing
|
||||
.ascii " ?\b\0"
|
||||
call getch ! Supposed to type RETURN now
|
||||
n0nboot:jmp nonboot ! Sorry, can't go further
|
||||
|
||||
! Get a character, either the patched-in, or one from the keyboard.
|
||||
getch:
|
||||
movb al, (bp) ! Get patched-in character
|
||||
testb al, al
|
||||
jz getkey
|
||||
inc bp
|
||||
jmp gotkey
|
||||
getkey: xorb ah, ah ! Wait for keypress
|
||||
int 0x16
|
||||
gotkey: testb dl, dl ! Ignore CR if disk number not yet set
|
||||
jns putch
|
||||
cmpb al, #0x0D ! Carriage return?
|
||||
je boot
|
||||
!jmp putch
|
||||
|
||||
! Print a character
|
||||
putch: movb ah, #0x0E ! Print character in teletype mode
|
||||
mov bx, #0x0001 ! Page 0, foreground color
|
||||
int 0x10
|
||||
ret
|
||||
|
||||
! Print a message.
|
||||
print: mov cx, si ! Save si
|
||||
pop si ! si = String following 'call print'
|
||||
prnext: lodsb ! al = *si++ is char to be printed
|
||||
testb al, al ! Null marks end
|
||||
jz prdone
|
||||
call putch
|
||||
jmp prnext
|
||||
prdone: xchg si, cx ! Restore si
|
||||
jmp (cx) ! Continue after the string
|
||||
|
||||
! Return typed (or in patched data) means to run the bootstrap now in core!
|
||||
boot:
|
||||
call print ! Make line on screen look proper
|
||||
.ascii "\b \r\n\0"
|
||||
jmp LOADOFF-BUFFER ! Jump to LOADOFF
|
||||
|
||||
! Compute address of chosen partition entry from choice al into si, then
|
||||
! continue to load the boot sector of that partition.
|
||||
choose_load:
|
||||
subb al, #0x30 ! al -= '0'
|
||||
cmpb al, #4 ! Only four partitions
|
||||
ja n0nboot
|
||||
movb ah, #PENTRYSIZE
|
||||
mulb ah ! al *= PENTRYSIZE
|
||||
add ax, #BUFFER+PART_TABLE
|
||||
mov si, ax ! si = &part_table[al - '0']
|
||||
movb al, sysind(si) ! System indicator
|
||||
testb al, al ! Unused partition?
|
||||
jz n0nboot
|
||||
!jmp load ! Continue to load boot sector
|
||||
|
||||
! Load boot sector of the current partition.
|
||||
load:
|
||||
push dx ! Save drive code
|
||||
push es ! Next call sets es
|
||||
movb ah, #0x08 ! Code for drive parameters
|
||||
int 0x13
|
||||
pop es
|
||||
andb cl, #0x3F ! cl = max sector number (1-origin)
|
||||
incb dh ! dh = 1 + max head number (0-origin)
|
||||
movb al, cl ! al = cl = sectors per track
|
||||
mulb dh ! dh = heads, ax = heads * sectors
|
||||
mov bx, ax ! bx = sectors per cylinder = heads * sectors
|
||||
mov ax, lowsec+0(si)
|
||||
mov dx, lowsec+2(si) ! dx:ax = sector within drive
|
||||
cmp dx, #[1024*255*63-255]>>16 ! Near 8G limit?
|
||||
jae bigdisk
|
||||
div bx ! ax = cylinder, dx = sector within cylinder
|
||||
xchg ax, dx ! ax = sector within cylinder, dx = cylinder
|
||||
movb ch, dl ! ch = low 8 bits of cylinder
|
||||
divb cl ! al = head, ah = sector (0-origin)
|
||||
xorb dl, dl ! About to shift bits 8-9 of cylinder into dl
|
||||
shr dx, #1
|
||||
shr dx, #1 ! dl[6..7] = high cylinder
|
||||
orb dl, ah ! dl[0..5] = sector (0-origin)
|
||||
movb cl, dl ! cl[0..5] = sector, cl[6..7] = high cyl
|
||||
incb cl ! cl[0..5] = sector (1-origin)
|
||||
pop dx ! Restore drive code in dl
|
||||
movb dh, al ! dh = al = head
|
||||
mov bx, #LOADOFF ! es:bx = where sector is loaded
|
||||
mov ax, #0x0201 ! ah = Code for read / al = one sector
|
||||
int 0x13
|
||||
jmp rdeval ! Evaluate read result
|
||||
bigdisk:
|
||||
mov bx, dx ! bx:ax = dx:ax = sector to read
|
||||
pop dx ! Restore drive code in dl
|
||||
push si ! Save si
|
||||
mov si, #BUFFER+ext_rw ! si = extended read/write parameter packet
|
||||
mov 8(si), ax ! Starting block number = bx:ax
|
||||
mov 10(si), bx
|
||||
movb ah, #0x42 ! Extended read
|
||||
int 0x13
|
||||
pop si ! Restore si to point to partition entry
|
||||
!jmp rdeval
|
||||
rdeval:
|
||||
jnc rdok
|
||||
rderr:
|
||||
call print
|
||||
.ascii "\r\nRead error\r\n\0"
|
||||
jmp again
|
||||
rdok:
|
||||
cmp LOADOFF+MAGIC, #0xAA55
|
||||
je sigok ! Signature ok?
|
||||
nonboot:
|
||||
call print
|
||||
.ascii "\r\nNot bootable\r\n\0"
|
||||
jmp again
|
||||
sigok:
|
||||
ret
|
||||
|
||||
! Get the partition table into my space.
|
||||
gettable:
|
||||
mov si, #LOADOFF+PART_TABLE
|
||||
mov di, #BUFFER+PART_TABLE
|
||||
mov cx, #4*PENTRYSIZE/2
|
||||
rep movs
|
||||
ret
|
||||
|
||||
! Sort the partition table.
|
||||
sort:
|
||||
mov cx, #4 ! Four times is enough to sort
|
||||
bubble: mov si, #BUFFER+PART_TABLE ! First table entry
|
||||
bubble1:lea di, PENTRYSIZE(si) ! Next entry
|
||||
cmpb sysind(si), ch ! Partition type, nonzero when in use
|
||||
jz exchg ! Unused entries sort to the end
|
||||
inuse: mov bx, lowsec+0(di)
|
||||
sub bx, lowsec+0(si) ! Compute di->lowsec - si->lowsec
|
||||
mov bx, lowsec+2(di)
|
||||
sbb bx, lowsec+2(si)
|
||||
jae order ! In order if si->lowsec <= di->lowsec
|
||||
exchg: movb bl, (si)
|
||||
xchgb bl, PENTRYSIZE(si) ! Exchange entries byte by byte
|
||||
movb (si), bl
|
||||
inc si
|
||||
cmp si, di
|
||||
jb exchg
|
||||
order: mov si, di
|
||||
cmp si, #BUFFER+PART_TABLE+3*PENTRYSIZE
|
||||
jb bubble1
|
||||
loop bubble
|
||||
ret
|
||||
|
||||
.data
|
||||
|
||||
! Extended read/write commands require a parameter packet.
|
||||
ext_rw:
|
||||
.data1 0x10 ! Length of extended r/w packet
|
||||
.data1 0 ! Reserved
|
||||
.data2 1 ! Blocks to transfer (just one)
|
||||
.data2 LOADOFF ! Buffer address offset
|
||||
.data2 0 ! Buffer address segment
|
||||
.data4 0 ! Starting block number low 32 bits (tbfi)
|
||||
zero: .data4 0 ! Starting block number high 32 bits
|
||||
|
||||
.align 2
|
||||
guide:
|
||||
! Guide characters and possibly a logical partition number patched here by
|
||||
! installboot, up to 6 bytes maximum.
|
||||
218
boot/masterboot.s
Normal file
218
boot/masterboot.s
Normal file
@@ -0,0 +1,218 @@
|
||||
! masterboot 2.0 - Master boot block code Author: Kees J. Bot
|
||||
!
|
||||
! This code may be placed in the first sector (the boot sector) of a floppy,
|
||||
! hard disk or hard disk primary partition. There it will perform the
|
||||
! following actions at boot time:
|
||||
!
|
||||
! - If the booted device is a hard disk and one of the partitions is active
|
||||
! then the active partition is booted.
|
||||
!
|
||||
! - Otherwise the next floppy or hard disk device is booted, trying them one
|
||||
! by one.
|
||||
!
|
||||
! To make things a little clearer, the boot path might be:
|
||||
! /dev/fd0 - Floppy disk containing data, tries fd1 then d0
|
||||
! [/dev/fd1] - Drive empty
|
||||
! /dev/c0d0 - Master boot block, selects active partition 2
|
||||
! /dev/c0d0p2 - Submaster, selects active subpartition 0
|
||||
! /dev/c0d0p2s0 - Minix bootblock, reads Boot Monitor /boot
|
||||
! Minix - Started by /boot from a kernel image in /minix
|
||||
|
||||
LOADOFF = 0x7C00 ! 0x0000:LOADOFF is where this code is loaded
|
||||
BUFFER = 0x0600 ! First free memory
|
||||
PART_TABLE = 446 ! Location of partition table within this code
|
||||
PENTRYSIZE = 16 ! Size of one partition table entry
|
||||
MAGIC = 510 ! Location of the AA55 magic number
|
||||
|
||||
! <ibm/partition>.h:
|
||||
bootind = 0
|
||||
sysind = 4
|
||||
lowsec = 8
|
||||
|
||||
|
||||
.text
|
||||
|
||||
! Find active (sub)partition, load its first sector, run it.
|
||||
|
||||
master:
|
||||
xor ax, ax
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
cli
|
||||
mov ss, ax ! ds = es = ss = Vector segment
|
||||
mov sp, #LOADOFF
|
||||
sti
|
||||
|
||||
! Copy this code to safety, then jump to it.
|
||||
mov si, sp ! si = start of this code
|
||||
push si ! Also where we'll return to eventually
|
||||
mov di, #BUFFER ! Buffer area
|
||||
mov cx, #512/2 ! One sector
|
||||
cld
|
||||
rep movs
|
||||
jmpf BUFFER+migrate, 0 ! To safety
|
||||
migrate:
|
||||
|
||||
! Find the active partition
|
||||
findactive:
|
||||
testb dl, dl
|
||||
jns nextdisk ! No bootable partitions on floppies
|
||||
mov si, #BUFFER+PART_TABLE
|
||||
find: cmpb sysind(si), #0 ! Partition type, nonzero when in use
|
||||
jz nextpart
|
||||
testb bootind(si), #0x80 ! Active partition flag in bit 7
|
||||
jz nextpart ! It's not active
|
||||
loadpart:
|
||||
call load ! Load partition bootstrap
|
||||
jc error1 ! Not supposed to fail
|
||||
bootstrap:
|
||||
ret ! Jump to the master bootstrap
|
||||
nextpart:
|
||||
add si, #PENTRYSIZE
|
||||
cmp si, #BUFFER+PART_TABLE+4*PENTRYSIZE
|
||||
jb find
|
||||
! No active partition, tell 'em
|
||||
call print
|
||||
.ascii "No active partition\0"
|
||||
jmp reboot
|
||||
|
||||
! There are no active partitions on this drive, try the next drive.
|
||||
nextdisk:
|
||||
incb dl ! Increment dl for the next drive
|
||||
testb dl, dl
|
||||
js nexthd ! Hard disk if negative
|
||||
int 0x11 ! Get equipment configuration
|
||||
shl ax, #1 ! Highest floppy drive # in bits 6-7
|
||||
shl ax, #1 ! Now in bits 0-1 of ah
|
||||
andb ah, #0x03 ! Extract bits
|
||||
cmpb dl, ah ! Must be dl <= ah for drive to exist
|
||||
ja nextdisk ! Otherwise try disk 0 eventually
|
||||
call load0 ! Read the next floppy bootstrap
|
||||
jc nextdisk ! It failed, next disk please
|
||||
ret ! Jump to the next master bootstrap
|
||||
nexthd: call load0 ! Read the hard disk bootstrap
|
||||
error1: jc error ! No disk?
|
||||
ret
|
||||
|
||||
|
||||
! Load sector 0 from the current device. It's either a floppy bootstrap or
|
||||
! a hard disk master bootstrap.
|
||||
load0:
|
||||
mov si, #BUFFER+zero-lowsec ! si = where lowsec(si) is zero
|
||||
!jmp load
|
||||
|
||||
! Load sector lowsec(si) from the current device. The obvious head, sector,
|
||||
! and cylinder numbers are ignored in favour of the more trustworthy absolute
|
||||
! start of partition.
|
||||
load:
|
||||
mov di, #3 ! Three retries for floppy spinup
|
||||
retry: push dx ! Save drive code
|
||||
push es
|
||||
push di ! Next call destroys es and di
|
||||
movb ah, #0x08 ! Code for drive parameters
|
||||
int 0x13
|
||||
pop di
|
||||
pop es
|
||||
andb cl, #0x3F ! cl = max sector number (1-origin)
|
||||
incb dh ! dh = 1 + max head number (0-origin)
|
||||
movb al, cl ! al = cl = sectors per track
|
||||
mulb dh ! dh = heads, ax = heads * sectors
|
||||
mov bx, ax ! bx = sectors per cylinder = heads * sectors
|
||||
mov ax, lowsec+0(si)
|
||||
mov dx, lowsec+2(si)! dx:ax = sector within drive
|
||||
cmp dx, #[1024*255*63-255]>>16 ! Near 8G limit?
|
||||
jae bigdisk
|
||||
div bx ! ax = cylinder, dx = sector within cylinder
|
||||
xchg ax, dx ! ax = sector within cylinder, dx = cylinder
|
||||
movb ch, dl ! ch = low 8 bits of cylinder
|
||||
divb cl ! al = head, ah = sector (0-origin)
|
||||
xorb dl, dl ! About to shift bits 8-9 of cylinder into dl
|
||||
shr dx, #1
|
||||
shr dx, #1 ! dl[6..7] = high cylinder
|
||||
orb dl, ah ! dl[0..5] = sector (0-origin)
|
||||
movb cl, dl ! cl[0..5] = sector, cl[6..7] = high cyl
|
||||
incb cl ! cl[0..5] = sector (1-origin)
|
||||
pop dx ! Restore drive code in dl
|
||||
movb dh, al ! dh = al = head
|
||||
mov bx, #LOADOFF ! es:bx = where sector is loaded
|
||||
mov ax, #0x0201 ! Code for read, just one sector
|
||||
int 0x13 ! Call the BIOS for a read
|
||||
jmp rdeval ! Evaluate read result
|
||||
bigdisk:
|
||||
mov bx, dx ! bx:ax = dx:ax = sector to read
|
||||
pop dx ! Restore drive code in dl
|
||||
push si ! Save si
|
||||
mov si, #BUFFER+ext_rw ! si = extended read/write parameter packet
|
||||
mov 8(si), ax ! Starting block number = bx:ax
|
||||
mov 10(si), bx
|
||||
movb ah, #0x42 ! Extended read
|
||||
int 0x13
|
||||
pop si ! Restore si to point to partition entry
|
||||
!jmp rdeval
|
||||
rdeval:
|
||||
jnc rdok ! Read succeeded
|
||||
cmpb ah, #0x80 ! Disk timed out? (Floppy drive empty)
|
||||
je rdbad
|
||||
dec di
|
||||
jl rdbad ! Retry count expired
|
||||
xorb ah, ah
|
||||
int 0x13 ! Reset
|
||||
jnc retry ! Try again
|
||||
rdbad: stc ! Set carry flag
|
||||
ret
|
||||
rdok: cmp LOADOFF+MAGIC, #0xAA55
|
||||
jne nosig ! Error if signature wrong
|
||||
ret ! Return with carry still clear
|
||||
nosig: call print
|
||||
.ascii "Not bootable\0"
|
||||
jmp reboot
|
||||
|
||||
! A read error occurred, complain and hang
|
||||
error:
|
||||
mov si, #LOADOFF+errno+1
|
||||
prnum: movb al, ah ! Error number in ah
|
||||
andb al, #0x0F ! Low 4 bits
|
||||
cmpb al, #10 ! A-F?
|
||||
jb digit ! 0-9!
|
||||
addb al, #7 ! 'A' - ':'
|
||||
digit: addb (si), al ! Modify '0' in string
|
||||
dec si
|
||||
movb cl, #4 ! Next 4 bits
|
||||
shrb ah, cl
|
||||
jnz prnum ! Again if digit > 0
|
||||
call print
|
||||
.ascii "Read error "
|
||||
errno: .ascii "00\0"
|
||||
!jmp reboot
|
||||
|
||||
reboot:
|
||||
call print
|
||||
.ascii ". Hit any key to reboot.\0"
|
||||
xorb ah, ah ! Wait for keypress
|
||||
int 0x16
|
||||
call print
|
||||
.ascii "\r\n\0"
|
||||
int 0x19
|
||||
|
||||
! Print a message.
|
||||
print: pop si ! si = String following 'call print'
|
||||
prnext: lodsb ! al = *si++ is char to be printed
|
||||
testb al, al ! Null marks end
|
||||
jz prdone
|
||||
movb ah, #0x0E ! Print character in teletype mode
|
||||
mov bx, #0x0001 ! Page 0, foreground color
|
||||
int 0x10
|
||||
jmp prnext
|
||||
prdone: jmp (si) ! Continue after the string
|
||||
|
||||
.data
|
||||
|
||||
! Extended read/write commands require a parameter packet.
|
||||
ext_rw:
|
||||
.data1 0x10 ! Length of extended r/w packet
|
||||
.data1 0 ! Reserved
|
||||
.data2 1 ! Blocks to transfer (just one)
|
||||
.data2 LOADOFF ! Buffer address offset
|
||||
.data2 0 ! Buffer address segment
|
||||
.data4 0 ! Starting block number low 32 bits (tbfi)
|
||||
zero: .data4 0 ! Starting block number high 32 bits
|
||||
137
boot/mkfhead.s
Normal file
137
boot/mkfhead.s
Normal file
@@ -0,0 +1,137 @@
|
||||
! Mkfhead.s - DOS & BIOS support for mkfile.c Author: Kees J. Bot
|
||||
! 9 May 1998
|
||||
!
|
||||
! This file contains the startup and low level support for the MKFILE.COM
|
||||
! utility. See doshead.ack.s for more comments on .COM files.
|
||||
!
|
||||
.sect .text; .sect .rom; .sect .data; .sect .bss
|
||||
.sect .text
|
||||
|
||||
.define _PSP
|
||||
_PSP:
|
||||
.space 256 ! Program Segment Prefix
|
||||
|
||||
mkfile:
|
||||
cld ! C compiler wants UP
|
||||
xor ax, ax ! Zero
|
||||
mov di, _edata ! Start of bss is at end of data
|
||||
mov cx, _end ! End of bss (begin of heap)
|
||||
sub cx, di ! Number of bss bytes
|
||||
shr cx, 1 ! Number of words
|
||||
rep stos ! Clear bss
|
||||
|
||||
xor cx, cx ! cx = argc
|
||||
xor bx, bx
|
||||
push bx ! argv[argc] = NULL
|
||||
movb bl, (_PSP+0x80) ! Argument byte count
|
||||
0: movb _PSP+0x81(bx), ch ! Null terminate
|
||||
dec bx
|
||||
js 9f
|
||||
cmpb _PSP+0x81(bx), 0x20 ! Whitespace?
|
||||
jbe 0b
|
||||
1: dec bx ! One argument character
|
||||
js 2f
|
||||
cmpb _PSP+0x81(bx), 0x20 ! More argument characters?
|
||||
ja 1b
|
||||
2: lea ax, _PSP+0x81+1(bx) ! Address of argument
|
||||
push ax ! argv[n]
|
||||
inc cx ! argc++;
|
||||
test bx, bx
|
||||
jns 0b ! More arguments?
|
||||
9: movb _PSP+0x81(bx), ch ! Make a null string
|
||||
lea ax, _PSP+0x81(bx)
|
||||
push ax ! to use as argv[0]
|
||||
inc cx ! Final value of argc
|
||||
mov ax, sp
|
||||
push ax ! argv
|
||||
push cx ! argc
|
||||
call _main ! main(argc, argv)
|
||||
push ax
|
||||
call _exit ! exit(main(argc, argv))
|
||||
|
||||
! int creat(const char *path, mode_t mode)
|
||||
! Create a file with the old creat() call.
|
||||
.define _creat
|
||||
_creat:
|
||||
mov bx, sp
|
||||
mov dx, 2(bx) ! Filename
|
||||
xor cx, cx ! Ignore mode, always read-write
|
||||
movb ah, 0x3C ! "CREAT"
|
||||
dos: int 0x21 ! ax = creat(path, 0666);
|
||||
jc seterrno
|
||||
ret
|
||||
|
||||
seterrno:
|
||||
mov (_errno), ax ! Set errno to the DOS error code
|
||||
mov ax, -1
|
||||
cwd ! return -1L;
|
||||
ret
|
||||
|
||||
! int open(const char *path, int oflag)
|
||||
! Open a file with the oldfashioned two-argument open() call.
|
||||
.define _open
|
||||
_open:
|
||||
mov bx, sp
|
||||
mov dx, 2(bx) ! Filename
|
||||
movb al, 4(bx) ! O_RDONLY, O_WRONLY, O_RDWR
|
||||
movb ah, 0x3D ! "OPEN"
|
||||
jmp dos
|
||||
|
||||
! int close(int fd)
|
||||
! Close an open file.
|
||||
.define _close
|
||||
_close:
|
||||
mov bx, sp
|
||||
mov bx, 2(bx) ! bx = file handle
|
||||
movb ah, 0x3E ! "CLOSE"
|
||||
jmp dos
|
||||
|
||||
! void exit(int status)
|
||||
! void _exit(int status)
|
||||
! Return to DOS.
|
||||
.define _exit, __exit, ___exit
|
||||
_exit:
|
||||
__exit:
|
||||
___exit:
|
||||
pop ax
|
||||
pop ax ! al = status
|
||||
movb ah, 0x4C ! "EXIT"
|
||||
int 0x21
|
||||
hlt
|
||||
|
||||
! ssize_t read(int fd, void *buf, size_t n)
|
||||
! Read bytes from an open file.
|
||||
.define _read
|
||||
_read:
|
||||
mov bx, sp
|
||||
mov cx, 6(bx)
|
||||
mov dx, 4(bx)
|
||||
mov bx, 2(bx)
|
||||
movb ah, 0x3F ! "READ"
|
||||
jmp dos
|
||||
|
||||
! ssize_t write(int fd, const void *buf, size_t n)
|
||||
! Write bytes to an open file.
|
||||
.define _write
|
||||
_write:
|
||||
mov bx, sp
|
||||
mov cx, 6(bx)
|
||||
mov dx, 4(bx)
|
||||
mov bx, 2(bx)
|
||||
movb ah, 0x40 ! "WRITE"
|
||||
jmp dos
|
||||
|
||||
! off_t lseek(int fd, off_t offset, int whence)
|
||||
! Set file position for read or write.
|
||||
.define _lseek
|
||||
_lseek:
|
||||
mov bx, sp
|
||||
movb al, 8(bx) ! SEEK_SET, SEEK_CUR, SEEK_END
|
||||
mov dx, 4(bx)
|
||||
mov cx, 6(bx) ! cx:dx = offset
|
||||
mov bx, 2(bx)
|
||||
movb ah, 0x42 ! "LSEEK"
|
||||
jmp dos
|
||||
|
||||
!
|
||||
! $PchId: mkfhead.ack.s,v 1.3 1999/01/14 21:17:06 philip Exp $
|
||||
179
boot/mkfile.c
Normal file
179
boot/mkfile.c
Normal file
@@ -0,0 +1,179 @@
|
||||
/* mkfile 1.0 - create a file under DOS for use as a Minix "disk".
|
||||
* Author: Kees J. Bot
|
||||
* 9 May 1998
|
||||
*/
|
||||
#define nil 0
|
||||
#include <sys/types.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
|
||||
/* Stuff normally found in <unistd.h>, <errno.h>, etc. */
|
||||
extern int errno;
|
||||
int creat(const char *file, int mode);
|
||||
int open(const char *file, int oflag);
|
||||
off_t lseek(int fd, off_t offset, int whence);
|
||||
ssize_t write(int fd, const char *buf, size_t len);
|
||||
void exit(int status);
|
||||
int printf(const char *fmt, ...);
|
||||
|
||||
#define O_WRONLY 1
|
||||
#define SEEK_SET 0
|
||||
#define SEEK_END 2
|
||||
|
||||
/* Kernel printf requires a putk() function. */
|
||||
void putk(int c)
|
||||
{
|
||||
char ch = c;
|
||||
|
||||
if (c == 0) return;
|
||||
if (c == '\n') putk('\r');
|
||||
(void) write(2, &ch, 1);
|
||||
}
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
printf("Usage: mkfile <size>[gmk] <file>\n"
|
||||
"(Example sizes, all 50 meg: 52428800, 51200k, 50m)\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
char *strerror(int err)
|
||||
/* Translate some DOS error numbers to text. */
|
||||
{
|
||||
static struct errlist {
|
||||
int err;
|
||||
char *what;
|
||||
} errlist[] = {
|
||||
{ 0, "No error" },
|
||||
{ 1, "Function number invalid" },
|
||||
{ 2, "File not found" },
|
||||
{ 3, "Path not found" },
|
||||
{ 4, "Too many open files" },
|
||||
{ 5, "Access denied" },
|
||||
{ 6, "Invalid handle" },
|
||||
{ 12, "Access code invalid" },
|
||||
{ 39, "Insufficient disk space" },
|
||||
};
|
||||
struct errlist *ep;
|
||||
static char unknown[]= "Error 65535";
|
||||
unsigned e;
|
||||
char *p;
|
||||
|
||||
for (ep= errlist; ep < errlist + sizeof(errlist)/sizeof(errlist[0]);
|
||||
ep++) {
|
||||
if (ep->err == err) return ep->what;
|
||||
}
|
||||
p= unknown + sizeof(unknown) - 1;
|
||||
e= err;
|
||||
do *--p= '0' + (e % 10); while ((e /= 10) > 0);
|
||||
strcpy(unknown + 6, p);
|
||||
return unknown;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
static char buf[512];
|
||||
unsigned long size, mul;
|
||||
off_t offset;
|
||||
char *cp;
|
||||
int fd;
|
||||
char *file;
|
||||
|
||||
if (argc != 3) usage();
|
||||
|
||||
cp= argv[1];
|
||||
size= 0;
|
||||
while ((unsigned) (*cp - '0') < 10) {
|
||||
unsigned d= *cp++ - '0';
|
||||
if (size <= (ULONG_MAX-9) / 10) {
|
||||
size= size * 10 + d;
|
||||
} else {
|
||||
size= ULONG_MAX;
|
||||
}
|
||||
}
|
||||
if (cp == argv[1]) usage();
|
||||
while (*cp != 0) {
|
||||
mul = 1;
|
||||
switch (*cp++) {
|
||||
case 'G':
|
||||
case 'g': mul *= 1024;
|
||||
case 'M':
|
||||
case 'm': mul *= 1024;
|
||||
case 'K':
|
||||
case 'k': mul *= 1024;
|
||||
case 'B':
|
||||
case 'b': break;
|
||||
default: usage();
|
||||
}
|
||||
if (size <= ULONG_MAX / mul) {
|
||||
size *= mul;
|
||||
} else {
|
||||
size= ULONG_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
if (size > 1024L*1024*1024) {
|
||||
printf("mkfile: A file size over 1G is a bit too much\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Open existing file, or create a new file. */
|
||||
file= argv[2];
|
||||
if ((fd= open(file, O_WRONLY)) < 0) {
|
||||
if (errno == 2) {
|
||||
fd= creat(file, 0666);
|
||||
}
|
||||
}
|
||||
if (fd < 0) {
|
||||
printf("mkfile: Can't open %s: %s\n", file, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* How big is the file now? */
|
||||
if ((offset= lseek(fd, 0, SEEK_END)) == -1) {
|
||||
printf("mkfile: Can't seek in %s: %s\n", file, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (offset == 0 && size == 0) exit(0); /* Huh? */
|
||||
|
||||
/* Write the first bit if the file is zero length. This is necessary
|
||||
* to circumvent a DOS bug by extending a new file by lseek. We also
|
||||
* want to make sure there are zeros in the first sector.
|
||||
*/
|
||||
if (offset == 0) {
|
||||
if (write(fd, buf, sizeof(buf)) == -1) {
|
||||
printf("mkfile: Can't write to %s: %s\n",
|
||||
file, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Seek to the required size and write 0 bytes to extend/truncate the
|
||||
* file to that size.
|
||||
*/
|
||||
if (lseek(fd, size, SEEK_SET) == -1) {
|
||||
printf("mkfile: Can't seek in %s: %s\n", file, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
if (write(fd, buf, 0) == -1) {
|
||||
printf("mkfile: Can't write to %s: %s\n",
|
||||
file, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Did the file become the required size? */
|
||||
if ((offset= lseek(fd, 0, SEEK_END)) == -1) {
|
||||
printf("mkfile: Can't seek in %s: %s\n", file, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
if (offset != size) {
|
||||
printf("mkfile: Failed to extend %s. Disk full?\n", file);
|
||||
exit(1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* $PchId: mkfile.c,v 1.4 2000/08/13 22:06:40 philip Exp $
|
||||
*/
|
||||
330
boot/rawfs.c
Normal file
330
boot/rawfs.c
Normal file
@@ -0,0 +1,330 @@
|
||||
/* rawfs.c - Raw Minix file system support. Author: Kees J. Bot
|
||||
* 23 Dec 1991
|
||||
* Based on readfs by Paul Polderman
|
||||
*/
|
||||
#define _POSIX_SOURCE 1
|
||||
#define _MINIX 1
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <minix/config.h>
|
||||
#include <minix/const.h>
|
||||
#include <minix/type.h>
|
||||
#include <servers/mfs/const.h>
|
||||
#include <servers/mfs/type.h>
|
||||
#include <servers/mfs/buf.h>
|
||||
#include <servers/mfs/super.h>
|
||||
#include <servers/mfs/inode.h>
|
||||
#include "rawfs.h"
|
||||
|
||||
void readblock(off_t blockno, char *buf, int);
|
||||
|
||||
/* The following code handles two file system types: Version 1 with small
|
||||
* inodes and 16-bit disk addresses and Version 2 with big inodes and 32-bit
|
||||
* disk addresses.
|
||||
#ifdef FLEX
|
||||
* To make matters worse, Minix-vmd knows about the normal Unix Version 7
|
||||
* directories and directories with flexible entries.
|
||||
#endif
|
||||
*/
|
||||
|
||||
/* File system parameters. */
|
||||
static unsigned nr_dzones; /* Fill these in after reading superblock. */
|
||||
static unsigned nr_indirects;
|
||||
static unsigned inodes_per_block;
|
||||
static int block_size;
|
||||
#ifdef FLEX
|
||||
#include <dirent.h>
|
||||
#define direct _v7_direct
|
||||
#else
|
||||
#include <sys/dir.h>
|
||||
#endif
|
||||
|
||||
#if __minix_vmd
|
||||
static struct v12_super_block super; /* Superblock of file system */
|
||||
#define s_log_zone_size s_dummy /* Zones are obsolete. */
|
||||
#else
|
||||
static struct super_block super; /* Superblock of file system */
|
||||
#define SUPER_V1 SUPER_MAGIC /* V1 magic has a weird name. */
|
||||
#endif
|
||||
|
||||
static struct inode curfil; /* Inode of file under examination */
|
||||
static char indir[_MAX_BLOCK_SIZE]; /* Single indirect block. */
|
||||
static char dindir[_MAX_BLOCK_SIZE]; /* Double indirect block. */
|
||||
static char dirbuf[_MAX_BLOCK_SIZE]; /* Scratch/Directory block. */
|
||||
#define scratch dirbuf
|
||||
|
||||
static block_t a_indir, a_dindir; /* Addresses of the indirects. */
|
||||
static off_t dirpos; /* Reading pos in a dir. */
|
||||
|
||||
#define fsbuf(b) (* (union fsdata_u *) (b))
|
||||
|
||||
#define zone_shift (super.s_log_zone_size) /* zone to block ratio */
|
||||
|
||||
off_t r_super(int *bs)
|
||||
/* Initialize variables, return size of file system in blocks,
|
||||
* (zero on error).
|
||||
*/
|
||||
{
|
||||
/* Read superblock. (The superblock is always at 1kB offset,
|
||||
* that's why we lie to readblock and say the block size is 1024
|
||||
* and we want block number 1 (the 'second block', at offset 1kB).)
|
||||
*/
|
||||
readblock(1, scratch, 1024);
|
||||
|
||||
memcpy(&super, scratch, sizeof(super));
|
||||
|
||||
/* Is it really a MINIX file system ? */
|
||||
if (super.s_magic == SUPER_V2 || super.s_magic == SUPER_V3) {
|
||||
if(super.s_magic == SUPER_V2)
|
||||
super.s_block_size = 1024;
|
||||
*bs = block_size = super.s_block_size;
|
||||
if(block_size < _MIN_BLOCK_SIZE ||
|
||||
block_size > _MAX_BLOCK_SIZE) {
|
||||
return 0;
|
||||
}
|
||||
nr_dzones= V2_NR_DZONES;
|
||||
nr_indirects= V2_INDIRECTS(block_size);
|
||||
inodes_per_block= V2_INODES_PER_BLOCK(block_size);
|
||||
return (off_t) super.s_zones << zone_shift;
|
||||
} else
|
||||
if (super.s_magic == SUPER_V1) {
|
||||
*bs = block_size = 1024;
|
||||
nr_dzones= V1_NR_DZONES;
|
||||
nr_indirects= V1_INDIRECTS;
|
||||
inodes_per_block= V1_INODES_PER_BLOCK;
|
||||
return (off_t) super.s_nzones << zone_shift;
|
||||
} else {
|
||||
/* Filesystem not recognized as Minix. */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void r_stat(Ino_t inum, struct stat *stp)
|
||||
/* Return information about a file like stat(2) and remember it. */
|
||||
{
|
||||
block_t block;
|
||||
block_t ino_block;
|
||||
ino_t ino_offset;
|
||||
union fsdata_u *blockbuf;
|
||||
|
||||
/* Calculate start of i-list */
|
||||
block = START_BLOCK + super.s_imap_blocks + super.s_zmap_blocks;
|
||||
|
||||
/* Calculate block with inode inum */
|
||||
ino_block = ((inum - 1) / inodes_per_block);
|
||||
ino_offset = ((inum - 1) % inodes_per_block);
|
||||
block += ino_block;
|
||||
|
||||
/* Fetch the block */
|
||||
blockbuf = (union fsdata_u *) scratch;
|
||||
readblock(block, (char *) blockbuf, block_size);
|
||||
|
||||
if (super.s_magic == SUPER_V2 || super.s_magic == SUPER_V3) {
|
||||
d2_inode *dip;
|
||||
int i;
|
||||
|
||||
dip= &blockbuf->b__v2_ino[(unsigned int) ino_offset];
|
||||
|
||||
curfil.i_mode= dip->d2_mode;
|
||||
curfil.i_nlinks= dip->d2_nlinks;
|
||||
curfil.i_uid= dip->d2_uid;
|
||||
curfil.i_gid= dip->d2_gid;
|
||||
curfil.i_size= dip->d2_size;
|
||||
curfil.i_atime= dip->d2_atime;
|
||||
curfil.i_mtime= dip->d2_mtime;
|
||||
curfil.i_ctime= dip->d2_ctime;
|
||||
for (i= 0; i < V2_NR_TZONES; i++)
|
||||
curfil.i_zone[i]= dip->d2_zone[i];
|
||||
} else {
|
||||
d1_inode *dip;
|
||||
int i;
|
||||
|
||||
dip= &blockbuf->b__v1_ino[(unsigned int) ino_offset];
|
||||
|
||||
curfil.i_mode= dip->d1_mode;
|
||||
curfil.i_nlinks= dip->d1_nlinks;
|
||||
curfil.i_uid= dip->d1_uid;
|
||||
curfil.i_gid= dip->d1_gid;
|
||||
curfil.i_size= dip->d1_size;
|
||||
curfil.i_atime= dip->d1_mtime;
|
||||
curfil.i_mtime= dip->d1_mtime;
|
||||
curfil.i_ctime= dip->d1_mtime;
|
||||
for (i= 0; i < V1_NR_TZONES; i++)
|
||||
curfil.i_zone[i]= dip->d1_zone[i];
|
||||
}
|
||||
curfil.i_dev= -1; /* Can't fill this in alas. */
|
||||
curfil.i_num= inum;
|
||||
|
||||
stp->st_dev= curfil.i_dev;
|
||||
stp->st_ino= curfil.i_num;
|
||||
stp->st_mode= curfil.i_mode;
|
||||
stp->st_nlink= curfil.i_nlinks;
|
||||
stp->st_uid= curfil.i_uid;
|
||||
stp->st_gid= curfil.i_gid;
|
||||
stp->st_rdev= (dev_t) curfil.i_zone[0];
|
||||
stp->st_size= curfil.i_size;
|
||||
stp->st_atime= curfil.i_atime;
|
||||
stp->st_mtime= curfil.i_mtime;
|
||||
stp->st_ctime= curfil.i_ctime;
|
||||
|
||||
a_indir= a_dindir= 0;
|
||||
dirpos= 0;
|
||||
}
|
||||
|
||||
ino_t r_readdir(char *name)
|
||||
/* Read next directory entry at "dirpos" from file "curfil". */
|
||||
{
|
||||
ino_t inum= 0;
|
||||
int blkpos;
|
||||
struct direct *dp;
|
||||
|
||||
if (!S_ISDIR(curfil.i_mode)) { errno= ENOTDIR; return -1; }
|
||||
|
||||
if(!block_size) { errno = 0; return -1; }
|
||||
|
||||
while (inum == 0 && dirpos < curfil.i_size) {
|
||||
if ((blkpos= (int) (dirpos % block_size)) == 0) {
|
||||
/* Need to fetch a new directory block. */
|
||||
|
||||
readblock(r_vir2abs(dirpos / block_size), dirbuf, block_size);
|
||||
}
|
||||
#ifdef FLEX
|
||||
if (super.s_flags & S_FLEX) {
|
||||
struct _fl_direct *dp;
|
||||
|
||||
dp= (struct _fl_direct *) (dirbuf + blkpos);
|
||||
if ((inum= dp->d_ino) != 0) strcpy(name, dp->d_name);
|
||||
|
||||
dirpos+= (1 + dp->d_extent) * FL_DIR_ENTRY_SIZE;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
/* Let dp point to the next entry. */
|
||||
dp= (struct direct *) (dirbuf + blkpos);
|
||||
|
||||
if ((inum= dp->d_ino) != 0) {
|
||||
/* This entry is occupied, return name. */
|
||||
strncpy(name, dp->d_name, sizeof(dp->d_name));
|
||||
name[sizeof(dp->d_name)]= 0;
|
||||
}
|
||||
dirpos+= DIR_ENTRY_SIZE;
|
||||
}
|
||||
return inum;
|
||||
}
|
||||
|
||||
off_t r_vir2abs(off_t virblk)
|
||||
/* Translate a block number in a file to an absolute disk block number.
|
||||
* Returns 0 for a hole and -1 if block is past end of file.
|
||||
*/
|
||||
{
|
||||
block_t b= virblk;
|
||||
zone_t zone, ind_zone;
|
||||
block_t z, zone_index;
|
||||
int i;
|
||||
|
||||
if(!block_size) return -1;
|
||||
|
||||
/* Check if virblk within file. */
|
||||
if (virblk * block_size >= curfil.i_size) return -1;
|
||||
|
||||
/* Calculate zone in which the datablock number is contained */
|
||||
zone = (zone_t) (b >> zone_shift);
|
||||
|
||||
/* Calculate index of the block number in the zone */
|
||||
zone_index = b - ((block_t) zone << zone_shift);
|
||||
|
||||
/* Go get the zone */
|
||||
if (zone < (zone_t) nr_dzones) { /* direct block */
|
||||
zone = curfil.i_zone[(int) zone];
|
||||
z = ((block_t) zone << zone_shift) + zone_index;
|
||||
return z;
|
||||
}
|
||||
|
||||
/* The zone is not a direct one */
|
||||
zone -= (zone_t) nr_dzones;
|
||||
|
||||
/* Is it single indirect ? */
|
||||
if (zone < (zone_t) nr_indirects) { /* single indirect block */
|
||||
ind_zone = curfil.i_zone[nr_dzones];
|
||||
} else { /* double indirect block */
|
||||
/* Fetch the double indirect block */
|
||||
if ((ind_zone = curfil.i_zone[nr_dzones + 1]) == 0) return 0;
|
||||
|
||||
z = (block_t) ind_zone << zone_shift;
|
||||
if (a_dindir != z) {
|
||||
readblock(z, dindir, block_size);
|
||||
a_dindir= z;
|
||||
}
|
||||
/* Extract the indirect zone number from it */
|
||||
zone -= (zone_t) nr_indirects;
|
||||
|
||||
i = zone / (zone_t) nr_indirects;
|
||||
ind_zone = (super.s_magic == SUPER_V2 || super.s_magic == SUPER_V3)
|
||||
? fsbuf(dindir).b__v2_ind[i]
|
||||
: fsbuf(dindir).b__v1_ind[i];
|
||||
zone %= (zone_t) nr_indirects;
|
||||
}
|
||||
if (ind_zone == 0) return 0;
|
||||
|
||||
/* Extract the datablock number from the indirect zone */
|
||||
z = (block_t) ind_zone << zone_shift;
|
||||
if (a_indir != z) {
|
||||
readblock(z, indir, block_size);
|
||||
a_indir= z;
|
||||
}
|
||||
zone = (super.s_magic == SUPER_V2 || super.s_magic == SUPER_V3)
|
||||
? fsbuf(indir).b__v2_ind[(int) zone]
|
||||
: fsbuf(indir).b__v1_ind[(int) zone];
|
||||
|
||||
/* Calculate absolute datablock number */
|
||||
z = ((block_t) zone << zone_shift) + zone_index;
|
||||
return z;
|
||||
}
|
||||
|
||||
ino_t r_lookup(Ino_t cwd, const char *path)
|
||||
/* Translates a pathname to an inode number. This is just a nice utility
|
||||
* function, it only needs r_stat and r_readdir.
|
||||
*/
|
||||
{
|
||||
char name[NAME_MAX+1], r_name[NAME_MAX+1];
|
||||
char *n;
|
||||
struct stat st;
|
||||
ino_t ino;
|
||||
|
||||
ino= path[0] == '/' ? ROOT_INO : cwd;
|
||||
|
||||
for (;;) {
|
||||
if (ino == 0) {
|
||||
errno= ENOENT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (*path == '/') path++;
|
||||
|
||||
if (*path == 0) return ino;
|
||||
|
||||
r_stat(ino, &st);
|
||||
|
||||
if (!S_ISDIR(st.st_mode)) {
|
||||
errno= ENOTDIR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
n= name;
|
||||
while (*path != 0 && *path != '/')
|
||||
if (n < name + NAME_MAX) *n++ = *path++;
|
||||
*n= 0;
|
||||
|
||||
while ((ino= r_readdir(r_name)) != 0
|
||||
&& strcmp(name, r_name) != 0) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* $PchId: rawfs.c,v 1.8 1999/11/05 23:14:15 philip Exp $
|
||||
*/
|
||||
48
boot/rawfs.h
Normal file
48
boot/rawfs.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/* rawfs.h - Raw Minix file system support. Author: Kees J. Bot
|
||||
*
|
||||
* off_t r_super(int *block_size);
|
||||
* Initialize variables, returns the size of a valid Minix
|
||||
* file system blocks, but zero on error.
|
||||
*
|
||||
* void r_stat(ino_t file, struct stat *stp);
|
||||
* Return information about a file like stat(2) and
|
||||
* remembers file for the next two calls.
|
||||
*
|
||||
* off_t r_vir2abs(off_t virblockno);
|
||||
* Translate virtual block number in file to absolute
|
||||
* disk block number. Returns 0 if the file contains
|
||||
* a hole, or -1 if the block lies past the end of file.
|
||||
*
|
||||
* ino_t r_readdir(char *name);
|
||||
* Return next directory entry or 0 if there are no more.
|
||||
* Returns -1 and sets errno on error.
|
||||
*
|
||||
* ino_t r_lookup(ino_t cwd, const char *path);
|
||||
* A utility function that translates a pathname to an
|
||||
* inode number. It starts from directory "cwd" unless
|
||||
* path starts with a '/', then from ROOT_INO.
|
||||
* Returns 0 and sets errno on error.
|
||||
*
|
||||
* One function needs to be provided by the outside world:
|
||||
*
|
||||
* void readblock(off_t blockno, char *buf, int block_size);
|
||||
* Read a block into the buffer. Outside world handles
|
||||
* errors.
|
||||
*/
|
||||
|
||||
#ifndef INC_RAWFS_H
|
||||
#define INC_RAWFS_H
|
||||
|
||||
#define ROOT_INO ((ino_t) 1) /* Inode nr of root dir. */
|
||||
|
||||
extern off_t r_super(int *);
|
||||
extern void r_stat(Ino_t file, struct stat *stp);
|
||||
extern off_t r_vir2abs(off_t virblockno);
|
||||
extern ino_t r_readdir(char *name);
|
||||
extern ino_t r_lookup(Ino_t cwd, const char *path);
|
||||
|
||||
/*
|
||||
* $PchId: rawfs.h,v 1.4 1996/04/19 08:16:36 philip Exp $
|
||||
*/
|
||||
|
||||
#endif
|
||||
27
boot/updateboot.sh
Executable file
27
boot/updateboot.sh
Executable file
@@ -0,0 +1,27 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
BOOT=/boot/boot
|
||||
ROOT=`printroot -r`
|
||||
|
||||
if [ ! -b "$ROOT" ]
|
||||
then echo root device $ROOT not found
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo -n "Install boot as $BOOT on current root and patch into $ROOT? (y/N) "
|
||||
read ans
|
||||
|
||||
if [ ! "$ans" = y ]
|
||||
then echo Aborting.
|
||||
exit 1
|
||||
fi
|
||||
|
||||
make install || true
|
||||
|
||||
echo Installing boot monitor into $BOOT.
|
||||
cp boot $BOOT
|
||||
|
||||
echo Patching position of $BOOT into $ROOT.
|
||||
installboot -d "$ROOT" /usr/mdec/bootblock $BOOT
|
||||
sync
|
||||
@@ -182,7 +182,7 @@ do
|
||||
des="audio" dev=audio
|
||||
;;
|
||||
14,0)
|
||||
des="faulty block device driver" dev=fbd
|
||||
des="audio mixer" dev=mixer
|
||||
;;
|
||||
15,0)
|
||||
des="kernel log" dev=klog
|
||||
|
||||
28
commands/M/M.sh
Normal file
28
commands/M/M.sh
Normal file
@@ -0,0 +1,28 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# M, U - mount or unmount standard devices.
|
||||
|
||||
case $#:$2 in
|
||||
1:|2:-r) ;;
|
||||
*) echo "Usage: $0 <abbreviation> [-r]" >&2; exit 1
|
||||
esac
|
||||
|
||||
. /etc/fstab
|
||||
|
||||
dev=$1 dir=$1
|
||||
|
||||
case $1 in
|
||||
0) dev=/dev/fd0 dir=fd0 ;;
|
||||
1) dev=/dev/fd1 dir=fd1 ;;
|
||||
PS0|at0|fd0|pat0|pc0|ps0) dev=/dev/$dev dir=fd0 ;;
|
||||
PS1|at1|fd1|pat1|pc1|ps1) dev=/dev/$dev dir=fd1 ;;
|
||||
root) dev=$root ;;
|
||||
tmp) dev=$tmp ;;
|
||||
usr) dev=$usr ;;
|
||||
*) dev=/dev/$dev dir=mnt
|
||||
esac
|
||||
|
||||
case $0 in
|
||||
*M) mount $dev /$dir $2 ;;
|
||||
*U) umount $dev
|
||||
esac
|
||||
7
commands/M/Makefile
Normal file
7
commands/M/Makefile
Normal file
@@ -0,0 +1,7 @@
|
||||
SCRIPTS= M.sh
|
||||
BINDIR= /bin
|
||||
MAN=
|
||||
|
||||
LINKS+= ${BINDIR}/M ${BINDIR}/U
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
@@ -23,7 +23,7 @@ case $#:$1 in
|
||||
ttypa ttypb ttypc ttypd ttype ttypf \
|
||||
ttyq0 ttyq1 ttyq2 ttyq3 ttyq4 ttyq5 ttyq6 ttyq7 ttyq8 ttyq9 \
|
||||
ttyqa ttyqb ttyqc ttyqd ttyqe ttyqf \
|
||||
eth klog random uds filter fbd hello
|
||||
eth klog random uds filter hello
|
||||
;;
|
||||
0:|1:-\?)
|
||||
cat >&2 <<EOF
|
||||
@@ -49,7 +49,6 @@ Where key is one of the following:
|
||||
kbd # Make /dev/kbd
|
||||
kbdaux # Make /dev/kbdaux
|
||||
filter # Make /dev/filter
|
||||
fbd # Make /dev/fbd
|
||||
hello # Make /dev/hello
|
||||
video # Make /dev/video
|
||||
std # All standard devices
|
||||
@@ -268,11 +267,6 @@ do
|
||||
$e mknod filter b 11 0
|
||||
$e chmod 644 filter
|
||||
;;
|
||||
fbd)
|
||||
# faulty block device driver
|
||||
$e mknod fbd b 14 0
|
||||
$e chmod 600 fbd
|
||||
;;
|
||||
hello)
|
||||
# hello driver
|
||||
$e mknod hello c 17 0
|
||||
|
||||
@@ -2,43 +2,43 @@
|
||||
|
||||
.include <bsd.own.mk>
|
||||
|
||||
SUBDIR= add_route arp ash at awk \
|
||||
backup badblocks banner basename \
|
||||
btrace cal calendar \
|
||||
cat cawf cd cdprobe checkhier cpp \
|
||||
SUBDIR= aal add_route adduser advent arp ash at autil awk \
|
||||
backup badblocks banner basename bigmake binpackage \
|
||||
binpackages binsizes bzip2 bzip2recover cal calendar \
|
||||
cat cawf cd cdprobe checkhier chmem \
|
||||
chmod chown chroot ci cksum cleantmp clear cmp co \
|
||||
comm compress cp crc cron crontab cut \
|
||||
dd decomp16 DESCRIBE dev2name devsize df dhcpd \
|
||||
dhrystone diff dirname diskctl du dumpcore \
|
||||
ed eject elvis env expand factor fbdctl file \
|
||||
comm compress cp crc cron crontab cut date \
|
||||
dd de decomp16 DESCRIBE dev2name devsize df dhcpd \
|
||||
dhrystone diff dirname dis88 diskctl du dumpcore \
|
||||
ed eject elle elvis env expand factor file \
|
||||
find finger fingerd fix fold format fortune fsck.mfs \
|
||||
ftp101 gcore gcov-pull getty grep head hexdump host \
|
||||
hostaddr id ifconfig ifdef install \
|
||||
fsck1 ftp101 ftpd200 gcov-pull getty grep gomoku head hexdump host \
|
||||
hostaddr id ifconfig ifdef indent install \
|
||||
intr ipcrm ipcs irdpd isoread join kill last leave \
|
||||
less lex loadkeys loadramdisk logger login look lp \
|
||||
lpd ls lspci mail make MAKEDEV \
|
||||
mdb mesg mined mkfifo mkfs.mfs mknod \
|
||||
less lex life loadkeys loadramdisk logger login look lp \
|
||||
lpd ls lspci M m4 mail make MAKEDEV man \
|
||||
mdb mdocml mesg mined mkdep mkdir mkdist mkfifo mkfs.mfs mknod \
|
||||
mkproto modem mount mt netconf newroot nice acknm nohup \
|
||||
nonamed od paste patch pax \
|
||||
nonamed od packman passwd paste patch pax \
|
||||
ping postinstall poweroff pr prep printf printroot \
|
||||
profile progressbar proto pr_routes ps pwd pwdauth \
|
||||
ramdisk rarpd rawspeed rcp rdate readall readclock \
|
||||
reboot remsync rev rget rlogin rlogind \
|
||||
rotate rsh rshd sed service setup shar acksize \
|
||||
sleep slip sort spell split srccrc \
|
||||
stty su sum svclog swifi sync synctree sysenv \
|
||||
syslogd tail tar tcpd tcpdp tcpstat tee telnet \
|
||||
telnetd term termcap tget time touch tr \
|
||||
truncate tsort tty udpstat umount uname unexpand \
|
||||
unstack update uud uue version vol wc \
|
||||
readfs reboot remsync rev rget rlogin rlogind rmdir \
|
||||
rotate rsh rshd sed service setup shar size \
|
||||
sleep slip sort spell split srccrc stat strings ackstrip \
|
||||
stty su sum svclog swapfs swifi sync synctree sysenv \
|
||||
syslogd tail talk talkd tar tcpd tcpdp tcpstat tee telnet \
|
||||
telnetd term termcap tget time tinyhalt top touch tr \
|
||||
truncate tsort ttt tty udpstat umount uname unexpand \
|
||||
uniq unstack update urlget uud uue version vol wc \
|
||||
whereis which who write writeisofs fetch \
|
||||
xargs yacc yes zdump zmodem pkgin_cd \
|
||||
mktemp worldstone updateboot
|
||||
xargs yacc yes zdump zic zmodem pkg_install pkgin_cd
|
||||
|
||||
.if ${ARCH} == "i386"
|
||||
SUBDIR+= atnormalize dosread fdisk loadfont \
|
||||
autopart part partition playwave \
|
||||
recwave repartition screendump
|
||||
mixer autopart part partition playwave postmort \
|
||||
recwave repartition screendump padtext
|
||||
SUBDIR+= acd asmconv gas2ack
|
||||
.endif
|
||||
|
||||
.include <bsd.subdir.mk>
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
CPPFLAGS+= -D_MINIX -D_NETBSD_SOURCE -D_MINIX_COMPAT
|
||||
LDADD+= -lminlib -lcompat_minix -lasyn -lterminfo
|
||||
CPPFLAGS+= -D_MINIX -D_POSIX_SOURCE
|
||||
BINDIR?=/usr/bin
|
||||
|
||||
11
commands/aal/Makefile
Normal file
11
commands/aal/Makefile
Normal file
@@ -0,0 +1,11 @@
|
||||
# Makefile for aal
|
||||
|
||||
PROG= aal
|
||||
SRCS= archiver.c print.c rd.c rd_arhdr.c rd_unsig2.c sprint.c \
|
||||
wr_arhdr.c wr_bytes.c wr_int2.c wr_long.c wr_ranlib.c \
|
||||
format.c rd_bytes.c system.c write.c long2str.c
|
||||
CPPFLAGS+= -I${.CURDIR} -DAAL -DSTB -DNDEBUG -DDISTRIBUTION
|
||||
|
||||
MAN=
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
28
commands/aal/arch.h
Normal file
28
commands/aal/arch.h
Normal file
@@ -0,0 +1,28 @@
|
||||
/* $Header$ */
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
|
||||
#ifndef __ARCH_H_INCLUDED
|
||||
#define __ARCH_H_INCLUDED
|
||||
|
||||
#define ARMAG 0177545
|
||||
#define AALMAG 0177454
|
||||
|
||||
struct ar_hdr {
|
||||
char ar_name[14];
|
||||
long ar_date;
|
||||
char ar_uid;
|
||||
char ar_gid;
|
||||
short ar_mode;
|
||||
long ar_size;
|
||||
};
|
||||
|
||||
#define AR_TOTAL 26
|
||||
#define AR_SIZE 22
|
||||
|
||||
extern int rd_arhdr(int fd, register struct ar_hdr arhdr[]);
|
||||
extern void wr_arhdr(int fd, struct ar_hdr arhdr[]);
|
||||
|
||||
#endif /* __ARCH_H_INCLUDED */
|
||||
813
commands/aal/archiver.c
Normal file
813
commands/aal/archiver.c
Normal file
@@ -0,0 +1,813 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* ar - archiver Author: Michiel Huisjes */
|
||||
/* Made into arch/aal by Ceriel Jacobs
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "rd.h"
|
||||
#include "wr_bytes.h"
|
||||
#include "wr_long.h"
|
||||
#include "wr_int2.h"
|
||||
#include "arch.h"
|
||||
#include "archiver.h"
|
||||
#include "print.h"
|
||||
|
||||
static char RcsId[] = "$Header$";
|
||||
|
||||
/*
|
||||
* Usage: [arch|aal] [adprtvx] archive [file] ...
|
||||
* v: verbose
|
||||
* x: extract
|
||||
* a: append
|
||||
* r: replace (append when not in archive)
|
||||
* d: delete
|
||||
* t: print contents of archive
|
||||
* p: print named files
|
||||
* l: temporaries in current directory instead of /usr/tmp
|
||||
* c: don't give "create" message
|
||||
* u: replace only if dated later than member in archive
|
||||
#ifdef DISTRIBUTION
|
||||
* D: make distribution: use distr_time, uid=2, gid=2, mode=0644
|
||||
#endif
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#ifndef S_IREAD
|
||||
#define S_IREAD S_IRUSR
|
||||
#endif
|
||||
#ifndef S_IWRITE
|
||||
#define S_IWRITE S_IWUSR
|
||||
#endif
|
||||
#ifndef S_IEXEC
|
||||
#define S_IEXEC S_IXUSR
|
||||
#endif
|
||||
#include <signal.h>
|
||||
#include <arch.h>
|
||||
#ifdef AAL
|
||||
#include <ranlib.h>
|
||||
#include <out.h>
|
||||
#define MAGIC_NUMBER AALMAG
|
||||
long offset;
|
||||
struct ranlib *tab;
|
||||
unsigned int tnum = 0;
|
||||
char *tstrtab;
|
||||
unsigned int tssiz = 0;
|
||||
long time();
|
||||
unsigned int tabsz, strtabsz;
|
||||
#else
|
||||
#define MAGIC_NUMBER ARMAG
|
||||
#endif
|
||||
long lseek();
|
||||
|
||||
#define odd(nr) (nr & 01)
|
||||
#define even(nr) (odd(nr) ? nr + 1 : nr)
|
||||
|
||||
typedef char BOOL;
|
||||
#define FALSE 0
|
||||
#define TRUE 1
|
||||
|
||||
#define READ 0
|
||||
#define APPEND 2
|
||||
#define CREATE 1
|
||||
|
||||
#define MEMBER struct ar_hdr
|
||||
|
||||
#define IO_SIZE (10 * 1024)
|
||||
|
||||
#define equal(str1, str2) (!strncmp((str1), (str2), 14))
|
||||
#ifndef S_ISDIR
|
||||
#define S_ISDIR(m) (m & S_IFDIR) /* is a directory */
|
||||
#endif
|
||||
|
||||
BOOL verbose;
|
||||
BOOL app_fl;
|
||||
BOOL ex_fl;
|
||||
BOOL show_fl;
|
||||
BOOL pr_fl;
|
||||
BOOL rep_fl;
|
||||
BOOL del_fl;
|
||||
BOOL nocr_fl;
|
||||
BOOL local_fl;
|
||||
BOOL update_fl;
|
||||
#ifdef DISTRIBUTION
|
||||
BOOL distr_fl;
|
||||
long distr_time;
|
||||
#endif
|
||||
|
||||
int ar_fd;
|
||||
|
||||
char io_buffer[IO_SIZE];
|
||||
|
||||
char *progname;
|
||||
|
||||
char temp_buf[32];
|
||||
char *temp_arch = &temp_buf[0];
|
||||
extern char *mktemp();
|
||||
extern char *ctime();
|
||||
|
||||
/* Forward declarations. */
|
||||
static void enter_name(struct outname *namep);
|
||||
static void do_names(struct outhead *headp);
|
||||
static void do_object(int f, long size);
|
||||
static void show(char *s, char *name);
|
||||
static void write_symdef(void);
|
||||
static void mwrite(int fd, char *address, int bytes);
|
||||
static void extract(register MEMBER *member);
|
||||
static void copy_member(MEMBER *member, int from, int to, int extracting);
|
||||
static void add(char *name, int fd, char *mess);
|
||||
static void get(int argc, char *argv[]);
|
||||
|
||||
/*VARARGS2*/
|
||||
void error1(BOOL quit, char *str1)
|
||||
{
|
||||
fputs(str1,stderr);
|
||||
if (quit) {
|
||||
unlink(temp_arch);
|
||||
_exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void error2(BOOL quit, char *str1, char *str2)
|
||||
{
|
||||
fprintf(stderr,str1,str2);
|
||||
if (quit) {
|
||||
unlink(temp_arch);
|
||||
_exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void error3(BOOL quit, char *str1, char *str2, char *str3)
|
||||
{
|
||||
fprintf(stderr,str1,str2,str3);
|
||||
if (quit) {
|
||||
unlink(temp_arch);
|
||||
_exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void usage()
|
||||
{
|
||||
error3(TRUE, "usage: %s %s archive [file] ...\n",
|
||||
progname,
|
||||
#ifdef AAL
|
||||
"[acdrtxvlu]"
|
||||
#else
|
||||
"[acdprtxvlu]"
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
char *basename(char *path)
|
||||
{
|
||||
register char *ptr = path;
|
||||
register char *last = NULL;
|
||||
|
||||
while (*ptr != '\0') {
|
||||
if (*ptr == '/')
|
||||
last = ptr;
|
||||
ptr++;
|
||||
}
|
||||
if (last == NULL)
|
||||
return path;
|
||||
if (*(last + 1) == '\0') {
|
||||
*last = '\0';
|
||||
return basename(path);
|
||||
}
|
||||
return last + 1;
|
||||
}
|
||||
|
||||
extern unsigned int rd_unsigned2();
|
||||
|
||||
int open_archive(char *name, int mode)
|
||||
{
|
||||
unsigned short magic = 0;
|
||||
int fd;
|
||||
|
||||
if (mode == CREATE) {
|
||||
if ((fd = creat(name, 0666)) < 0)
|
||||
error2(TRUE, "cannot creat %s\n", name);
|
||||
magic = MAGIC_NUMBER;
|
||||
wr_int2(fd, magic);
|
||||
return fd;
|
||||
}
|
||||
|
||||
if ((fd = open(name, mode)) < 0) {
|
||||
if (mode == APPEND) {
|
||||
close(open_archive(name, CREATE));
|
||||
if (!nocr_fl) error3(FALSE, "%s: creating %s\n", progname, name);
|
||||
return open_archive(name, APPEND);
|
||||
}
|
||||
error2(TRUE, "cannot open %s\n", name);
|
||||
}
|
||||
lseek(fd, 0L, 0);
|
||||
magic = rd_unsigned2(fd);
|
||||
if (magic != AALMAG && magic != ARMAG)
|
||||
error2(TRUE, "%s is not in ar format\n", name);
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
#if __STDC__
|
||||
void catch(int sig)
|
||||
#else
|
||||
catch()
|
||||
#endif
|
||||
{
|
||||
unlink(temp_arch);
|
||||
_exit (2);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
register char *ptr;
|
||||
int needs_arg = 0;
|
||||
|
||||
progname = argv[0];
|
||||
|
||||
if (argc < 3)
|
||||
usage();
|
||||
|
||||
for (ptr = argv[1]; *ptr; ptr++) {
|
||||
switch (*ptr) {
|
||||
case 't' :
|
||||
show_fl = TRUE;
|
||||
break;
|
||||
case 'v' :
|
||||
verbose = TRUE;
|
||||
break;
|
||||
case 'x' :
|
||||
ex_fl = TRUE;
|
||||
break;
|
||||
case 'a' :
|
||||
needs_arg = 1;
|
||||
app_fl = TRUE;
|
||||
break;
|
||||
case 'c' :
|
||||
nocr_fl = TRUE;
|
||||
break;
|
||||
#ifndef AAL
|
||||
case 'p' :
|
||||
needs_arg = 1;
|
||||
pr_fl = TRUE;
|
||||
break;
|
||||
#endif
|
||||
case 'd' :
|
||||
needs_arg = 1;
|
||||
del_fl = TRUE;
|
||||
break;
|
||||
case 'r' :
|
||||
needs_arg = 1;
|
||||
rep_fl = TRUE;
|
||||
break;
|
||||
case 'l' :
|
||||
local_fl = TRUE;
|
||||
break;
|
||||
case 'u' :
|
||||
update_fl = TRUE;
|
||||
break;
|
||||
#ifdef DISTRIBUTION
|
||||
case 'D' :
|
||||
distr_fl = TRUE;
|
||||
break;
|
||||
#endif
|
||||
default :
|
||||
usage();
|
||||
}
|
||||
}
|
||||
|
||||
if (needs_arg && argc <= 3)
|
||||
usage();
|
||||
#ifdef DISTRIBUTION
|
||||
if (distr_fl) {
|
||||
struct stat statbuf;
|
||||
|
||||
stat(progname, &statbuf);
|
||||
distr_time = statbuf.st_mtime;
|
||||
}
|
||||
#endif
|
||||
if (local_fl) strcpy(temp_arch, "ar.XXXXXX");
|
||||
else strcpy(temp_arch, "/usr/tmp/ar.XXXXXX");
|
||||
|
||||
if (app_fl + ex_fl + del_fl + rep_fl + show_fl + pr_fl != 1)
|
||||
usage();
|
||||
|
||||
if (update_fl && !rep_fl)
|
||||
usage();
|
||||
|
||||
if (rep_fl || del_fl
|
||||
#ifdef AAL
|
||||
|| app_fl
|
||||
#endif
|
||||
) {
|
||||
mktemp(temp_arch);
|
||||
}
|
||||
#ifdef AAL
|
||||
tab = (struct ranlib *) malloc(512 * sizeof(struct ranlib));
|
||||
tstrtab = malloc(4096);
|
||||
if (!tab || !tstrtab) error1(TRUE,"Out of core\n");
|
||||
tabsz = 512;
|
||||
strtabsz = 4096;
|
||||
#endif
|
||||
|
||||
signal(SIGINT, catch);
|
||||
get(argc, argv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
MEMBER *
|
||||
get_member()
|
||||
{
|
||||
static MEMBER member;
|
||||
|
||||
again:
|
||||
if (rd_arhdr(ar_fd, &member) == 0)
|
||||
return NULL;
|
||||
if (member.ar_size < 0) {
|
||||
error1(TRUE, "archive has member with negative size\n");
|
||||
}
|
||||
#ifdef AAL
|
||||
if (equal(SYMDEF, member.ar_name)) {
|
||||
lseek(ar_fd, member.ar_size, 1);
|
||||
goto again;
|
||||
}
|
||||
#endif
|
||||
return &member;
|
||||
}
|
||||
|
||||
char *get_mode();
|
||||
|
||||
static void get(int argc, char *argv[])
|
||||
{
|
||||
register MEMBER *member;
|
||||
int i = 0;
|
||||
int temp_fd, read_chars;
|
||||
|
||||
ar_fd = open_archive(argv[2], (show_fl || pr_fl || ex_fl) ? READ : APPEND);
|
||||
if (rep_fl || del_fl
|
||||
#ifdef AAL
|
||||
|| app_fl
|
||||
#endif
|
||||
)
|
||||
temp_fd = open_archive(temp_arch, CREATE);
|
||||
while ((member = get_member()) != NULL) {
|
||||
if (argc > 3) {
|
||||
for (i = 3; i < argc; i++) {
|
||||
if (equal(basename(argv[i]), member->ar_name))
|
||||
break;
|
||||
}
|
||||
if (i == argc || app_fl) {
|
||||
if (rep_fl || del_fl
|
||||
#ifdef AAL
|
||||
|| app_fl
|
||||
#endif
|
||||
) {
|
||||
#ifdef AAL
|
||||
if (i != argc) {
|
||||
print("%s: already in archive\n", argv[i]);
|
||||
argv[i] = "";
|
||||
}
|
||||
#endif
|
||||
wr_arhdr(temp_fd, member);
|
||||
copy_member(member, ar_fd, temp_fd, 0);
|
||||
}
|
||||
else {
|
||||
#ifndef AAL
|
||||
if (app_fl && i != argc) {
|
||||
print("%s: already in archive\n", argv[i]);
|
||||
argv[i] = "";
|
||||
}
|
||||
#endif
|
||||
lseek(ar_fd, even(member->ar_size),1);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (ex_fl || pr_fl)
|
||||
extract(member);
|
||||
else {
|
||||
if (rep_fl) {
|
||||
int isold = 0;
|
||||
if(update_fl) {
|
||||
struct stat status;
|
||||
if (stat(argv[i], &status) >= 0) {
|
||||
if(status.st_mtime <= member->ar_date)
|
||||
isold = 1;
|
||||
}
|
||||
}
|
||||
if(!isold)
|
||||
add(argv[i], temp_fd, "r - %s\n");
|
||||
else {
|
||||
wr_arhdr(temp_fd, member);
|
||||
copy_member(member, ar_fd, temp_fd, 0);
|
||||
if(verbose)
|
||||
show("r - %s (old)\n", member->ar_name);
|
||||
}
|
||||
}
|
||||
else if (show_fl) {
|
||||
char buf[sizeof(member->ar_name) + 2];
|
||||
register char *p = buf, *q = member->ar_name;
|
||||
|
||||
while (q <= &member->ar_name[sizeof(member->ar_name)-1] && *q) {
|
||||
*p++ = *q++;
|
||||
}
|
||||
*p++ = '\n';
|
||||
*p = '\0';
|
||||
if (verbose) {
|
||||
char *mode = get_mode(member->ar_mode);
|
||||
char *date = ctime(&(member->ar_date));
|
||||
|
||||
*(date + 16) = '\0';
|
||||
*(date + 24) = '\0';
|
||||
|
||||
print("%s%3u/%u%7ld %s %s %s",
|
||||
mode,
|
||||
(unsigned) (member->ar_uid & 0377),
|
||||
(unsigned) (member->ar_gid & 0377),
|
||||
member->ar_size,
|
||||
date+4,
|
||||
date+20,
|
||||
buf);
|
||||
}
|
||||
else print(buf);
|
||||
}
|
||||
else if (del_fl)
|
||||
show("d - %s\n", member->ar_name);
|
||||
lseek(ar_fd, even(member->ar_size), 1);
|
||||
}
|
||||
argv[i] = "";
|
||||
}
|
||||
|
||||
if (argc > 3) {
|
||||
for (i = 3; i < argc; i++)
|
||||
if (argv[i][0] != '\0') {
|
||||
#ifndef AAL
|
||||
if (app_fl)
|
||||
add(argv[i], ar_fd, "a - %s\n");
|
||||
else
|
||||
#endif
|
||||
if (rep_fl
|
||||
#ifdef AAL
|
||||
|| app_fl
|
||||
#endif
|
||||
)
|
||||
add(argv[i], temp_fd, "a - %s\n");
|
||||
else {
|
||||
print("%s: not found\n", argv[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (rep_fl || del_fl
|
||||
#ifdef AAL
|
||||
|| app_fl
|
||||
#endif
|
||||
) {
|
||||
signal(SIGINT, SIG_IGN);
|
||||
close(ar_fd);
|
||||
close(temp_fd);
|
||||
ar_fd = open_archive(argv[2], CREATE);
|
||||
temp_fd = open_archive(temp_arch, APPEND);
|
||||
#ifdef AAL
|
||||
write_symdef();
|
||||
#endif
|
||||
while ((read_chars = read(temp_fd, io_buffer, IO_SIZE)) > 0)
|
||||
mwrite(ar_fd, io_buffer, read_chars);
|
||||
close(temp_fd);
|
||||
unlink(temp_arch);
|
||||
}
|
||||
close(ar_fd);
|
||||
}
|
||||
|
||||
static void add(char *name, int fd, char *mess)
|
||||
{
|
||||
static MEMBER member;
|
||||
register int read_chars;
|
||||
struct stat status;
|
||||
int src_fd;
|
||||
|
||||
if (stat(name, &status) < 0) {
|
||||
error2(FALSE, "cannot find %s\n", name);
|
||||
return;
|
||||
}
|
||||
else if (S_ISDIR(status.st_mode)) {
|
||||
error2(FALSE, "%s is a directory (ignored)\n", name);
|
||||
return;
|
||||
}
|
||||
else if ((src_fd = open(name, 0)) < 0) {
|
||||
error2(FALSE, "cannot open %s\n", name);
|
||||
return;
|
||||
}
|
||||
|
||||
strncpy (member.ar_name, basename (name), sizeof(member.ar_name));
|
||||
member.ar_uid = status.st_uid;
|
||||
member.ar_gid = status.st_gid;
|
||||
member.ar_mode = status.st_mode;
|
||||
member.ar_date = status.st_mtime;
|
||||
member.ar_size = status.st_size;
|
||||
#ifdef DISTRIBUTION
|
||||
if (distr_fl) {
|
||||
member.ar_uid = 2;
|
||||
member.ar_gid = 2;
|
||||
member.ar_mode = 0644;
|
||||
member.ar_date = distr_time;
|
||||
}
|
||||
#endif
|
||||
wr_arhdr(fd, &member);
|
||||
#ifdef AAL
|
||||
do_object(src_fd, member.ar_size);
|
||||
lseek(src_fd, 0L, 0);
|
||||
offset += AR_TOTAL + even(member.ar_size);
|
||||
#endif
|
||||
while (status.st_size > 0) {
|
||||
int x = IO_SIZE;
|
||||
|
||||
read_chars = x;
|
||||
if (status.st_size < x) {
|
||||
x = status.st_size;
|
||||
read_chars = x;
|
||||
status.st_size = 0;
|
||||
x = even(x);
|
||||
}
|
||||
else status.st_size -= x;
|
||||
if (read(src_fd, io_buffer, read_chars) != read_chars) {
|
||||
error2(FALSE,"%s seems to shrink\n", name);
|
||||
break;
|
||||
}
|
||||
mwrite(fd, io_buffer, x);
|
||||
}
|
||||
|
||||
if (verbose)
|
||||
show(mess, member.ar_name);
|
||||
close(src_fd);
|
||||
}
|
||||
|
||||
static void extract(register MEMBER *member)
|
||||
{
|
||||
int fd = 1;
|
||||
char buf[sizeof(member->ar_name) + 1];
|
||||
|
||||
strncpy(buf, member->ar_name, sizeof(member->ar_name));
|
||||
buf[sizeof(member->ar_name)] = 0;
|
||||
if (pr_fl == FALSE && (fd = creat(buf, 0666)) < 0) {
|
||||
error2(FALSE, "cannot create %s\n", buf);
|
||||
fd = -1;
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
if (pr_fl == FALSE) show("x - %s\n", buf);
|
||||
else show("\n<%s>\n\n", buf);
|
||||
}
|
||||
|
||||
copy_member(member, ar_fd, fd, 1);
|
||||
|
||||
if (fd >= 0 && fd != 1)
|
||||
close(fd);
|
||||
if (pr_fl == FALSE) chmod(buf, member->ar_mode);
|
||||
}
|
||||
|
||||
static void copy_member(MEMBER *member, int from, int to, int extracting)
|
||||
{
|
||||
register int rest;
|
||||
long mem_size = member->ar_size;
|
||||
BOOL is_odd = odd(mem_size) ? TRUE : FALSE;
|
||||
|
||||
#ifdef AAL
|
||||
if (! extracting) {
|
||||
long pos = lseek(from, 0L, 1);
|
||||
|
||||
do_object(from, mem_size);
|
||||
offset += AR_TOTAL + even(mem_size);
|
||||
lseek(from, pos, 0);
|
||||
}
|
||||
#endif
|
||||
do {
|
||||
rest = mem_size > (long) IO_SIZE ? IO_SIZE : (int) mem_size;
|
||||
if (read(from, io_buffer, rest) != rest) {
|
||||
char buf[sizeof(member->ar_name) + 1];
|
||||
|
||||
strncpy(buf, member->ar_name, sizeof(member->ar_name));
|
||||
buf[sizeof(member->ar_name)] = 0;
|
||||
error2(TRUE, "read error on %s\n", buf);
|
||||
}
|
||||
if (to >= 0) mwrite(to, io_buffer, rest);
|
||||
mem_size -= (long) rest;
|
||||
} while (mem_size > 0L);
|
||||
|
||||
if (is_odd) {
|
||||
lseek(from, 1L, 1);
|
||||
if (to >= 0 && ! extracting)
|
||||
lseek(to, 1L, 1);
|
||||
}
|
||||
}
|
||||
|
||||
char *
|
||||
get_mode(mode)
|
||||
register int mode;
|
||||
{
|
||||
static char mode_buf[11];
|
||||
register int tmp = mode;
|
||||
int i;
|
||||
|
||||
mode_buf[9] = ' ';
|
||||
for (i = 0; i < 3; i++) {
|
||||
mode_buf[i * 3] = (tmp & S_IREAD) ? 'r' : '-';
|
||||
mode_buf[i * 3 + 1] = (tmp & S_IWRITE) ? 'w' : '-';
|
||||
mode_buf[i * 3 + 2] = (tmp & S_IEXEC) ? 'x' : '-';
|
||||
tmp <<= 3;
|
||||
}
|
||||
if (mode & S_ISUID)
|
||||
mode_buf[2] = 's';
|
||||
if (mode & S_ISGID)
|
||||
mode_buf[5] = 's';
|
||||
return mode_buf;
|
||||
}
|
||||
|
||||
void wr_fatal()
|
||||
{
|
||||
error1(TRUE, "write error\n");
|
||||
}
|
||||
|
||||
void rd_fatal()
|
||||
{
|
||||
error1(TRUE, "read error\n");
|
||||
}
|
||||
|
||||
static void mwrite(int fd, char *address, int bytes)
|
||||
{
|
||||
if (write(fd, address, bytes) != bytes)
|
||||
error1(TRUE, "write error\n");
|
||||
}
|
||||
|
||||
static void show(char *s, char *name)
|
||||
{
|
||||
MEMBER x;
|
||||
char buf[sizeof(x.ar_name)+1];
|
||||
register char *p = buf, *q = name;
|
||||
|
||||
while (q <= &name[sizeof(x.ar_name)-1] && *q) *p++ = *q++;
|
||||
*p++ = '\0';
|
||||
print(s, buf);
|
||||
}
|
||||
|
||||
#ifdef AAL
|
||||
/*
|
||||
* Write out the ranlib table: first 4 bytes telling how many ranlib structs
|
||||
* there are, followed by the ranlib structs,
|
||||
* then 4 bytes giving the size of the string table, followed by the string
|
||||
* table itself.
|
||||
*/
|
||||
static void write_symdef(void)
|
||||
{
|
||||
register struct ranlib *ran;
|
||||
register int i;
|
||||
register long delta;
|
||||
MEMBER arbuf;
|
||||
|
||||
if (odd(tssiz))
|
||||
tstrtab[tssiz++] = '\0';
|
||||
for (i = 0; i < sizeof(arbuf.ar_name); i++)
|
||||
arbuf.ar_name[i] = '\0';
|
||||
strcpy(arbuf.ar_name, SYMDEF);
|
||||
arbuf.ar_size = 4 + 2 * 4 * (long)tnum + 4 + (long)tssiz;
|
||||
time(&arbuf.ar_date);
|
||||
arbuf.ar_uid = getuid();
|
||||
arbuf.ar_gid = getgid();
|
||||
arbuf.ar_mode = 0444;
|
||||
#ifdef DISTRIBUTION
|
||||
if (distr_fl) {
|
||||
arbuf.ar_uid = 2;
|
||||
arbuf.ar_gid = 2;
|
||||
arbuf.ar_date = distr_time;
|
||||
}
|
||||
#endif
|
||||
wr_arhdr(ar_fd,&arbuf);
|
||||
wr_long(ar_fd, (long) tnum);
|
||||
/*
|
||||
* Account for the space occupied by the magic number
|
||||
* and the ranlib table.
|
||||
*/
|
||||
delta = 2 + AR_TOTAL + arbuf.ar_size;
|
||||
for (ran = tab; ran < &tab[tnum]; ran++) {
|
||||
ran->ran_pos += delta;
|
||||
}
|
||||
|
||||
wr_ranlib(ar_fd, tab, (long) tnum);
|
||||
wr_long(ar_fd, (long) tssiz);
|
||||
wr_bytes(ar_fd, tstrtab, (long) tssiz);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return whether the bytes in `buf' form a good object header.
|
||||
* The header is put in `headp'.
|
||||
*/
|
||||
int
|
||||
is_outhead(register struct outhead *headp)
|
||||
{
|
||||
return !BADMAGIC(*headp) && headp->oh_nname != 0;
|
||||
}
|
||||
|
||||
static void do_object(int f, long size)
|
||||
{
|
||||
struct outhead headbuf;
|
||||
|
||||
if (size < SZ_HEAD) {
|
||||
/* It can't be an object file. */
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* Read a header to see if it is an object file.
|
||||
*/
|
||||
if (! rd_fdopen(f)) {
|
||||
rd_fatal();
|
||||
}
|
||||
rd_ohead(&headbuf);
|
||||
if (!is_outhead(&headbuf)) {
|
||||
return;
|
||||
}
|
||||
do_names(&headbuf);
|
||||
}
|
||||
|
||||
/*
|
||||
* First skip the names and read in the string table, then seek back to the
|
||||
* name table and read and write the names one by one. Update the ranlib table
|
||||
* accordingly.
|
||||
*/
|
||||
static void do_names(struct outhead *headp)
|
||||
{
|
||||
register char *strings;
|
||||
register int nnames = headp->oh_nname;
|
||||
#define NNAMES 100
|
||||
struct outname namebuf[NNAMES];
|
||||
long xxx = OFF_CHAR(*headp);
|
||||
|
||||
if ( headp->oh_nchar != (unsigned int)headp->oh_nchar ||
|
||||
(strings = malloc((unsigned int)headp->oh_nchar)) == (char *)0
|
||||
) {
|
||||
error1(TRUE, "string table too big\n");
|
||||
}
|
||||
rd_string(strings, headp->oh_nchar);
|
||||
while (nnames) {
|
||||
int i = nnames >= NNAMES ? NNAMES : nnames;
|
||||
register struct outname *p = namebuf;
|
||||
|
||||
nnames -= i;
|
||||
rd_name(namebuf, i);
|
||||
while (i--) {
|
||||
long off = p->on_foff - xxx;
|
||||
if (p->on_foff == (long)0) {
|
||||
p++;
|
||||
continue; /* An unrecognizable name. */
|
||||
}
|
||||
p->on_mptr = strings + off;
|
||||
/*
|
||||
* Only enter names that are exported and are really
|
||||
* defined. Also enter common names. Note, that
|
||||
* this might cause problems when the name is really
|
||||
* defined in a later file, with a value != 0.
|
||||
* However, this problem also exists on the Unix
|
||||
* ranlib archives.
|
||||
*/
|
||||
if ( (p->on_type & S_EXT) &&
|
||||
(p->on_type & S_TYP) != S_UND
|
||||
)
|
||||
enter_name(p);
|
||||
p++;
|
||||
}
|
||||
}
|
||||
free(strings);
|
||||
}
|
||||
|
||||
static void enter_name(struct outname *namep)
|
||||
{
|
||||
register char *cp;
|
||||
|
||||
if (tnum >= tabsz) {
|
||||
tab = (struct ranlib *)
|
||||
realloc((char *) tab, (tabsz += 512) * sizeof(struct ranlib));
|
||||
if (! tab) error1(TRUE, "Out of core\n");
|
||||
}
|
||||
tab[tnum].ran_off = tssiz;
|
||||
tab[tnum].ran_pos = offset;
|
||||
|
||||
for (cp = namep->on_mptr;; cp++) {
|
||||
if (tssiz >= strtabsz) {
|
||||
tstrtab = realloc(tstrtab, (strtabsz += 4096));
|
||||
if (! tstrtab) error1(TRUE, "string table overflow\n");
|
||||
}
|
||||
tstrtab[tssiz++] = *cp;
|
||||
if (!*cp) break;
|
||||
}
|
||||
tnum++;
|
||||
}
|
||||
#endif /* AAL */
|
||||
3
commands/aal/archiver.h
Normal file
3
commands/aal/archiver.h
Normal file
@@ -0,0 +1,3 @@
|
||||
|
||||
extern void rd_fatal();
|
||||
extern void wr_fatal();
|
||||
9
commands/aal/byte_order.h
Normal file
9
commands/aal/byte_order.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#if defined(mc68020) || defined(mc68000) || defined(sparc)
|
||||
#define BYTES_REVERSED 1
|
||||
#define WORDS_REVERSED 1
|
||||
#define CHAR_UNSIGNED 0
|
||||
#else
|
||||
#define BYTES_REVERSED 0
|
||||
#define WORDS_REVERSED 0
|
||||
#define CHAR_UNSIGNED 0
|
||||
#endif
|
||||
112
commands/aal/format.c
Normal file
112
commands/aal/format.c
Normal file
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* $Header$ */
|
||||
|
||||
#if __STDC__
|
||||
#include <stdarg.h>
|
||||
#else
|
||||
#include <varargs.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
|
||||
extern char *long2str();
|
||||
|
||||
static int
|
||||
integral(int c)
|
||||
{
|
||||
switch (c) {
|
||||
case 'b':
|
||||
return -2;
|
||||
case 'd':
|
||||
return 10;
|
||||
case 'o':
|
||||
return -8;
|
||||
case 'u':
|
||||
return -10;
|
||||
case 'x':
|
||||
return -16;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*VARARGS2*/
|
||||
/*FORMAT1 $
|
||||
%s = char *
|
||||
%l = long
|
||||
%c = int
|
||||
%[uxbo] = unsigned int
|
||||
%d = int
|
||||
$ */
|
||||
int
|
||||
_format(char *buf, char *fmt, va_list argp)
|
||||
{
|
||||
register char *pf = fmt;
|
||||
register char *pb = buf;
|
||||
|
||||
while (*pf) {
|
||||
if (*pf == '%') {
|
||||
register int width, base, pad, npad;
|
||||
char *arg;
|
||||
char cbuf[2];
|
||||
char *badformat = "<bad format>";
|
||||
|
||||
/* get padder */
|
||||
if (*++pf == '0') {
|
||||
pad = '0';
|
||||
++pf;
|
||||
}
|
||||
else
|
||||
pad = ' ';
|
||||
|
||||
/* get width */
|
||||
width = 0;
|
||||
while (*pf >= '0' && *pf <= '9')
|
||||
width = 10 * width + *pf++ - '0';
|
||||
|
||||
if (*pf == 's') {
|
||||
arg = va_arg(argp, char *);
|
||||
}
|
||||
else
|
||||
if (*pf == 'c') {
|
||||
cbuf[0] = va_arg(argp, int);
|
||||
cbuf[1] = '\0';
|
||||
arg = &cbuf[0];
|
||||
}
|
||||
else
|
||||
if (*pf == 'l') {
|
||||
/* alignment ??? */
|
||||
base = integral(*++pf);
|
||||
if (base) {
|
||||
arg = long2str(va_arg(argp,long), base);
|
||||
}
|
||||
else {
|
||||
pf--;
|
||||
arg = badformat;
|
||||
}
|
||||
}
|
||||
else
|
||||
if ((base = integral(*pf))) {
|
||||
arg = long2str((long)va_arg(argp,int), base);
|
||||
}
|
||||
else
|
||||
if (*pf == '%')
|
||||
arg = "%";
|
||||
else
|
||||
arg = badformat;
|
||||
|
||||
npad = width - strlen(arg);
|
||||
|
||||
while (npad-- > 0)
|
||||
*pb++ = pad;
|
||||
|
||||
while (*pb++ = *arg++);
|
||||
pb--;
|
||||
pf++;
|
||||
}
|
||||
else
|
||||
*pb++ = *pf++;
|
||||
}
|
||||
return pb - buf;
|
||||
}
|
||||
2
commands/aal/format.h
Normal file
2
commands/aal/format.h
Normal file
@@ -0,0 +1,2 @@
|
||||
|
||||
extern int _format(char *buf, char *fmt, va_list argp);
|
||||
19
commands/aal/local.h
Normal file
19
commands/aal/local.h
Normal file
@@ -0,0 +1,19 @@
|
||||
/* $Header$ */
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* collection of options, selected by including or excluding 'defines' */
|
||||
|
||||
/* Version number of the EM object code */
|
||||
# define VERSION 3 /* 16 bits number */
|
||||
|
||||
/* The default machine used by ack, acc, apc */
|
||||
# define ACKM "minix"
|
||||
|
||||
/* size of local machine, either 0 (for 16 bit address space), or 1 */
|
||||
# undef BIGMACHINE
|
||||
|
||||
/* operating system, SYS_5, V7, BSD4_1 or BSD4_2; Do NOT delete the comment
|
||||
in the next line! */
|
||||
# define V7 1 /* SYSTEM */
|
||||
67
commands/aal/long2str.c
Normal file
67
commands/aal/long2str.c
Normal file
@@ -0,0 +1,67 @@
|
||||
/* $Header$ */
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* Integer to String translator
|
||||
-> base is a value from [-16,-2] V [2,16]
|
||||
-> base < 0: see 'val' as unsigned value
|
||||
-> no checks for buffer overflow and illegal parameters
|
||||
(1985, EHB)
|
||||
*/
|
||||
|
||||
#define MAXWIDTH 32
|
||||
|
||||
char *
|
||||
long2str(val, base)
|
||||
register long val;
|
||||
register int base;
|
||||
{
|
||||
static char numbuf[MAXWIDTH];
|
||||
static char vec[] = "0123456789ABCDEF";
|
||||
register char *p = &numbuf[MAXWIDTH];
|
||||
int sign = (base > 0);
|
||||
|
||||
*--p = '\0'; /* null-terminate string */
|
||||
if (val) {
|
||||
if (base > 0) {
|
||||
if (val < 0L) {
|
||||
long v1 = -val;
|
||||
if (v1 == val)
|
||||
goto overflow;
|
||||
val = v1;
|
||||
}
|
||||
else
|
||||
sign = 0;
|
||||
}
|
||||
else
|
||||
if (base < 0) { /* unsigned */
|
||||
base = -base;
|
||||
if (val < 0L) { /* taken from Amoeba src */
|
||||
register int mod, i;
|
||||
overflow:
|
||||
mod = 0;
|
||||
for (i = 0; i < 8 * sizeof val; i++) {
|
||||
mod <<= 1;
|
||||
if (val < 0)
|
||||
mod++;
|
||||
val <<= 1;
|
||||
if (mod >= base) {
|
||||
mod -= base;
|
||||
val++;
|
||||
}
|
||||
}
|
||||
*--p = vec[mod];
|
||||
}
|
||||
}
|
||||
do {
|
||||
*--p = vec[(int) (val % base)];
|
||||
val /= base;
|
||||
} while (val != 0L);
|
||||
if (sign)
|
||||
*--p = '-'; /* don't forget it !! */
|
||||
}
|
||||
else
|
||||
*--p = '0'; /* just a simple 0 */
|
||||
return p;
|
||||
}
|
||||
76
commands/aal/object.h
Normal file
76
commands/aal/object.h
Normal file
@@ -0,0 +1,76 @@
|
||||
/* $Header$ */
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
#include "byte_order.h"
|
||||
#include <local.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#if CHAR_UNSIGNED
|
||||
#define Xchar(ch) (ch)
|
||||
#else
|
||||
#define Xchar(ch) ((ch) & 0377)
|
||||
#endif
|
||||
|
||||
#if ! defined(BYTES_REVERSED)
|
||||
#define BYTES_REVERSED 1
|
||||
#endif
|
||||
|
||||
#if ! defined(WORDS_REVERSED)
|
||||
#define WORDS_REVERSED 1
|
||||
#endif
|
||||
|
||||
#if BYTES_REVERSED
|
||||
#define uget2(c) (Xchar((c)[0]) | ((unsigned) Xchar((c)[1]) << 8))
|
||||
#define Xput2(i, c) (((c)[0] = (i)), ((c)[1] = (i) >> 8))
|
||||
#define put2(i, c) { register int j = (i); Xput2(j, c); }
|
||||
#else
|
||||
#define uget2(c) (* ((unsigned short *) (c)))
|
||||
#define Xput2(i, c) (* ((short *) (c)) = (i))
|
||||
#define put2(i, c) Xput2(i, c)
|
||||
#endif
|
||||
|
||||
#define get2(c) ((short) uget2(c))
|
||||
|
||||
#if WORDS_REVERSED || BYTES_REVERSED
|
||||
#define get4(c) (uget2(c) | ((long) uget2((c)+2) << 16))
|
||||
#define put4(l, c) { register long x=(l); \
|
||||
Xput2((int)x,c); \
|
||||
Xput2((int)(x>>16),(c)+2); \
|
||||
}
|
||||
#else
|
||||
#define get4(c) (* ((long *) (c)))
|
||||
#define put4(l, c) (* ((long *) (c)) = (l))
|
||||
#endif
|
||||
|
||||
#define SECTCNT 3 /* number of sections with own output buffer */
|
||||
#if BIGMACHINE
|
||||
#define WBUFSIZ (8*BUFSIZ)
|
||||
#else
|
||||
#define WBUFSIZ BUFSIZ
|
||||
#endif
|
||||
|
||||
struct fil {
|
||||
int cnt;
|
||||
char *pnow;
|
||||
char *pbegin;
|
||||
long currpos;
|
||||
int fd;
|
||||
char pbuf[WBUFSIZ];
|
||||
};
|
||||
|
||||
extern struct fil __parts[];
|
||||
|
||||
#define PARTEMIT 0
|
||||
#define PARTRELO (PARTEMIT+SECTCNT)
|
||||
#define PARTNAME (PARTRELO+1)
|
||||
#define PARTCHAR (PARTNAME+1)
|
||||
#ifdef SYMDBUG
|
||||
#define PARTDBUG (PARTCHAR+1)
|
||||
#else
|
||||
#define PARTDBUG (PARTCHAR+0)
|
||||
#endif
|
||||
#define NPARTS (PARTDBUG + 1)
|
||||
|
||||
#define getsect(s) (PARTEMIT+((s)>=(SECTCNT-1)?(SECTCNT-1):(s)))
|
||||
126
commands/aal/out.h
Normal file
126
commands/aal/out.h
Normal file
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* $Header$ */
|
||||
|
||||
#ifndef __OUT_H_INCLUDED
|
||||
#define __OUT_H_INCLUDED
|
||||
/*
|
||||
* output format for ACK assemblers
|
||||
*/
|
||||
#ifndef ushort
|
||||
#define ushort unsigned short
|
||||
#endif /* ushort */
|
||||
|
||||
struct outhead {
|
||||
ushort oh_magic; /* magic number */
|
||||
ushort oh_stamp; /* version stamp */
|
||||
ushort oh_flags; /* several format flags */
|
||||
ushort oh_nsect; /* number of outsect structures */
|
||||
ushort oh_nrelo; /* number of outrelo structures */
|
||||
ushort oh_nname; /* number of outname structures */
|
||||
long oh_nemit; /* sum of all os_flen */
|
||||
long oh_nchar; /* size of string area */
|
||||
};
|
||||
|
||||
#define O_MAGIC 0x0201 /* magic number of output file */
|
||||
#define O_STAMP 0 /* version stamp */
|
||||
#define MAXSECT 64 /* Maximum number of sections */
|
||||
|
||||
#define HF_LINK 0x0004 /* unresolved references left */
|
||||
#define HF_8086 0x0008 /* os_base specially encoded */
|
||||
|
||||
struct outsect {
|
||||
long os_base; /* startaddress in machine */
|
||||
long os_size; /* section size in machine */
|
||||
long os_foff; /* startaddress in file */
|
||||
long os_flen; /* section size in file */
|
||||
long os_lign; /* section alignment */
|
||||
};
|
||||
|
||||
struct outrelo {
|
||||
char or_type; /* type of reference */
|
||||
char or_sect; /* referencing section */
|
||||
ushort or_nami; /* referenced symbol index */
|
||||
long or_addr; /* referencing address */
|
||||
};
|
||||
|
||||
struct outname {
|
||||
union {
|
||||
char *on_ptr; /* symbol name (in core) */
|
||||
long on_off; /* symbol name (in file) */
|
||||
} on_u;
|
||||
#define on_mptr on_u.on_ptr
|
||||
#define on_foff on_u.on_off
|
||||
ushort on_type; /* symbol type */
|
||||
ushort on_desc; /* debug info */
|
||||
long on_valu; /* symbol value */
|
||||
};
|
||||
|
||||
/*
|
||||
* relocation type bits
|
||||
*/
|
||||
#define RELSZ 0x07 /* relocation length */
|
||||
#define RELO1 1 /* 1 byte */
|
||||
#define RELO2 2 /* 2 bytes */
|
||||
#define RELO4 4 /* 4 bytes */
|
||||
#define RELPC 0x08 /* pc relative */
|
||||
#define RELBR 0x10 /* High order byte lowest address. */
|
||||
#define RELWR 0x20 /* High order word lowest address. */
|
||||
|
||||
/*
|
||||
* section type bits and fields
|
||||
*/
|
||||
#define S_TYP 0x007F /* undefined, absolute or relative */
|
||||
#define S_EXT 0x0080 /* external flag */
|
||||
#define S_ETC 0x7F00 /* for symbolic debug, bypassing 'as' */
|
||||
|
||||
/*
|
||||
* S_TYP field values
|
||||
*/
|
||||
#define S_UND 0x0000 /* undefined item */
|
||||
#define S_ABS 0x0001 /* absolute item */
|
||||
#define S_MIN 0x0002 /* first user section */
|
||||
#define S_MAX (S_TYP-1) /* last user section */
|
||||
#define S_CRS S_TYP /* on_valu is symbol index which contains value */
|
||||
|
||||
/*
|
||||
* S_ETC field values
|
||||
*/
|
||||
#define S_SCT 0x0100 /* section names */
|
||||
#define S_LIN 0x0200 /* hll source line item */
|
||||
#define S_FIL 0x0300 /* hll source file item */
|
||||
#define S_MOD 0x0400 /* ass source file item */
|
||||
#define S_COM 0x1000 /* Common name. */
|
||||
#define S_STB 0xe000 /* entries with any of these bits set are
|
||||
reserved for debuggers
|
||||
*/
|
||||
|
||||
/*
|
||||
* structure format strings
|
||||
*/
|
||||
#define SF_HEAD "22222244"
|
||||
#define SF_SECT "44444"
|
||||
#define SF_RELO "1124"
|
||||
#define SF_NAME "4224"
|
||||
|
||||
/*
|
||||
* structure sizes (bytes in file; add digits in SF_*)
|
||||
*/
|
||||
#define SZ_HEAD 20
|
||||
#define SZ_SECT 20
|
||||
#define SZ_RELO 8
|
||||
#define SZ_NAME 12
|
||||
|
||||
/*
|
||||
* file access macros
|
||||
*/
|
||||
#define BADMAGIC(x) ((x).oh_magic!=O_MAGIC)
|
||||
#define OFF_SECT(x) SZ_HEAD
|
||||
#define OFF_EMIT(x) (OFF_SECT(x) + ((long)(x).oh_nsect * SZ_SECT))
|
||||
#define OFF_RELO(x) (OFF_EMIT(x) + (x).oh_nemit)
|
||||
#define OFF_NAME(x) (OFF_RELO(x) + ((long)(x).oh_nrelo * SZ_RELO))
|
||||
#define OFF_CHAR(x) (OFF_NAME(x) + ((long)(x).oh_nname * SZ_NAME))
|
||||
|
||||
#endif /* __OUT_H_INCLUDED */
|
||||
7
commands/aal/param.h
Normal file
7
commands/aal/param.h
Normal file
@@ -0,0 +1,7 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* $Header$ */
|
||||
|
||||
#define SSIZE 1024
|
||||
44
commands/aal/print.c
Normal file
44
commands/aal/print.c
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* $Header$ */
|
||||
|
||||
#if __STDC__
|
||||
#include <stdarg.h>
|
||||
#else
|
||||
#include <varargs.h>
|
||||
#endif
|
||||
#include <system.h>
|
||||
#include "param.h"
|
||||
#include "format.h"
|
||||
#include "write.h"
|
||||
|
||||
/*VARARGS*/
|
||||
/*FORMAT0v $
|
||||
%s = char *
|
||||
%l = long
|
||||
%c = int
|
||||
%[uxbo] = unsigned int
|
||||
%d = int
|
||||
$ */
|
||||
void
|
||||
#if __STDC__
|
||||
print(char *fmt, ...)
|
||||
#else
|
||||
print(fmt, va_alist)
|
||||
char *fmt;
|
||||
va_dcl
|
||||
#endif
|
||||
{
|
||||
va_list args;
|
||||
char buf[SSIZE];
|
||||
|
||||
#if __STDC__
|
||||
va_start(args, fmt);
|
||||
#else
|
||||
va_start(args);
|
||||
#endif
|
||||
sys_write(STDOUT, buf, _format(buf, fmt, args));
|
||||
va_end(args);
|
||||
}
|
||||
2
commands/aal/print.h
Normal file
2
commands/aal/print.h
Normal file
@@ -0,0 +1,2 @@
|
||||
|
||||
extern void print(char *fmt, ...);
|
||||
36
commands/aal/ranlib.h
Normal file
36
commands/aal/ranlib.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* $Header$ */
|
||||
|
||||
#ifndef __RANLIB_H_INCLUDED
|
||||
#define __RANLIB_H_INCLUDED
|
||||
|
||||
#ifndef SYMDEF
|
||||
# define SYMDEF "__.SYMDEF"
|
||||
#endif /* SYMDEF */
|
||||
|
||||
/*
|
||||
* Structure of the SYMDEF table of contents for an archive.
|
||||
* SYMDEF begins with a long giving the number of ranlib
|
||||
* structures that immediately follow, and then continues with a string
|
||||
* table consisting of a long giving the number of bytes of
|
||||
* strings that follow and then the strings themselves.
|
||||
*/
|
||||
struct ranlib {
|
||||
union {
|
||||
char *ran__ptr; /* symbol name (in core) */
|
||||
long ran__off; /* symbol name (in file) */
|
||||
} ran_u;
|
||||
#define ran_ptr ran_u.ran__ptr
|
||||
#define ran_off ran_u.ran__off
|
||||
long ran_pos; /* library member is at this position */
|
||||
};
|
||||
|
||||
#define SZ_RAN 8
|
||||
#define SF_RAN "44"
|
||||
|
||||
extern void wr_ranlib(int fd, struct ranlib ran[], long cnt);
|
||||
#endif /* __RANLIB_H_INCLUDED */
|
||||
|
||||
247
commands/aal/rd.c
Normal file
247
commands/aal/rd.c
Normal file
@@ -0,0 +1,247 @@
|
||||
/* $Header$ */
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include "out.h"
|
||||
#include "object.h"
|
||||
#include "rd.h"
|
||||
#include "rd_bytes.h"
|
||||
|
||||
extern long lseek();
|
||||
|
||||
/*
|
||||
* Parts of the output file.
|
||||
*/
|
||||
#undef PARTEMIT
|
||||
#undef PARTRELO
|
||||
#undef PARTNAME
|
||||
#undef PARTCHAR
|
||||
#undef PARTDBUG
|
||||
#undef NPARTS
|
||||
|
||||
#define PARTEMIT 0
|
||||
#define PARTRELO 1
|
||||
#define PARTNAME 2
|
||||
#define PARTCHAR 3
|
||||
#ifdef SYMDBUG
|
||||
#define PARTDBUG 4
|
||||
#else
|
||||
#define PARTDBUG 3
|
||||
#endif
|
||||
#define NPARTS (PARTDBUG + 1)
|
||||
|
||||
static long offset[MAXSECT];
|
||||
|
||||
static int outfile;
|
||||
static long outseek[NPARTS];
|
||||
static long currpos;
|
||||
static long rd_base;
|
||||
#define OUTSECT(i) \
|
||||
(outseek[PARTEMIT] = offset[i])
|
||||
#define BEGINSEEK(p, o) \
|
||||
(outseek[(p)] = (o))
|
||||
|
||||
static int sectionnr;
|
||||
|
||||
static
|
||||
void OUTREAD(int p, char *b, long n)
|
||||
{
|
||||
register long l = outseek[p];
|
||||
|
||||
if (currpos != l) {
|
||||
lseek(outfile, l, 0);
|
||||
}
|
||||
rd_bytes(outfile, b, n);
|
||||
l += n;
|
||||
currpos = l;
|
||||
outseek[p] = l;
|
||||
}
|
||||
|
||||
/*
|
||||
* Open the output file according to the chosen strategy.
|
||||
*/
|
||||
int
|
||||
rd_open(char *f)
|
||||
{
|
||||
int outfile = open(f, 0);
|
||||
if (outfile < 0)
|
||||
return 0;
|
||||
return rd_fdopen(outfile);
|
||||
}
|
||||
|
||||
static int offcnt;
|
||||
|
||||
int rd_fdopen(int fd)
|
||||
{
|
||||
register int i;
|
||||
|
||||
for (i = 0; i < NPARTS; i++) outseek[i] = 0;
|
||||
offcnt = 0;
|
||||
rd_base = lseek(fd, 0L, 1);
|
||||
if (rd_base < 0) {
|
||||
return 0;
|
||||
}
|
||||
currpos = rd_base;
|
||||
outseek[PARTEMIT] = currpos;
|
||||
outfile = fd;
|
||||
sectionnr = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void rd_close()
|
||||
{
|
||||
|
||||
close(outfile);
|
||||
outfile = -1;
|
||||
}
|
||||
|
||||
int rd_fd()
|
||||
{
|
||||
return outfile;
|
||||
}
|
||||
|
||||
void rd_ohead(register struct outhead *head)
|
||||
{
|
||||
register long off;
|
||||
|
||||
OUTREAD(PARTEMIT, (char *) head, (long) SZ_HEAD);
|
||||
#if ! (BYTES_REVERSED || WORDS_REVERSED)
|
||||
if (sizeof(struct outhead) != SZ_HEAD)
|
||||
#endif
|
||||
{
|
||||
register char *c = (char *) head + (SZ_HEAD-4);
|
||||
|
||||
head->oh_nchar = get4(c);
|
||||
c -= 4; head->oh_nemit = get4(c);
|
||||
c -= 2; head->oh_nname = uget2(c);
|
||||
c -= 2; head->oh_nrelo = uget2(c);
|
||||
c -= 2; head->oh_nsect = uget2(c);
|
||||
c -= 2; head->oh_flags = uget2(c);
|
||||
c -= 2; head->oh_stamp = uget2(c);
|
||||
c -= 2; head->oh_magic = uget2(c);
|
||||
}
|
||||
off = OFF_RELO(*head) + rd_base;
|
||||
BEGINSEEK(PARTRELO, off);
|
||||
off += (long) head->oh_nrelo * SZ_RELO;
|
||||
BEGINSEEK(PARTNAME, off);
|
||||
off += (long) head->oh_nname * SZ_NAME;
|
||||
BEGINSEEK(PARTCHAR, off);
|
||||
#ifdef SYMDBUG
|
||||
off += head->oh_nchar;
|
||||
BEGINSEEK(PARTDBUG, off);
|
||||
#endif
|
||||
}
|
||||
|
||||
void rd_rew_relos(head)
|
||||
register struct outhead *head;
|
||||
{
|
||||
register long off = OFF_RELO(*head) + rd_base;
|
||||
|
||||
BEGINSEEK(PARTRELO, off);
|
||||
}
|
||||
|
||||
void rd_sect(sect, cnt)
|
||||
register struct outsect *sect;
|
||||
register unsigned int cnt;
|
||||
{
|
||||
register char *c = (char *) sect + cnt * SZ_SECT;
|
||||
|
||||
OUTREAD(PARTEMIT, (char *) sect, (long)cnt * SZ_SECT);
|
||||
sect += cnt;
|
||||
offcnt += cnt;
|
||||
while (cnt--) {
|
||||
sect--;
|
||||
#if ! (BYTES_REVERSED || WORDS_REVERSED)
|
||||
if (sizeof(struct outsect) != SZ_SECT)
|
||||
#endif
|
||||
{
|
||||
c -= 4; sect->os_lign = get4(c);
|
||||
c -= 4; sect->os_flen = get4(c);
|
||||
c -= 4; sect->os_foff = get4(c);
|
||||
}
|
||||
offset[--offcnt] = sect->os_foff + rd_base;
|
||||
#if ! (BYTES_REVERSED || WORDS_REVERSED)
|
||||
if (sizeof(struct outsect) != SZ_SECT)
|
||||
#endif
|
||||
{
|
||||
c -= 4; sect->os_size = get4(c);
|
||||
c -= 4; sect->os_base = get4(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void rd_outsect(int s)
|
||||
{
|
||||
OUTSECT(s);
|
||||
sectionnr = s;
|
||||
}
|
||||
|
||||
/*
|
||||
* We don't have to worry about byte order here.
|
||||
*/
|
||||
void rd_emit(emit, cnt)
|
||||
char *emit;
|
||||
long cnt;
|
||||
{
|
||||
OUTREAD(PARTEMIT, emit, cnt);
|
||||
offset[sectionnr] += cnt;
|
||||
}
|
||||
|
||||
void rd_relo(relo, cnt)
|
||||
register struct outrelo *relo;
|
||||
register unsigned int cnt;
|
||||
{
|
||||
OUTREAD(PARTRELO, (char *) relo, (long) cnt * SZ_RELO);
|
||||
#if ! (BYTES_REVERSED || WORDS_REVERSED)
|
||||
if (sizeof(struct outrelo) != SZ_RELO)
|
||||
#endif
|
||||
{
|
||||
register char *c = (char *) relo + (long) cnt * SZ_RELO;
|
||||
|
||||
relo += cnt;
|
||||
while (cnt--) {
|
||||
relo--;
|
||||
c -= 4; relo->or_addr = get4(c);
|
||||
c -= 2; relo->or_nami = uget2(c);
|
||||
relo->or_sect = *--c;
|
||||
relo->or_type = *--c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void rd_name(struct outname *name, unsigned int cnt)
|
||||
{
|
||||
|
||||
OUTREAD(PARTNAME, (char *) name, (long) cnt * SZ_NAME);
|
||||
#if ! (BYTES_REVERSED || WORDS_REVERSED)
|
||||
if (sizeof(struct outname) != SZ_NAME)
|
||||
#endif
|
||||
{
|
||||
register char *c = (char *) name + (long) cnt * SZ_NAME;
|
||||
|
||||
name += cnt;
|
||||
while (cnt--) {
|
||||
name--;
|
||||
c -= 4; name->on_valu = get4(c);
|
||||
c -= 2; name->on_desc = uget2(c);
|
||||
c -= 2; name->on_type = uget2(c);
|
||||
c -= 4; name->on_foff = get4(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void rd_string(char *addr, long len)
|
||||
{
|
||||
OUTREAD(PARTCHAR, addr, len);
|
||||
}
|
||||
|
||||
#ifdef SYMDBUG
|
||||
void rd_dbug(char *buf, long size)
|
||||
{
|
||||
OUTREAD(PARTDBUG, buf, size);
|
||||
}
|
||||
#endif
|
||||
10
commands/aal/rd.h
Normal file
10
commands/aal/rd.h
Normal file
@@ -0,0 +1,10 @@
|
||||
/*
|
||||
* Headers for rd.c
|
||||
*/
|
||||
|
||||
#include "out.h"
|
||||
|
||||
extern void rd_string(char *addr, long len);
|
||||
extern void rd_name(struct outname name[], unsigned int cnt);
|
||||
extern int rd_fdopen(int fd);
|
||||
extern void rd_ohead(register struct outhead head[]);
|
||||
39
commands/aal/rd_arhdr.c
Normal file
39
commands/aal/rd_arhdr.c
Normal file
@@ -0,0 +1,39 @@
|
||||
/* $Header$ */
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <arch.h>
|
||||
#include "object.h"
|
||||
|
||||
#include "arch.h"
|
||||
#include "archiver.h"
|
||||
|
||||
int
|
||||
rd_arhdr(int fd, register struct ar_hdr *arhdr)
|
||||
{
|
||||
char buf[AR_TOTAL];
|
||||
register char *c = buf;
|
||||
register char *p = arhdr->ar_name;
|
||||
register int i;
|
||||
|
||||
i = read(fd, c, AR_TOTAL);
|
||||
if (i == 0) return 0;
|
||||
if (i != AR_TOTAL) {
|
||||
rd_fatal();
|
||||
}
|
||||
i = 14;
|
||||
while (i--) {
|
||||
*p++ = *c++;
|
||||
}
|
||||
arhdr->ar_date = ((long) get2(c)) << 16; c += 2;
|
||||
arhdr->ar_date |= ((long) get2(c)) & 0xffff; c += 2;
|
||||
arhdr->ar_uid = *c++;
|
||||
arhdr->ar_gid = *c++;
|
||||
arhdr->ar_mode = get2(c); c += 2;
|
||||
arhdr->ar_size = (long) get2(c) << 16; c += 2;
|
||||
arhdr->ar_size |= (long) get2(c) & 0xffff;
|
||||
return 1;
|
||||
}
|
||||
35
commands/aal/rd_bytes.c
Normal file
35
commands/aal/rd_bytes.c
Normal file
@@ -0,0 +1,35 @@
|
||||
/* $Header$ */
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
#define MININT (1 << (sizeof(int) * 8 - 1))
|
||||
#define MAXCHUNK (~MININT) /* Highest count we read(2). */
|
||||
/* Unfortunately, MAXCHUNK is too large with some compilers. Put it in
|
||||
an int!
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "archiver.h"
|
||||
#include "rd_bytes.h"
|
||||
|
||||
static int maxchunk = MAXCHUNK;
|
||||
|
||||
/*
|
||||
* We don't have to worry about byte order here.
|
||||
* Just read "cnt" bytes from file-descriptor "fd".
|
||||
*/
|
||||
void rd_bytes(int fd, char *string, long cnt)
|
||||
{
|
||||
|
||||
while (cnt) {
|
||||
register int n = cnt >= maxchunk ? maxchunk : cnt;
|
||||
|
||||
if (read(fd, string, n) != n)
|
||||
rd_fatal();
|
||||
string += n;
|
||||
cnt -= n;
|
||||
}
|
||||
}
|
||||
2
commands/aal/rd_bytes.h
Normal file
2
commands/aal/rd_bytes.h
Normal file
@@ -0,0 +1,2 @@
|
||||
|
||||
extern void rd_bytes(int fd, char *string, long cnt);
|
||||
16
commands/aal/rd_unsig2.c
Normal file
16
commands/aal/rd_unsig2.c
Normal file
@@ -0,0 +1,16 @@
|
||||
/* $Header$ */
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
#include "object.h"
|
||||
#include "rd_bytes.h"
|
||||
|
||||
unsigned int
|
||||
rd_unsigned2(int fd)
|
||||
{
|
||||
char buf[2];
|
||||
|
||||
rd_bytes(fd, buf, 2L);
|
||||
return uget2(buf);
|
||||
}
|
||||
43
commands/aal/sprint.c
Normal file
43
commands/aal/sprint.c
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* $Header$ */
|
||||
|
||||
#if __STDC__
|
||||
#include <stdarg.h>
|
||||
#else
|
||||
#include <varargs.h>
|
||||
#endif
|
||||
#include <system.h>
|
||||
#include "param.h"
|
||||
#include "format.h"
|
||||
|
||||
/*VARARGS*/
|
||||
/*FORMAT1v $
|
||||
%s = char *
|
||||
%l = long
|
||||
%c = int
|
||||
%[uxbo] = unsigned int
|
||||
%d = int
|
||||
$ */
|
||||
char *
|
||||
#if __STDC__
|
||||
sprint(char *buf, char *fmt, ...)
|
||||
#else
|
||||
sprint(buf, fmt, va_alist)
|
||||
char *buf, *fmt;
|
||||
va_dcl
|
||||
#endif
|
||||
{
|
||||
va_list args;
|
||||
|
||||
#if __STDC__
|
||||
va_start(args, fmt);
|
||||
#else
|
||||
va_start(args);
|
||||
#endif
|
||||
buf[_format(buf, fmt, args)] = '\0';
|
||||
va_end(args);
|
||||
return buf;
|
||||
}
|
||||
24
commands/aal/system.c
Normal file
24
commands/aal/system.c
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* RCS: $Header$ */
|
||||
|
||||
#include <system.h>
|
||||
|
||||
File _sys_ftab[SYS_NOPEN] = {
|
||||
{ 0, OP_READ},
|
||||
{ 1, OP_APPEND},
|
||||
{ 2, OP_APPEND}
|
||||
};
|
||||
|
||||
File *
|
||||
_get_entry()
|
||||
{
|
||||
register File *fp;
|
||||
|
||||
for (fp = &_sys_ftab[0]; fp < &_sys_ftab[SYS_NOPEN]; fp++)
|
||||
if (fp->o_flags == 0)
|
||||
return fp;
|
||||
return (File *)0;
|
||||
}
|
||||
49
commands/aal/system.h
Normal file
49
commands/aal/system.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* RCS: $Header$ */
|
||||
#ifndef __SYSTEM_INCLUDED__
|
||||
#define __SYSTEM_INCLUDED__
|
||||
|
||||
struct _sys_fildes {
|
||||
int o_fd; /* UNIX filedescriptor */
|
||||
int o_flags; /* flags for open; 0 if not used */
|
||||
};
|
||||
|
||||
typedef struct _sys_fildes File;
|
||||
|
||||
extern File _sys_ftab[];
|
||||
|
||||
/* flags for sys_open() */
|
||||
#define OP_READ 01
|
||||
#define OP_WRITE 02
|
||||
#define OP_APPEND 04
|
||||
|
||||
/* flags for sys_access() */
|
||||
#define AC_EXIST 00
|
||||
#define AC_READ 04
|
||||
#define AC_WRITE 02
|
||||
#define AC_EXEC 01
|
||||
|
||||
/* flags for sys_stop() */
|
||||
#define S_END 0
|
||||
#define S_EXIT 1
|
||||
#define S_ABORT 2
|
||||
|
||||
/* standard file decsriptors */
|
||||
#define STDIN &_sys_ftab[0]
|
||||
#define STDOUT &_sys_ftab[1]
|
||||
#define STDERR &_sys_ftab[2]
|
||||
|
||||
/* maximum number of open files */
|
||||
#define SYS_NOPEN 20
|
||||
|
||||
/* return value for sys_break */
|
||||
#define ILL_BREAK ((char *)0)
|
||||
|
||||
/* system's idea of block */
|
||||
#ifndef BUFSIZ
|
||||
#define BUFSIZ 1024
|
||||
#endif
|
||||
#endif /* __SYSTEM_INCLUDED__ */
|
||||
16
commands/aal/varargs.h
Normal file
16
commands/aal/varargs.h
Normal file
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* $Header$ */
|
||||
|
||||
#ifndef _VARARGS_H
|
||||
#define _VARARGS_H
|
||||
|
||||
typedef char *va_list;
|
||||
# define __va_sz(mode) (((sizeof(mode) + sizeof(int) - 1) / sizeof(int)) * sizeof(int))
|
||||
# define va_dcl int va_alist;
|
||||
# define va_start(list) (list = (char *) &va_alist)
|
||||
# define va_end(list)
|
||||
# define va_arg(list,mode) (*((mode *)((list += __va_sz(mode)) - __va_sz(mode))))
|
||||
#endif /* _VARARGS_H */
|
||||
30
commands/aal/wr_arhdr.c
Normal file
30
commands/aal/wr_arhdr.c
Normal file
@@ -0,0 +1,30 @@
|
||||
/* $Header$ */
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
#include <arch.h>
|
||||
#include "object.h"
|
||||
#include "arch.h"
|
||||
#include "write.h"
|
||||
#include "wr_bytes.h"
|
||||
|
||||
void wr_arhdr(int fd, struct ar_hdr *arhdr)
|
||||
{
|
||||
char buf[AR_TOTAL];
|
||||
register char *c = buf;
|
||||
register char *p = arhdr->ar_name;
|
||||
register int i = 14;
|
||||
|
||||
while (i--) {
|
||||
*c++ = *p++;
|
||||
}
|
||||
put2((int)(arhdr->ar_date>>16),c); c += 2;
|
||||
put2((int)(arhdr->ar_date),c); c += 2;
|
||||
*c++ = arhdr->ar_uid;
|
||||
*c++ = arhdr->ar_gid;
|
||||
put2(arhdr->ar_mode,c); c += 2;
|
||||
put2((int)(arhdr->ar_size>>16),c); c += 2;
|
||||
put2((int)(arhdr->ar_size),c);
|
||||
wr_bytes(fd, buf, (long) AR_TOTAL);
|
||||
}
|
||||
33
commands/aal/wr_bytes.c
Normal file
33
commands/aal/wr_bytes.c
Normal file
@@ -0,0 +1,33 @@
|
||||
/* $Header$ */
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
#define MININT (1 << (sizeof(int) * 8 - 1))
|
||||
#define MAXCHUNK (~MININT) /* Highest count we write(2). */
|
||||
/* Notice that MAXCHUNK itself might be too large with some compilers.
|
||||
You have to put it in an int!
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include "wr_bytes.h"
|
||||
#include "archiver.h"
|
||||
|
||||
static int maxchunk = MAXCHUNK;
|
||||
|
||||
/*
|
||||
* Just write "cnt" bytes to file-descriptor "fd".
|
||||
*/
|
||||
void wr_bytes(int fd, register char *string, long cnt)
|
||||
{
|
||||
|
||||
while (cnt) {
|
||||
register int n = cnt >= maxchunk ? maxchunk : cnt;
|
||||
|
||||
if (write(fd, string, n) != n)
|
||||
wr_fatal();
|
||||
string += n;
|
||||
cnt -= n;
|
||||
}
|
||||
}
|
||||
4
commands/aal/wr_bytes.h
Normal file
4
commands/aal/wr_bytes.h
Normal file
@@ -0,0 +1,4 @@
|
||||
/*
|
||||
* Exported symbols of wr_bytes.c
|
||||
*/
|
||||
extern void wr_bytes(int fd, register char *string, long cnt);
|
||||
16
commands/aal/wr_int2.c
Normal file
16
commands/aal/wr_int2.c
Normal file
@@ -0,0 +1,16 @@
|
||||
/* $Header$ */
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
#include "object.h"
|
||||
#include "wr_int2.h"
|
||||
#include "wr_bytes.h"
|
||||
|
||||
void wr_int2(int fd, int i)
|
||||
{
|
||||
char buf[2];
|
||||
|
||||
put2(i, buf);
|
||||
wr_bytes(fd, buf, 2L);
|
||||
}
|
||||
2
commands/aal/wr_int2.h
Normal file
2
commands/aal/wr_int2.h
Normal file
@@ -0,0 +1,2 @@
|
||||
|
||||
extern void wr_int2(int fd, int i);
|
||||
16
commands/aal/wr_long.c
Normal file
16
commands/aal/wr_long.c
Normal file
@@ -0,0 +1,16 @@
|
||||
/* $Header$ */
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
#include "object.h"
|
||||
#include "wr_bytes.h"
|
||||
#include "wr_long.h"
|
||||
|
||||
void wr_long(int fd, long l)
|
||||
{
|
||||
char buf[4];
|
||||
|
||||
put4(l, buf);
|
||||
wr_bytes(fd, buf, 4L);
|
||||
}
|
||||
2
commands/aal/wr_long.h
Normal file
2
commands/aal/wr_long.h
Normal file
@@ -0,0 +1,2 @@
|
||||
|
||||
extern void wr_long(int fd, long l);
|
||||
36
commands/aal/wr_ranlib.c
Normal file
36
commands/aal/wr_ranlib.c
Normal file
@@ -0,0 +1,36 @@
|
||||
/* $Header$ */
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
#include <ranlib.h>
|
||||
#include "object.h"
|
||||
#include "wr_bytes.h"
|
||||
#include "ranlib.h"
|
||||
|
||||
void wr_ranlib(int fd, struct ranlib *ran, long cnt)
|
||||
{
|
||||
#if ! (BYTES_REVERSED || WORDS_REVERSED)
|
||||
if (sizeof (struct ranlib) != SZ_RAN)
|
||||
#endif
|
||||
{
|
||||
char buf[100 * SZ_RAN];
|
||||
|
||||
while (cnt) {
|
||||
register int i = (cnt > 100) ? 100 : cnt;
|
||||
register char *c = buf;
|
||||
long j = i * SZ_RAN;
|
||||
|
||||
cnt -= i;
|
||||
while (i--) {
|
||||
put4(ran->ran_off,c); c += 4;
|
||||
put4(ran->ran_pos,c); c += 4;
|
||||
ran++;
|
||||
}
|
||||
wr_bytes(fd, buf, j);
|
||||
}
|
||||
}
|
||||
#if ! (BYTES_REVERSED || WORDS_REVERSED)
|
||||
else wr_bytes(fd, (char *) ran, cnt * SZ_RAN);
|
||||
#endif
|
||||
}
|
||||
17
commands/aal/write.c
Normal file
17
commands/aal/write.c
Normal file
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* $Header$ */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <system.h>
|
||||
#include "write.h"
|
||||
|
||||
int
|
||||
sys_write(File *fp, char *bufptr, int nbytes)
|
||||
{
|
||||
if (! fp) return 0;
|
||||
return write(fp->o_fd, bufptr, nbytes) == nbytes;
|
||||
}
|
||||
3
commands/aal/write.h
Normal file
3
commands/aal/write.h
Normal file
@@ -0,0 +1,3 @@
|
||||
|
||||
#include "system.h"
|
||||
extern int sys_write(File *fp, char *bufptr, int nbytes);
|
||||
13
commands/acd/Makefile
Normal file
13
commands/acd/Makefile
Normal file
@@ -0,0 +1,13 @@
|
||||
# Makefile for acd
|
||||
|
||||
.include <bsd.own.mk>
|
||||
|
||||
PROG= acd
|
||||
CPPFLAGS+= -DARCH=\"`arch`\" -DDESCR=\"/usr/lib/descr\"
|
||||
LINKS+= ${BINDIR}/acd ${BINDIR}/cc
|
||||
FILESDIR= /usr/lib
|
||||
FILES= acd.descr
|
||||
FILESNAME= descr
|
||||
MAN=
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
2701
commands/acd/acd.c
Normal file
2701
commands/acd/acd.c
Normal file
File diff suppressed because it is too large
Load Diff
438
commands/acd/acd.descr
Normal file
438
commands/acd/acd.descr
Normal file
@@ -0,0 +1,438 @@
|
||||
# ACD pass description for the ACK compilers.
|
||||
#
|
||||
# Pre-set variables.
|
||||
# PROGRAM - Name the compiler driver is called with.
|
||||
# ARCH - Default target architecture.
|
||||
|
||||
# Library directories search path.
|
||||
L = /lib /usr/lib
|
||||
|
||||
# ACK Compilers support search path.
|
||||
A = $L $L/ack
|
||||
|
||||
# ARCH must be defined.
|
||||
ifndef ARCH
|
||||
error "\$ARCH is not predefined"
|
||||
|
||||
# Get ARCH from the environment if set.
|
||||
import ARCH
|
||||
|
||||
# Compiler passes.
|
||||
ACK_CPP = $A/cpp.ansi $CPP_F $PREDEF $NOLINENO
|
||||
ACK_CEM = $A/em_cemcom.ansi -L $CPP_F $PREDEF \
|
||||
-Vw${W}.${W}i${W}.${W}p${P}.${W}f4.${W}s2.2l4.${W}d8.${W}
|
||||
ACK_M2 = $A/em_m2 -I$MOD_INCL -WR \
|
||||
-Vw${W}.${W}i${W}.${W}p${P}.${W}l4.${W}f4.${W}d8.${W}
|
||||
ACK_PC = $A/em_pc \
|
||||
-Vw${W}.${W}i${W}.${W}l4.${W}p${P}.${W}f8.${W}S${W}.${W}
|
||||
MOD_INCL = $A/m2 +
|
||||
ACK_DECODE = $A/em_decode
|
||||
ACK_ENCODE = $A/em_encode
|
||||
ACK_OPT = $A/em_opt
|
||||
ACK_EGO = $A/em_ego -P $A/ego -M$EGO_DESCR
|
||||
EGO_DESCR = $A/ego/${ARCH}descr +
|
||||
ACK_OPT2 = $A/em_opt2
|
||||
ACK_CG = $A/$ARCH/cg
|
||||
ACK_AS = $A/$ARCH/as \-
|
||||
ACK_LED = $A/em_led -a0:$W -a1:$W -a2:$W -a3:$W
|
||||
ACK_CV = $A/cv
|
||||
ASMCONV = /usr/bin/asmconv
|
||||
AAL = /usr/bin/aal
|
||||
|
||||
# Minix predefined symbols.
|
||||
CPP_F = -D__minix -D__minix3 -D__$ARCH
|
||||
|
||||
# Library path.
|
||||
LIBPATH = $USERLIBPATH $A/$ARCH
|
||||
|
||||
# Default output "model".
|
||||
MODEL = -sep
|
||||
|
||||
# Floating point is done in software.
|
||||
LIBS = -fsoft
|
||||
|
||||
# Default optimization level.
|
||||
OPT_LEVEL = 1
|
||||
|
||||
# Call names.
|
||||
if $PROGRAM = acc
|
||||
PROGRAM = cc
|
||||
if $PROGRAM = apc
|
||||
PROGRAM = pc
|
||||
if $PROGRAM = am2
|
||||
PROGRAM = m2
|
||||
if $PROGRAM = kcc
|
||||
PROGRAM = cc
|
||||
|
||||
# Default transformation target.
|
||||
stop .out
|
||||
|
||||
# Select the runtime environment by option or program name.
|
||||
arg -.c
|
||||
if $PROGRAM = cc
|
||||
ifndef RTSO
|
||||
RTSO = -.c
|
||||
LIBS = $LIBS + -.c
|
||||
|
||||
# Omit the runtime startoff, but keep the libraries.
|
||||
arg -.o
|
||||
RTSO =
|
||||
|
||||
arg -.$any
|
||||
error ".$any: unknown language"
|
||||
|
||||
# Select the target architecture.
|
||||
arg -m$arch
|
||||
ARCH = $arch
|
||||
|
||||
# Preprocessor directives.
|
||||
arg -D$name
|
||||
arg -D $name
|
||||
CPP_F = $CPP_F -D$name
|
||||
arg -U$name
|
||||
arg -U $name
|
||||
CPP_F = $CPP_F -U$name
|
||||
arg -I$dir
|
||||
arg -I $dir
|
||||
CPP_F = $CPP_F -I$dir
|
||||
ACK_M2 = $ACK_M2 -I$dir
|
||||
|
||||
# Debugging.
|
||||
arg -g # Add debugging info.
|
||||
ACK_CEM = $ACK_CEM -g
|
||||
ACK_CG = $ACK_CG -gdb
|
||||
|
||||
arg -n # Suppress line numbers.
|
||||
ACK_M2 = $ACK_M2 -L
|
||||
ACK_PC = $ACK_PC -L
|
||||
arg -a # Enable assertions.
|
||||
arg -A # Enable array bound checks.
|
||||
ACK_M2 = $ACK_M2 $*
|
||||
ACK_PC = $ACK_PC $*
|
||||
|
||||
# Language checking.
|
||||
arg -w # No warnings.
|
||||
ACK_CEM = $ACK_CEM $*
|
||||
ACK_M2 = $ACK_M2 $*
|
||||
ACK_PC = $ACK_PC $*
|
||||
|
||||
arg -ws # No strict warnings.
|
||||
ACK_CEM = $ACK_CEM -s
|
||||
ACK_M2 = $ACK_M2 -wR
|
||||
|
||||
arg -wa # No warnings and no strict warnings.
|
||||
ACK_CEM = $ACK_CEM -a
|
||||
ACK_M2 = $ACK_M2 -wR
|
||||
|
||||
arg -wo # No warnings about old style C.
|
||||
ACK_CPP = $ACK_CPP -o
|
||||
ACK_CEM = $ACK_CEM -o
|
||||
ACK_M2 = $ACK_M2 -wO
|
||||
|
||||
arg -3 # Only accept 3rd generation Modula-2.
|
||||
ACK_M2 = $ACK_M2 $*
|
||||
|
||||
arg -_ # Allow underscores in identifiers.
|
||||
ACK_M2 = $ACK_M2 -U
|
||||
ACK_PC = $ACK_PC -U
|
||||
|
||||
arg -w$any
|
||||
arg -F
|
||||
arg -m
|
||||
# Ignore strange -w flags, and past and present i86 compiler flags.
|
||||
|
||||
# Stop suffix.
|
||||
arg -c
|
||||
stop .o
|
||||
|
||||
arg -c.$stop
|
||||
stop .$stop
|
||||
|
||||
arg -E
|
||||
stop .E
|
||||
|
||||
arg -P
|
||||
CPP_F = $CPP_F -P
|
||||
stop .i
|
||||
|
||||
arg -S
|
||||
stop .s
|
||||
|
||||
# Optimization.
|
||||
arg -O
|
||||
OPT_LEVEL = 1
|
||||
|
||||
arg -OS # Optimize for size.
|
||||
ACK_EGO = $ACK_EGO -S
|
||||
arg -OT # Optimize for time.
|
||||
ACK_EGO = $ACK_EGO -T
|
||||
|
||||
arg -O$n
|
||||
numeric $n
|
||||
OPT_LEVEL = $n
|
||||
|
||||
# Library search path.
|
||||
arg -L$dir
|
||||
arg -L $dir
|
||||
USERLIBPATH = $USERLIBPATH $dir/$ARCH $dir
|
||||
|
||||
# -llib must be searched in $LIBPATH later.
|
||||
arg -l$lib
|
||||
arg -l $lib
|
||||
$> = $LIBPATH/lib$lib.a
|
||||
|
||||
# Software floating point, hardware floating point, or no floating point.
|
||||
arg -f
|
||||
arg -fp
|
||||
arg -fsoft
|
||||
LIBS = $LIBS + -fsoft
|
||||
|
||||
arg -fhard
|
||||
LIBS = $LIBS - -fsoft
|
||||
|
||||
arg -fnone
|
||||
LIBS = $LIBS + -fnone
|
||||
|
||||
# Output model.
|
||||
arg -com
|
||||
MODEL = # Common I&D.
|
||||
|
||||
arg -sep
|
||||
arg -i # Separate I&D.
|
||||
MODEL = -sep
|
||||
|
||||
arg -r # Relocatable object (combined .o)
|
||||
MODEL = -r
|
||||
|
||||
# Strip executable.
|
||||
arg -s
|
||||
ACK_LED = $ACK_LED -s
|
||||
|
||||
# Size of heap+stack.
|
||||
arg -stack $size
|
||||
ACK_CV = $ACK_CV -S $size
|
||||
|
||||
# Change output file.
|
||||
arg -o$out
|
||||
arg -o $out
|
||||
OUT = $out
|
||||
|
||||
# Complain about just -D, -U, -I, ...
|
||||
arg -D; arg -U; arg -I; arg -L; arg -l; arg -o; arg -stack
|
||||
error "argument expected after '$*'"
|
||||
|
||||
arg -R$pass-$flag # The ACK way of passing options to passes.
|
||||
arg -Wack-R$pass-$flag # The ACD way.
|
||||
if $pass = cpp
|
||||
ACK_CPP = $ACK_CPP -$flag
|
||||
if $pass = cem
|
||||
ACK_CEM = $ACK_CEM -$flag
|
||||
if $pass = m2
|
||||
ACK_M2 = $ACK_M2 -$flag
|
||||
if $pass = pc
|
||||
ACK_PC = $ACK_PC -$flag
|
||||
if $pass = opt
|
||||
ACK_OPT = $ACK_OPT -$flag
|
||||
if $pass = ego
|
||||
ACK_EGO = $ACK_EGO -$flag
|
||||
if $pass = opt2
|
||||
ACK_OPT2 = $ACK_OPT2 -$flag
|
||||
if $pass = cg
|
||||
ACK_CG = $ACK_CG -$flag
|
||||
if $pass = as
|
||||
ACK_AS = $ACK_AS -$flag
|
||||
if $pass = led
|
||||
ACK_LED = $ACK_LED -$flag
|
||||
|
||||
arg -Was-$dialect # Default assembly dialect.
|
||||
ASDIALECT = $dialect
|
||||
|
||||
arg -W$any
|
||||
# Ignore any other -W options.
|
||||
|
||||
# Complain about unknown options, don't give them to the loader.
|
||||
arg -$any
|
||||
error "$*: unknown option"
|
||||
|
||||
# Do the scanning phase early, we need to know the architecture.
|
||||
scan
|
||||
|
||||
# The word and pointer sizes of the target.
|
||||
if $ARCH = i86
|
||||
W = 2; P = 2
|
||||
if $ARCH = i386
|
||||
W = 4; P = 4
|
||||
|
||||
ifndef W
|
||||
error "$ARCH: unsupported architecture"
|
||||
|
||||
# Optimize -O2 or higher?
|
||||
if (0 1 - $OPT_LEVEL) = (0 1)
|
||||
ACK_EGO = $ACK_EGO -O$OPT_LEVEL
|
||||
ACK_OPT = $ACK_OPT -m0 # Leave multiplication optimization to opt2.
|
||||
prefer .m .gk
|
||||
|
||||
# Tell cem to reverse bitfields on the i386 to be compatible with gcc.
|
||||
if $ARCH = i386
|
||||
ACK_CEM = $ACK_CEM -Vr
|
||||
|
||||
# Predefined preprocessor flags.
|
||||
PREDEF = -D_EM_WSIZE=$W -D_EM_PSIZE=$P -D_EM_SSIZE=2 -D_EM_LSIZE=4 \
|
||||
-D_EM_FSIZE=4 -D_EM_DSIZE=8 -D__ACK__ -D_ACK
|
||||
|
||||
# Preprocess C source.
|
||||
transform .c .i
|
||||
$ACK_CPP $* > $>
|
||||
|
||||
# Preprocess any type of file and send it to standard output or $OUT.
|
||||
transform "" .E
|
||||
if $* = "-"
|
||||
file = # Standard input.
|
||||
else
|
||||
file = $*
|
||||
ifndef OUT
|
||||
$ACK_CPP $file
|
||||
else
|
||||
$ACK_CPP $file > $OUT
|
||||
|
||||
# Compile C source to EM-code.
|
||||
transform .c .k
|
||||
transform .i .k
|
||||
$ACK_CEM $* $>
|
||||
ifndef RTSO
|
||||
RTSO = -.c
|
||||
LIBS = $LIBS + -.c
|
||||
|
||||
# Compact EM to readable EM.
|
||||
transform .k .e
|
||||
transform .m .e
|
||||
transform .gk .e
|
||||
transform .g .e
|
||||
$ACK_DECODE $* > $>
|
||||
|
||||
# Readable EM to compact EM.
|
||||
transform .e .k
|
||||
ifhash $*
|
||||
NOLINENO = -P # Encode chokes on cpp line directives.
|
||||
apply .c .i
|
||||
unset NOLINENO
|
||||
$ACK_ENCODE $* > $>
|
||||
|
||||
# Peephole optimization.
|
||||
transform .k .m
|
||||
$ACK_OPT $* > $>
|
||||
|
||||
# Global optimization.
|
||||
transform .m .gk
|
||||
$ACK_EGO $* > $>
|
||||
|
||||
# Second peephole optimization after global optimization.
|
||||
transform .gk .g
|
||||
$ACK_OPT2 $* > $>
|
||||
|
||||
# EM-code to target machine assembly.
|
||||
transform .m .ack.s
|
||||
transform .g .ack.s
|
||||
transform .m .s
|
||||
transform .g .s
|
||||
if $ARCH = i386
|
||||
$ACK_CG -F__fp_hook $* > $>
|
||||
else
|
||||
$ACK_CG $* > $>
|
||||
|
||||
# How to treat plain .s?
|
||||
ifndef ASDIALECT
|
||||
transform .s .ack.s
|
||||
$> = $*
|
||||
|
||||
# Assembly to object file.
|
||||
transform .ack.s .o
|
||||
ifhash $*
|
||||
apply .c .i
|
||||
if $> = $<.o
|
||||
ifdef OUT
|
||||
$> = $OUT
|
||||
$ACK_AS -o $> $*
|
||||
|
||||
# Combine object files and libraries to an executable.
|
||||
combine (.o .a) .out
|
||||
if $MODEL = ()
|
||||
model = -b0:0
|
||||
if $MODEL = (-sep)
|
||||
model = -b0:0 -b1:0
|
||||
rtso =
|
||||
if $RTSO = -.c
|
||||
rtso = $A/$ARCH/crtso.o
|
||||
libd = ; libc = ; libfp =
|
||||
if (-.c - $LIBS) = ()
|
||||
libd = $A/$ARCH/libd.a
|
||||
libc = $A/$ARCH/libc.a
|
||||
if (-fsoft - $LIBS) = ()
|
||||
libfp = $A/$ARCH/libfp.a
|
||||
libs = $libd $libc $libfp $A/$ARCH/libe.a
|
||||
ifndef OUT
|
||||
OUT = a.out
|
||||
if (-r - $MODEL) = ()
|
||||
# Combine to an object file.
|
||||
$ACK_LED -r -o $OUT $*
|
||||
else
|
||||
# Combine to an executable.
|
||||
mktemp EXE
|
||||
$ACK_LED $model -o $EXE $rtso $* $libs $A/$ARCH/libend.a
|
||||
$ACK_CV -x -m$ARCH $EXE $OUT
|
||||
|
||||
# Add object files to a library.
|
||||
combine (.o) .a
|
||||
if $> = $<.a
|
||||
ifdef OUT
|
||||
$> = $OUT
|
||||
$AAL cr $> $*
|
||||
|
||||
# Assembly conversions.
|
||||
|
||||
# ACK assembly to ACK Xenix assembly.
|
||||
transform .ack.s .ncc.s
|
||||
ifhash $*
|
||||
apply .c .i
|
||||
$ASMCONV -m$ARCH ack ncc $* $>
|
||||
|
||||
# ACK assembly to GNU assembly.
|
||||
transform .ack.s .gnu.s
|
||||
ifhash $*
|
||||
apply .c .i
|
||||
$ASMCONV -m$ARCH ack gnu $* $>
|
||||
|
||||
# ACK Xenix assembly to ACK assembly.
|
||||
transform .ncc.s .ack.s
|
||||
ifhash $*
|
||||
apply .c .i
|
||||
$ASMCONV -m$ARCH ncc ack $* $>
|
||||
|
||||
# ACK Xenix assembly to GNU assembly.
|
||||
transform .ncc.s .gnu.s
|
||||
ifhash $*
|
||||
apply .c .i
|
||||
$ASMCONV -m$ARCH ncc gnu $* $>
|
||||
|
||||
# BCC assembly to ACK assembly.
|
||||
transform .bas.s .ack.s
|
||||
ifhash $*
|
||||
apply .c .i
|
||||
$ASMCONV -m$ARCH bas ack $* $>
|
||||
|
||||
# BCC assembly to ACK Xenix assembly.
|
||||
transform .bas.s .ncc.s
|
||||
ifhash $*
|
||||
apply .c .i
|
||||
$ASMCONV -m$ARCH bas ncc $* $>
|
||||
|
||||
# BCC assembly to GNU assembly.
|
||||
transform .bas.s .gnu.s
|
||||
ifhash $*
|
||||
apply .c .i
|
||||
$ASMCONV -m$ARCH bas gnu $* $>
|
||||
|
||||
#ifdef ASDIALECT
|
||||
# Treat plain .s as being in the given dialect.
|
||||
transform .s .$ASDIALECT.s
|
||||
$> = $*
|
||||
@@ -1,4 +0,0 @@
|
||||
PROG= acksize
|
||||
MAN=
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
4
commands/ackstrip/Makefile
Normal file
4
commands/ackstrip/Makefile
Normal file
@@ -0,0 +1,4 @@
|
||||
PROG= ackstrip
|
||||
MAN=
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
169
commands/ackstrip/ackstrip.c
Normal file
169
commands/ackstrip/ackstrip.c
Normal file
@@ -0,0 +1,169 @@
|
||||
/* strip - remove symbols. Author: Dick van Veen */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <a.out.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* Strip [file] ...
|
||||
*
|
||||
* - when no file is present, a.out is assumed.
|
||||
*
|
||||
*/
|
||||
|
||||
#define A_OUT "a.out"
|
||||
#define NAME_LENGTH 128 /* max file path name */
|
||||
|
||||
char buffer[BUFSIZ]; /* used to copy executable */
|
||||
char new_file[NAME_LENGTH]; /* contains name of temporary */
|
||||
struct exec header;
|
||||
|
||||
_PROTOTYPE(int main, (int argc, char **argv));
|
||||
_PROTOTYPE(void strip, (char *file));
|
||||
_PROTOTYPE(int read_header, (int fd));
|
||||
_PROTOTYPE(int write_header, (int fd));
|
||||
_PROTOTYPE(int make_tmp, (char *new_name, char *name));
|
||||
_PROTOTYPE(int copy_file, (int fd1, int fd2, long size));
|
||||
|
||||
int main(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
argv++;
|
||||
if (*argv == NULL)
|
||||
strip(A_OUT);
|
||||
else
|
||||
while (*argv != NULL) {
|
||||
strip(*argv);
|
||||
argv++;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
void strip(file)
|
||||
char *file;
|
||||
{
|
||||
int fd, new_fd;
|
||||
struct stat buf;
|
||||
long symb_size, relo_size;
|
||||
|
||||
fd = open(file, O_RDONLY);
|
||||
if (fd == -1) {
|
||||
fprintf(stderr, "can't open %s\n", file);
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
if (read_header(fd)) {
|
||||
fprintf(stderr, "%s: not an executable file\n", file);
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
if (header.a_syms == 0L) {
|
||||
close(fd); /* no symbol table present */
|
||||
return;
|
||||
}
|
||||
symb_size = header.a_syms;
|
||||
header.a_syms = 0L; /* remove table size */
|
||||
fstat(fd, &buf);
|
||||
relo_size = buf.st_size - (A_MINHDR + header.a_text + header.a_data + symb_size);
|
||||
new_fd = make_tmp(new_file, file);
|
||||
if (new_fd == -1) {
|
||||
fprintf(stderr, "can't create temporary file\n");
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
if (write_header(new_fd)) {
|
||||
fprintf(stderr, "can't write temporary file\n");
|
||||
unlink(new_file);
|
||||
close(fd);
|
||||
close(new_fd);
|
||||
return;
|
||||
}
|
||||
if (copy_file(fd, new_fd, header.a_text + header.a_data)) {
|
||||
fprintf(stderr, "can't copy %s\n", file);
|
||||
unlink(new_file);
|
||||
close(fd);
|
||||
close(new_fd);
|
||||
return;
|
||||
}
|
||||
if (relo_size != 0) {
|
||||
lseek(fd, symb_size, 1);
|
||||
if (copy_file(fd, new_fd, relo_size)) {
|
||||
fprintf(stderr, "can't copy %s\n", file);
|
||||
unlink(new_file);
|
||||
close(fd);
|
||||
close(new_fd);
|
||||
return;
|
||||
}
|
||||
}
|
||||
close(fd);
|
||||
close(new_fd);
|
||||
if (unlink(file) == -1) {
|
||||
fprintf(stderr, "can't unlink %s\n", file);
|
||||
unlink(new_file);
|
||||
return;
|
||||
}
|
||||
link(new_file, file);
|
||||
unlink(new_file);
|
||||
chmod(file, buf.st_mode);
|
||||
}
|
||||
|
||||
int read_header(fd)
|
||||
int fd;
|
||||
{
|
||||
if (read(fd, (char *) &header, A_MINHDR) != A_MINHDR) return(1);
|
||||
if (BADMAG(header)) return (1);
|
||||
if (header.a_hdrlen > sizeof(struct exec)) return (1);
|
||||
lseek(fd, 0L, SEEK_SET); /* variable size header */
|
||||
if (read(fd, (char *)&header, (int)header.a_hdrlen) != (int) header.a_hdrlen)
|
||||
return(1);
|
||||
return(0);
|
||||
}
|
||||
|
||||
int write_header(fd)
|
||||
int fd;
|
||||
{
|
||||
lseek(fd, 0L, SEEK_SET);
|
||||
if (write(fd, (char *)&header, (int)header.a_hdrlen) != (int)header.a_hdrlen)
|
||||
return(1);
|
||||
return(0);
|
||||
}
|
||||
|
||||
int make_tmp(new_name, name)
|
||||
char *new_name, *name;
|
||||
{
|
||||
int len;
|
||||
char *nameptr;
|
||||
|
||||
len = strlen(name);
|
||||
if (len + 1 > NAME_LENGTH) return(-1);
|
||||
strcpy(new_name, name);
|
||||
nameptr = strrchr(new_name, '/');
|
||||
if (nameptr == NULL) nameptr = new_name - 1;
|
||||
if (nameptr - new_name + 6 + 1 > NAME_LENGTH) return (-1);
|
||||
strcpy(nameptr + 1, "XXXXXX");
|
||||
mktemp(new_name);
|
||||
return(creat(new_name, 0777));
|
||||
}
|
||||
|
||||
int copy_file(fd1, fd2, size)
|
||||
int fd1, fd2;
|
||||
long size;
|
||||
{
|
||||
int length;
|
||||
|
||||
while (size > 0) {
|
||||
if (size < sizeof(buffer))
|
||||
length = size;
|
||||
else
|
||||
length = sizeof(buffer);
|
||||
if (read(fd1, buffer, length) != length) return(1);
|
||||
if (write(fd2, buffer, length) != length) return (1);
|
||||
size -= length;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
@@ -181,49 +181,26 @@ int main(int argc, char *argv[])
|
||||
if (!(high_byte & 0x80)) /* class A or 0 */
|
||||
{
|
||||
if (destination)
|
||||
#ifdef __NBSD_LIBC
|
||||
defaultmask= htonl(0xff000000);
|
||||
#else
|
||||
defaultmask= HTONL(0xff000000);
|
||||
#endif
|
||||
|
||||
}
|
||||
else if (!(high_byte & 0x40)) /* class B */
|
||||
{
|
||||
#ifdef __NBSD_LIBC
|
||||
defaultmask= htonl(0xffff0000);
|
||||
#else
|
||||
defaultmask= HTONL(0xffff0000);
|
||||
#endif
|
||||
|
||||
}
|
||||
else if (!(high_byte & 0x20)) /* class C */
|
||||
{
|
||||
#ifdef __NBSD_LIBC
|
||||
defaultmask= htonl(0xffffff00);
|
||||
#else
|
||||
defaultmask= HTONL(0xffffff00);
|
||||
|
||||
#endif
|
||||
}
|
||||
else /* class D is multicast ... */
|
||||
{
|
||||
fprintf(stderr, "%s: Warning: Martian address '%s'\n",
|
||||
prog_name, inet_ntoa(destination));
|
||||
#ifdef __NBSD_LIBC
|
||||
defaultmask= htonl(0xffffffff);
|
||||
#else
|
||||
defaultmask= HTONL(0xffffffff);
|
||||
#endif
|
||||
}
|
||||
if (destination & ~defaultmask)
|
||||
{
|
||||
/* host route */
|
||||
#ifdef __NBSD_LIBC
|
||||
defaultmask= htonl(0xffffffff);
|
||||
#else
|
||||
defaultmask= HTONL(0xffffffff);
|
||||
#endif
|
||||
}
|
||||
if (!cidr)
|
||||
netmask= defaultmask;
|
||||
|
||||
4
commands/adduser/Makefile
Normal file
4
commands/adduser/Makefile
Normal file
@@ -0,0 +1,4 @@
|
||||
SCRIPTS= adduser.sh
|
||||
MAN=
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
121
commands/adduser/adduser.sh
Normal file
121
commands/adduser/adduser.sh
Normal file
@@ -0,0 +1,121 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# adduser 1.0 - add a new user to the system Author: Kees J. Bot
|
||||
# 16 Jan 1996
|
||||
|
||||
# Check arguments.
|
||||
case "$#" in
|
||||
3) user="$1"; group="$2"; home="$3"
|
||||
;;
|
||||
*) echo "Usage: adduser user group home-dir" >&2; exit 1
|
||||
esac
|
||||
|
||||
# We need to be root.
|
||||
case "`id`" in
|
||||
'uid=0('*)
|
||||
;;
|
||||
*) echo "adduser: you must be root to add users" >&2; exit 1
|
||||
esac
|
||||
|
||||
# User and group names must be alphanumeric and no longer than 8 characters.
|
||||
len=`expr "$user" : '[a-z][a-z0-9]*$'`
|
||||
if [ "$len" -eq 0 -o "$len" -gt 8 ]
|
||||
then
|
||||
echo >&2 \
|
||||
"adduser: the user name must be alphanumeric and no longer than 8 characters"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
len=`expr "$group" : '[a-z][a-z0-9]*$'`
|
||||
if [ "$len" -eq 0 -o "$len" -gt 8 ]
|
||||
then
|
||||
echo >&2 \
|
||||
"adduser: the group name must be alphanumeric and no longer than 8 characters"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# The new user name must not exist, but the group must exist.
|
||||
if grep "^$user:" /etc/passwd >/dev/null
|
||||
then
|
||||
echo "adduser: user $user already exists" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
gid=`sed -e "/^$group:/!d" -e 's/^[^:]*:[^:]*:\\([^:]*\\):.*/\\1/' /etc/group`
|
||||
if [ `expr "$gid" : '[0-9]*$'` -eq 0 ]
|
||||
then
|
||||
echo "adduser: group $group does not exist" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Find the first free user-id of 10 or higher.
|
||||
uid=10
|
||||
while grep "^[^:]*:[^:]*:$uid:.*" /etc/passwd >/dev/null
|
||||
do
|
||||
uid=`expr $uid + 1`
|
||||
done
|
||||
|
||||
# No interruptions.
|
||||
trap '' 1 2 3 15
|
||||
|
||||
# Lock the password file.
|
||||
ln /etc/passwd /etc/ptmp || {
|
||||
echo "adduser: password file busy, try again later"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Make the new home directory, it should not exist already.
|
||||
mkdir "$home" || {
|
||||
rm -rf /etc/ptmp
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Make the new home directory by copying the honorary home directory of our
|
||||
# fearless leader.
|
||||
echo cpdir /usr/ast "$home"
|
||||
cpdir /usr/ast "$home" || {
|
||||
rm -rf /etc/ptmp "$home"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Change the ownership to the new user.
|
||||
echo chown -R $uid:$gid "$home"
|
||||
chown -R $uid:$group "$home" || {
|
||||
rm -rf /etc/ptmp "$home"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Is there a shadow password file? If so add an entry.
|
||||
if [ -f /etc/shadow ]
|
||||
then
|
||||
echo "echo $user::0:0::: >>/etc/shadow"
|
||||
echo "$user::0:0:::" >>/etc/shadow || {
|
||||
rm -rf /etc/ptmp "$home"
|
||||
exit 1
|
||||
}
|
||||
pwd="##$user"
|
||||
else
|
||||
pwd=
|
||||
fi
|
||||
|
||||
# Finish up by adding a password file entry.
|
||||
echo "echo $user:$pwd:$uid:$gid:$user:$home: >>/etc/passwd"
|
||||
echo "$user:$pwd:$uid:$gid:$user:$home:" >>/etc/passwd || {
|
||||
rm -rf /etc/ptmp "$home"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Remove the lock.
|
||||
rm /etc/ptmp || exit
|
||||
|
||||
echo "
|
||||
The new user $user has been added to the system. Note that the password,
|
||||
full name, and shell may be changed with the commands passwd(1), chfn(1),
|
||||
and chsh(1). The password is now empty, so only console logins are possible."
|
||||
if [ $gid = 0 ]
|
||||
then
|
||||
echo "\
|
||||
Also note that a new operator needs an executable search path (\$PATH) that
|
||||
does not contain the current directory (an empty field or "." in \$PATH)."
|
||||
fi
|
||||
exit 0
|
||||
34
commands/advent/Makefile
Normal file
34
commands/advent/Makefile
Normal file
@@ -0,0 +1,34 @@
|
||||
# Makefile for advent
|
||||
|
||||
PROG= advent
|
||||
SRCS= advent.c database.c english.c initial.c itverb.c score.c \
|
||||
travel.c turn.c utility.c verb.c vocab.c
|
||||
|
||||
# Where to put the adventure text files
|
||||
# Need the trailing "/" on TEXTDIR
|
||||
TEXTDIR= /usr/lib/advent/
|
||||
FILESDIR= ${TEXTDIR}
|
||||
DATFILES= advent1.dat advent2.dat advent3.dat advent4.dat
|
||||
FILES= ${DATFILES}
|
||||
MAN=
|
||||
|
||||
database.o: advtext.h
|
||||
|
||||
setup: setup.c advent.h
|
||||
${CC} ${CPPFLAGS} ${LDFLAGS} -o $@ ${.CURDIR}/setup.c
|
||||
|
||||
advtext.h advent1.dat advent2.dat advent3.dat advent4.dat: \
|
||||
setup advent1.txt advent2.txt advent3.txt advent4.txt
|
||||
./setup ${.CURDIR}
|
||||
|
||||
database.d: touch-genfiles
|
||||
|
||||
touch-genfiles:
|
||||
[ -e advtext.h ] || touch -t 197001010000.00 advtext.h
|
||||
|
||||
CPPFLAGS.advent.c= -DTEXTDIR='"${TEXTDIR}"'
|
||||
|
||||
CLEANFILES+= ${DATFILES} advtext.h setup
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
|
||||
1357
commands/advent/advcave.h
Normal file
1357
commands/advent/advcave.h
Normal file
File diff suppressed because it is too large
Load Diff
71
commands/advent/advdec.h
Normal file
71
commands/advent/advdec.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/* header ADVDEC.H *
|
||||
* WARNING: GLOBAL (EXTERNAL) declarations for adventure */
|
||||
|
||||
#ifndef EXTERN /* #define as '' to define the variables */
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
EXTERN boolean gaveup; /* TRUE if he quits early */
|
||||
EXTERN FILE *fd1, *fd2, *fd3, *fd4;
|
||||
|
||||
/*
|
||||
English variables
|
||||
*/
|
||||
EXTERN char *vtxt[MAXWORDS], *iotxt[MAXITEMS], *otxt[MAXITEMS];
|
||||
EXTERN int verbs[MAXWORDS], objs[MAXITEMS], iobjs[MAXITEMS];
|
||||
EXTERN int vrbx, objx, iobx;
|
||||
EXTERN int verb, object, motion, iobj, prep;
|
||||
EXTERN boolean newtravel, is_wiz;
|
||||
|
||||
/*
|
||||
Play variables
|
||||
*/
|
||||
extern int plac[MAXOBJ]; /* initial location */
|
||||
extern int fixd[MAXOBJ];
|
||||
struct playinfo {
|
||||
int turns;
|
||||
int loc, oldloc, oldloc2, newloc; /* location variables */
|
||||
long loc_attrib[MAXLOC+1]; /* location status */
|
||||
int place[MAXOBJ]; /* object location */
|
||||
int fixed[MAXOBJ]; /* second object loc */
|
||||
int weight[MAXOBJ];
|
||||
int atloc[MAXLOC+1];
|
||||
int link[MAXOBJ * 2];
|
||||
int holder[MAXOBJ];
|
||||
int hlink[MAXOBJ];
|
||||
int visited[MAXLOC+1]; /* >0 if has been here */
|
||||
int prop[MAXOBJ]; /* status of object */
|
||||
long obj_state[MAXOBJ];
|
||||
long points[MAXOBJ];
|
||||
int hinted[HNTMAX+1];
|
||||
int hints[HNTMAX+1][5];
|
||||
int hintlc[HNTMAX+1];
|
||||
int tally, tally2; /* item counts */
|
||||
int limit; /* time limit */
|
||||
int lmwarn; /* lamp warning flag */
|
||||
int wzdark, closing, closed; /* game state flags */
|
||||
int holding; /* count of held items */
|
||||
int detail; /* LOOK count */
|
||||
int knfloc; /* knife location */
|
||||
int clock, clock2, panic; /* timing variables */
|
||||
int dloc[DWARFMAX+1]; /* dwarf locations */
|
||||
int dflag; /* dwarf flag */
|
||||
int dseen[DWARFMAX+1]; /* dwarf seen flag */
|
||||
int odloc[DWARFMAX+1]; /* dwarf old locations */
|
||||
int daltloc; /* alternate appearance */
|
||||
int dkill; /* dwarves killed */
|
||||
int chloc, chloc2; /* chest locations */
|
||||
int bonus; /* to pass to end */
|
||||
int numdie; /* number of deaths */
|
||||
int foobar; /* fee fie foe foo... */
|
||||
int combo; /* combination for safe */
|
||||
boolean terse;
|
||||
int abbnum;
|
||||
int health;
|
||||
int chase;
|
||||
boolean flg239;
|
||||
|
||||
|
||||
int lastglob; /* to get space req. */
|
||||
};
|
||||
extern struct playinfo g;
|
||||
136
commands/advent/advent.c
Normal file
136
commands/advent/advent.c
Normal file
@@ -0,0 +1,136 @@
|
||||
/** Adventure translated from Fortran to "C"
|
||||
and ported to Minix by:
|
||||
Robert R. Hall
|
||||
San Diego, Calif 92115
|
||||
hall@crash.cts.com
|
||||
*/
|
||||
|
||||
/** program ADVENT.C *
|
||||
* "advent.c" allocates GLOBAL storage space by *
|
||||
* #defining EXTERN before #including "advdec.h". */
|
||||
|
||||
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include "advent.h" /* #define preprocessor equates */
|
||||
#include "advdec.h"
|
||||
|
||||
#ifndef TEXTDIR
|
||||
#define TEXTDIR ""
|
||||
#endif
|
||||
|
||||
char textdir[] = TEXTDIR; /* directory where text files
|
||||
live. */
|
||||
|
||||
_PROTOTYPE(int main, (int, char **));
|
||||
_PROTOTYPE(static void opentxt, (void));
|
||||
_PROTOTYPE(static void file_error, (char *));
|
||||
|
||||
int main(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
opentxt();
|
||||
initialize();
|
||||
rspeak(325);
|
||||
if (argc == 2)
|
||||
restore(argv[1]);
|
||||
else {
|
||||
g.hinted[3] = yes(65, 1, 0);
|
||||
g.limit = (g.hinted[3] ? 800 : 550);
|
||||
}
|
||||
gaveup = FALSE;
|
||||
srand((unsigned) time(NULL)); /* seed random */
|
||||
while (!gaveup)
|
||||
turn();
|
||||
fclose(fd1);
|
||||
fclose(fd2);
|
||||
fclose(fd3);
|
||||
fclose(fd4);
|
||||
return (EXIT_SUCCESS); /* exit = ok */
|
||||
} /* main */
|
||||
|
||||
/*
|
||||
Open advent?.txt files
|
||||
*/
|
||||
static void opentxt()
|
||||
{
|
||||
static char filename[sizeof(textdir) + 16];
|
||||
static FILE **fp[] = {0, &fd1, &fd2, &fd3, &fd4};
|
||||
int i;
|
||||
for (i = 1; i <= 4; i++) {
|
||||
sprintf(filename, "%sadvent%d.dat", textdir, i);
|
||||
*fp[i] = fopen(filename, "r");
|
||||
if (!*fp[i])
|
||||
file_error(filename);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
save adventure game
|
||||
*/
|
||||
void saveadv(username)
|
||||
char *username;
|
||||
{
|
||||
int cnt;
|
||||
FILE *savefd;
|
||||
|
||||
savefd = fopen(username, "wb");
|
||||
if (savefd == NULL) {
|
||||
perror(username);
|
||||
return;
|
||||
}
|
||||
cnt = fwrite((void *) &g, 1, sizeof(struct playinfo), savefd);
|
||||
if (cnt != sizeof(struct playinfo)) {
|
||||
fprintf(stderr, "wrote %d of %u bytes\n",
|
||||
cnt, (unsigned) sizeof(struct playinfo));
|
||||
if (ferror(savefd)) {
|
||||
fprintf(stderr, "errno is: 0x%.4x\n", errno);
|
||||
perror(username);
|
||||
}
|
||||
}
|
||||
if (fclose(savefd) == -1) {
|
||||
perror(username);
|
||||
}
|
||||
printf("Saved in %s.\n", username);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
restore saved game handler
|
||||
*/
|
||||
void restore(username)
|
||||
char *username;
|
||||
{
|
||||
int cnt;
|
||||
FILE *restfd;
|
||||
|
||||
restfd = fopen(username, "rb");
|
||||
if (restfd == NULL)
|
||||
file_error(username);
|
||||
cnt = fread((void *) &g, 1, sizeof(struct playinfo), restfd);
|
||||
if (cnt != sizeof(struct playinfo)) {
|
||||
fprintf(stderr, "read %d bytes, expected %u\n",
|
||||
cnt, (unsigned) sizeof(struct playinfo));
|
||||
if (ferror(restfd)) {
|
||||
fprintf(stderr, "errno is: 0x%.4x\n", errno);
|
||||
perror(username);
|
||||
}
|
||||
}
|
||||
if (fclose(restfd) == -1) {
|
||||
perror(username);
|
||||
}
|
||||
printf("Restored from %s.\n", username);
|
||||
return;
|
||||
}
|
||||
|
||||
static void file_error(filename)
|
||||
char *filename;
|
||||
{
|
||||
perror(filename);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
405
commands/advent/advent.h
Normal file
405
commands/advent/advent.h
Normal file
@@ -0,0 +1,405 @@
|
||||
/* header ADVENT.H *
|
||||
* WARNING: HEADER file for all adventure modules */
|
||||
|
||||
#ifndef EXIT_FAILURE
|
||||
#define EXIT_FAILURE 1
|
||||
#define EXIT_SUCCESS (!(EXIT_FAILURE))
|
||||
#endif
|
||||
|
||||
#define INPUTBUFLEN 80 /* Max input line length */
|
||||
|
||||
typedef int boolean;
|
||||
#define FALSE (0)
|
||||
#define TRUE (!FALSE)
|
||||
|
||||
#define MAXOBJ 123 /* max # of objects in cave */
|
||||
#define MAXLOC 248 /* max # of cave locations */
|
||||
#define WORDSIZE 20 /* max # of chars in commands */
|
||||
#define MAXMSG 408 /* max # of long location descr */
|
||||
#define HNTMAX 18 /* max # of hints */
|
||||
#define HNTMIN 7 /* hints starting count */
|
||||
|
||||
#define MAXWORDS 25
|
||||
#define MAXITEMS 45
|
||||
|
||||
#define CLASS(word) ((word)<0 ? -((-(word)) / 1000) : (word) / 1000)
|
||||
#define VAL(word) ((word)<0 ? -((-(word)) % 1000) : (word) % 1000)
|
||||
#define MAXTRAV (23+1) /* max # of travel directions from loc */
|
||||
/* +1 for terminator travel[x].tdest=-1 */
|
||||
#define DWARFMAX 6 /* max # of nasty dwarves */
|
||||
#define MAXDIE 3 /* max # of deaths before close */
|
||||
#define MAXTRS 79 /* max # of */
|
||||
|
||||
#define Y2 33
|
||||
/*
|
||||
Object definitions
|
||||
*/
|
||||
#define ANVIL 91
|
||||
#define AXE 28
|
||||
#define BATTERIES 39
|
||||
#define BEAR 35
|
||||
#define BEES 87
|
||||
#define BILLBD 116
|
||||
#define BIRD 101
|
||||
#define BOAT 48
|
||||
#define BOOK 110
|
||||
#define BOOK2 BOOK + 1
|
||||
#define BOOTH 93
|
||||
#define BOTTLE 20
|
||||
#define BRUSH 114
|
||||
#define CAGE 4
|
||||
#define CAKES 107
|
||||
#define CARVNG 115
|
||||
#define CASK 71
|
||||
#define CHAIN 64
|
||||
#define CHASM 21
|
||||
#define CHASM2 CHASM + 1
|
||||
#define CHEST 55
|
||||
#define CLAM 14
|
||||
#define CLOAK 47
|
||||
#define COINS 54
|
||||
#define CROWN 66
|
||||
#define DOG 98
|
||||
#define DOOR 41 /* giant door */
|
||||
#define DRAGON 31
|
||||
#define DWARF 17
|
||||
#define EGGS 56
|
||||
#define EMERALD 59
|
||||
#define FISSURE 12
|
||||
#define FLOWER 46
|
||||
#define FLY 69
|
||||
#define FOOD 19
|
||||
#define GNOME 105
|
||||
#define GRAIL 70
|
||||
#define GRATE 3
|
||||
#define HIVE 97
|
||||
#define HONEY 96
|
||||
#define HORN 52
|
||||
#define JEWELS 53
|
||||
#define KEYS 102
|
||||
#define KNIFE 18
|
||||
#define LAMP 2
|
||||
#define LYRE 68
|
||||
#define MAGAZINE 16
|
||||
#define MESSAGE 36
|
||||
#define MIRROR 23
|
||||
#define MUSHRM 106
|
||||
#define NUGGET 50
|
||||
#define OIL 83
|
||||
#define OIL2 OIL + 1
|
||||
#define OYSTER 15
|
||||
#define PLAGUE 125
|
||||
#define PEARL 61
|
||||
#define PHONE 94
|
||||
#define PILLOW 10
|
||||
#define PLANT 24
|
||||
#define PLANT2 PLANT + 1
|
||||
#define POLE 9
|
||||
#define POSTER 113
|
||||
#define PYRAMID 60
|
||||
#define RADIUM 119
|
||||
#define RING 72
|
||||
#define ROCKS 92
|
||||
#define ROD 5
|
||||
#define ROD2 ROD + 1
|
||||
#define RUG 62
|
||||
#define SAFE 112
|
||||
#define SAPPHIRE 69
|
||||
#define SHIELD 118
|
||||
#define SHOES 67
|
||||
#define SKEY 90
|
||||
#define SLUGS 95
|
||||
#define SNAKE 11
|
||||
#define SPHERE 120
|
||||
#define SPICES 63
|
||||
#define SPIDER 121
|
||||
#define STEPS 7
|
||||
#define STICKS 49
|
||||
#define SWORD 65
|
||||
#define TABLET 13
|
||||
#define TDOOR 42 /* tiny door */
|
||||
#define TDOOR2 TDOOR + 1 /* wrought-iron door */
|
||||
#define PDOOR TDOOR2 + 1 /* door to phone booth */
|
||||
#define TRIDENT 57
|
||||
#define TROLL 33
|
||||
#define TROLL2 TROLL + 1
|
||||
#define VASE 58
|
||||
#define VEND 38
|
||||
#define WALL 88
|
||||
#define WALL2 WALL + 1
|
||||
#define WATER 81 /* in bottle */
|
||||
#define WATER2 WATER + 1 /* in cask */
|
||||
#define WINE 85 /* in bottle */
|
||||
#define WINE2 WINE + 1 /* in cask */
|
||||
#define WUMPUS 99
|
||||
|
||||
/*
|
||||
Verb definitions
|
||||
*/
|
||||
#define BACK 8
|
||||
#define CAVE 67
|
||||
#define DEPRESSION 63
|
||||
#define ENTRANCE 64
|
||||
#define EXIT 11
|
||||
#define NULLX 21
|
||||
|
||||
/*
|
||||
Action verb definitions
|
||||
*/
|
||||
#define TAKE 1
|
||||
#define DROP 2
|
||||
#define SAY 3
|
||||
#define OPEN 4
|
||||
#define NOTHING 5
|
||||
#define CLOSE 6
|
||||
#define ON 7
|
||||
#define OFF 8
|
||||
#define WAVE 9
|
||||
#define CALM 10
|
||||
#define WALK 11
|
||||
#define KILL 12
|
||||
#define POUR 13
|
||||
#define EAT 14
|
||||
#define DRINK 15
|
||||
#define RUB 16
|
||||
#define THROW 17
|
||||
#define QUIT 18
|
||||
#define FIND 19
|
||||
#define INVENTORY 20
|
||||
#define FEED 21
|
||||
#define FILL 22
|
||||
#define BLAST 23
|
||||
#define SCORE 24
|
||||
#define FOO 25
|
||||
#define BRIEF 26
|
||||
#define READ 27
|
||||
#define BREAK 28
|
||||
#define WAKE 29
|
||||
#define SUSPEND 30
|
||||
#define RESTORE 31
|
||||
#define YANK 32
|
||||
#define WEAR 33
|
||||
#define HIT 34
|
||||
#define ANSWER 35
|
||||
#define BLOW 36
|
||||
#define LEAVE 37
|
||||
#define YELL 38
|
||||
#define DIAL 39
|
||||
#define PLAY 40
|
||||
#define PICK 41
|
||||
#define PUT 42
|
||||
#define TURN 43
|
||||
#define GET 44
|
||||
#define INSRT 45
|
||||
#define REMOVE 46
|
||||
#define BURN 47
|
||||
#define GRIPE 48
|
||||
#define LOCK 49
|
||||
#define UNLOCK 50
|
||||
#define HEALTH 51
|
||||
#define LOOK 52
|
||||
#define COMBO 53
|
||||
#define SWEEP 54
|
||||
#define TERSE 55
|
||||
#define WIZ 56
|
||||
#define MAP 57
|
||||
#define GATE 58
|
||||
#define PIRLOC 59
|
||||
|
||||
#define GO 11
|
||||
#define SHUT 6
|
||||
#define LOG 33
|
||||
|
||||
#define MOTION 0 /* CLASSD */
|
||||
#define NOUN 1 /* CLASSN */
|
||||
#define ACTION 2 /* CLASSA */
|
||||
#define MISC 3 /* CLASSM */
|
||||
#define PREPOSITION 4 /* CLASSP */
|
||||
#define ADJACTIVE 5 /* CLASSJ */
|
||||
#define CONJUNCTION 6 /* CLASSC */
|
||||
|
||||
/*
|
||||
and a few preposition. prefix PREP to distinguish them from
|
||||
verbs or nouns
|
||||
*/
|
||||
#define PREPAT 9
|
||||
#define PREPDN 8
|
||||
#define PREPIN 1
|
||||
#define PREPFR 5
|
||||
#define PREPOF 6
|
||||
#define PREPOFF 6
|
||||
#define PREPON 2
|
||||
|
||||
/*
|
||||
BIT mapping of "cond" array which indicates location status
|
||||
*/
|
||||
#define LIGHT 1
|
||||
#define WATOIL 2
|
||||
#define LIQUID 4
|
||||
#define NOPIRAT 16
|
||||
|
||||
/* Object condition bit functions */
|
||||
#define OPENBT 2
|
||||
#define LOCKBT 4
|
||||
#define BURNBT 6
|
||||
#define DEADBT 10
|
||||
#define WEARBT 12
|
||||
/*
|
||||
Structure definitions
|
||||
*/
|
||||
struct wac {
|
||||
char *aword;
|
||||
int acode;
|
||||
};
|
||||
|
||||
struct trav {
|
||||
int tdest;
|
||||
int tverb;
|
||||
int tcond;
|
||||
};
|
||||
|
||||
/* Function prototypes.
|
||||
"#if (__STDC__)" should have been be enough,
|
||||
but some compilers are stupid, so allow Makefile to say -DHAS_STDC=whatever.
|
||||
*/
|
||||
#if defined(HAS_STDC) ? (HAS_STDC) : (__STDC__)
|
||||
#undef HAS_STDC
|
||||
#define HAS_STDC 1
|
||||
#define _PROTOTYPE(function, params) function params
|
||||
#define _CONST const
|
||||
#else
|
||||
#define _PROTOTYPE(function, params) function ()
|
||||
#define _CONST
|
||||
#endif
|
||||
|
||||
/* Advent.c */
|
||||
|
||||
_PROTOTYPE(void saveadv, (char *username));
|
||||
_PROTOTYPE(void restore, (char *username));
|
||||
|
||||
/* Initialize.c */
|
||||
|
||||
_PROTOTYPE(void initialize, (void));
|
||||
|
||||
/* Database.c */
|
||||
|
||||
_PROTOTYPE(int yes, (int msg1, int msg2, int msg3));
|
||||
_PROTOTYPE(void rspeak, (int msg));
|
||||
_PROTOTYPE(void pspeak, (int item, int state));
|
||||
_PROTOTYPE(void desclg, (int loc));
|
||||
_PROTOTYPE(void descsh, (int loc));
|
||||
|
||||
/* English.c */
|
||||
|
||||
_PROTOTYPE(int english, (void));
|
||||
_PROTOTYPE(int analyze, (char *word, int *type, int *value));
|
||||
|
||||
/* Itverb.c */
|
||||
|
||||
_PROTOTYPE(void itverb, (void));
|
||||
_PROTOTYPE(void ivblast, (void));
|
||||
_PROTOTYPE(void ivlook, (void));
|
||||
|
||||
/* Turn.c */
|
||||
|
||||
_PROTOTYPE(void turn, (void));
|
||||
_PROTOTYPE(void describe, (void));
|
||||
_PROTOTYPE(void descitem, (void));
|
||||
_PROTOTYPE(void dwarfend, (void));
|
||||
_PROTOTYPE(void normend, (void));
|
||||
_PROTOTYPE(void score, (int));
|
||||
_PROTOTYPE(void death, (void));
|
||||
_PROTOTYPE(char *probj, (void));
|
||||
_PROTOTYPE(void trobj, (void));
|
||||
_PROTOTYPE(void dwarves, (void));
|
||||
_PROTOTYPE(void dopirate, (void));
|
||||
_PROTOTYPE(int stimer, (void));
|
||||
|
||||
/* Verb.c */
|
||||
|
||||
_PROTOTYPE(void trverb, (void));
|
||||
_PROTOTYPE(void vtake, (void));
|
||||
_PROTOTYPE(void vdrop, (void));
|
||||
_PROTOTYPE(void vopen, (void));
|
||||
_PROTOTYPE(void vsay, (void));
|
||||
_PROTOTYPE(void von, (void));
|
||||
_PROTOTYPE(void voff, (void));
|
||||
_PROTOTYPE(void vwave, (void));
|
||||
_PROTOTYPE(void vkill, (void));
|
||||
_PROTOTYPE(void vpour, (void));
|
||||
_PROTOTYPE(void veat, (void));
|
||||
_PROTOTYPE(void vdrink, (void));
|
||||
_PROTOTYPE(void vthrow, (void));
|
||||
_PROTOTYPE(void vfind, (void));
|
||||
_PROTOTYPE(void vfill, (void));
|
||||
_PROTOTYPE(void vfeed, (void));
|
||||
_PROTOTYPE(void vread, (void));
|
||||
_PROTOTYPE(void vbreak, (void));
|
||||
_PROTOTYPE(void vwake, (void));
|
||||
_PROTOTYPE(void actspk, (int verb));
|
||||
_PROTOTYPE(void vyank, (void));
|
||||
_PROTOTYPE(void vwear, (void));
|
||||
_PROTOTYPE(void vlock, (void));
|
||||
_PROTOTYPE(void vunlock, (void));
|
||||
_PROTOTYPE(void vclose, (void));
|
||||
|
||||
/* Utility.c */
|
||||
|
||||
_PROTOTYPE(boolean ajar, (int));
|
||||
_PROTOTYPE(boolean at, (int item));
|
||||
_PROTOTYPE(boolean athand, (int));
|
||||
_PROTOTYPE(void bitoff, (int, int));
|
||||
_PROTOTYPE(void biton, (int, int));
|
||||
_PROTOTYPE(boolean bitset, (long, int));
|
||||
_PROTOTYPE(boolean blind, (void));
|
||||
_PROTOTYPE(int burden, (int));
|
||||
_PROTOTYPE(void carry, (int obj, int where));
|
||||
_PROTOTYPE(int confuz, (void));
|
||||
_PROTOTYPE(boolean dark, (void));
|
||||
_PROTOTYPE(boolean dcheck, (void));
|
||||
_PROTOTYPE(boolean dead, (int));
|
||||
_PROTOTYPE(void drop, (int obj, int where));
|
||||
_PROTOTYPE(void destroy, (int obj));
|
||||
_PROTOTYPE(boolean edible, (int));
|
||||
_PROTOTYPE(boolean enclosed, (int));
|
||||
_PROTOTYPE(void extract, (int));
|
||||
_PROTOTYPE(boolean forced, (int atloc));
|
||||
_PROTOTYPE(boolean here, (int item));
|
||||
_PROTOTYPE(boolean hinged, (int));
|
||||
_PROTOTYPE(boolean holding, (int));
|
||||
_PROTOTYPE(void insert, (int, int));
|
||||
_PROTOTYPE(boolean inside, (int));
|
||||
_PROTOTYPE(void juggle, (int loc));
|
||||
_PROTOTYPE(int liq, (int));
|
||||
_PROTOTYPE(int liqloc, (int loc));
|
||||
_PROTOTYPE(int liq2, (int pbottle));
|
||||
_PROTOTYPE(boolean living, (int));
|
||||
_PROTOTYPE(boolean locked, (int));
|
||||
_PROTOTYPE(boolean locks, (int));
|
||||
_PROTOTYPE(void lookin, (int));
|
||||
_PROTOTYPE(void move, (int obj, int where));
|
||||
_PROTOTYPE(int noway, (void));
|
||||
_PROTOTYPE(boolean opaque, (int));
|
||||
_PROTOTYPE(boolean outside, (int));
|
||||
_PROTOTYPE(boolean pct, (int x));
|
||||
_PROTOTYPE(boolean plural, (int));
|
||||
_PROTOTYPE(boolean portal, (int));
|
||||
_PROTOTYPE(boolean printed, (int));
|
||||
_PROTOTYPE(int put, (int obj, int where, int pval));
|
||||
_PROTOTYPE(int ranz, (int));
|
||||
_PROTOTYPE(boolean small, (int));
|
||||
_PROTOTYPE(boolean toting, (int item));
|
||||
_PROTOTYPE(boolean treasr, (int));
|
||||
_PROTOTYPE(boolean vessel, (int));
|
||||
_PROTOTYPE(boolean wearng, (int));
|
||||
_PROTOTYPE(boolean worn, (int));
|
||||
_PROTOTYPE(void bug, (unsigned int n));
|
||||
_PROTOTYPE(char *ask, (char *prompt, char *buf, int buflen));
|
||||
_PROTOTYPE(void panic, (char *msg, boolean save));
|
||||
|
||||
/* travel.c */
|
||||
_PROTOTYPE(void domove, (void));
|
||||
_PROTOTYPE(void gettrav, (int loc, struct trav *travel));
|
||||
|
||||
/* vocab.c */
|
||||
_PROTOTYPE(int vocab, (char *word, int val));
|
||||
827
commands/advent/advent1.txt
Normal file
827
commands/advent/advent1.txt
Normal file
@@ -0,0 +1,827 @@
|
||||
#1
|
||||
You are standing at the end of a road before a small brick building.
|
||||
Around you is a forest. A small stream flows out of the building and
|
||||
down a gully.
|
||||
#2
|
||||
You have walked up a hill, still in the forest. The road slopes back
|
||||
down the other side of the hill. There is a building in the distance.
|
||||
#3
|
||||
You are inside a building, a well house for a large spring. Off
|
||||
to one side is a small pantry.
|
||||
#4
|
||||
You are in a valley in the forest beside a stream tumbling along a
|
||||
rocky bed.
|
||||
#5
|
||||
You are in open forest, with a deep valley to one side. Not far
|
||||
is a large billboard.
|
||||
#6
|
||||
You are in open forest near both a valley and a road.
|
||||
#7
|
||||
At your feet all the water of the stream splashes into a 2-inch slit
|
||||
in the rock. Downstream the stream bed is bare rock.
|
||||
#8
|
||||
You are in a 20-foot depression floored with bare dirt. Set into the
|
||||
dirt is a strong steel grate mounted in concrete. A dry stream bed
|
||||
leads into the depression.
|
||||
#9
|
||||
You are in a small chamber beneath a 3x3 steel grate to the surface.
|
||||
A low crawl over cobbles leads inward to the west.
|
||||
#10
|
||||
You are crawling over cobbles in a low passage. There is a dim light
|
||||
at the east end of the passage.
|
||||
#11
|
||||
You are in a debris room filled with stuff washed in from the surface.
|
||||
A low wide passage with cobbles becomes plugged with mud and debris
|
||||
here, but an awkward canyon leads upward and west. A note on the wall
|
||||
says "Magic Word XYZZY".
|
||||
#12
|
||||
You are in an awkward sloping east/west canyon.
|
||||
#13
|
||||
You are in a splendid chamber thirty feet high. The walls are frozen
|
||||
rivers of orange stone. An awkward canyon and a good passage exit
|
||||
from east and west sides of the chamber.
|
||||
#14
|
||||
At your feet is a small pit breathing traces of white mist. An east
|
||||
passage ends here except for a small crack leading on.
|
||||
#15
|
||||
You are at one end of a vast hall stretching forward out of sight to
|
||||
the west. There are openings to either side. Nearby, a wide stone
|
||||
staircase leads downward. The hall is filled with wisps of white mist
|
||||
swaying to and fro almost as if alive. A cold wind blows up the
|
||||
staircase. There is a passage at the top of a dome behind you.
|
||||
#16
|
||||
The crack is far too small for you to follow.
|
||||
#17
|
||||
You are on the east bank of a fissure slicing clear across the hall.
|
||||
The mist is quite thick here, and the fissure is too wide to jump.
|
||||
#18
|
||||
This is a low room with a crude note on the wall. The note says,
|
||||
"You won't get it up the steps".
|
||||
#19
|
||||
You are in the Hall of the Mountain King, with passages off in all
|
||||
directions.
|
||||
#20
|
||||
You are at the bottom of the pit with a broken neck.
|
||||
#21
|
||||
You didn't make it.
|
||||
#22
|
||||
The dome is unclimbable.
|
||||
#23
|
||||
You are at the west end of the Twopit Room. There is a large hole in
|
||||
the wall above the pit at this end of the room.
|
||||
#24
|
||||
You are at the bottom of the eastern pit in the Twopit Room. There is
|
||||
a small pool of oil in one corner of the pit.
|
||||
#25
|
||||
You are at the bottom of the western pit in the Twopit Room. There is
|
||||
a large hole in the wall about 25 feet above you.
|
||||
#26
|
||||
You clamber up the plant and scurry through the hole at the top.
|
||||
#27
|
||||
You are on the west side of the fissure in the Hall of Mists.
|
||||
#28
|
||||
You are in a low N/S passage at a hole in the floor. The hole goes
|
||||
down to an E/W passage.
|
||||
#29
|
||||
You are in the South Side Chamber.
|
||||
#30
|
||||
You are in the West Side Chamber of the Hall of the Mountain King.
|
||||
A passage continues west and up here.
|
||||
#31
|
||||
<$$<
|
||||
#32
|
||||
You can't get by the snake.
|
||||
#33
|
||||
You are in a large room, with a passage to the south, a passage to the
|
||||
west, and a wall of broken rock to the east. There is a large "Y2" on
|
||||
a rock in the room's center.
|
||||
#34
|
||||
You are in a jumble of rock, with cracks everywhere.
|
||||
#35
|
||||
You're at a low window overlooking a huge pit, which extends up out of
|
||||
sight. A floor is indistinctly visible over 50 feet below. Traces of
|
||||
white mist cover the floor of the pit, becoming thicker to the right.
|
||||
Marks in the dust around the window would seem to indicate that
|
||||
someone has been here recently. Directly across the pit from you and
|
||||
25 feet away there is a similar window looking into a lighted room. A
|
||||
shadowy figure can be seen there peering back at you.
|
||||
#36
|
||||
You are in a dirty broken passage. To the east is a crawl. To the
|
||||
west is a large passage. Above you is a hole to another passage.
|
||||
#37
|
||||
You are on the brink of a small clean climbable pit. A crawl leads
|
||||
west.
|
||||
#38
|
||||
You are in the bottom of a small pit with a little stream, which
|
||||
enters and exits through tiny slits.
|
||||
#39
|
||||
You are in a large room full of dusty rocks. There is a big hole in
|
||||
the floor. There are cracks everywhere, and a passage leading east.
|
||||
#40
|
||||
You have crawled through a very low wide passage parallel to and north
|
||||
of the Hall of Mists.
|
||||
#41
|
||||
You are at the west end of Hall of Mists. A low wide crawl continues
|
||||
west and another goes north. To the south is a little passage 6 feet
|
||||
off the floor.
|
||||
#42
|
||||
You are in a maze of twisty little passages, all alike.
|
||||
#43
|
||||
You are in a maze of twisty little passages, all alike.
|
||||
#44
|
||||
You are in a maze of twisty little passages, all alike.
|
||||
#45
|
||||
You are in a maze of twisty little passages, all alike.
|
||||
#46
|
||||
Dead end.
|
||||
#47
|
||||
Dead end.
|
||||
#48
|
||||
Dead end.
|
||||
#49
|
||||
You are in a maze of twisty little passages, all alike.
|
||||
#50
|
||||
You are in a maze of twisty little passages, all alike.
|
||||
#51
|
||||
You are in a maze of twisty little passages, all alike.
|
||||
#52
|
||||
You are in a maze of twisty little passages, all alike.
|
||||
#53
|
||||
You are in a maze of twisty little passages, all alike.
|
||||
#54
|
||||
Dead end.
|
||||
#55
|
||||
You are in a maze of twisty little passages, all alike.
|
||||
#56
|
||||
Dead end.
|
||||
#57
|
||||
You are on the brink of a thirty foot pit with a massive orange column
|
||||
down one wall. You could climb down here but you could not get back
|
||||
up. The maze continues at this level.
|
||||
#58
|
||||
Dead end.
|
||||
#59
|
||||
You have crawled through a very low wide passage parallel to and north
|
||||
of the Hall of Mists.
|
||||
#60
|
||||
You are at the east end of a very long hall apparently without side
|
||||
chambers. In the south wall are several wide cracks and a high
|
||||
hole, but the hole is far above your head. To the east a wide
|
||||
crawl slants up. To the north a round two foot hole slants down.
|
||||
#61
|
||||
You are at the west end of a very long featureless hall. The hall
|
||||
joins up with a narrow north/south passage.
|
||||
#62
|
||||
You are at a crossover of a high N/S passage and a low E/W one.
|
||||
#63
|
||||
Dead end.
|
||||
#64
|
||||
You are at a complex junction. A low hands and knees passage from the
|
||||
north joins a higher crawl from the east to make a walking passage
|
||||
going west. There is also a large room above. The air is damp here.
|
||||
#65
|
||||
You are in Bedquilt, a long east/west passage with holes everywhere.
|
||||
To explore at random select north, south, up, or down.
|
||||
#66
|
||||
You are in a room whose walls resemble swiss cheese. Obvious passages
|
||||
go west, east, NE, and NW. Part of the room is occupied by a large
|
||||
bedrock block.
|
||||
#67
|
||||
You are at the east end of the Twopit Room. The floor here is
|
||||
littered with thin rock slabs, which make it easy to descend the pits.
|
||||
There is a path here bypassing the pits to connect passages from east
|
||||
and west. There are holes all over, but the only big one is on the
|
||||
wall directly over the west pit where you can't get to it.
|
||||
#68
|
||||
You are in a large low circular chamber whose floor is an immense slab
|
||||
fallen from the ceiling (Slab Room). East and west there once were
|
||||
large passages, but they are now filled with boulders. Low small
|
||||
passages go north and south, and the south one quickly bends west
|
||||
around the boulders.
|
||||
#69
|
||||
You are in a secret N/S canyon above a large room.
|
||||
#70
|
||||
You are in a secret N/S canyon above a sizable passage.
|
||||
#71
|
||||
You are in a secret canyon at a junction of three canyons, bearing
|
||||
north, south, and SE. The north one is as tall as the other two
|
||||
combined.
|
||||
#72
|
||||
You are in a large low room. Crawls lead north, NE, and SW.
|
||||
#73
|
||||
Dead end crawl.
|
||||
#74
|
||||
You are in a secret canyon which here runs E/W. It crosses over a
|
||||
very tight canyon 15 feet below. If you go down you may not be able
|
||||
to get back up.
|
||||
#75
|
||||
You are at a wide place in a very tight N/S canyon.
|
||||
#76
|
||||
The canyon here becomes too tight to go further south.
|
||||
#77
|
||||
You are in a tall E/W canyon. A low tight crawl goes 3 feet north and
|
||||
seems to open up.
|
||||
#78
|
||||
The canyon runs into a mass of boulders -- dead end.
|
||||
#79
|
||||
The stream flows out through a pair of 1 foot diameter sewer pipes.
|
||||
It would be advisable to use the exit.
|
||||
#80
|
||||
You are in a maze of twisty little passages, all alike.
|
||||
#81
|
||||
Dead end.
|
||||
#82
|
||||
Dead end.
|
||||
#83
|
||||
You are in a maze of twisty little passages, all alike.
|
||||
#84
|
||||
You are in a maze of twisty little passages, all alike.
|
||||
#85
|
||||
Dead end.
|
||||
#86
|
||||
Dead end.
|
||||
#87
|
||||
You are in a maze of twisty little passages, all alike.
|
||||
#88
|
||||
You are in a long, narrow corridor stretching out of sight to the
|
||||
west. At the eastern end is a hole through which you can see a
|
||||
profusion of leaves.
|
||||
#89
|
||||
There is nothing here to climb. Use "up" or "out" to leave the pit.
|
||||
#90
|
||||
You have climbed up the plant and out of the pit.
|
||||
#91
|
||||
You are at the top of a steep incline above a large room. You could
|
||||
climb down here, but you would not be able to climb up. There is a
|
||||
passage leading back to the north.
|
||||
#92
|
||||
You are in the Giant Room. The ceiling here is too high up for your
|
||||
lamp to show it. Cavernous passages lead east, north, and south. On
|
||||
the west wall is scrawled the inscription, "FEE FIE FOE FOO" [sic].
|
||||
#93
|
||||
The passage here is blocked by a recent cave-in.
|
||||
#94
|
||||
You are at one end of an immense north/south passage.
|
||||
#95
|
||||
You are in a magnificent cavern with a rushing stream, which cascades
|
||||
over a sparkling waterfall into a roaring whirlpool which disappears
|
||||
through a hole in the floor. Passages exit to the south and west.
|
||||
#96
|
||||
You are in the Soft Room. The walls are covered with heavy curtains,
|
||||
the floor with a thick pile carpet. Moss covers the ceiling.
|
||||
#97
|
||||
This is the Oriental Room. Ancient oriental cave drawings cover the
|
||||
walls. A gently sloping passage leads upward to the north, another
|
||||
passage leads SE, and a hands and knees crawl leads east.
|
||||
#98
|
||||
You are following a wide path around the outer edge of a large cavern.
|
||||
Far below, through a heavy white mist, strange splashing noises can be
|
||||
heard. The mist rises up through a fissure in the ceiling. The path
|
||||
hugs the cavern's rim to the NE and south, while another branch forks
|
||||
west. A round chute with extremely smooth walls angles sharply up
|
||||
to the southwest.
|
||||
#99
|
||||
You are in an alcove. A small NW path seems to widen after a short
|
||||
distance. An extremely tight tunnel leads east. It looks like a very
|
||||
tight squeeze. An eerie light can be seen at the other end.
|
||||
#100
|
||||
You're in a small chamber lit by an eerie green light. An extremely
|
||||
narrow tunnel exits to the west, and a dark corridor leads NE.
|
||||
#101
|
||||
You're in the Dark-Room. A corridor leading south is the only exit.
|
||||
#102
|
||||
You are in an arched hall. A coral passage once continued up and east
|
||||
from here, but is now blocked by debris. The air smells of sea water.
|
||||
#103
|
||||
You're in a large room carved out of sedimentary rock. The floor and
|
||||
walls are littered with bits of shells imbedded in the stone. A
|
||||
shallow passage proceeds downward, and a somewhat steeper one leads
|
||||
up. A low hands and knees passage enters from the south.
|
||||
#104
|
||||
You are in a long sloping corridor with ragged sharp walls.
|
||||
#105
|
||||
You are in a cul-de-sac about eight feet across.
|
||||
#106
|
||||
You are in an anteroom leading to a large passage to the east. Small
|
||||
passages go west and up. The remnants of recent digging are evident.
|
||||
A sign in midair here says "Cave under construction beyond this point.
|
||||
Proceed at own risk. [Witt Construction Company]".
|
||||
#107
|
||||
You are in a maze of twisty little passages, all different.
|
||||
#108
|
||||
You are at Witt's End. Passages lead off in *ALL* directions.
|
||||
#109
|
||||
You are in a north/south canyon about 25 feet across. The floor is
|
||||
covered by white mist seeping in from the north. The walls extend
|
||||
upward for well over 100 feet. Suspended from some unseen point far
|
||||
above you, an enormous two-sided mirror is hanging parallel to and
|
||||
midway between the canyon walls. (The mirror is obviously provided
|
||||
for the use of the dwarves, who as you know, are extremely vain.) A
|
||||
small window can be seen in either wall, some fifty feet up.
|
||||
#110
|
||||
You're at a low window overlooking a huge pit, which extends up out of
|
||||
sight. A floor is indistinctly visible over 50 feet below. Traces of
|
||||
white mist cover the floor of the pit, becoming thicker to the left.
|
||||
Marks in the dust around the window would seem to indicate that
|
||||
someone has been here recently. Directly across the pit from you and
|
||||
25 feet away there is a similar window looking into a lighted room. A
|
||||
shadowy figure can be seen there peering back at you.
|
||||
#111
|
||||
A large stalactite extends from the roof and almost reaches the floor
|
||||
below. You could climb down it, and jump from it to the floor, but
|
||||
having done so you would be unable to reach it to climb back up.
|
||||
#112
|
||||
You are in a little maze of twisting passages, all different.
|
||||
#113
|
||||
You are at the edge of a large underground reservoir. An opaque cloud
|
||||
of white mist fills the room and rises rapidly upward. The lake is
|
||||
fed by a stream, which tumbles out of a hole in the wall about 10 feet
|
||||
overhead and splashes noisily into the water somewhere within the
|
||||
mist. The indistinct shape of the opposite shore can be dimly seen
|
||||
through the mist. The only passage goes back toward the south.
|
||||
#114
|
||||
Dead end.
|
||||
#115
|
||||
You are at the northeast end of an immense room, even larger than the
|
||||
Giant Room. It appears to be a repository for the "ADVENTURE"
|
||||
program. Massive torches far overhead bathe the room with smoky
|
||||
yellow light. Scattered about you can be seen a pile of bottles (all
|
||||
of them empty), a nursery of young beanstalks murmuring quietly, a bed
|
||||
of oysters, a bundle of black rods with rusty stars on their ends, and
|
||||
a collection of brass lanterns. Off to one side a great many dwarves
|
||||
are sleeping on the floor, snoring loudly. A sign nearby reads: "Do
|
||||
not disturb the dwarves!" An immense mirror is hanging against one
|
||||
wall, and stretches to the other end of the room, where various other
|
||||
sundry objects can be glimpsed dimly in the distance. An unoccupied
|
||||
telephone booth stands against the north wall.
|
||||
#116
|
||||
You are at the southwest end of the repository. To one side is a pit
|
||||
full of fierce green snakes. On the other side is a row of small
|
||||
wicker cages, each of which contains a little sulking bird. In one
|
||||
corner is a bundle of black rods with rusty marks on their ends. A
|
||||
large number of velvet pillows are scattered about on the floor.
|
||||
Beside one of the pillows is a large, dusty, leather-bound volume
|
||||
with the title "History of Adventure" embossed in pure gold.
|
||||
A vast mirror stretches off to the northeast, almost reaching the
|
||||
phone booth. At your feet is a large steel grate, next to which is
|
||||
a sign which reads, "Treasure Vault. Keys in Main Office."
|
||||
#117
|
||||
You are on one side of a large, deep chasm. A heavy white mist rising
|
||||
up from below obscures all view of the far side. A SW path leads away
|
||||
from the chasm into a winding corridor.
|
||||
#118
|
||||
You are in a long winding corridor sloping out of sight in both
|
||||
directions.
|
||||
#119
|
||||
You are in a secret canyon which exits to the north and east.
|
||||
#120
|
||||
You are in a secret canyon which exits to the north and east.
|
||||
#121
|
||||
You are in a secret canyon which exits to the north and east.
|
||||
#122
|
||||
You are on the northeast side of a deep chasm. A NE path leads away
|
||||
from the chasm on this side.
|
||||
#123
|
||||
You're in a long east/west corridor. A faint rumbling noise can be
|
||||
heard in the distance.
|
||||
#124
|
||||
The path forks here. The left fork leads northeast. A dull rumbling
|
||||
seems to get louder in that direction. The right fork leads southeast
|
||||
down a gentle slope. The main corridor enters from the west.
|
||||
#125
|
||||
The walls are quite warm here. From the north can be heard a steady
|
||||
roar, so loud that the entire cave seems to be trembling. Another
|
||||
passage leads south, and a low crawl goes east.
|
||||
#126
|
||||
You are on the edge of a breathtaking view. Far below you is an
|
||||
active volcano, from which great gouts of molten lava come surging
|
||||
out, cascading back down into the depths. The glowing rock fills the
|
||||
farthest reaches of the cavern with a blood-red glare, giving every-
|
||||
thing an eerie, macabre appearance. The air is filled with flickering
|
||||
sparks of ash and a heavy smell of brimstone. The walls are hot to
|
||||
the touch, and the thundering of the volcano drowns out all other
|
||||
sounds. Embedded in the jagged roof far overhead are myriad twisted
|
||||
formations composed of pure white alabaster, which scatter the murky
|
||||
light into sinister apparitions upon the walls. To one side is a deep
|
||||
gorge, filled with a bizarre chaos of tortured rock which seems to
|
||||
have been crafted by the devil himself. An immense river of fire
|
||||
crashes out from the depths of the volcano, burns its way through the
|
||||
gorge, and plummets into a bottomless pit far off to your left. To
|
||||
the right, an immense geyser of blistering steam erupts continuously
|
||||
from a barren island in the center of a sulfurous lake, which bubbles
|
||||
ominously. The far right wall is aflame with an incandescence of its
|
||||
own, which lends an additional infernal splendor to the already
|
||||
hellish scene. A dark, foreboding passage exits to the south.
|
||||
#127
|
||||
You are in a small chamber filled with large boulders. The walls are
|
||||
very warm, causing the air in the room to be almost stifling from the
|
||||
heat. The only exit is a crawl heading west, through which is coming
|
||||
a low rumbling.
|
||||
#128
|
||||
You are walking along a gently sloping north/south passage lined with
|
||||
oddly shaped limestone formations.
|
||||
#129
|
||||
You are standing at the entrance to a large, barren room. A sign
|
||||
posted above the entrance reads: "Caution! Bear in room!"
|
||||
#130
|
||||
You are inside a barren room. The center of the room is completely
|
||||
empty except for some dust. Marks in the dust lead away toward the
|
||||
far end of the room. The only exit is the way you came in.
|
||||
#131
|
||||
You are in a maze of twisting little passages, all different.
|
||||
#132
|
||||
You are in a little maze of twisty passages, all different.
|
||||
#133
|
||||
You are in a twisting maze of little passages, all different.
|
||||
#134
|
||||
You are in a twisting little maze of passages, all different.
|
||||
#135
|
||||
You are in a twisty little maze of passages, all different.
|
||||
#136
|
||||
You are in a twisty maze of little passages, all different.
|
||||
#137
|
||||
You are in a little twisty maze of passages, all different.
|
||||
#138
|
||||
You are in a maze of little twisting passages, all different.
|
||||
#139
|
||||
You are in a maze of little twisty passages, all different.
|
||||
#140
|
||||
Dead end.
|
||||
#141
|
||||
You are on a narrow promontory at the foot of a waterfall, which
|
||||
spurts from an overhead hole in the rock wall and splashes into a
|
||||
large reservoir, sending up clouds of mist and spray.
|
||||
Through the thick white mist looms a polished marble slab, to
|
||||
which is affixed an enormous rusty iron anvil. In golden letters
|
||||
are written the words: "Whoso Pulleth Out This Sword of This
|
||||
Stone and Anvil, is Right wise King-Born of All This Mountain."
|
||||
There is a narrow chimney on the east side of the promontory.
|
||||
#142
|
||||
You are on a narrow shelf above and east of the top of a very steep
|
||||
chimney. A long smooth granite slide curves down out of sight
|
||||
to the east. If you go down the slide, you may not be able to
|
||||
climb back up.
|
||||
#143
|
||||
You are in the private chamber of the Mountain King. Hewn into the
|
||||
solid rock of the east wall of the chamber is an intricately-wrought
|
||||
throne of elvish design. There is an exit to the west.
|
||||
#144
|
||||
You are on the east side of the throne room. On the arm of the throne
|
||||
has been hung a sign which reads "Gone for the day: visiting
|
||||
sick snake. --M.K."
|
||||
#145
|
||||
You are dragged down, down, into the depths of the whirlpool.
|
||||
Just as you can no longer hold your breath, you are shot out over
|
||||
a waterfall into the shallow end of a large reservoir. Gasping
|
||||
and sputtering, you crawl weakly towards the shore....
|
||||
#146
|
||||
You are in dense forest, with a hill to one side. The trees appear
|
||||
to thin out towards the north and east.
|
||||
#147
|
||||
You are at the high point of a wide grassy knoll, partially surrounded
|
||||
by dense forest. The land rises to the south and east, and drops off
|
||||
sharply to the north and west. The air smells of sea water.
|
||||
#148
|
||||
You are at the edge of a trackless salt marsh. Tall reeds obscure
|
||||
the view.
|
||||
#149
|
||||
You're in salt marsh.
|
||||
#150
|
||||
You're in salty marsh.
|
||||
#151
|
||||
You are in salt marsh.
|
||||
#152
|
||||
Dead end.
|
||||
#153
|
||||
You're on a sandy beach at the edge of the open sea. The beach
|
||||
ends a short distance south and the land rises to a point. To
|
||||
the north, the beach ends cliffs and broken rocks.
|
||||
#154
|
||||
You are at a jumble of large broken rocks. A gentle path leads up
|
||||
to the top of the nearby cliffs. A narrow treacherous path
|
||||
disappears among the rocks at the foot of the cliff.
|
||||
#155
|
||||
You are on a high cliff overlooking the sea. Far below the
|
||||
rolling breakers smash into a jumble of large broken rocks.
|
||||
The thunder of the surf is deafening.
|
||||
#156
|
||||
You're at the bottom of the cliff, smashed to smithereens by the
|
||||
pounding surf.
|
||||
#157
|
||||
You are at Thunder Hole, a funnel shaped cavern opening onto the sea.
|
||||
The noise of the surf pounding against the outer rocks of the cave is
|
||||
amplified by the peculiar shape of the cave, causing a thunder-like
|
||||
booming sound to reverberate throughout the cave. Outside, a narrow
|
||||
path leads south towards some large rocks.
|
||||
#158
|
||||
You are at the top of some arched steps. On one side is a blank wall
|
||||
with a tiny door at the base and a shelf overhead. On the other side
|
||||
a westward passage leads to the sea.
|
||||
#159
|
||||
You are in a low cramped chamber at the back of a small cave.
|
||||
There is a shelf in the rock wall at about the height of your
|
||||
shoulder.
|
||||
#160
|
||||
You are on a wide ledge, bounded on one side by a rock wall,
|
||||
and on the other by a sheer cliff. The only way past is through
|
||||
a large wrought-iron door.
|
||||
#161
|
||||
You feel dizzy...Everything around you is spinning, expanding,
|
||||
growing larger.... Dear me! Is the cave bigger or are you smaller?
|
||||
#162
|
||||
You are again overcome by a sickening vertigo, but this time
|
||||
everything around you is shrinking...Shrinking...
|
||||
#163
|
||||
You are again overcome by a sickening vertigo, but this time
|
||||
everything is shrinking... I mean, you are growing. This is
|
||||
terribly confusing!
|
||||
#164
|
||||
You feel dizzy...Everything around you is spinning, expanding,
|
||||
growing larger....
|
||||
#165
|
||||
You're at the bottom of the cliff with a broken neck.
|
||||
#166
|
||||
You are at the western tip of the Blue Grotto. A large lake almost
|
||||
covers the cavern floor, except for where you are standing. Small
|
||||
holes high in the rock wall to the east admit a dim light. The
|
||||
reflection of the light from the water suffuses the cavern with
|
||||
a hazy bluish glow.
|
||||
#167
|
||||
You are on the shore of an underground sea. A high wooden
|
||||
structure of vast proportions extends out into the water to the
|
||||
east. The way west is through a wrought-iron door.
|
||||
#168
|
||||
You are on the eastern shore of the Blue Grotto. An ascending
|
||||
tunnel disappears into the darkness to the SE.
|
||||
#169
|
||||
You are at a high rock on the NE side of a watery chamber at the mouth
|
||||
of a small brook. An unknown gas bubbles up through the water from
|
||||
the chamber floor. A bluish light can be seen to the southwest.
|
||||
#170
|
||||
You are in a windy tunnel between two large rooms.
|
||||
#171
|
||||
You are in the Bat Cave. The walls and ceiling are covered with
|
||||
sleeping bats. The floor is buried by a mass of dry, foul-smelling
|
||||
guano. The stench is overpowering. Exits to the NW and east.
|
||||
#172
|
||||
You are in a very tight N/S crack. The passage seems to widen to
|
||||
the south.
|
||||
#173
|
||||
You are in a very tight N/S crack. The passage south is blocked
|
||||
by a recent cave-in.
|
||||
#174
|
||||
You're in the Cloakroom. This is where the dreaded Wumpus repairs
|
||||
to sleep off heavy meals. (Adventurers are his favorite dinner!)
|
||||
Two very narrow passages exit NW and NE.
|
||||
#175
|
||||
You're in a room containing several small climbable pits. Passages
|
||||
exit to the east and north.
|
||||
#176
|
||||
You are at the bottom of a small featureless pit.
|
||||
#177
|
||||
You are at a high hole in a rock wall.
|
||||
#178
|
||||
The NE passage is blocked by a recent cave-in.
|
||||
#179
|
||||
You are in a sloping muddy defile, next to a tumbling brook.
|
||||
#180
|
||||
You are in a level E/W passage partially blocked by an overhanging
|
||||
tongue of rock. A steep scramble would take you up over the tongue,
|
||||
whence continues an upward crawl.
|
||||
#181
|
||||
The dog won't let you pass.
|
||||
#182
|
||||
You're in the Upper Passage, a long level E/W tunnel.
|
||||
#183
|
||||
You are in a star-shaped chamber. Passages exit north, east, south,
|
||||
and west.
|
||||
#184
|
||||
You are at an elbow in a winding E/W passage.
|
||||
#185
|
||||
Dead end.
|
||||
#186
|
||||
You're at the intersection of two long tunnels. One goes NW,
|
||||
the other NE.
|
||||
#187
|
||||
You're in a long narrow east-west passage which curves out of sight
|
||||
at both ends.
|
||||
#188
|
||||
You're in the Rotunda. Corridors radiate in all directions.
|
||||
There is a telephone booth standing against the north wall.
|
||||
#189
|
||||
You are standing in a telephone booth at the side of a large chamber.
|
||||
Hung on the wall is a banged-up pay telephone of ancient design.
|
||||
#190
|
||||
You're at the Devil's Chair, a large crystallization shaped like a
|
||||
seat, at the edge of a black abyss. You can't see the bottom.
|
||||
An upward path leads away from the abyss.
|
||||
#191
|
||||
You're in a dead-end crack.
|
||||
#192
|
||||
You're on a small gravel beach at the south wall of the Blue Grotto.
|
||||
A gravelly path leads east.
|
||||
#193
|
||||
You are in the Flower Room. The walls are covered with colorful,
|
||||
intricate, flowerlike patterns of crystallized gypsum. A hole leads
|
||||
to the west.
|
||||
#194
|
||||
You are at the end of a short E/W corridor.
|
||||
#195
|
||||
You are looking west from the end of a short E/W corridor. At your
|
||||
feet is a pile of loose rubble. On your left is a hole into another
|
||||
chamber.
|
||||
#196
|
||||
You are in an arched hall. The remnants of a now-plugged coral
|
||||
passage lie to the east. The north wall has partially crumbled,
|
||||
exposing a large connecting hole to another room.
|
||||
#197
|
||||
You're in the Vestibule, a short east-west passage between two rooms.
|
||||
#198
|
||||
You are in the Fairy Grotto. All around you innumerable stalactites,
|
||||
arranged in immense colonnades, form elegant arches. On every side
|
||||
you hear the dripping of water, like the footsteps of a thousand
|
||||
fairies. A small stream runs from the SW corner. A bright glow
|
||||
emanates from the south side of the grotto, and a steep passage
|
||||
descends to the east.
|
||||
#199
|
||||
You have approached the lower end of a steep passage, but it is
|
||||
just too cold here to hang around, and you aren't properly equipped
|
||||
to continue. With teeth chattering, you climb back up....
|
||||
#200
|
||||
You are in the Crystal Palace. An overhead vein of phosphorescent
|
||||
quartz casts a luminous glow which is reflected by countless chips of
|
||||
mica embedded in both walls, which consist of some sort of highly
|
||||
reflective glass, apparently of volcanic origin. A winding path
|
||||
of yellow sandstone leads west and rises steeply to the east.
|
||||
#201
|
||||
You are following a yellow sandstone path. There is a glow
|
||||
to the west.
|
||||
#202
|
||||
You are in a very tall chamber whose walls are comprised of many
|
||||
different rock strata. Layers of red and yellow sandstone
|
||||
intertwine with bright bands of calcareous limestone in a rainbow-
|
||||
like profusion of color. The rainbow effect is so real, you
|
||||
are almost tempted to look for a pot of gold! Poised far over
|
||||
your head, a gigantic slab, wedged tightly between the north and
|
||||
south walls, forms a natural bridge across the roof of the chamber.
|
||||
A trail leads east and west.
|
||||
#203
|
||||
You're in a steeply sloping passage. It is very cold here.
|
||||
#204
|
||||
You are in the Hall of Ice, in the deepest part of the caverns.
|
||||
During winter, frigid outside air settles here, making this room
|
||||
extremely cold all year round. The walls and ceilings are covered
|
||||
with a thick coating of ice. An upward passage exits to the west.
|
||||
#205
|
||||
You are standing on a natural bridge far above the floor of a circular
|
||||
chamber whose walls are a rainbow of multicolored rock. The bridge
|
||||
was formed eons ago by a huge slab which fell from the ceiling and
|
||||
is now jammed between the north and south walls of the chamber.
|
||||
#206
|
||||
You are in a low, wide room below another chamber. A small green
|
||||
pond fills the center of the room. The lake is apparently spring
|
||||
fed. A small stream exits through a narrow passage to the north.
|
||||
A larger passage continues west.
|
||||
#207
|
||||
You are in a tight north/south crawl through a stratum of red
|
||||
colored rock. The air is damp with mist.
|
||||
#208
|
||||
You are in a tall canyon on the south side of a swift, wide river.
|
||||
Written in the mud in crude letters are the words: "You Have Found
|
||||
Lost River." A wide path leads east and west along the bank. A tight
|
||||
crawl way would take you south out of the canyon.
|
||||
#209
|
||||
You are standing on a large flat rock table at the western end of
|
||||
Lost River Canyon. Beneath your feet, the river disappears amidst
|
||||
foam and spray into a large sinkhole. A gentle path leads east
|
||||
along the river's south shore. Another leads sharply upward along
|
||||
the river's north side.
|
||||
#210
|
||||
You are at a niche in the canyon wall, far above a raging river.
|
||||
The air is filled with mist and spray, making it difficult to see
|
||||
ahead. A downward sloping ledge narrows to the east. The path
|
||||
to the west is easier.
|
||||
#211
|
||||
The ledge is growing very narrow and treacherous, and falls off almost
|
||||
vertically. You could go down, but you won't be able to climb back.
|
||||
#212
|
||||
You are standing in a telephone booth at the side of the Repository.
|
||||
#213
|
||||
You're at the east end of a level passage at a hole in the floor.
|
||||
#214
|
||||
You're at the north edge of a dark cove.
|
||||
#215
|
||||
You are in a dry granite basin, worn smooth eons ago by water
|
||||
swirling down from a now-dry spillway.
|
||||
#216
|
||||
You're in a dry spillway east of and above a smooth rock basin.
|
||||
#217
|
||||
You are in the Winery, a cool dark room which extends some
|
||||
distance off to the east.
|
||||
#218
|
||||
You are to the east of the Winery, where the room ends in a thicket
|
||||
of high, sharp, pointed, climbable limestone pinnacles. There is a
|
||||
narrow ledge just above the top of the spires. If you go up, it
|
||||
might be difficult to get back down.
|
||||
#219
|
||||
You are in a high-vaulted cavern whose roof rises over fifty
|
||||
meters to culminate in a series of pointed arches directly over
|
||||
your head. There are also two low arches to either side, forming
|
||||
side portals. The whole effect is that of a gothic cathedral.
|
||||
You can proceed north, south, east, or west.
|
||||
#220
|
||||
You're at the east portal of the Gothic Cathedral. The path leads
|
||||
east and west.
|
||||
#221
|
||||
You're at the west portal of the Gothic Cathedral.
|
||||
#222
|
||||
You are at the foot of the Altar, an immense, broad stalagmite.
|
||||
An opening leads south.
|
||||
#223
|
||||
You're on top of an enormous, broad stalagmite. There is a hole
|
||||
in the ceiling overhead.
|
||||
#224
|
||||
You are in a room the size and shape of a small crypt. A narrow
|
||||
cut exits east. There is a hole in the floor.
|
||||
#225
|
||||
You are in the Gothic Chapel, a small chamber adjoining the Gothic
|
||||
Cathedral. A path leads west.
|
||||
#226
|
||||
You are on the floor of the Rainbow Room. In fact, you are spread
|
||||
*ALL OVER* the floor of the Rainbow Room.
|
||||
#227
|
||||
You are in a dimly lit passage behind Thunder Hole. Etched into
|
||||
the rock wall are the ominous words:
|
||||
* "You are approaching the River Styx. *
|
||||
* Laciate Ogni Speranza Voi Ch'Entrate." *
|
||||
#228
|
||||
You are at the River Styx, a narrow little stream cutting directly
|
||||
across the passageway. The edge of the stream is littered with sticks
|
||||
and other debris washed in by a recent rainfall. On the far side
|
||||
of the river, the passage continues east.
|
||||
#229
|
||||
You're on the east side of the river's sticks.
|
||||
#230
|
||||
You are on a ledge at the northern end of a long N/S crawl. The
|
||||
ledge is above a large number of sharp vertical limestone spires.
|
||||
An attempt to climb down could be dangerous, if you get my *point*!
|
||||
#231
|
||||
You are very neatly skewered on the point of a sharp rock.
|
||||
#232
|
||||
You have poled your boat across the calm water.
|
||||
#233
|
||||
You have poled your boat across the dark water.
|
||||
#234
|
||||
You have poled your boat across the Blue Grotto.
|
||||
#235
|
||||
You're at Dante's Rest, on the north side of a yawning dark chasm.
|
||||
A passage continues west along the chasm's edge.
|
||||
#236
|
||||
You are at the east end of a river bank path in Lost River Canyon.
|
||||
#237
|
||||
The staircase is now unclimbable.
|
||||
#238
|
||||
You're in the caretaker's pantry.
|
||||
#239
|
||||
You are on a small rise overlooking a beautiful bay. In the center
|
||||
of the bay is the castle of the elves.
|
||||
#240
|
||||
You are on the highest pinnacle of the castle in the bay.
|
||||
Steps lead down into the garden.
|
||||
#241
|
||||
You are in the outer courtyard of the garden of the elves.
|
||||
Steps lead up to the tower, and to the west, separating you
|
||||
from the inner courtyard, is a maze of hedges, living things,
|
||||
but almost crystalline in their multicolored splendor.
|
||||
#242
|
||||
From the inside the maze looks like a kaleidoscope, with
|
||||
swatches of color dancing as you move. In this part the colors
|
||||
are produced by shining red berries on the branches.
|
||||
#243
|
||||
You are surrounded by a tall hedge with sharp iridescent leaves
|
||||
and metallic orange flowers.
|
||||
#244
|
||||
You are in the center of the living maze. The plants here are
|
||||
dormant this season, but still carry brilliant yellow leaves.
|
||||
#245
|
||||
Unlike the other areas of the hedge system, this area seems to
|
||||
have no metallic gleam; nevertheless it is still breathtaking.
|
||||
The trees and bushes are all variegated shades of green, the
|
||||
evergreens being a rich dark shade while the seasonal bushes
|
||||
are a lighter yellowish green, making a startling contrast.
|
||||
#246
|
||||
You are near the edge of the maze. You sample the blueberries
|
||||
on the bushes. They are delicious.
|
||||
#247
|
||||
You are at the western end of the living maze. Beside the
|
||||
shrubs forming the walls are tastefully planted beds of
|
||||
violets and brilliant purple pansies.
|
||||
To the west is the inner garden.
|
||||
#248
|
||||
You are in the inner garden of the elves. In the center is
|
||||
a living tree, with shimmering silvery bark, glistening metallic
|
||||
green leaves, and flowers ripe with nectar. As the nectar falls
|
||||
to the ground it forms droplets of silver. Around the tree is
|
||||
a hedge of briars which cannot be crossed. Unfortunately for
|
||||
adventurers such as you, most of the nectar falls inside the hedge.
|
||||
The exit is to the east.
|
||||
514
commands/advent/advent2.txt
Normal file
514
commands/advent/advent2.txt
Normal file
@@ -0,0 +1,514 @@
|
||||
#1
|
||||
You're at end of road again.
|
||||
#2
|
||||
You're at hill in road.
|
||||
#3
|
||||
You're inside building.
|
||||
#4
|
||||
You're in valley.
|
||||
#5
|
||||
You're in forest.
|
||||
#6
|
||||
You're in forest.
|
||||
#7
|
||||
You're at slit in streambed.
|
||||
#8
|
||||
You're outside grate.
|
||||
#9
|
||||
You're below the grate.
|
||||
#10
|
||||
You're in cobble crawl.
|
||||
#11
|
||||
You're in Debris Room.
|
||||
#12
|
||||
You are in an awkward sloping east/west canyon.
|
||||
#13
|
||||
You're in Bird Chamber.
|
||||
#14
|
||||
You're at top of small pit.
|
||||
#15
|
||||
You're in Hall of Mists.
|
||||
#16
|
||||
The crack is far too small for you to follow.
|
||||
#17
|
||||
You're on east bank of fissure.
|
||||
#18
|
||||
You're in Nugget of Gold Room.
|
||||
#19
|
||||
You're in Hall of Mt King.
|
||||
#20
|
||||
You are at the bottom of the pit with a broken neck.
|
||||
#21
|
||||
You didn't make it.
|
||||
#22
|
||||
The dome is unclimbable.
|
||||
#23
|
||||
You're at west end of Twopit Room.
|
||||
#24
|
||||
You're in east pit.
|
||||
#25
|
||||
You're in west pit.
|
||||
#26
|
||||
You clamber up the plant and scurry through the hole at the top.
|
||||
#27
|
||||
You are on the west side of the fissure in the Hall of Mists.
|
||||
#28
|
||||
You are in a low N/S passage at a hole in the floor. The hole goes
|
||||
down to an E/W passage.
|
||||
#29
|
||||
You are in the South Side Chamber.
|
||||
#30
|
||||
You are in the West Side Chamber of the Hall of the Mountain King.
|
||||
#31
|
||||
<$$<
|
||||
#32
|
||||
You can't get by the snake.
|
||||
#33
|
||||
You're at "Y2".
|
||||
#34
|
||||
You are in a jumble of rock, with cracks everywhere.
|
||||
#35
|
||||
You're at window on pit.
|
||||
#36
|
||||
You're in dirty passage.
|
||||
#37
|
||||
You are on the brink of a small clean climbable pit.
|
||||
#38
|
||||
You are in the bottom of a small pit with a little stream.
|
||||
#39
|
||||
You're in dusty rock room.
|
||||
#40
|
||||
You have crawled through a very low wide passage parallel.
|
||||
#41
|
||||
You're at west end of Hall of Mists.
|
||||
#42
|
||||
You are in a maze of twisty little passages, all alike.
|
||||
#43
|
||||
You are in a maze of twisty little passages, all alike.
|
||||
#44
|
||||
You are in a maze of twisty little passages, all alike.
|
||||
#45
|
||||
You are in a maze of twisty little passages, all alike.
|
||||
#46
|
||||
Dead end.
|
||||
#47
|
||||
Dead end.
|
||||
#48
|
||||
Dead end.
|
||||
#49
|
||||
You are in a maze of twisty little passages, all alike.
|
||||
#50
|
||||
You are in a maze of twisty little passages, all alike.
|
||||
#51
|
||||
You are in a maze of twisty little passages, all alike.
|
||||
#52
|
||||
You are in a maze of twisty little passages, all alike.
|
||||
#53
|
||||
You are in a maze of twisty little passages, all alike.
|
||||
#54
|
||||
Dead end.
|
||||
#55
|
||||
You are in a maze of twisty little passages, all alike.
|
||||
#56
|
||||
Dead end.
|
||||
#57
|
||||
You're at brink of pit.
|
||||
#58
|
||||
Dead end.
|
||||
#59
|
||||
You have crawled through a very low wide passage.
|
||||
#60
|
||||
You're at east end of Long Hall.
|
||||
#61
|
||||
You're at west end of Long Hall.
|
||||
#62
|
||||
You are at a crossover of a high N/S passage and a low E/W one.
|
||||
#63
|
||||
Dead end.
|
||||
#64
|
||||
You're at Complex Junction.
|
||||
#65
|
||||
You are in Bedquilt.
|
||||
#66
|
||||
You're in Swiss Cheese Room.
|
||||
#67
|
||||
You're at east end of Twopit Room.
|
||||
#68
|
||||
You're in Slab Room.
|
||||
#69
|
||||
You are in a secret N/S canyon above a large room.
|
||||
#70
|
||||
You are in a secret N/S canyon above a sizable passage.
|
||||
#71
|
||||
You're at junction of three secret canyons.
|
||||
#72
|
||||
You are in a large low room. Crawls lead north, NE, and SW.
|
||||
#73
|
||||
Dead end crawl.
|
||||
#74
|
||||
You're in secret E/W canyon above tight canyon.
|
||||
#75
|
||||
You are at a wide place in a very tight N/S canyon.
|
||||
#76
|
||||
The canyon here becomes too tight to go further south.
|
||||
#77
|
||||
You are in a tall E/W canyon.
|
||||
#78
|
||||
The canyon runs into a mass of boulders -- dead end.
|
||||
#79
|
||||
The stream flows out through a pair of 1 foot diameter sewer pipes.
|
||||
#80
|
||||
You are in a maze of twisty little passages, all alike.
|
||||
#81
|
||||
Dead end.
|
||||
#82
|
||||
Dead end.
|
||||
#83
|
||||
You are in a maze of twisty little passages, all alike.
|
||||
#84
|
||||
You are in a maze of twisty little passages, all alike.
|
||||
#85
|
||||
Dead end.
|
||||
#86
|
||||
Dead end.
|
||||
#87
|
||||
You are in a maze of twisty little passages, all alike.
|
||||
#88
|
||||
You're in narrow corridor.
|
||||
#89
|
||||
There is nothing here to climb. Use "up" or "out" to leave the pit.
|
||||
#90
|
||||
You have climbed up the plant and out of the pit.
|
||||
#91
|
||||
You're at steep incline above large room.
|
||||
#92
|
||||
You're in Giant Room.
|
||||
#93
|
||||
The passage here is blocked by a recent cave-in.
|
||||
#94
|
||||
You are at one end of an immense north/south passage.
|
||||
#95
|
||||
You're in cavern with waterfall.
|
||||
#96
|
||||
You're in Soft Room.
|
||||
#97
|
||||
You're in Oriental Room.
|
||||
#98
|
||||
You're in Misty Cavern.
|
||||
#99
|
||||
You're in Alcove.
|
||||
#100
|
||||
You're in Plover Room.
|
||||
#101
|
||||
You're in Dark-Room.
|
||||
#102
|
||||
You're in Arched Hall.
|
||||
#103
|
||||
You're in Shell Room.
|
||||
#104
|
||||
You are in a long sloping corridor with ragged sharp walls.
|
||||
#105
|
||||
You are in a cul-de-sac about eight feet across.
|
||||
#106
|
||||
You're in Anteroom.
|
||||
#107
|
||||
You are in a maze of twisty little passages, all different.
|
||||
#108
|
||||
You're at Witt's End.
|
||||
#109
|
||||
You're in Mirror Canyon.
|
||||
#110
|
||||
You're at window on pit.
|
||||
#111
|
||||
You're at top of stalactite.
|
||||
#112
|
||||
You are in a little maze of twisting passages, all different.
|
||||
#113
|
||||
You're at Reservoir.
|
||||
#114
|
||||
Dead end.
|
||||
#115
|
||||
You're at NE end.
|
||||
#116
|
||||
You're at SW end.
|
||||
#117
|
||||
You're on SW side of chasm.
|
||||
#118
|
||||
You're in sloping corridor.
|
||||
#119
|
||||
You are in a secret canyon which exits to the north and east.
|
||||
#120
|
||||
You are in a secret canyon which exits to the north and east.
|
||||
#121
|
||||
You are in a secret canyon which exits to the north and east.
|
||||
#122
|
||||
You're on NE side of chasm.
|
||||
#123
|
||||
You're in corridor.
|
||||
#124
|
||||
You're at fork in path.
|
||||
#125
|
||||
You're at junction with warm walls.
|
||||
#126
|
||||
You're at breath-taking view.
|
||||
#127
|
||||
You're in Chamber of Boulders.
|
||||
#128
|
||||
You're in Limestone Passage.
|
||||
#129
|
||||
You're in front of Barren Room.
|
||||
#130
|
||||
You're in Barren Room.
|
||||
#131
|
||||
You are in a maze of twisting little passages, all different.
|
||||
#132
|
||||
You are in a little maze of twisty passages, all different.
|
||||
#133
|
||||
You are in a twisting maze of little passages, all different.
|
||||
#134
|
||||
You are in a twisting little maze of passages, all different.
|
||||
#135
|
||||
You are in a twisty little maze of passages, all different.
|
||||
#136
|
||||
You are in a twisty maze of little passages, all different.
|
||||
#137
|
||||
You are in a little twisty maze of passages, all different.
|
||||
#138
|
||||
You are in a maze of little twisting passages, all different.
|
||||
#139
|
||||
You are in a maze of little twisty passages, all different.
|
||||
#140
|
||||
Dead end.
|
||||
#141
|
||||
You're at Sword Point.
|
||||
#142
|
||||
You're at top of slide.
|
||||
#143
|
||||
You're at entrance to Throne Room.
|
||||
#144
|
||||
You're on east side of Throne Room.
|
||||
#145
|
||||
<$$<
|
||||
#146
|
||||
You're in forest.
|
||||
#147
|
||||
You're on grassy knoll.
|
||||
#148
|
||||
You are at the edge of a trackless salt marsh. Tall reeds obscure
|
||||
the view.
|
||||
#149
|
||||
You're in salt marsh.
|
||||
#150
|
||||
You're in salty marsh.
|
||||
#151
|
||||
You are in salt marsh.
|
||||
#152
|
||||
Dead end.
|
||||
#153
|
||||
You're on sandy beach.
|
||||
#154
|
||||
You're at broken rocks.
|
||||
#155
|
||||
You're at Ocean Vista.
|
||||
#156
|
||||
You're at the bottom of the cliff.
|
||||
#157
|
||||
You're at Thunder Hole.
|
||||
#158
|
||||
You're at top of steps in back of Thunder Hole.
|
||||
#159
|
||||
You're in cramped chamber.
|
||||
#160
|
||||
You're at ledge by wrought-iron door.
|
||||
#161
|
||||
You feel dizzy...Everything around you is spinning, expanding,
|
||||
growing larger.... Dear me! Is the cave bigger or are you smaller?
|
||||
#162
|
||||
You are again overcome by a sickening vertigo, but this time
|
||||
everything around you is shrinking...Shrinking...
|
||||
#163
|
||||
You are again overcome by a sickening vertigo, but this time
|
||||
everything is shrinking... I mean, you are growing. This is
|
||||
terribly confusing!
|
||||
#164
|
||||
You feel dizzy...Everything around you is spinning, expanding,
|
||||
growing larger....
|
||||
#165
|
||||
You're at the bottom of the cliff with a broken neck.
|
||||
#166
|
||||
You're at west wall of Blue Grotto.
|
||||
#167
|
||||
You're at underground sea.
|
||||
#168
|
||||
You're on east side of the Blue Grotto.
|
||||
#169
|
||||
You're in Bubble Chamber.
|
||||
#170
|
||||
You are in a windy tunnel between two large rooms.
|
||||
#171
|
||||
You're in Bat Cave.
|
||||
#172
|
||||
You are in a very tight N/S crack.
|
||||
#173
|
||||
You are in a very tight N/S crack.
|
||||
#174
|
||||
You're in the Cloakroom.
|
||||
#175
|
||||
You're in a room containing several small climbable pits.
|
||||
#176
|
||||
You are at the bottom of a small featureless pit.
|
||||
#177
|
||||
You are at a high hole in a rock wall.
|
||||
#178
|
||||
The NE passage is blocked by a recent cave-in.
|
||||
#179
|
||||
You are in a sloping muddy defile, next to a tumbling brook.
|
||||
#180
|
||||
You're at Tongue of Rock.
|
||||
#181
|
||||
The dog won't let you pass.
|
||||
#182
|
||||
You're in the Upper Passage, a long level E/W tunnel.
|
||||
#183
|
||||
You're in Star Chamber.
|
||||
#184
|
||||
You are at an elbow in a winding E/W passage.
|
||||
#185
|
||||
Dead end.
|
||||
#186
|
||||
You're at the intersection of two long tunnels.
|
||||
#187
|
||||
You're in a long narrow east-west passage.
|
||||
#188
|
||||
You're in Rotunda.
|
||||
#189
|
||||
You're in phone booth.
|
||||
#190
|
||||
You're at Devil's Chair.
|
||||
#191
|
||||
You're in a dead-end crack.
|
||||
#192
|
||||
You're on gravel beach.
|
||||
#193
|
||||
You're in Flower Room.
|
||||
#194
|
||||
You are at east end of short E/W corridor.
|
||||
#195
|
||||
You are at east end of short E/W corridor.
|
||||
#196
|
||||
You're in Arched Hall.
|
||||
#197
|
||||
You're in the Vestibule, a short east-west passage between two rooms.
|
||||
#198
|
||||
You're in the Fairy Grotto.
|
||||
#199
|
||||
You have approached the lower end of a steep passage.
|
||||
#200
|
||||
You're in the Crystal Palace.
|
||||
#201
|
||||
You are following a yellow sandstone path.
|
||||
#202
|
||||
You're in the Rainbow Room.
|
||||
#203
|
||||
You're in a steeply sloping passage. It is very cold here.
|
||||
#204
|
||||
You're in the Hall of Ice.
|
||||
#205
|
||||
You are over the Rainbow (Room).
|
||||
#206
|
||||
You're in Green Lake Room.
|
||||
#207
|
||||
You're in red rock crawl.
|
||||
#208
|
||||
You're on south side of Lost River Canyon.
|
||||
#209
|
||||
You're at end of Lost River Canyon.
|
||||
#210
|
||||
You're at niche in ledge above Lost River.
|
||||
#211
|
||||
A very narrow and treacherous ledge.
|
||||
#212
|
||||
You're in phone booth.
|
||||
#213
|
||||
You're at the east end of a level passage at a hole in the floor.
|
||||
#214
|
||||
You're in dark cove.
|
||||
#215
|
||||
You're in dry basin.
|
||||
#216
|
||||
You're in old spillway.
|
||||
#217
|
||||
You're in the Winery.
|
||||
#218
|
||||
You're at limestone pinnacles.
|
||||
#219
|
||||
You're in Gothic Cathedral.
|
||||
#220
|
||||
You're at the east portal of the Gothic Cathedral.
|
||||
#221
|
||||
You're at the west portal of the Gothic Cathedral.
|
||||
#222
|
||||
You are at the foot of the Altar, an immense, broad stalagmite.
|
||||
#223
|
||||
You're on top of stalagmite.
|
||||
#224
|
||||
You're in the Crypt.
|
||||
#225
|
||||
You're in Gothic Chapel.
|
||||
#226
|
||||
You are on the floor of the Rainbow Room.
|
||||
#227
|
||||
You are at approach to River Styx.
|
||||
#228
|
||||
You're at the River Styx.
|
||||
#229
|
||||
You're on the east side of the river's sticks.
|
||||
#230
|
||||
You're on ledge above limestone pinnacles.
|
||||
#231
|
||||
You are very neatly skewered on the point of a sharp rock.
|
||||
#232
|
||||
You have poled your boat across the calm water.
|
||||
#233
|
||||
You have poled your boat across the dark water.
|
||||
#234
|
||||
You have poled your boat across the Blue Grotto.
|
||||
#235
|
||||
You're at Dante's Rest.
|
||||
#236
|
||||
You're at east end of Lost River Canyon.
|
||||
#237
|
||||
The staircase is now unclimbable.
|
||||
#238
|
||||
You're in the caretaker's pantry.
|
||||
#239
|
||||
You're on a small rise over the bay.
|
||||
#240
|
||||
You are on the highest pinnacle of the castle in the bay.
|
||||
Steps lead down into the garden.
|
||||
#241
|
||||
You are in the outer courtyard of the elves.
|
||||
#242
|
||||
You are in the living maze. There are red berries here.
|
||||
#243
|
||||
You are surrounded by a tall hedge with sharp iridescent leaves
|
||||
and metallic orange flowers.
|
||||
#244
|
||||
You are in the center of the living maze. The plants here are
|
||||
dormant this season, but still carry brilliant yellow leaves.
|
||||
#245
|
||||
Unlike the other areas of the hedge system, this area seems to
|
||||
have no metallic gleam; nevertheless it is still breathtaking.
|
||||
The trees and bushes are all variegated shades of green, the
|
||||
evergreens being a rich dark shade while the seasonal bushes
|
||||
are a lighter yellowish green, making a startling contrast.
|
||||
#246
|
||||
You are near the edge of the maze. You sample the blueberries
|
||||
on the bushes. They are delicious.
|
||||
#247
|
||||
You are at the western end of the living maze. Beside the
|
||||
shrubs forming the walls are tastefully planted beds of
|
||||
violets and brilliant purple pansies.
|
||||
To the west is the inner garden.
|
||||
#248
|
||||
You're in the inner courtyard of the elves.
|
||||
539
commands/advent/advent3.txt
Normal file
539
commands/advent/advent3.txt
Normal file
@@ -0,0 +1,539 @@
|
||||
#1
|
||||
#2
|
||||
/Brass lantern
|
||||
/There is a shiny brass lamp nearby.
|
||||
/There is a lamp shining nearby.
|
||||
/
|
||||
#3
|
||||
/*Grate
|
||||
/The grate is locked.
|
||||
/The grate is open.
|
||||
/
|
||||
#4
|
||||
/Wicker cage
|
||||
/There is a small wicker cage discarded nearby.
|
||||
/
|
||||
#5
|
||||
/Black rod
|
||||
/A three foot black rod with a rusty star on an end lies nearby.
|
||||
/
|
||||
#6
|
||||
/Black rod
|
||||
/A three foot black rod with a rusty mark on an end lies nearby.
|
||||
/
|
||||
#7
|
||||
/*Steps
|
||||
/Rough stone steps lead down the pit.
|
||||
/Rough stone steps lead up the dome.
|
||||
/
|
||||
#8
|
||||
#9
|
||||
/Wooden pole
|
||||
/A wooden pole is lying nearby.
|
||||
/A wooden pole has been stuck in the mud here.
|
||||
/
|
||||
#10
|
||||
/Velvet pillow
|
||||
/A small velvet pillow lies on the floor.
|
||||
/
|
||||
#11
|
||||
/*Snake
|
||||
/A huge green fierce snake bars the way!
|
||||
/<$$< (Chased away)
|
||||
/
|
||||
#12
|
||||
/*Fissure
|
||||
/<$$<
|
||||
/A crystal bridge now spans the fissure.
|
||||
/The crystal bridge has vanished!
|
||||
/
|
||||
#13
|
||||
/*Stone tablet
|
||||
/A massive stone tablet imbedded in the wall reads:
|
||||
"Congratulations on bringing light into the Dark-Room!"
|
||||
/
|
||||
#14
|
||||
/Giant clam >grunt!<
|
||||
/There is an enormous clam here with its shell tightly closed.
|
||||
/
|
||||
#15
|
||||
/Giant oyster >groan!<
|
||||
/There is an enormous oyster here with its shell tightly closed.
|
||||
/Interesting. There seems to be something written on the underside of
|
||||
the oyster.
|
||||
/
|
||||
#16
|
||||
/"Spelunker Today"
|
||||
/There are a few recent issues of "Spelunker Today" magazine here.
|
||||
/
|
||||
#17
|
||||
#18
|
||||
#19
|
||||
/Tasty food
|
||||
/There is food here.
|
||||
/
|
||||
#20
|
||||
/Small bottle
|
||||
/There is a small bottle here.
|
||||
/There is an empty bottle here.
|
||||
/There is a small bottle here.
|
||||
/There is a broken bottle here.
|
||||
/There is a small bottle here.
|
||||
/
|
||||
#21
|
||||
/*Chasm - troll bridge
|
||||
/A rickety wooden bridge extends across the chasm, vanishing into the
|
||||
mist. A sign posted on the bridge reads, "Stop! Pay troll!"
|
||||
/The wreckage of a bridge (and a dead bear) can be seen at the bottom
|
||||
of the chasm.
|
||||
/
|
||||
#22
|
||||
/*Chasm2 & decrepit natural bridge
|
||||
/A decrepit natural bridge spans the chasm. A message scrawled into
|
||||
the rock wall reads: "Bridge out of repair. Maximum load: 35 Foonts."
|
||||
/The remnants of a natural bridge partially overhang the chasm.
|
||||
/
|
||||
#23
|
||||
/*Mirror
|
||||
/<$$<
|
||||
/
|
||||
#24
|
||||
/*plant
|
||||
/There is a tiny little plant in the pit, murmuring "Water, water, ..."
|
||||
/The plant spurts into furious growth for a few seconds.
|
||||
/There is a 12-foot-tall beanstalk stretching up out of the pit,
|
||||
bellowing "Water!! Water!!"
|
||||
/The plant grows explosively, almost filling the bottom of the pit.
|
||||
/There is a gigantic beanstalk stretching all the way up to the hole.
|
||||
/You've over-watered the plant! It's shriveling up! It's, it's...
|
||||
/
|
||||
#25
|
||||
/*Phony plant (seen in twopit room only when tall enough)
|
||||
/<$$<
|
||||
/The top of a 12-foot-tall beanstalk is poking out of the west pit.
|
||||
/There is a huge beanstalk growing out of the west pit up to the hole.
|
||||
/
|
||||
#26
|
||||
/*Stalactite
|
||||
/<$$<
|
||||
/
|
||||
#27
|
||||
/*shadowy figure
|
||||
/The shadowy figure seems to be trying to attract your attention.
|
||||
/
|
||||
#28
|
||||
/Dwarf's axe
|
||||
/There is a little axe here.
|
||||
/There is a little axe lying beside the bear.
|
||||
/There is a little axe lying beside the Wumpus.
|
||||
/There is a little axe lying beside the dog.
|
||||
/
|
||||
#29
|
||||
/*Cave drawings
|
||||
/<$$<
|
||||
/
|
||||
#30
|
||||
/*pirate
|
||||
/<$$<
|
||||
/
|
||||
#31
|
||||
/*dragon
|
||||
/A huge green fierce dragon bars the way!
|
||||
/Congratulations! You have just vanquished a dragon with your bare
|
||||
hands! (Unbelievable, isn't it?)
|
||||
/The body of a huge green dead dragon is lying off to one side.
|
||||
/
|
||||
#32
|
||||
#33
|
||||
/*Troll
|
||||
/A burly troll stands by the bridge and insists you throw him a
|
||||
treasure before you may cross.
|
||||
/The troll steps out from beneath the bridge and blocks your way.
|
||||
/<$$< (Chased away)
|
||||
/
|
||||
#34
|
||||
/*phony troll
|
||||
/The troll is nowhere to be seen.
|
||||
/
|
||||
#35
|
||||
/<$$< (Bear uses rtext 141)
|
||||
/There is a ferocious cave bear eying you from the far end of the room!
|
||||
/There is a gentle cave bear sitting placidly in one corner.
|
||||
/There is a contented-looking bear wandering about nearby.
|
||||
/<$$< (Dead)
|
||||
/
|
||||
#36
|
||||
/*Message in second maze
|
||||
/There is a message scrawled in the dust in a flowery script, reading:
|
||||
"This is not the maze where the pirate leaves his treasure chest."
|
||||
/
|
||||
#37
|
||||
/*Volcano and/or geyser
|
||||
/<$$<
|
||||
/
|
||||
#38
|
||||
/*Vending machine
|
||||
/There is a massive vending machine here. The instructions on it
|
||||
read: "Insert coins to receive fresh batteries."
|
||||
/There is a massive vending machine here.
|
||||
/
|
||||
#39
|
||||
/Batteries
|
||||
/There are fresh batteries here.
|
||||
/Some worn-out batteries have been discarded nearby.
|
||||
/Some worn-out batteries have been discarded nearby.
|
||||
/
|
||||
#40
|
||||
/*Carpet and/or moss
|
||||
/<$$<
|
||||
/
|
||||
#41
|
||||
/*Rusty door
|
||||
/The way north is barred by a massive, rusty, iron door.
|
||||
/The way north leads through a massive, rusty, iron door.
|
||||
/
|
||||
#42
|
||||
/*Tiny door
|
||||
/The only way past the wall is through a tiny locked door.
|
||||
/The only way past the wall is through a tiny open door.
|
||||
/
|
||||
#43
|
||||
/*Tiny door-2
|
||||
/The door is locked.
|
||||
/The door is open.
|
||||
/
|
||||
#44
|
||||
/*Phone booth door
|
||||
/<$$<
|
||||
/
|
||||
#45
|
||||
#46
|
||||
/Beautiful flowers
|
||||
/There are some beautiful flowers here!
|
||||
/On the other side of the room a swarm of bees eagerly buzzes over
|
||||
a bunch of fresh flowers.
|
||||
/
|
||||
#47
|
||||
/Silken cloak
|
||||
/There is a silken cloak here!
|
||||
/<$$< (wearing cloak)
|
||||
/A lovely silken cloak lies partially buried under a pile of
|
||||
loose rocks.
|
||||
/
|
||||
#48
|
||||
/Wooden boat
|
||||
/There is a small wooden boat here.
|
||||
/You are in a wooden boat.
|
||||
/
|
||||
#49
|
||||
/*Sticks at Styx
|
||||
/<$$<
|
||||
/
|
||||
#50
|
||||
/Large gold nugget
|
||||
/There is a large sparkling nugget of gold here!
|
||||
/
|
||||
#51
|
||||
/Several diamonds
|
||||
/There are diamonds here!
|
||||
/
|
||||
#52
|
||||
/Silver horn
|
||||
/There is a silver horn here!
|
||||
/
|
||||
#53
|
||||
/Precious jewelry
|
||||
/There is precious jewelry here!
|
||||
/<$$< (wearing jewelry)
|
||||
/
|
||||
#54
|
||||
/Rare coins
|
||||
/There are many coins here!
|
||||
/
|
||||
#55
|
||||
/Treasure chest
|
||||
/The pirate's treasure chest is here!
|
||||
/
|
||||
#56
|
||||
/Golden eggs
|
||||
/There is a large nest here, full of golden eggs!
|
||||
/The nest of golden eggs has vanished!
|
||||
/Done!
|
||||
/
|
||||
#57
|
||||
/Jeweled trident
|
||||
/There is a jewel-encrusted trident here!
|
||||
/
|
||||
#58
|
||||
/Ming vase
|
||||
/There is a delicate, precious, ming vase here!
|
||||
/The vase is now resting, delicately, on a velvet pillow.
|
||||
/The floor is littered with worthless shards of pottery.
|
||||
/The ming vase drops with a delicate crash.
|
||||
/
|
||||
#59
|
||||
/Egg-sized emerald
|
||||
/There is an emerald here the size of a plover's egg!
|
||||
/
|
||||
#60
|
||||
/Platinum pyramid
|
||||
/There is a platinum pyramid here, 8 inches on a side!
|
||||
/
|
||||
#61
|
||||
/Glistening pearl
|
||||
/Off to one side lies a glistening pearl!
|
||||
/
|
||||
#62
|
||||
/Persian rug
|
||||
/There is a persian rug spread out on the floor!
|
||||
/The dragon is sprawled out on a persian rug!!
|
||||
/
|
||||
#63
|
||||
/Rare spices
|
||||
/There are rare spices here!
|
||||
/
|
||||
#64
|
||||
/Golden chain
|
||||
/There is a golden chain lying in a heap on the floor!
|
||||
/The bear is locked to the wall with a golden chain!
|
||||
/There is a golden chain locked to the wall!
|
||||
/
|
||||
#65
|
||||
/Gleaming sword
|
||||
/There is a gleaming sword here!
|
||||
/A gleaming sword is stuck into the anvil!
|
||||
/You grasp the sword's handle and give a mighty heave, but with a
|
||||
loud clang the sword blade shatters into several fragments.
|
||||
/Rusty shards of a elven sword lie scattered about.
|
||||
/A very clean sword is stuck into the anvil!
|
||||
/An oily sword is stuck into the anvil.
|
||||
/
|
||||
#66
|
||||
/Elfin crown
|
||||
/An ancient crown of elfin kings lies here!
|
||||
/<$$< (wearing crown)
|
||||
/
|
||||
#67
|
||||
/Ruby slippers
|
||||
/There is a pair of ruby slippers here.
|
||||
/<$$< (wearing slippers)
|
||||
/There is a pair of ruby slippers here.
|
||||
/
|
||||
#68
|
||||
/Delicate lyre
|
||||
/There is a delicate lyre here!
|
||||
/
|
||||
#69
|
||||
/Star sapphire
|
||||
/There is a star sapphire here!
|
||||
/
|
||||
#70
|
||||
/Holy Grail
|
||||
/There is an ornate silver chalice here!
|
||||
/
|
||||
#71
|
||||
/Oaken cask
|
||||
/There is an oaken cask here.
|
||||
/There is an empty oaken cask here.
|
||||
/There is an oaken cask here.
|
||||
/<$$< (Unused)
|
||||
/There is an oaken cask here.
|
||||
/
|
||||
#72
|
||||
/Golden ring
|
||||
/There is a small gold ring here.
|
||||
/<$$< (wearing ring)
|
||||
/On the Wumpus' finger is a small gold ring.
|
||||
/
|
||||
#73
|
||||
/Four-leafed clover
|
||||
/There is a four-leafed clover here!
|
||||
/<$$< (wearing clover)
|
||||
/
|
||||
#74
|
||||
/Gold tree
|
||||
/There is a gold statue of a tree here.
|
||||
/
|
||||
#75
|
||||
/Silver droplet
|
||||
/There is a single droplet of silver on the ground here.
|
||||
/
|
||||
#76
|
||||
#77
|
||||
#78
|
||||
#79
|
||||
#80
|
||||
#81
|
||||
/Clear water
|
||||
/
|
||||
#82
|
||||
/Cool water
|
||||
/
|
||||
#83
|
||||
/Thick, black oil
|
||||
/
|
||||
#84
|
||||
/Thick, black oil
|
||||
/
|
||||
#85
|
||||
/Vintage wine
|
||||
/
|
||||
#86
|
||||
/Vintage wine
|
||||
/
|
||||
#87
|
||||
/*Bumblebees
|
||||
/<$$<
|
||||
/Some bumblebees are swarming around a bunch of fresh flowers.
|
||||
/
|
||||
#88
|
||||
/*Hollow wall
|
||||
/Your footsteps echo hollowly throughout the chamber.
|
||||
/<$$<
|
||||
/
|
||||
#89
|
||||
/*Wall with safe
|
||||
/A steel safe is embedded in the wall.
|
||||
/
|
||||
#90
|
||||
/Tiny brass key
|
||||
/There is a tiny brass key here.
|
||||
/There is a tiny brass key on the shelf.
|
||||
/
|
||||
#91
|
||||
/*Anvil
|
||||
/<$$<
|
||||
/
|
||||
#92
|
||||
/*rocks on cloak
|
||||
/<$$< (ON CLOAK)
|
||||
/<$$< (AFTER ROCK SLIDE)
|
||||
/
|
||||
#93
|
||||
/*telephone booth
|
||||
/The telephone booth is empty.
|
||||
|
||||
The phone is ringing.
|
||||
/The phone booth is occupied by a gnome. He is talking excitedly
|
||||
to someone at the other end.
|
||||
/The telephone booth is empty.
|
||||
/<$$<
|
||||
/
|
||||
#94
|
||||
/*Telephone
|
||||
/The phone is ringing.
|
||||
/The telephone is out of order.
|
||||
/The telephone is out of order. It is badly dented.
|
||||
/<$$<
|
||||
/
|
||||
#95
|
||||
/Lead slugs
|
||||
/There are some lead slugs here!
|
||||
/
|
||||
#96
|
||||
/Sweet honeycomb
|
||||
/There is a sweet honeycomb here!
|
||||
/
|
||||
#97
|
||||
/*Beehive
|
||||
/There is an active beehive nearby. The bees hum protectively
|
||||
around the hive.
|
||||
/There is an empty beehive nearby.
|
||||
/
|
||||
#98
|
||||
/*Black dog
|
||||
/A hideous black dog bares his teeth and growls at your approach.
|
||||
/Nearby, a large black dog is in a deep slumber.
|
||||
/
|
||||
#99
|
||||
/*Dreaded Wumpus
|
||||
/In the corner, a Wumpus is sleeping peacefully.
|
||||
/A sleepy Wumpus is ambling towards you. He wants to invite you to
|
||||
dinner. He wants you to *be* the dinner!
|
||||
/The Wumpus is still on your trail! And he's getting closer!!
|
||||
/The Wumpus is only a few steps behind you! All this exercise is
|
||||
making him veerrrrry hungry!
|
||||
/The Wumpus almost has you in his grasp! You can feel his hot breath
|
||||
on your neck!
|
||||
/"Chomp, chomp." Crunch! Chew! Slurp! Smack! Yum!!!
|
||||
/Nearby is the smashed body of a defunct Wumpus.
|
||||
/
|
||||
#100
|
||||
#101
|
||||
/Little bird in cage
|
||||
/A cheerful little bird is sitting here singing.
|
||||
/There is a little bird in the cage.
|
||||
/
|
||||
#102
|
||||
/Set of keys
|
||||
/There are some keys on the ground here.
|
||||
/
|
||||
#103
|
||||
/*Fountain
|
||||
/There is a fountain of sparkling vintage wine here!
|
||||
/
|
||||
#104
|
||||
/*Bats & guano in bat-cave
|
||||
/<$$<
|
||||
/
|
||||
#105
|
||||
/*gnome in phone booth
|
||||
/<$$<
|
||||
/
|
||||
#106
|
||||
/Colored mushrooms
|
||||
/There are some oddly-colored mushrooms here.
|
||||
/
|
||||
#107
|
||||
/Tiny cakes
|
||||
/There are some tiny cakes on the shelf.
|
||||
/
|
||||
#108
|
||||
/Leather Sack
|
||||
/There is a leather sack here.
|
||||
/
|
||||
#109
|
||||
#110
|
||||
/Rare book
|
||||
/There is a dusty, leather-bound volume here.
|
||||
/
|
||||
#111
|
||||
/Rare book
|
||||
/There is a dusty, leather-bound volume here.
|
||||
/
|
||||
#112
|
||||
/Steel wall-safe
|
||||
/The safe door is locked.
|
||||
/The safe door is open.
|
||||
/
|
||||
#113
|
||||
/Faded poster
|
||||
/Taped to the wall is a faded poster.
|
||||
/There is a faded poster here.
|
||||
/
|
||||
#114
|
||||
/Whiskbroom
|
||||
/There is a small whiskbroom here.
|
||||
/
|
||||
#115
|
||||
/*Carving on dusty rocks
|
||||
/<$$<
|
||||
/<$$<
|
||||
/
|
||||
#116
|
||||
/*Billboard
|
||||
/
|
||||
/
|
||||
#117
|
||||
#118
|
||||
/Small metal canister
|
||||
/There is a heavy, grey, metal canister here.
|
||||
/
|
||||
#119
|
||||
/Glowing stone
|
||||
/Nearby, a strange, greenish stone is glowing brightly.
|
||||
/
|
||||
#120
|
||||
/Quartz sphere
|
||||
/There is a polished sphere of pure quartz here!
|
||||
/
|
||||
1068
commands/advent/advent4.txt
Normal file
1068
commands/advent/advent4.txt
Normal file
File diff suppressed because it is too large
Load Diff
141
commands/advent/database.c
Normal file
141
commands/advent/database.c
Normal file
@@ -0,0 +1,141 @@
|
||||
/* program DATABASE.C */
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "advent.h"
|
||||
#include "advdec.h"
|
||||
#include "advtext.h"
|
||||
|
||||
static char oline[256];
|
||||
|
||||
_PROTOTYPE(void rdupto, (FILE *, int, int, char *));
|
||||
_PROTOTYPE(void rdskip, (FILE *, int, int));
|
||||
|
||||
/*
|
||||
Function to scan a file up to a specified
|
||||
point and either print or return a string.
|
||||
*/
|
||||
void rdupto(fdi, uptoc, print, string)
|
||||
FILE *fdi;
|
||||
int uptoc, print;
|
||||
char *string;
|
||||
{
|
||||
int c, i;
|
||||
static _CONST unsigned char key[4] = {'c' | 0x80, 'L' | 0x80,
|
||||
'y' | 0x80, 'D' | 0x80};
|
||||
|
||||
i = 1;
|
||||
while ((c = getc(fdi)) != uptoc && c != EOF) {
|
||||
if (c == '\n')
|
||||
i = 1;
|
||||
if (c >= 0x80)
|
||||
c ^= key[i++ & 3];
|
||||
if (c == '\r')
|
||||
continue;
|
||||
if (print)
|
||||
putchar(c);
|
||||
else
|
||||
*string++ = (char) c;
|
||||
}
|
||||
if (!print)
|
||||
*string = '\0';
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
Function to read a file skipping
|
||||
a given character a specified number
|
||||
of times, with or without repositioning
|
||||
the file.
|
||||
*/
|
||||
void rdskip(fdi, skipc, n)
|
||||
FILE *fdi;
|
||||
int skipc, n;
|
||||
{
|
||||
int c;
|
||||
|
||||
while (n--)
|
||||
while ((c = getc(fdi)) != skipc)
|
||||
if (c == EOF)
|
||||
bug(32);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
Routine to request a yes or no answer to a question.
|
||||
*/
|
||||
boolean yes(msg1, msg2, msg3)
|
||||
int msg1, msg2, msg3;
|
||||
{
|
||||
char answer[INPUTBUFLEN];
|
||||
|
||||
if (msg1)
|
||||
rspeak(msg1);
|
||||
do {
|
||||
switch (*ask("\n> ", answer, sizeof(answer))) {
|
||||
case 'n':
|
||||
case 'N':
|
||||
if (msg3)
|
||||
rspeak(msg3);
|
||||
return (FALSE);
|
||||
case 'y':
|
||||
case 'Y':
|
||||
if (msg2)
|
||||
rspeak(msg2);
|
||||
return (TRUE);
|
||||
default:
|
||||
fputs("Please answer Y (yes) or N (no).", stdout);
|
||||
}
|
||||
} while (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
Print a location description from "advent4.txt"
|
||||
*/
|
||||
void rspeak(msg)
|
||||
int msg;
|
||||
{
|
||||
if (msg == 54)
|
||||
printf("ok.\n");
|
||||
else {
|
||||
fseek(fd4, idx4[msg - 1], 0);
|
||||
rdupto(fd4, '#', 1, 0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
Print an item message for a given state from "advent3.txt"
|
||||
*/
|
||||
void pspeak(item, state)
|
||||
int item, state;
|
||||
{
|
||||
fseek(fd3, idx3[item - 1], 0);
|
||||
rdskip(fd3, '/', state + 2);
|
||||
rdupto(fd3, '/', FALSE, oline);
|
||||
if (strncmp(oline, "<$$<", 4) != 0)
|
||||
printf("%s", oline);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
Print a long location description from "advent1.txt"
|
||||
*/
|
||||
void desclg(loc)
|
||||
int loc;
|
||||
{
|
||||
fseek(fd1, idx1[loc - 1], 0);
|
||||
rdupto(fd1, '#', 1, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
Print a short location description from "advent2.txt"
|
||||
*/
|
||||
void descsh(loc)
|
||||
int loc;
|
||||
{
|
||||
fseek(fd2, idx2[loc - 1], 0);
|
||||
rdupto(fd2, '#', 1, 0);
|
||||
return;
|
||||
}
|
||||
676
commands/advent/english.c
Normal file
676
commands/advent/english.c
Normal file
@@ -0,0 +1,676 @@
|
||||
/* program ENGLISH.C */
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include "advent.h"
|
||||
#include "advdec.h"
|
||||
|
||||
#define ALL 109
|
||||
|
||||
#define ENTER 3
|
||||
#define CRAWL 17
|
||||
#define JUMP 39
|
||||
#define CLIMB 56
|
||||
#define XYZZY 62
|
||||
#define PLUGH 65
|
||||
#define PLOVER 71
|
||||
#define PHUCE 82
|
||||
|
||||
_PROTOTYPE(static void getwords, (void));
|
||||
_PROTOTYPE(static void clrlin, (void));
|
||||
_PROTOTYPE(static void doobj, (int *));
|
||||
_PROTOTYPE(static boolean doiobj, (void));
|
||||
_PROTOTYPE(static boolean do_scoop_up, (void));
|
||||
_PROTOTYPE(static boolean check_next, (void));
|
||||
|
||||
static char buffer[INPUTBUFLEN] = {'\0', '\0', '\0', '\0'};
|
||||
static char *txt[MAXWORDS] = {buffer, buffer, buffer, buffer};
|
||||
static char *cindex = buffer;
|
||||
static boolean pflag;
|
||||
static int vrbkey, words[MAXWORDS] = {0, 0, 0, 0}, word, wdx = 0;
|
||||
static int takdir[20] = {2, 6, 9, 10, 11, 13, 14, 17, 23, 25,
|
||||
33, 34, 36, 37, 39, 78, 79, 80, 89, -1};
|
||||
|
||||
static int vkey[60] = {
|
||||
0, 199, 9, 0, 130, 0, 197, 0, 0, 243,
|
||||
0, 0, 89, 140, 0, 5, 0, 227, 0, 0,
|
||||
0, 31, 42, 0, 0, 0, 0, 172, 1, 0,
|
||||
0, 0, 254, 0, 69, 0, 0, 92, 0, 0,
|
||||
138, 137, 149, 239, 45, 74, 183, 0, 0, 112,
|
||||
241, 0, 114, 0, 30, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
static int ptab[260] = {
|
||||
0, 3028, 3065, 3009, -3005, 5071, 5070, 5058, -5020, 19055,
|
||||
19108, 19038, 19020, 19071, 19070, 19058, 19004, 19048, 19091, 19094,
|
||||
19112, 19002, 19118, 2062, 2066, 2047, 2067, 2053, 2065, -2010,
|
||||
-3114, 4034, 4011, 4101, 4035, 4099, 4098, 4017, 4104, 4014,
|
||||
4015, -4087, 3083, 3085, -3081, 5055, 5108, 5020, 5071, 5070,
|
||||
5058, 5004, 5048, 5091, 5112, 5099, 5118, 19055, 19108, 19020,
|
||||
19071, 19070, 19058, 19004, 19048, 19091, 19112, 19099,-19118, 3028,
|
||||
3065, 3009, 3005, -3018, 19055, 19108, 19038, 19020, 19071, 19070,
|
||||
19058, 19004, 19004, 19048, 19091, 19094, 19112, 19002,-19118, 3028,
|
||||
3065, -3018, 19055, 19108, 19038, 19020, 19071, 19070, 19058, 19004,
|
||||
19048, 19091, 19094, 19112, 19118, 2062, 2066, 2047, 2067, 2053,
|
||||
2065, -2010, 3102, -3090, 19055, 19108, 19020, 19071, 19070, 19058,
|
||||
19004, 19048, 19091, 19014, 19015, 19112, 19118, 19120, 19120, -9999,
|
||||
3090, 3102, 3028, 3057, 3065, 3009, -3005,-29999, 2052, -2068,
|
||||
2024, 2065, 2091, 2042, 2073, 5071, 5070, 5058, -5020, 30999,
|
||||
2062, 2066, 2047, 2067, 2053, 2065, 2010, 2073, 19055, 19108,
|
||||
19038, 19020, 19071, 19070, 19058, 19004, 19048, 19091, 19094, 19112,
|
||||
19002,-19118, 2014, 2015, 2013, 2999, 5014, 5015, 5013, 5999,
|
||||
5110, 5113, -5999, 5055, 5108, 5020, 5071, 5070, 5058, 5004,
|
||||
5048, 5091, 5014, 5015, 5112, 5099, -5118, 3102, -3090, 6066,
|
||||
6047, 6067, 6053, 6072, 6073, 5055, 5108, 5020, 5071, 5070,
|
||||
5004, 5004, 5048, 5091, 5112, 5099, 5118, 19055, 19108, 19020,
|
||||
19071, 19070, 19058, 19004, 19048, 19091,-19118, 4034, 4011, 4101,
|
||||
4035, 4099, 4098, 4017, 4104, 4027, 4087, 9999,-30999, 2002,
|
||||
-6002, 3102, -3090, 9999, 4034, 4011, 4101, 4035, 4099, 4087,
|
||||
4098, 4017, 4104, -4027, -5999, 0, 0, 0, 0, 0,
|
||||
};
|
||||
|
||||
static int adjkey[40] = {
|
||||
0, 15, 38, 64, 4, 63, 1, 61, 62, 67,
|
||||
9, 27, 53, 46, 47, 60, 31, 39, 40, 6,
|
||||
43, 26, 32, 28, 34, 50, 49, 45, 44, 10,
|
||||
20, 25, 21, 36, 37, 30, 33, 0, 0, 0
|
||||
};
|
||||
|
||||
static int adjtab[70] = {
|
||||
0, 5, 98, -83, 2, -90, 66, 41, -90, -39,
|
||||
41, 14, 15, 50, -11, 50, 64, 56, 72, -74,
|
||||
-19, 119, 59, 73, -118, -119, -70, -41, 95, -118,
|
||||
-118, -58, -71, -120, 110, -108, -120, -73, -62, -60,
|
||||
110, 54, -63, -67, -41, -27, -47, 52, -75, -69,
|
||||
65, 112, -3, 41, 72, 90, 20, 101, 107, -118,
|
||||
-55, -10, -38, -4, 48, 9, -71, -39, 0, 0
|
||||
};
|
||||
|
||||
/*
|
||||
Analyze a two word sentence
|
||||
*/
|
||||
int english()
|
||||
{
|
||||
|
||||
char *ch_ptr, *word1, *word2;
|
||||
int type, val, type2, val2, adj, k, kk;
|
||||
static int iwest = 0;
|
||||
|
||||
if (!(words[++wdx])) {
|
||||
getwords();
|
||||
wdx = 0;
|
||||
}
|
||||
pflag = FALSE;
|
||||
word = words[wdx];
|
||||
if (word < 0) { /* check first word */
|
||||
printf("I didn't understand the word \"%s\"\n", txt[wdx]);
|
||||
words[wdx+1] = 0;
|
||||
return (FALSE); /* didn't know it */
|
||||
}
|
||||
type2 = val2 = -1;
|
||||
type = CLASS(word);
|
||||
clrlin();
|
||||
val = VAL(word);
|
||||
if (words[wdx + 1] && CLASS(words[wdx + 1]) != CONJUNCTION) {
|
||||
|
||||
/* 'SAY' or 'CALL'. If no next word, pass on to higher powers. */
|
||||
if (type == ACTION && (val == SAY || val == YELL)) {
|
||||
word = words[++wdx];
|
||||
if (!(word == XYZZY || word == PLUGH
|
||||
|| word == PLOVER || word == PHUCE)) {
|
||||
if (val == SAY)
|
||||
printf("Okay, \"%s\".\n", txt[wdx]);
|
||||
else {
|
||||
for (ch_ptr = txt[wdx]; *ch_ptr; ch_ptr++)
|
||||
if (islower(*ch_ptr))
|
||||
*ch_ptr = toupper(*ch_ptr);
|
||||
printf("Okay, \"%s\"!!!!!\n", txt[wdx]);
|
||||
}
|
||||
return (FALSE);
|
||||
}
|
||||
} else {
|
||||
word1 = txt[wdx];
|
||||
word2 = txt[wdx + 1];
|
||||
|
||||
/* Special stuff for 'ENTER'. Can't go into water. 'ENTER
|
||||
BOAT' means 'TAKE BOAT' */
|
||||
if (word == ENTER) {
|
||||
if (CLASS(words[wdx + 1]) == NOUN && VAL(words[wdx + 1]) == BOAT)
|
||||
word = TAKE + 2000;
|
||||
else if ((strcmp(word2, "stream") == 0)
|
||||
|| (strcmp(word2, "water") == 0)
|
||||
|| (strcmp(word2, "reservoir") == 0)
|
||||
|| (strcmp(word2, "ocean") == 0)
|
||||
|| (strcmp(word2, "sea") == 0)
|
||||
|| (strcmp(word2, "pool") == 0)) {
|
||||
rspeak(liqloc(g.loc) == WATER ? 70 : 43);
|
||||
wdx++;
|
||||
return (FALSE);
|
||||
}
|
||||
} else {
|
||||
type2 = CLASS(words[wdx + 1]);
|
||||
val2 = VAL(words[wdx + 1]);
|
||||
|
||||
/* 'LEAVE' is motion verb, unsless leaving an object.
|
||||
E.G., 'LEAVE BOAT' or 'LEAVE BOTTLE'. BUt make sure
|
||||
to leave ('DROP') only totable objects. */
|
||||
if (strcmp(word1, "leave") == 0 && type2 == NOUN) {
|
||||
if (!hinged(val2) || g.fixed[val2])
|
||||
word = LEAVE + 2000;
|
||||
|
||||
/* IF 'LIGHT LAMP', Light must be taken as an
|
||||
action verb, not a noun. */
|
||||
} else if (strcmp(word1, "light") == 0
|
||||
&& VAL(words[wdx + 1]) == LAMP) {
|
||||
word = ON + 2000;
|
||||
|
||||
/* 'WATER PLANT' becomes 'POUR WATER', If we are at
|
||||
plant. 'OIL DOOR' becomes 'POUR OIL', etc., etc. */
|
||||
} else if ((strcmp(word1, "water") == 0 || strcmp(word1, "oil") == 0)
|
||||
&& (strcmp(word2, "plant") == 0 || strcmp(word2, "door") == 0
|
||||
|| strcmp(word2, "sword") == 0 || strcmp(word2, "anvil") == 0)
|
||||
&& at(val2)) {
|
||||
words[wdx + 1] = word;
|
||||
txt[wdx + 1] = txt[wdx];
|
||||
word = POUR + 2000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/* This is the 'inner' loop. Dispatching of all word in a clause
|
||||
after the first comes through here. */
|
||||
do {
|
||||
switch (CLASS(word)) {
|
||||
case MOTION:
|
||||
{
|
||||
boolean do_part2;
|
||||
int i;
|
||||
|
||||
do_part2 = FALSE;
|
||||
type = CLASS(verbs[vrbx]);
|
||||
val = VAL(verbs[vrbx]);
|
||||
if (!vrbx)
|
||||
do_part2 = TRUE;
|
||||
else {
|
||||
if (type > ACTION) {
|
||||
rspeak(confuz());
|
||||
return (FALSE);
|
||||
}
|
||||
}
|
||||
if (type == ACTION) {
|
||||
if (val == GO)
|
||||
do_part2 = TRUE;
|
||||
else {
|
||||
if (val == TAKE) {
|
||||
for (i = 0; i < 20; i++)
|
||||
if (takdir[i] == val)
|
||||
do_part2 = TRUE;
|
||||
}
|
||||
if (!do_part2) {
|
||||
word = vocab(txt[wdx], 1);
|
||||
if (word)
|
||||
words[wdx--] = word;
|
||||
}
|
||||
}
|
||||
} else if (type != CRAWL && type != JUMP
|
||||
&& type != CLIMB)
|
||||
do_part2 = TRUE;
|
||||
if (do_part2) {
|
||||
verbs[1] = word;
|
||||
vrbx = 1;
|
||||
if (strcmp(txt[wdx], "west") == 0) {
|
||||
iwest++;
|
||||
if (iwest == 10)
|
||||
rspeak(17);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NOUN:
|
||||
if (pflag) {
|
||||
if (!doiobj())
|
||||
return (FALSE);
|
||||
} else {
|
||||
word = VAL(word);
|
||||
if (word == ALL) {
|
||||
if (!do_scoop_up())
|
||||
return (FALSE);
|
||||
} else {
|
||||
doobj(&word);
|
||||
if (word > 0) {
|
||||
objs[++objx] = word;
|
||||
otxt[objx] = txt[wdx];
|
||||
} else {
|
||||
clrlin();
|
||||
pflag = FALSE;
|
||||
wdx++;
|
||||
while (words[wdx]) {
|
||||
if (CLASS(words[wdx]) == CONJUNCTION)
|
||||
break;
|
||||
wdx++;
|
||||
}
|
||||
if (words[wdx] == 0)
|
||||
return (FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ACTION:
|
||||
if (vrbx == 0)
|
||||
vrbx++;
|
||||
else {
|
||||
if (VAL(verbs[vrbx]) == TAKE) {
|
||||
val = VAL(word);
|
||||
if (val == DRINK || val == INVENTORY
|
||||
|| val == SCORE || val == NOTHING
|
||||
|| val == LOOK);
|
||||
else if (val == GO && (
|
||||
strcmp(txt[wdx], "walk") == 0
|
||||
|| strcmp(txt[wdx], "run") == 0
|
||||
|| strcmp(txt[wdx], "hike") == 0));
|
||||
else {
|
||||
rspeak(confuz());
|
||||
return (FALSE);
|
||||
}
|
||||
} else if (objx || CLASS(words[wdx - 1]) == CONJUNCTION) {
|
||||
rspeak(confuz());
|
||||
return (FALSE);
|
||||
}
|
||||
}
|
||||
verbs[vrbx] = word;
|
||||
vtxt[vrbx] = txt[wdx];
|
||||
break;
|
||||
case MISC:
|
||||
if (vrbx) {
|
||||
rspeak(confuz());
|
||||
return (FALSE);
|
||||
}
|
||||
verbs[1] = word;
|
||||
vrbx = 1;
|
||||
break;
|
||||
case PREPOSITION:
|
||||
if (CLASS(verbs[vrbx]) != ACTION || iobx) {
|
||||
rspeak(confuz());
|
||||
return (FALSE);
|
||||
}
|
||||
vrbkey = vkey[VAL(verbs[vrbx])];
|
||||
if (!vrbkey) {
|
||||
rspeak(confuz());
|
||||
return (FALSE);
|
||||
}
|
||||
prep = VAL(word);
|
||||
pflag = TRUE;
|
||||
break;
|
||||
case ADJACTIVE:
|
||||
/* Adjective handler. Scarf the next word, make sure it is
|
||||
a valid object for this object. Then call getobj to see
|
||||
if it is really there, Then link into object code. */
|
||||
adj = VAL(word);
|
||||
if (!check_next())
|
||||
return (FALSE);
|
||||
else if (CLASS(word) == CONJUNCTION) {
|
||||
printf("%s what?\n", txt[wdx - 1]);
|
||||
return (FALSE);
|
||||
} else {
|
||||
if (CLASS(word) != NOUN)
|
||||
word = vocab(txt[wdx], NOUN);
|
||||
if (word == -1 || CLASS(word) != NOUN || VAL(word) == ALL) {
|
||||
rspeak(confuz());
|
||||
return (FALSE);
|
||||
}
|
||||
words[wdx] = word;
|
||||
kk = VAL(word);
|
||||
for (k = adjkey[adj]; adjtab[k] >= 0; k++) {
|
||||
if (kk == abs(adjtab[k]))
|
||||
break;
|
||||
}
|
||||
if (adjtab[k] < 0) {
|
||||
rspeak(confuz());
|
||||
return (FALSE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CONJUNCTION:
|
||||
if (!check_next())
|
||||
return (FALSE);
|
||||
switch (CLASS(word)) {
|
||||
case MOTION:
|
||||
case ACTION:
|
||||
case MISC:
|
||||
words[wdx--] = 0;
|
||||
break;
|
||||
case NOUN:
|
||||
case ADJACTIVE:
|
||||
break;
|
||||
case PREPOSITION:
|
||||
case CONJUNCTION:
|
||||
rspeak(confuz());
|
||||
return (FALSE);
|
||||
default:
|
||||
bug(33);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
bug(33);
|
||||
}
|
||||
word = words[++wdx];
|
||||
if (word < 0) {
|
||||
if (pct(50))
|
||||
printf("I don't understand the word %s?\n", txt[wdx]);
|
||||
else
|
||||
printf("Mumble ? %s\n", txt[wdx]);
|
||||
|
||||
words[wdx+1] = 0;
|
||||
return (FALSE);
|
||||
}
|
||||
type = CLASS(word);
|
||||
if (type == NOUN) {
|
||||
/* It's not the first: Make sure he included a comma or
|
||||
'and'. Differenctiate between direct & indirect objects.
|
||||
Check for special case of multiple ofjects: 'feed bear
|
||||
honey' or 'throw troll nugget'. */
|
||||
if ((pflag ? iobx : objx)
|
||||
&& CLASS(words[wdx - 1]) != CONJUNCTION) {
|
||||
val = VAL(verbs[vrbx]);
|
||||
if (!living(objs[objx]) || (val != THROW && val != FEED)) {
|
||||
rspeak(confuz());
|
||||
return (FALSE);
|
||||
}
|
||||
iobx++;
|
||||
iobjs[iobx] = objs[objx];
|
||||
objs[objx] = 0;
|
||||
objx++;
|
||||
}
|
||||
}
|
||||
} while (word);
|
||||
|
||||
if (verbs[1] == 0) {
|
||||
if (objs[1] == 0) {
|
||||
rspeak(confuz());
|
||||
clrlin();
|
||||
} else if (objs[2])
|
||||
printf("What do you want to do with them?\n");
|
||||
else
|
||||
printf("What do you want to do with %s?\n", otxt[1]);
|
||||
return (FALSE);
|
||||
} else if (objx > 1 && iobx > 1) {
|
||||
rspeak(confuz());
|
||||
return (FALSE);
|
||||
}
|
||||
return (TRUE);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
retrieve input line (max INPUTBUFLEN chars), convert to lower case
|
||||
& rescan for first two words (max. WORDSIZE-1 chars).
|
||||
*/
|
||||
static void getwords()
|
||||
{
|
||||
static int wdx = 0;
|
||||
int i, term_loc;
|
||||
char terminator;
|
||||
|
||||
if (*cindex == '\0') {
|
||||
while (!*ask("\n> ", buffer, sizeof(buffer))) ;
|
||||
for (cindex = buffer; *cindex; cindex++)
|
||||
if (isupper(*cindex))
|
||||
*cindex = tolower(*cindex);
|
||||
cindex = buffer;
|
||||
}
|
||||
wdx = 0;
|
||||
buffer[sizeof(buffer)-1] = '\0';
|
||||
for (i = 0; i < MAXWORDS; i++) {
|
||||
txt[i] = &buffer[sizeof(buffer)-1];
|
||||
words[i] = 0;
|
||||
}
|
||||
do {
|
||||
while (*cindex == ' ')
|
||||
cindex++;
|
||||
txt[wdx] = cindex;
|
||||
term_loc = strcspn(cindex, " ,.;\n");
|
||||
cindex += term_loc;
|
||||
terminator = *cindex;
|
||||
*cindex++ = '\0';
|
||||
if ((strcmp(txt[wdx], "a") != 0)
|
||||
&& (strcmp(txt[wdx], "the") != 0)
|
||||
&& (strcmp(txt[wdx], "an") != 0)) {
|
||||
words[wdx] = vocab(txt[wdx], 0);
|
||||
wdx++;
|
||||
}
|
||||
if (terminator == ',') {
|
||||
txt[wdx] = "and";
|
||||
words[wdx] = vocab(txt[wdx], 0);
|
||||
wdx++;
|
||||
}
|
||||
}
|
||||
while ((terminator != ';') && (terminator != '.')
|
||||
&& (terminator != '\0') && (terminator != '\n'));
|
||||
if (terminator == '\0')
|
||||
cindex--;
|
||||
return;
|
||||
}
|
||||
|
||||
/* CLRIN, clears out all surrent syntax args in preparation for
|
||||
* new input line
|
||||
*/
|
||||
|
||||
static void clrlin()
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAXWORDS; i++) {
|
||||
verbs[i] = 0;
|
||||
vtxt[i] = &buffer[sizeof(buffer)-1];
|
||||
}
|
||||
|
||||
for (i = 0; i < MAXITEMS; i++) {
|
||||
objs[i] = 0;
|
||||
otxt[i] = &buffer[sizeof(buffer)-1];
|
||||
iobjs[i] = 0;
|
||||
iotxt[i] = &buffer[sizeof(buffer)-1];
|
||||
}
|
||||
vrbx = 0;
|
||||
objx = 0;
|
||||
iobx = 0;
|
||||
prep = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
Routine to process an object.
|
||||
*/
|
||||
static void doobj(object)
|
||||
int *object;
|
||||
{
|
||||
int msg;
|
||||
|
||||
if (holding(*object))
|
||||
return;
|
||||
if (blind()) {
|
||||
printf("I see no %s here.\n", txt[wdx]);
|
||||
*object = 0;
|
||||
return;
|
||||
}
|
||||
/* Is object here? if so, transitive */
|
||||
if (g.fixed[*object] == g.loc || athand(*object))
|
||||
return;
|
||||
else if (here(*object)) {
|
||||
msg = plural(*object) ? 373 : 335;
|
||||
*object = 0;
|
||||
rspeak(msg);
|
||||
}
|
||||
/* Did he give grate as destination? */
|
||||
else if (*object == GRATE) {
|
||||
if (g.loc == 1 || g.loc == 4 || g.loc == 7) {
|
||||
verbs[1] = DEPRESSION;
|
||||
vrbx = 1;
|
||||
return;
|
||||
} else if (g.loc > 9 && g.loc < 15) {
|
||||
verbs[1] = ENTRANCE;
|
||||
vrbx = 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* Is it a dwarf he is after? */
|
||||
else if (dcheck() && g.dflag >= 2) {
|
||||
*object = DWARF;
|
||||
}
|
||||
/* Is he trying to get/use a liquid? */
|
||||
else if (liqloc(g.loc) == *object
|
||||
|| (liq(BOTTLE) == *object && athand(BOTTLE))
|
||||
|| (liq(CASK) == *object && athand(CASK)));
|
||||
else if (*object == PLANT && at(PLANT2) &&
|
||||
g.prop[PLANT2] == 0) {
|
||||
*object = PLANT2;
|
||||
} else if (*object == ROCKS && at(CARVNG)) {
|
||||
*object = CARVNG;
|
||||
}
|
||||
/* Is he trying to grab a knife? */
|
||||
else if (*object == KNIFE && g.knfloc == g.loc) {
|
||||
rspeak(116);
|
||||
g.knfloc = -1;
|
||||
}
|
||||
/* Is he trying to get at dynamite? */
|
||||
else if (*object == ROD && athand(ROD2)) {
|
||||
*object = ROD2;
|
||||
} else if (*object == DOOR && (at(SAFE) || at(TDOOR)
|
||||
|| at(TDOOR2) || at(PDOOR))) {
|
||||
if (at(TDOOR2))
|
||||
*object = TDOOR2;
|
||||
else if (at(PDOOR))
|
||||
*object = PDOOR;
|
||||
else if (at(SAFE))
|
||||
*object = SAFE;
|
||||
else
|
||||
*object = TDOOR;
|
||||
} else if (*object == BOOK && athand(BOOK2)) {
|
||||
*object = BOOK2;
|
||||
} else if (!(verbs[vrbx] == FIND || verbs[vrbx] == INVENTORY)) {
|
||||
*object = 0;
|
||||
printf("I see no %s here.\n", txt[wdx]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static boolean doiobj()
|
||||
{
|
||||
char dk[INPUTBUFLEN], dkk[INPUTBUFLEN];
|
||||
int kk;
|
||||
boolean ok;
|
||||
|
||||
/* checks object is valid for this preposition */
|
||||
ok = TRUE;
|
||||
word = VAL(word);
|
||||
if (word != ALL) {
|
||||
doobj(&word);
|
||||
if (word > 0) {
|
||||
iobjs[++iobx] = word;
|
||||
iotxt[iobx] = txt[wdx];
|
||||
} else
|
||||
ok = FALSE;
|
||||
}
|
||||
kk = abs(ptab[vrbkey]) / 1000;
|
||||
if (kk == prep) {
|
||||
/* preprosition is valid with this verb now check object of
|
||||
preprosition */
|
||||
|
||||
if (word == 0 || CLASS(word) == CONJUNCTION) {
|
||||
/* no object following prepresition: check special cases */
|
||||
|
||||
pflag = FALSE;
|
||||
strcpy(dk, txt[--wdx]);
|
||||
strcpy(dkk, vtxt[vrbx]);
|
||||
ok = FALSE;
|
||||
if ((strcmp(dk, "on") == 0
|
||||
|| strcmp(dk, "off") == 0)
|
||||
&& (strcmp(dkk, "turn") == 0
|
||||
|| objs[objx] == LAMP))
|
||||
ok = TRUE;
|
||||
if (strcmp(dkk, "take") == 0
|
||||
|| strcmp(dkk, "put") == 0)
|
||||
ok = TRUE;
|
||||
if (strcmp(dk, "up") == 0
|
||||
&& strcmp(dkk, "pick") == 0)
|
||||
ok = TRUE;
|
||||
if (strcmp(dk, "down") == 0
|
||||
&& (strcmp(dkk, "put") == 0 || verbs[vrbx] == THROW) )
|
||||
ok = TRUE;
|
||||
} else {
|
||||
/* object follows preposition See if it's plausible. */
|
||||
|
||||
kk = abs(ptab[vrbkey]) % 1000;
|
||||
if (kk == word && kk == ALL) {
|
||||
if (!do_scoop_up())
|
||||
return (FALSE);
|
||||
} else if (!(kk == word || kk == 999)) {
|
||||
vrbkey++;
|
||||
ok = ptab[vrbkey - 1] < 0 ? FALSE : TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (ok);
|
||||
}
|
||||
|
||||
static boolean do_scoop_up()
|
||||
{
|
||||
int i, val;
|
||||
|
||||
val = VAL(verbs[vrbx]);
|
||||
if (val == DROP || val == PUT || val == LEAVE) {
|
||||
for (i = 1; i < MAXOBJ; i++) {
|
||||
if (!athand(i) || g.fixed[i])
|
||||
continue;
|
||||
if (i > WATER && i <= WINE + 1)
|
||||
continue;
|
||||
if (toting(i)) {
|
||||
objs[++objx] = i;
|
||||
otxt[objx] = "BUG???";
|
||||
if (objx >= 44)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (val == TAKE || val == PICK || val == GET) {
|
||||
if (blind()) {
|
||||
rspeak(357);
|
||||
return (FALSE);
|
||||
} else {
|
||||
for (i = 1; i < MAXOBJ; i++) {
|
||||
if (!athand(i) || g.fixed[i])
|
||||
continue;
|
||||
if (i > WATER && i <= WINE + 1)
|
||||
continue;
|
||||
if (!toting(i)) {
|
||||
objs[++objx] = i;
|
||||
otxt[objx] = "BUG???";
|
||||
if (objx >= 44)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
static boolean check_next()
|
||||
{
|
||||
|
||||
word = words[wdx + 1];
|
||||
if (word > 0)
|
||||
return (TRUE);
|
||||
else if (word == 0)
|
||||
rspeak(confuz());
|
||||
else {
|
||||
if (pct(50))
|
||||
printf("I don't understand the word %s?\n", txt[wdx]);
|
||||
else
|
||||
printf("Mumble ? %s\n", txt[wdx]);
|
||||
words[wdx+1] = 0;
|
||||
}
|
||||
|
||||
return (FALSE);
|
||||
}
|
||||
264
commands/advent/initial.c
Normal file
264
commands/advent/initial.c
Normal file
@@ -0,0 +1,264 @@
|
||||
/*
|
||||
Initialization of adventure play variables
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "advent.h" /* #define preprocessor equates */
|
||||
#define EXTERN /* define, not declare, in advdec.h */
|
||||
#include "advdec.h"
|
||||
|
||||
int plac[MAXOBJ] = {
|
||||
0, 0, 3, 8, 10, 11, 0, 14, 0, 148, /* 0 - 9 */
|
||||
96, 19, 17, 101, 103, 0, 106, 0, 0, 238, /* 10 - 19 */
|
||||
238, 117, 190, 109, 25, 23, 111, 35, 0, 97, /* 20 - 29 */
|
||||
0, 119, 0, 117, 0, 130, 0, 126, 140, 0, /* 30 - 39 */
|
||||
96, 94, 158, 160, 188, 0, 155, 174, 166, 228, /* 40 - 49 */
|
||||
18, 204, 27, 29, 30, 0, 92, 168, 97, 100, /* 50 - 59 */
|
||||
101, 0, 119, 127, 130, 141, 144, 205, 28, 182, /* 60 - 69 */
|
||||
225, 230, 0, 147, 241, 248, 0, 0, 0, 0, /* 70 - 79 */
|
||||
0, 0, 0, 0, 0, 0, 0, 193, 102, 0, /* 80 - 89 */
|
||||
159, 141, 172, 188, 189, 0, 0, 193, 227, 174, /* 90 - 99 */
|
||||
0, 13, 238, 217, 171, 0, 146, 159, 3, 0, /* 100 - 109 */
|
||||
0, 0, 0, 3, 180, 39, 5, 0, 110, 169, /* 110 - 119 */
|
||||
200
|
||||
};
|
||||
|
||||
int fixd[MAXOBJ] = {
|
||||
0, 0, 0, 9, 0, 0, 0, 15, 0, 0, /* 0 - 9 */
|
||||
0, -1, 27, -1, 0, 0, 0, -1, 0, 0, /* 10 - 19 */
|
||||
0, 122, 235, -1, -1, 67, -1, 110, 0, -1, /* 20 - 29 */
|
||||
-1, 121, 0, 122, 0, -1, -1, -1, -1, 0, /* 30 - 39 */
|
||||
-1, -1, 166, 167, 189, 0, 0, -1, 0, 229, /* 40 - 49 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 50 - 59 */
|
||||
0, 0, 121, 0, -1, 0, 0, 0, 0, 0, /* 60 - 69 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 70 - 79 */
|
||||
0, 0, 0, 0, 0, 0, 0, -1, 194, -1, /* 80 - 89 */
|
||||
0, -1, 174, -1, -1, 0, 0, -1, -1, -1, /* 90 - 99 */
|
||||
0, 0, 0, -1, -1, -1, 0, 0, 0, 0, /* 100 - 109 */
|
||||
0, 0, -1, 0, 0, -1, -1, 0, 0, 0, /* 110 - 119 */
|
||||
0
|
||||
};
|
||||
|
||||
struct playinfo g = {
|
||||
0, /* turns */
|
||||
1, /* loc */
|
||||
1, /* oldloc */
|
||||
1, /* oldloc2 */
|
||||
1, /* newloc */
|
||||
{ /* loc_attrib[MAXLOC] */
|
||||
0, 73, 65, 73, 73, /* 0 - 4 */
|
||||
65, 65, 73, 1601, 33, /* 5 - 9 */
|
||||
32, 32, 32, 1824, 32, /* 10 - 14 */
|
||||
0, 2, 0, 0, 2816, /* 15 - 19 */
|
||||
2, 2, 2, 0, 10, /* 20 - 24 */
|
||||
0, 2, 0, 0, 0, /* 25 - 29 */
|
||||
0, 2, 2, 8, 0, /* 30 - 34 */
|
||||
0, 0, 0, 8, 0, /* 35 - 39 */
|
||||
2, 0, 256, 256, 256, /* 40 - 44 */
|
||||
256, 272, 272, 272, 256, /* 45 - 49 */
|
||||
256, 0, 256, 256, 272, /* 50 - 54 */
|
||||
256, 272, 0, 16, 2, /* 55 - 59 */
|
||||
0, 0, 0, 0, 0, /* 60 - 64 */
|
||||
0, 0, 0, 0, 0, /* 65 - 69 */
|
||||
0, 0, 0, 0, 0, /* 70 - 74 */
|
||||
0, 0, 0, 0, 2, /* 75 - 79 */
|
||||
256, 256, 272, 0, 0, /* 80 - 84 */
|
||||
16, 272, 0, 0, 2, /* 85 - 89 */
|
||||
2, 0, 0, 0, 0, /* 90 - 94 */
|
||||
8, 0, 0, 1280, 513, /* 95 - 99 */
|
||||
513, 512, 0, 0, 0, /* 00 - 04 */
|
||||
0, 0, 0, 768, 0, /* 105 - 109 */
|
||||
0, 0, 0, 8, 0, /* 110 - 114 */
|
||||
1, 1, 0, 0, 0, /* 115 - 119 */
|
||||
0, 0, 16, 16, 16, /* 120 - 124 */
|
||||
16, 17, 16, 16, 16, /* 125 - 129 */
|
||||
16, 0, 0, 0, 0, /* 130 - 134 */
|
||||
0, 0, 0, 0, 0, /* 135 - 139 */
|
||||
0, 1040, 16, 0, 0, /* 140 - 144 */
|
||||
2, 65, 65, 65, 65, /* 145 - 149 */
|
||||
65, 65, 65, 65, 65, /* 150 - 154 */
|
||||
65, 3, 2625, 2113, 65, /* 155 - 159 */
|
||||
65, 3, 3, 3, 3, /* 160 - 164 */
|
||||
3, 41, 41, 9, 9, /* 165 - 169 */
|
||||
0, 0, 0, 0, 0, /* 170 - 174 */
|
||||
0, 0, 0, 2, 0, /* 175 - 179 */
|
||||
0, 2, 0, 0, 0, /* 180 - 184 */
|
||||
0, 0, 0, 0, 16, /* 185 - 189 */
|
||||
0, 0, 9, 0, 0, /* 190 - 194 */
|
||||
0, 0, 0, 9, 2, /* 195 - 199 */
|
||||
1, 1, 2304, 0, 0, /* 200 - 204 */
|
||||
0, 8, 8, 8, 0, /* 205 - 209 */
|
||||
0, 0, 1, 0, 9, /* 210 - 214 */
|
||||
0, 0, 12, 0, 0, /* 215 - 219 */
|
||||
0, 0, 0, 0, 0, /* 220 - 224 */
|
||||
0, 2, 2625, 73, 73, /* 225 - 229 */
|
||||
0, 2, 2, 2, 2, /* 230 - 234 */
|
||||
0, 0, 2, 65, 3137, /* 235 - 239 */
|
||||
65, 65, 65, 65, 65, /* 240 - 244 */
|
||||
65, 65, 65, 65 /* 245 - 249 */
|
||||
}, /* loc_attrib[MAXLOC] */
|
||||
{0 }, /* place[MAXOBJ] */
|
||||
{0 }, /* fixed[MAXOBJ] */
|
||||
{ /* weight[MAXOBJ] */
|
||||
0, 0, 1, 0, 1, 2, 2, 0, 0, 2, /* 0 - 9 */
|
||||
1, 0, 0, 0, 7, 7, 1, 0, 0, 2, /* 10 - 19 */
|
||||
1, 0, 0, 0, 0, 0, 0, 0, 3, 0, /* 20 - 29 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 3, /* 30 - 39 */
|
||||
0, 0, 0, 0, 0, 0, 1, 1, 0, 0, /* 40 - 49 */
|
||||
6, 1, 2, 2, 3, 5, 4, 3, 2, 3, /* 50 - 59 */
|
||||
4, 1, 3, 1, 3, 2, 1, 1, 2, 2, /* 60 - 69 */
|
||||
2, 3, 1, 1, 3, 1, 0, 0, 0, 0, /* 70 - 79 */
|
||||
0, 2, 2, 2, 2, 2, 2, 0, 0, 0, /* 70 - 79 */
|
||||
1, 0, 0, 0, 0, 3, 2, 0, 0, 0, /* 80 - 89 */
|
||||
0, 2, 1, 0, 0, 0, 1, 1, 2, 0, /* 100 - 109 */
|
||||
3, 3, 0, 1, 1, 0, 0, 0, 3, 1, /* 110 - 119 */
|
||||
2, 0, 0 /* 120 - 129 */
|
||||
}, /* weight[MAXOBJ] */
|
||||
{0 }, /* atloc[MAXLOC] */
|
||||
{0 }, /* link[MAXOBJ * 2] */
|
||||
{0 }, /* holder[MAXOBJ] */
|
||||
{0 }, /* hlink[MAXOBJ] */
|
||||
{0 }, /* visited[MAXLOC] */
|
||||
{0 }, /* prop[MAXOBJ] */
|
||||
{ /* obj_state[MAXOBJ] */
|
||||
0, 0, 32800, 26, 32770, /* 0 - 4 */
|
||||
32, 32, 8192, 0, 0, /* 5 - 9 */
|
||||
32, 512, 0, 256, 770, /* 10 - 14 */
|
||||
770, 288, 512, 0, 160, /* 15 - 19 */
|
||||
32802, 0, 0, 0, 128, /* 20 - 24 */
|
||||
0, 0, 0, 32, 8192, /* 25 - 29 */
|
||||
512, 512, 0, 512, 0, /* 30 - 34 */
|
||||
512, 256, 0, 32768, 8224, /* 35 - 39 */
|
||||
0, 18, 26, 26, 2, /* 40 - 44 */
|
||||
0, 8320, 18464, 32768, 0, /* 45 - 49 */
|
||||
16384, 16416, 16416, 26656, 24608, /* 50 - 54 */
|
||||
49240, 24608, 16384, 49184, 16416, /* 55 - 59 */
|
||||
16416, 16416, 16384, 16544, 16442, /* 60 - 64 */
|
||||
16416, 18464, 26656, 16416, 16416, /* 65 - 69 */
|
||||
49184, 49154, 18464, 18464, 16416, /* 70 - 74 */
|
||||
16416, 0, 0, 0, 0, /* 75 - 79 */
|
||||
0, 0, 0, 0, 0, /* 80 - 84 */
|
||||
0, 0, 8704, 0, 0, /* 85 - 89 */
|
||||
0, 0, 0, 0, 32768, /* 90 - 94 */
|
||||
0, 128, 0, 0, 0, /* 95 - 99 */
|
||||
0, 160, 8224, 0, 0, /* 100 - 104 */
|
||||
0, 8352, 8352, 32870, 0, /* 105 - 109 */
|
||||
16674, 258, 32858, 288, 32, /* 110 - 114 */
|
||||
256, 0, 0, 32866, 16416, /* 115 - 119 */
|
||||
16416, 0, 0 /* 120 - 123 */
|
||||
}, /* obj_state[MAXOBJ] */
|
||||
{ /* points[MAXOBJ] */
|
||||
0, 0, 0, 0, 0, /* 0 - 4 */
|
||||
0, 0, 0, 0, 0, /* 5 - 9 */
|
||||
0, 0, 0, 0, 0, /* 10 - 14 */
|
||||
0, 1000108, 0, 0, 0, /* 15 - 19 */
|
||||
0, 0, 0, 0, 0, /* 20 - 24 */
|
||||
0, 0, 0, 0, 0, /* 25 - 29 */
|
||||
0, 0, 0, 0, 0, /* 30 - 34 */
|
||||
0, 0, 0, 0, 0, /* 35 - 39 */
|
||||
0, 0, 0, 0, 0, /* 40 - 44 */
|
||||
0, 0, -3000112, 0, 0, /* 45 - 49 */
|
||||
-2000055, -2000112, -2000112, -1000112, -5000112, /* 50 - 54 */
|
||||
5000003, -3000112, -2000055, 2000003, -3000112, /* 55 - 59 */
|
||||
-4000112, -4000112, 3000003, -1000112, -4000112, /* 60 - 64 */
|
||||
-4000112, -2000112, -3000112, -1000112, -1000112, /* 65 - 69 */
|
||||
-2000112, -3012055, -4000112, -1000112, -5000112, /* 70 - 74 */
|
||||
-5000112, 0, 0, 0, 0, /* 75 - 79 */
|
||||
0, 0, 0, 0, 0, /* 80 - 84 */
|
||||
0, 0, 0, 0, 0, /* 85 - 89 */
|
||||
0, 0, 0, 0, 0, /* 90 - 94 */
|
||||
0, 0, 0, 0, 0, /* 95 - 99 */
|
||||
0, 0, 0, 0, 0, /* 100 - 104 */
|
||||
0, 0, 0, 0, 0, /* 105 - 109 */
|
||||
-2000112, 0, 0, 0, 0, /* 110 - 114 */
|
||||
0, 0, 0, 0, -4000118, /* 115 - 119 */
|
||||
-2000112, 0 /* 120 - 122 */
|
||||
}, /* points[MAXOBJ] */
|
||||
{0 }, /* hinted[HNTMAX+1] */
|
||||
{ /* hints[HNTMAX+1][5] */
|
||||
{ 0, 0, 0, 0, 0 }, /* 0 */
|
||||
{ 0, 9999, 4, 0, 0 }, /* 1 */
|
||||
{ 0, 9999, 10, 0, 0 }, /* 2 */
|
||||
{ 0, 9999, 5, 0, 0 }, /* 3 */
|
||||
{ 0, 0, 0, 0, 0 }, /* 4 */
|
||||
{ 0, 0, 0, 0, 0 }, /* 5 */
|
||||
{ 0, 0, 0, 0, 0 }, /* 6 */
|
||||
{ 0, 15, 4, 176, 177 }, /* 7 */
|
||||
{ 0, 8, 5, 178, 179 }, /* 8 */
|
||||
{ 0, 13, 3, 180, 181 }, /* 9 */
|
||||
{ 0, 6, 10, 211, 212 }, /* 10 */
|
||||
{ 0, 6, 5, 213, 214 }, /* 11 */
|
||||
{ 0, 4, 2, 62, 63 }, /* 12 */
|
||||
{ 0, 5, 2, 18, 19 }, /* 13 */
|
||||
{ 0, 4, 2, 62, 233 }, /* 14 */
|
||||
{ 0, 6, 5, 274, 275 }, /* 15 */
|
||||
{ 0, 10, 5, 289, 290 }, /* 16 */
|
||||
{ 0, 8, 2, 20, 21 }, /* 17 */
|
||||
{ 0, 5, 2, 404, 405 } /* 18 */
|
||||
}, /* hints[HNTMAX+1][5] */
|
||||
{0 }, /* hintlc[HNTMAX+1] */
|
||||
0, /* tally */
|
||||
0, /* tally2 */
|
||||
0, /* limit */
|
||||
0, /* lmwarn */
|
||||
0, /* wzdark */
|
||||
0, /* closing */
|
||||
0, /* closed */
|
||||
0, /* holding */
|
||||
0, /* detail */
|
||||
0, /* knfloc */
|
||||
30, /* clock */
|
||||
50, /* clock2 */
|
||||
0, /* panic */
|
||||
{ 0, 19, 27, 33, 44, 64, 114 }, /* dloc[DWARFMAX+1] */
|
||||
0, /* dflag */
|
||||
{ 0, 0, 0, 0, 0, 0, 0 }, /* dseen[DWARFMAX+1] */
|
||||
{ 0, 0, 0, 0, 0, 0, 0 }, /* odloc[DWARFMAX+1] */
|
||||
18, /* daltloc */
|
||||
0, /* dkill */
|
||||
114, /* chloc */
|
||||
140, /* chloc2 */
|
||||
0, /* bonus */
|
||||
0, /* numdie */
|
||||
0, /* foobar */
|
||||
0, /* combo */
|
||||
0, /* terse */
|
||||
5, /* abbnum */
|
||||
100, /* health */
|
||||
0, /* chase */
|
||||
FALSE, /* flg239 */
|
||||
0 /* lastglob */
|
||||
};
|
||||
|
||||
/*
|
||||
Initialization of adventure play variables
|
||||
*/
|
||||
void initialize()
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = MAXOBJ; i > 0; i--) {
|
||||
g.fixed[i] = fixd[i];
|
||||
if (fixd[i] > 0) {
|
||||
drop(i + MAXOBJ, fixd[i]);
|
||||
drop(i, plac[i]);
|
||||
}
|
||||
if ((plac[i] != 0) && (fixd[i] <= 0))
|
||||
drop(i, plac[i]);
|
||||
}
|
||||
|
||||
for (i = 1; i <= MAXOBJ; i++) {
|
||||
if (treasr(i)) {
|
||||
g.prop[i] = -1;
|
||||
g.tally++;
|
||||
}
|
||||
}
|
||||
|
||||
newtravel = TRUE;
|
||||
g.place[BOOK] = -1;
|
||||
insert(BOOK, SAFE);
|
||||
g.place[WATER] = -1;
|
||||
insert(WATER, BOTTLE);
|
||||
g.prop[BOTTLE] = 8;
|
||||
return;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user