Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2ec255bb5e | ||
|
|
cd445fe22a | ||
|
|
64b1205e6c | ||
|
|
94881e6d4a | ||
|
|
6677a8c8e0 | ||
|
|
255ad2ab37 | ||
|
|
7dc782dd1a | ||
|
|
e9eb2c4f8b |
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__*
|
||||
130
Makefile
130
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,9 @@ 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 clean # Remove all compiler results"
|
||||
@echo ""
|
||||
@echo "Run 'make' in tools/ to create a new MINIX configuration."
|
||||
@@ -29,96 +29,64 @@ 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
|
||||
.elif ${COMPILER_TYPE} == "gnu"
|
||||
world: mkfiles includes depend gnu-libraries install
|
||||
.endif
|
||||
|
||||
mkfiles:
|
||||
make -C share/mk install
|
||||
cp etc/mk/*.mk /etc/mk/
|
||||
|
||||
includes:
|
||||
$(MAKE) -C include includes
|
||||
$(MAKE) -C lib includes NBSD_LIBC=yes
|
||||
cd include && $(MAKE) includes
|
||||
|
||||
MKHEADERSS=/usr/pkg/gcc*/libexec/gcc/*/*/install-tools/mkheaders
|
||||
libraries:
|
||||
cd lib && sh ack_build.sh obj depend all install
|
||||
|
||||
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
|
||||
gnu-includes: includes
|
||||
SHELL=/bin/sh; for d in $(MKHEADERSS); do if [ -f $$d ] ; then sh -e $$d ; fi; done
|
||||
SHELL=/bin/sh; if [ -f $(MKHEADERS411) ] ; then sh -e $(MKHEADERS411) ; fi
|
||||
SHELL=/bin/sh; if [ -f $(MKHEADERS443) ] ; then sh -e $(MKHEADERS443) ; fi
|
||||
|
||||
libraries: includes
|
||||
$(MAKE) -C lib dependall install
|
||||
gnu-libraries:
|
||||
cd lib && sh gnu_build.sh obj depend all install
|
||||
|
||||
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
|
||||
commands:
|
||||
cd commands && $(MAKE) 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::
|
||||
cd boot && $(MAKE) depend
|
||||
cd commands && $(MAKE) depend
|
||||
cd kernel && $(MAKE) depend
|
||||
cd servers && $(MAKE) depend
|
||||
cd drivers && $(MAKE) depend
|
||||
|
||||
etcfiles:
|
||||
$(MAKE) -C etc install
|
||||
etcfiles::
|
||||
cd etc && $(MAKE) install
|
||||
|
||||
etcforce:
|
||||
$(MAKE) -C etc installforce
|
||||
all::
|
||||
cd boot && $(MAKE) all
|
||||
cd commands && $(MAKE) all
|
||||
cd tools && $(MAKE) all
|
||||
|
||||
all:
|
||||
$(MAKE) -C sys 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::
|
||||
cd boot && $(MAKE) install
|
||||
cd man && $(MAKE) install makedb
|
||||
cd commands && $(MAKE) install
|
||||
cd share && $(MAKE) install
|
||||
cd tools && $(MAKE) install
|
||||
|
||||
install:
|
||||
$(MAKE) -C sys install
|
||||
$(MAKE) -C libexec 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::
|
||||
cd boot && $(MAKE) clean
|
||||
cd commands && $(MAKE) clean
|
||||
cd tools && $(MAKE) clean
|
||||
cd lib && sh ack_build.sh clean
|
||||
cd lib && sh gnu_build.sh clean
|
||||
cd test && $(MAKE) clean
|
||||
|
||||
clean: mkfiles
|
||||
$(MAKE) -C sys 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 test clean
|
||||
|
||||
cleandepend: mkfiles
|
||||
$(MAKE) -C lib cleandepend
|
||||
$(MAKE) -C sys 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
|
||||
cleandepend::
|
||||
cd boot && $(MAKE) cleandepend
|
||||
cd commands && $(MAKE) cleandepend
|
||||
cd tools && $(MAKE) cleandepend
|
||||
|
||||
@@ -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 */
|
||||
}
|
||||
79
boot/Makefile
Normal file
79
boot/Makefile
Normal file
@@ -0,0 +1,79 @@
|
||||
# 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 bootexec boot masterboot \
|
||||
jumpboot installboot edparams
|
||||
|
||||
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.bootexec= 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.bootexec= ${I86LDFLAGS}
|
||||
DPADD.bootexec= ${LIBSYS}
|
||||
LDADD.bootexec= -lsys
|
||||
BINDIR.bootexec= /usr/mdec
|
||||
MAN.bootexec=
|
||||
|
||||
BINDIR.boot= /usr/mdec
|
||||
MAN.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=
|
||||
|
||||
rawfs86.c: rawfs.c
|
||||
ln -f rawfs.c rawfs86.c
|
||||
|
||||
edparams.c: boot.c
|
||||
ln -f boot.c edparams.c
|
||||
|
||||
cdbootblock.s: bootblock.s
|
||||
ln -f bootblock.s cdbootblock.s
|
||||
|
||||
boot: bootexec
|
||||
install -S 22kb bootexec
|
||||
cp bootexec boot
|
||||
|
||||
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
|
||||
|
||||
.include <minix.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);
|
||||
}
|
||||
|
||||
2041
boot/boot.c
Normal file
2041
boot/boot.c
Normal file
File diff suppressed because it is too large
Load Diff
220
boot/boot.h
Normal file
220
boot/boot.h
Normal file
@@ -0,0 +1,220 @@
|
||||
/* 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;
|
||||
|
||||
EXTERN memory mem[3]; /* List of available memory. */
|
||||
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.
|
||||
1548
boot/boothead.s
Normal file
1548
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%x, 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("(%dk)\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("Unsuspected 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
|
||||
@@ -193,9 +193,6 @@ do
|
||||
17,0)
|
||||
des="hello" dev=hello
|
||||
;;
|
||||
18,0)
|
||||
des="UNIX domain socket" dev=uds
|
||||
;;
|
||||
BAD,BAD)
|
||||
des= dev=
|
||||
;;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
SCRIPTS= DESCRIBE.sh
|
||||
MAN=
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
.include <minix.prog.mk>
|
||||
|
||||
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 <minix.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 filter hello
|
||||
;;
|
||||
0:|1:-\?)
|
||||
cat >&2 <<EOF
|
||||
@@ -45,11 +45,9 @@ Where key is one of the following:
|
||||
audio mixer # Make audio devices
|
||||
klog # Make /dev/klog
|
||||
random # Make /dev/random, /dev/urandom
|
||||
uds # Make /dev/uds
|
||||
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
|
||||
@@ -252,12 +250,6 @@ do
|
||||
$e mknod urandom c 16 0; $e chmod 644 urandom
|
||||
$e chgrp operator random urandom
|
||||
;;
|
||||
uds)
|
||||
# unix domain sockets device
|
||||
$e mknod uds c 18 0; $e chmod 644 random
|
||||
$e chgrp operator uds
|
||||
$e chmod 666 uds
|
||||
;;
|
||||
klog)
|
||||
# logging device.
|
||||
$e mknod klog c 15 0
|
||||
@@ -268,11 +260,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
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
SCRIPTS= MAKEDEV.sh
|
||||
MAN=
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
.include <minix.prog.mk>
|
||||
|
||||
@@ -1,44 +1,44 @@
|
||||
# Makefile for commands.
|
||||
|
||||
.include <bsd.own.mk>
|
||||
.include <minix.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 cdiff cdprobe cgrep 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 \
|
||||
find finger fingerd fix fold format fortune fsck.mfs \
|
||||
ftp101 gcore gcov-pull getty grep head hexdump host \
|
||||
hostaddr id ifconfig ifdef install \
|
||||
comm compress cp crc cron crontab cut datasizes date \
|
||||
dd de decomp16 DESCRIBE dev2name devsize df dhcpd \
|
||||
dhrystone diff dirname dis88 du dumpcore easypack \
|
||||
ed eject elle elvis env expand factor fgrep file \
|
||||
find finger fingerd fix fold format fortune fsck \
|
||||
fsck1 ftp101 ftpd200 getty gomoku grep head 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 \
|
||||
mkproto modem mount mt netconf newroot nice acknm nohup \
|
||||
nonamed od paste patch pax \
|
||||
lex life loadkeys loadramdisk logger login look lp \
|
||||
lpd ls lspci M m4 mail make MAKEDEV makewhatis man \
|
||||
mdb mesg mined mkdep mkdir mkdist mkfifo mkfs mknod \
|
||||
mkproto modem mount mt netconf newroot nice nm nohup \
|
||||
nonamed od packit 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 \
|
||||
whereis which who write writeisofs fetch \
|
||||
xargs yacc yes zdump zmodem pkgin_cd \
|
||||
mktemp worldstone updateboot
|
||||
readfs reboot remsync rev rget rlogin rlogind rmdir \
|
||||
rotate rsh rshd sed service setup shar size \
|
||||
sleep slip sort spell split srccrc stat strings strip \
|
||||
stty su sum svclog swapfs swifi sync synctree sysenv \
|
||||
syslogd tail talk talkd 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 \
|
||||
whatis whereis which who whoami write writeisofs \
|
||||
xargs yacc yap yes zdump zic zmodem
|
||||
|
||||
.if ${ARCH} == "i386"
|
||||
SUBDIR+= atnormalize dosread fdisk loadfont \
|
||||
autopart part partition playwave \
|
||||
mixer autopart part partition playwave postmort \
|
||||
recwave repartition screendump
|
||||
SUBDIR+= acd asmconv gas2ack
|
||||
.endif
|
||||
|
||||
.include <bsd.subdir.mk>
|
||||
.include <minix.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
|
||||
|
||||
12
commands/aal/Makefile
Normal file
12
commands/aal/Makefile
Normal file
@@ -0,0 +1,12 @@
|
||||
# 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
|
||||
|
||||
LINKS+= ${BINDIR}/aal ${BINDIR}/ar
|
||||
MAN=
|
||||
|
||||
.include <minix.prog.mk>
|
||||
25
commands/aal/arch.h
Normal file
25
commands/aal/arch.h
Normal file
@@ -0,0 +1,25 @@
|
||||
/* $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
|
||||
|
||||
#endif /* __ARCH_H_INCLUDED */
|
||||
796
commands/aal/archiver.c
Normal file
796
commands/aal/archiver.c
Normal file
@@ -0,0 +1,796 @@
|
||||
/*
|
||||
* (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
|
||||
*/
|
||||
|
||||
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 <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();
|
||||
|
||||
usage()
|
||||
{
|
||||
error(TRUE, "usage: %s %s archive [file] ...\n",
|
||||
progname,
|
||||
#ifdef AAL
|
||||
"[acdrtxvlu]"
|
||||
#else
|
||||
"[acdprtxvlu]"
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
/*VARARGS2*/
|
||||
error(quit, str1, str2, str3, str4)
|
||||
BOOL quit;
|
||||
char *str1, *str2, *str3, *str4;
|
||||
{
|
||||
char errbuf[256];
|
||||
|
||||
sprint(errbuf, str1, str2, str3, str4);
|
||||
write(2, errbuf, strlen(errbuf));
|
||||
if (quit) {
|
||||
unlink(temp_arch);
|
||||
_exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
char *basename(path)
|
||||
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();
|
||||
|
||||
open_archive(name, mode)
|
||||
register char *name;
|
||||
register int mode;
|
||||
{
|
||||
unsigned short magic = 0;
|
||||
int fd;
|
||||
|
||||
if (mode == CREATE) {
|
||||
if ((fd = creat(name, 0666)) < 0)
|
||||
error(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) error(FALSE, "%s: creating %s\n", progname, name);
|
||||
return open_archive(name, APPEND);
|
||||
}
|
||||
error(TRUE, "cannot open %s\n", name);
|
||||
}
|
||||
lseek(fd, 0L, 0);
|
||||
magic = rd_unsigned2(fd);
|
||||
if (magic != AALMAG && magic != ARMAG)
|
||||
error(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);
|
||||
}
|
||||
|
||||
main(argc, argv)
|
||||
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) error(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) {
|
||||
error(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();
|
||||
|
||||
get(argc, argv)
|
||||
int argc;
|
||||
register 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);
|
||||
}
|
||||
|
||||
add(name, fd, mess)
|
||||
char *name;
|
||||
int fd;
|
||||
char *mess;
|
||||
{
|
||||
static MEMBER member;
|
||||
register int read_chars;
|
||||
struct stat status;
|
||||
int src_fd;
|
||||
|
||||
if (stat(name, &status) < 0) {
|
||||
error(FALSE, "cannot find %s\n", name);
|
||||
return;
|
||||
}
|
||||
else if (S_ISDIR(status.st_mode)) {
|
||||
error(FALSE, "%s is a directory (ignored)\n", name);
|
||||
return;
|
||||
}
|
||||
else if ((src_fd = open(name, 0)) < 0) {
|
||||
error(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) {
|
||||
error(FALSE,"%s seems to shrink\n", name);
|
||||
break;
|
||||
}
|
||||
mwrite(fd, io_buffer, x);
|
||||
}
|
||||
|
||||
if (verbose)
|
||||
show(mess, member.ar_name);
|
||||
close(src_fd);
|
||||
}
|
||||
|
||||
extract(member)
|
||||
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) {
|
||||
error(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);
|
||||
}
|
||||
|
||||
copy_member(member, from, to, extracting)
|
||||
register MEMBER *member;
|
||||
int from, to;
|
||||
{
|
||||
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;
|
||||
error(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;
|
||||
}
|
||||
|
||||
wr_fatal()
|
||||
{
|
||||
error(TRUE, "write error\n");
|
||||
}
|
||||
|
||||
rd_fatal()
|
||||
{
|
||||
error(TRUE, "read error\n");
|
||||
}
|
||||
|
||||
mwrite(fd, address, bytes)
|
||||
int fd;
|
||||
register char *address;
|
||||
register int bytes;
|
||||
{
|
||||
if (write(fd, address, bytes) != bytes)
|
||||
error(TRUE, "write error\n");
|
||||
}
|
||||
|
||||
show(s, name)
|
||||
char *s, *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.
|
||||
*/
|
||||
write_symdef()
|
||||
{
|
||||
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(headp)
|
||||
register struct outhead *headp;
|
||||
{
|
||||
|
||||
return !BADMAGIC(*headp) && headp->oh_nname != 0;
|
||||
}
|
||||
|
||||
do_object(f, size)
|
||||
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.
|
||||
*/
|
||||
do_names(headp)
|
||||
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
|
||||
) {
|
||||
error(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);
|
||||
}
|
||||
|
||||
enter_name(namep)
|
||||
struct outname *namep;
|
||||
{
|
||||
register char *cp;
|
||||
|
||||
if (tnum >= tabsz) {
|
||||
tab = (struct ranlib *)
|
||||
realloc((char *) tab, (tabsz += 512) * sizeof(struct ranlib));
|
||||
if (! tab) error(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) error(TRUE, "string table overflow\n");
|
||||
}
|
||||
tstrtab[tssiz++] = *cp;
|
||||
if (!*cp) break;
|
||||
}
|
||||
tnum++;
|
||||
}
|
||||
#endif /* AAL */
|
||||
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
|
||||
|
||||
extern char *long2str();
|
||||
|
||||
static int
|
||||
integral(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(buf, fmt, argp)
|
||||
char *buf, *fmt;
|
||||
register va_list argp;
|
||||
{
|
||||
register char *pf = fmt;
|
||||
register char *pb = buf;
|
||||
|
||||
while (*pf) {
|
||||
if (*pf == '%') {
|
||||
register 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 ??? */
|
||||
if (base = integral(*++pf)) {
|
||||
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;
|
||||
}
|
||||
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 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 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
|
||||
42
commands/aal/print.c
Normal file
42
commands/aal/print.c
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* (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"
|
||||
|
||||
/*VARARGS*/
|
||||
/*FORMAT0v $
|
||||
%s = char *
|
||||
%l = long
|
||||
%c = int
|
||||
%[uxbo] = unsigned int
|
||||
%d = int
|
||||
$ */
|
||||
int
|
||||
#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);
|
||||
}
|
||||
34
commands/aal/ranlib.h
Normal file
34
commands/aal/ranlib.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* (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"
|
||||
|
||||
#endif /* __RANLIB_H_INCLUDED */
|
||||
254
commands/aal/rd.c
Normal file
254
commands/aal/rd.c
Normal file
@@ -0,0 +1,254 @@
|
||||
/* $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 <out.h>
|
||||
#include "object.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
|
||||
OUTREAD(p, b, n)
|
||||
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(f)
|
||||
char *f;
|
||||
{
|
||||
|
||||
if ((outfile = open(f, 0)) < 0)
|
||||
return 0;
|
||||
return rd_fdopen(outfile);
|
||||
}
|
||||
|
||||
static int offcnt;
|
||||
|
||||
rd_fdopen(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;
|
||||
}
|
||||
|
||||
rd_close()
|
||||
{
|
||||
|
||||
close(outfile);
|
||||
outfile = -1;
|
||||
}
|
||||
|
||||
rd_fd()
|
||||
{
|
||||
return outfile;
|
||||
}
|
||||
|
||||
rd_ohead(head)
|
||||
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
|
||||
}
|
||||
|
||||
rd_rew_relos(head)
|
||||
register struct outhead *head;
|
||||
{
|
||||
register long off = OFF_RELO(*head) + rd_base;
|
||||
|
||||
BEGINSEEK(PARTRELO, off);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rd_outsect(s)
|
||||
{
|
||||
OUTSECT(s);
|
||||
sectionnr = s;
|
||||
}
|
||||
|
||||
/*
|
||||
* We don't have to worry about byte order here.
|
||||
*/
|
||||
rd_emit(emit, cnt)
|
||||
char *emit;
|
||||
long cnt;
|
||||
{
|
||||
OUTREAD(PARTEMIT, emit, cnt);
|
||||
offset[sectionnr] += cnt;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rd_name(name, cnt)
|
||||
register struct outname *name;
|
||||
register 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rd_string(addr, len)
|
||||
char *addr;
|
||||
long len;
|
||||
{
|
||||
|
||||
OUTREAD(PARTCHAR, addr, len);
|
||||
}
|
||||
|
||||
#ifdef SYMDBUG
|
||||
rd_dbug(buf, size)
|
||||
char *buf;
|
||||
long size;
|
||||
{
|
||||
OUTREAD(PARTDBUG, buf, size);
|
||||
}
|
||||
#endif
|
||||
35
commands/aal/rd_arhdr.c
Normal file
35
commands/aal/rd_arhdr.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".
|
||||
*/
|
||||
#include <arch.h>
|
||||
#include "object.h"
|
||||
|
||||
int
|
||||
rd_arhdr(fd, arhdr)
|
||||
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;
|
||||
}
|
||||
32
commands/aal/rd_bytes.c
Normal file
32
commands/aal/rd_bytes.c
Normal file
@@ -0,0 +1,32 @@
|
||||
/* $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!
|
||||
*/
|
||||
|
||||
static int maxchunk = MAXCHUNK;
|
||||
|
||||
/*
|
||||
* We don't have to worry about byte order here.
|
||||
* Just read "cnt" bytes from file-descriptor "fd".
|
||||
*/
|
||||
int
|
||||
rd_bytes(fd, string, cnt)
|
||||
register char *string;
|
||||
register long cnt;
|
||||
{
|
||||
|
||||
while (cnt) {
|
||||
register int n = cnt >= maxchunk ? maxchunk : cnt;
|
||||
|
||||
if (read(fd, string, n) != n)
|
||||
rd_fatal();
|
||||
string += n;
|
||||
cnt -= n;
|
||||
}
|
||||
}
|
||||
15
commands/aal/rd_unsig2.c
Normal file
15
commands/aal/rd_unsig2.c
Normal file
@@ -0,0 +1,15 @@
|
||||
/* $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"
|
||||
|
||||
unsigned int
|
||||
rd_unsigned2(fd)
|
||||
{
|
||||
char buf[2];
|
||||
|
||||
rd_bytes(fd, buf, 2L);
|
||||
return uget2(buf);
|
||||
}
|
||||
42
commands/aal/sprint.c
Normal file
42
commands/aal/sprint.c
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* (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"
|
||||
|
||||
/*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;
|
||||
}
|
||||
47
commands/aal/system.h
Normal file
47
commands/aal/system.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* (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 */
|
||||
#define BUFSIZ 1024
|
||||
#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 */
|
||||
28
commands/aal/wr_arhdr.c
Normal file
28
commands/aal/wr_arhdr.c
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".
|
||||
*/
|
||||
#include <arch.h>
|
||||
#include "object.h"
|
||||
|
||||
wr_arhdr(fd, arhdr)
|
||||
register 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);
|
||||
}
|
||||
30
commands/aal/wr_bytes.c
Normal file
30
commands/aal/wr_bytes.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".
|
||||
*/
|
||||
#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!
|
||||
*/
|
||||
|
||||
static int maxchunk = MAXCHUNK;
|
||||
|
||||
/*
|
||||
* Just write "cnt" bytes to file-descriptor "fd".
|
||||
*/
|
||||
wr_bytes(fd, string, cnt)
|
||||
register char *string;
|
||||
register long cnt;
|
||||
{
|
||||
|
||||
while (cnt) {
|
||||
register int n = cnt >= maxchunk ? maxchunk : cnt;
|
||||
|
||||
if (write(fd, string, n) != n)
|
||||
wr_fatal();
|
||||
string += n;
|
||||
cnt -= n;
|
||||
}
|
||||
}
|
||||
14
commands/aal/wr_int2.c
Normal file
14
commands/aal/wr_int2.c
Normal file
@@ -0,0 +1,14 @@
|
||||
/* $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"
|
||||
|
||||
wr_int2(fd, i)
|
||||
{
|
||||
char buf[2];
|
||||
|
||||
put2(i, buf);
|
||||
wr_bytes(fd, buf, 2L);
|
||||
}
|
||||
15
commands/aal/wr_long.c
Normal file
15
commands/aal/wr_long.c
Normal file
@@ -0,0 +1,15 @@
|
||||
/* $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"
|
||||
|
||||
wr_long(fd, l)
|
||||
long l;
|
||||
{
|
||||
char buf[4];
|
||||
|
||||
put4(l, buf);
|
||||
wr_bytes(fd, buf, 4L);
|
||||
}
|
||||
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"
|
||||
|
||||
wr_ranlib(fd, ran, cnt)
|
||||
register struct ranlib *ran;
|
||||
register 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 <system.h>
|
||||
|
||||
int
|
||||
sys_write(fp, bufptr, nbytes)
|
||||
File *fp;
|
||||
char *bufptr;
|
||||
int nbytes;
|
||||
{
|
||||
if (! fp) return 0;
|
||||
return write(fp->o_fd, bufptr, nbytes) == nbytes;
|
||||
}
|
||||
13
commands/acd/Makefile
Normal file
13
commands/acd/Makefile
Normal file
@@ -0,0 +1,13 @@
|
||||
# Makefile for acd
|
||||
|
||||
.include <minix.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 <minix.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= acknm
|
||||
MAN=
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
@@ -1,4 +0,0 @@
|
||||
PROG= acksize
|
||||
MAN=
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
@@ -3,4 +3,4 @@ MAN=
|
||||
|
||||
LINKS+= ${BINDIR}/add_route ${BINDIR}/del_route
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
.include <minix.prog.mk>
|
||||
|
||||
@@ -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 <minix.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
|
||||
28
commands/advent/Makefile
Normal file
28
commands/advent/Makefile
Normal file
@@ -0,0 +1,28 @@
|
||||
# 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 setup setup.c
|
||||
|
||||
advtext.h advent1.dat advent2.dat advent3.dat advent4.dat: \
|
||||
setup advent1.txt advent2.txt advent3.txt advent4.txt
|
||||
./setup
|
||||
|
||||
CPPFLAGS.advent.c= -DTEXTDIR='"${TEXTDIR}"'
|
||||
|
||||
CLEANFILES+= ${DATFILES} advtext.h setup
|
||||
|
||||
.include <minix.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;
|
||||
}
|
||||
597
commands/advent/itverb.c
Normal file
597
commands/advent/itverb.c
Normal file
@@ -0,0 +1,597 @@
|
||||
/* program ITVERB.C */
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include "advent.h"
|
||||
#include "advdec.h"
|
||||
|
||||
_PROTOTYPE(void needobj, (void));
|
||||
_PROTOTYPE(void ivtake, (void));
|
||||
_PROTOTYPE(void ivopen, (void));
|
||||
_PROTOTYPE(void ivkill, (void));
|
||||
_PROTOTYPE(void ivdrink, (void));
|
||||
_PROTOTYPE(void ivquit, (void));
|
||||
_PROTOTYPE(void ivfoo, (void));
|
||||
_PROTOTYPE(void inventory, (void));
|
||||
_PROTOTYPE(void addobj, (int obj));
|
||||
_PROTOTYPE(void ivpour, (void));
|
||||
_PROTOTYPE(void ivfill, (void));
|
||||
_PROTOTYPE(void ivbrief, (void));
|
||||
_PROTOTYPE(void ivread, (void));
|
||||
_PROTOTYPE(void ivcombo, (void));
|
||||
_PROTOTYPE(void iveat, (void));
|
||||
/*
|
||||
Routines to process intransitive verbs
|
||||
*/
|
||||
void itverb()
|
||||
{
|
||||
int i;
|
||||
|
||||
newtravel = FALSE;
|
||||
switch (verb) {
|
||||
case DROP:
|
||||
case SAY:
|
||||
case WAVE:
|
||||
case CALM:
|
||||
case RUB:
|
||||
case THROW:
|
||||
case FIND:
|
||||
case FEED:
|
||||
case BREAK:
|
||||
case WAKE:
|
||||
case WEAR:
|
||||
case HIT:
|
||||
case DIAL:
|
||||
case PLAY:
|
||||
case PICK:
|
||||
case PUT:
|
||||
case TURN: needobj(); break;
|
||||
case TAKE:
|
||||
case YANK:
|
||||
case GET:
|
||||
case INSRT:
|
||||
case REMOVE:
|
||||
case BURN: ivtake(); break;
|
||||
case OPEN:
|
||||
case CLOSE:
|
||||
case LOCK:
|
||||
case UNLOCK: ivopen(); break;
|
||||
case NOTHING: rspeak(54); break;
|
||||
case ON:
|
||||
case OFF: trverb(); break;
|
||||
case WALK: actspk(verb); break;
|
||||
case KILL: ivkill(); break;
|
||||
case POUR: ivpour(); break;
|
||||
case EAT: iveat(); break;
|
||||
case DRINK: ivdrink(); break;
|
||||
case QUIT: ivquit(); break;
|
||||
case INVENTORY: inventory(); break;
|
||||
case FILL: ivfill(); break;
|
||||
case BLAST: ivblast(); break;
|
||||
case SCORE: score(TRUE); break;
|
||||
case FOO: ivfoo(); break;
|
||||
case BRIEF: ivbrief(); break;
|
||||
case READ: ivread(); break;
|
||||
case SUSPEND:
|
||||
if (g.closing)
|
||||
rspeak(378);
|
||||
else
|
||||
saveadv("advent.sav");
|
||||
break;
|
||||
case RESTORE: restore("advent.sav"); break;
|
||||
case ANSWER:
|
||||
if ((g.loc != 189) || (g.prop[PHONE] != 0))
|
||||
needobj();
|
||||
else {
|
||||
object = PHONE;
|
||||
itverb();
|
||||
}
|
||||
break;
|
||||
case BLOW: rspeak(268); break;
|
||||
/* Action verb 'LEAVE' has no object */
|
||||
case LEAVE: bug(29); break;
|
||||
/* Call if no phone is handy, yell. */
|
||||
case YELL:
|
||||
if (!here(PHONE))
|
||||
needobj();
|
||||
else if (!g.closed)
|
||||
rspeak(271);
|
||||
else {
|
||||
rspeak(283);
|
||||
normend();
|
||||
}
|
||||
break;
|
||||
/* Health. give him a diagnosis. */
|
||||
case HEALTH:
|
||||
if (g.numdie)
|
||||
fprintf(stdout, "You have been killed %d times otherwise\n",
|
||||
g.numdie);
|
||||
if (g.health >= 95) {
|
||||
if (pct(50))
|
||||
rspeak(348);
|
||||
else
|
||||
rspeak(349);
|
||||
} else {
|
||||
fprintf(stdout,
|
||||
"Your health rating is %2d out of a possible 100.\n",
|
||||
g.health);
|
||||
rspeak(381 + (100 - g.health) / 20);
|
||||
}
|
||||
break;
|
||||
case LOOK: ivlook(); break;
|
||||
case COMBO:
|
||||
if (at(SAFE))
|
||||
ivcombo();
|
||||
break;
|
||||
case SWEEP:
|
||||
/* Dust/sweep */
|
||||
if (!at(CARVNG) || !athand(BRUSH) || (g.prop[CARVNG] == 1))
|
||||
rspeak(342);
|
||||
else {
|
||||
g.prop[CARVNG] = 1;
|
||||
rspeak(363);
|
||||
rspeak(372);
|
||||
}
|
||||
break;
|
||||
case TERSE:
|
||||
/* Terse/unterse. supress all long_form descriptions. */
|
||||
g.terse = !g.terse;
|
||||
g.detail = 3;
|
||||
rspeak(54);
|
||||
break;
|
||||
case WIZ:
|
||||
is_wiz = !is_wiz;
|
||||
case MAP:
|
||||
rspeak(54);
|
||||
break;
|
||||
case GATE:
|
||||
if (is_wiz) {
|
||||
static char buf[INPUTBUFLEN];
|
||||
sscanf(ask("Location ? ", buf, sizeof(buf)), "%d", &g.loc);
|
||||
}
|
||||
rspeak(54);
|
||||
break;
|
||||
case PIRLOC:
|
||||
if (is_wiz) {
|
||||
fprintf(stdout, "The dwarfs are at locations:\n");
|
||||
for (i = 1; i < DWARFMAX; i++)
|
||||
fprintf(stdout, " %4d", g.dloc[i]);
|
||||
fprintf(stdout, "\nThe pirate is at location %4d\n",
|
||||
g.dloc[DWARFMAX]);
|
||||
}
|
||||
rspeak(54);
|
||||
break;
|
||||
default:
|
||||
printf("This intransitive not implemented yet\n");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
Routine to indicate no reasonable
|
||||
object for verb found. Used mostly by
|
||||
intransitive verbs.
|
||||
*/
|
||||
void needobj()
|
||||
{
|
||||
printf("%s what?\n", vtxt[vrbx]);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
CARRY, TAKE etc.
|
||||
*/
|
||||
void ivtake()
|
||||
{
|
||||
int anobj, item;
|
||||
|
||||
anobj = 0;
|
||||
for (item = 1; item < MAXOBJ; ++item)
|
||||
if (g.place[item] == g.loc)
|
||||
if (anobj == 0)
|
||||
anobj = item;
|
||||
else {
|
||||
needobj();
|
||||
return;
|
||||
}
|
||||
|
||||
if (anobj == 0 || (dcheck() && g.dflag >= 2) || blind())
|
||||
needobj();
|
||||
else {
|
||||
object = anobj;
|
||||
if (verb == YANK)
|
||||
vyank();
|
||||
else if (verb == WEAR)
|
||||
vwear();
|
||||
else
|
||||
vtake();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
OPEN, LOCK, UNLOCK
|
||||
*/
|
||||
void ivopen()
|
||||
{
|
||||
int obj_cnt, item;
|
||||
|
||||
for (item = 1, obj_cnt = 0; item < MAXOBJ; item++) {
|
||||
if ((g.place[item] == g.loc) && (hinged(item))) {
|
||||
object = item;
|
||||
obj_cnt++;
|
||||
}
|
||||
}
|
||||
if (obj_cnt != 1)
|
||||
needobj();
|
||||
else if (verb == LOCK)
|
||||
vlock();
|
||||
else if (verb == UNLOCK)
|
||||
vunlock();
|
||||
else if (verb == SHUT)
|
||||
vclose();
|
||||
else
|
||||
vopen();
|
||||
}
|
||||
|
||||
/*
|
||||
ATTACK, KILL etc
|
||||
*/
|
||||
boolean previous_obj;
|
||||
|
||||
void ivkill()
|
||||
{
|
||||
previous_obj = FALSE;
|
||||
if (dcheck() && g.dflag >= 2)
|
||||
object = DWARF;
|
||||
if (here(SNAKE))
|
||||
addobj(SNAKE);
|
||||
if (at(DRAGON) && g.prop[DRAGON] == 0)
|
||||
addobj(DRAGON);
|
||||
if (at(TROLL))
|
||||
addobj(TROLL);
|
||||
if (here(GNOME))
|
||||
addobj(GNOME);
|
||||
if (here(BEAR) && g.prop[BEAR] == 0)
|
||||
addobj(BEAR);
|
||||
if (here(WUMPUS) && g.prop[WUMPUS] == 0)
|
||||
addobj(WUMPUS);
|
||||
/* Can't attack bird by throwing axe */
|
||||
if (here(BIRD) && verb != THROW)
|
||||
addobj(BIRD);
|
||||
/* Clam and oyster both treated as clam for intransitive case; no
|
||||
harm done. */
|
||||
if (here(CLAM) || here(OYSTER))
|
||||
addobj(CLAM);
|
||||
|
||||
if ((previous_obj) || (object == 0))
|
||||
rspeak(44);
|
||||
else
|
||||
vkill();
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
POUR if no object, assume liq in container, if holding one.
|
||||
*/
|
||||
void ivpour()
|
||||
{
|
||||
if ((holding(BOTTLE)) && (liq(BOTTLE) != 0) && !holding(CASK))
|
||||
object = BOTTLE;
|
||||
if ((holding(CASK)) && (liq(CASK) != 0) && !holding(BOTTLE))
|
||||
object = CASK;
|
||||
|
||||
if (object == 0)
|
||||
needobj();
|
||||
else
|
||||
trverb();
|
||||
}
|
||||
|
||||
/*
|
||||
EAT. intransitive: assume edible if present, else ask what.
|
||||
If he as more than one edible, or none, 'EAT' is ambiguous
|
||||
without an explicit object.
|
||||
*/
|
||||
void iveat()
|
||||
{
|
||||
int i;
|
||||
|
||||
previous_obj = FALSE;
|
||||
for (i = 1; i < MAXOBJ; i++) {
|
||||
if ((here(i)) && (edible(i)))
|
||||
addobj(i);
|
||||
}
|
||||
if ((previous_obj) || (object == 0))
|
||||
needobj();
|
||||
else
|
||||
trverb();
|
||||
}
|
||||
|
||||
/*
|
||||
DRINK. If no object, assume water or wine and look for them here.
|
||||
If potable is in bottle or cask, drink that. If not, see if there
|
||||
is something drinkable nearby (stream, lake, wine fountain, etc.),
|
||||
and drink that. If he has stuff in both containers, ask which.
|
||||
*/
|
||||
void ivdrink()
|
||||
{
|
||||
int ll;
|
||||
|
||||
previous_obj = FALSE;
|
||||
ll = liqloc(g.loc);
|
||||
if ((ll == WATER) || (ll == WINE)) {
|
||||
object = ll;
|
||||
iobj = -1;
|
||||
}
|
||||
ll = liq(BOTTLE);
|
||||
if ((athand(BOTTLE)) && ((ll == WATER) || (ll == WINE))) {
|
||||
object = ll;
|
||||
iobj = BOTTLE;
|
||||
}
|
||||
ll = liq(CASK);
|
||||
if ((athand(CASK)) && ((ll == WATER) || (ll == WINE))
|
||||
&& iobj != BOTTLE) {
|
||||
object = ll;
|
||||
iobj = CASK;
|
||||
} else
|
||||
object = 0;
|
||||
|
||||
if (object == 0)
|
||||
needobj();
|
||||
else
|
||||
trverb();
|
||||
}
|
||||
|
||||
/*
|
||||
QUIT intransitive only. Verify intent and exit if that's what he wants
|
||||
*/
|
||||
void ivquit()
|
||||
{
|
||||
gaveup = yes(22, 54, 54);
|
||||
if (gaveup)
|
||||
normend();
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
INVENTORY
|
||||
*/
|
||||
void inventory()
|
||||
{
|
||||
int i, msg;
|
||||
boolean init_msg;
|
||||
|
||||
init_msg = TRUE;
|
||||
msg = 98;
|
||||
for (i = 1; i < MAXOBJ; i++) {
|
||||
if (!holding(i) || wearng(i) || i == BEAR || i == BOAT)
|
||||
continue;
|
||||
if (init_msg)
|
||||
rspeak(99);
|
||||
pspeak(i, -1);
|
||||
init_msg = FALSE;
|
||||
msg = 0;
|
||||
lookin(i);
|
||||
}
|
||||
|
||||
/* Tell him what he is wearing */
|
||||
init_msg = TRUE;
|
||||
for (i = 1; i < MAXOBJ; i++) {
|
||||
if (wearng(i)) {
|
||||
if (init_msg)
|
||||
fprintf(stdout, "\nYou are wearing:\n");
|
||||
fprintf(stdout, " ");
|
||||
pspeak(i, -1);
|
||||
msg = 0;
|
||||
init_msg = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (holding(BOAT)) {
|
||||
rspeak(221);
|
||||
lookin(BOAT);
|
||||
}
|
||||
if (holding(BEAR))
|
||||
msg = 141;
|
||||
|
||||
if (msg)
|
||||
rspeak(msg);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
FILL bottle or cask must be empty, and some liquid avaible
|
||||
*/
|
||||
void ivfill()
|
||||
{
|
||||
if ((g.prop[CASK] == 1) && !here(CASK))
|
||||
object = CASK;
|
||||
if ((g.prop[BOTTLE] == 1) && !here(BOTTLE))
|
||||
object = BOTTLE;
|
||||
|
||||
if ((here(BOTTLE) && here(CASK)) || (object == 0))
|
||||
needobj();
|
||||
else
|
||||
trverb();
|
||||
}
|
||||
|
||||
/*
|
||||
BLAST etc.
|
||||
*/
|
||||
void ivblast()
|
||||
{
|
||||
if (!g.closed)
|
||||
actspk(verb);
|
||||
else {
|
||||
g.bonus = 135;
|
||||
if (g.place[ROD2] == 212 && g.loc == 116)
|
||||
g.bonus = 133;
|
||||
if (g.place[ROD2] == 116 && g.loc != 116)
|
||||
g.bonus = 134;
|
||||
rspeak(g.bonus);
|
||||
normend();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
Handle fee fie foe foo...
|
||||
*/
|
||||
void ivfoo()
|
||||
{
|
||||
int k;
|
||||
int msg;
|
||||
|
||||
k = VAL(vocab(vtxt[vrbx], MISC));
|
||||
if (g.foobar != 1 - k) {
|
||||
if (g.foobar == 0)
|
||||
msg = 42;
|
||||
else
|
||||
msg = 151;
|
||||
rspeak(msg);
|
||||
return;
|
||||
}
|
||||
g.foobar = k;
|
||||
if (k != 4)
|
||||
return;
|
||||
g.foobar = 0;
|
||||
if (g.place[EGGS] == plac[EGGS] ||
|
||||
(toting(EGGS) && g.loc == plac[EGGS])) {
|
||||
rspeak(42);
|
||||
return;
|
||||
}
|
||||
/* Bring back troll if we steal the eggs back from him before
|
||||
crossing */
|
||||
if (g.place[EGGS] == 0 && g.place[TROLL] == 0 && g.prop[TROLL] == 0)
|
||||
g.prop[TROLL] = 1;
|
||||
|
||||
if (here(EGGS))
|
||||
k = 1;
|
||||
else if (g.loc == plac[EGGS])
|
||||
k = 0;
|
||||
else
|
||||
k = 2;
|
||||
move(EGGS, plac[EGGS]);
|
||||
pspeak(EGGS, k);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
brief/unbrief. intransitive only.
|
||||
suppress long descriptions after first time.
|
||||
*/
|
||||
void ivbrief()
|
||||
{
|
||||
int msg;
|
||||
|
||||
g.detail = 3;
|
||||
g.terse = FALSE;
|
||||
if (g.abbnum != 10000) {
|
||||
msg = 156;
|
||||
g.abbnum = 10000;
|
||||
} else {
|
||||
msg = 374;
|
||||
g.abbnum = 5;
|
||||
}
|
||||
rspeak(msg);
|
||||
}
|
||||
|
||||
/*
|
||||
read etc...
|
||||
*/
|
||||
void ivread()
|
||||
{
|
||||
previous_obj = FALSE;
|
||||
if (here(BOOK))
|
||||
object = BOOK;
|
||||
if (here(BOOK2))
|
||||
addobj(BOOK2);
|
||||
if (here(BILLBD))
|
||||
addobj(BILLBD);
|
||||
if (here(CARVNG))
|
||||
addobj(CARVNG);
|
||||
if (here(MAGAZINE))
|
||||
addobj(MAGAZINE);
|
||||
if (here(MESSAGE))
|
||||
addobj(MESSAGE);
|
||||
if (here(OYSTER))
|
||||
addobj(OYSTER);
|
||||
if (here(POSTER))
|
||||
addobj(POSTER);
|
||||
if (here(TABLET))
|
||||
addobj(TABLET);
|
||||
|
||||
if (previous_obj || object == 0 || dark())
|
||||
needobj();
|
||||
else
|
||||
vread();
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
LOOK. can't give more detail. Pretend it wasn't dark (though it may "now"
|
||||
be dark) so he won't fall into a pit staring into the gloom.
|
||||
*/
|
||||
void ivlook()
|
||||
{
|
||||
if (g.detail++ < 3)
|
||||
rspeak(15);
|
||||
g.wzdark = FALSE;
|
||||
g.visited[g.loc] = 0;
|
||||
g.newloc = g.loc;
|
||||
newtravel = TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
COMBO: trying to open safe. (see comments for fee fie foe foo)
|
||||
*/
|
||||
void ivcombo()
|
||||
{
|
||||
int k, msg;
|
||||
|
||||
k = VAL(vocab(vtxt[vrbx], MISC)) - 10;
|
||||
msg = 42;
|
||||
if (g.combo != 1 - k) {
|
||||
if (g.combo != 0)
|
||||
msg = 366;
|
||||
rspeak(msg);
|
||||
return;
|
||||
}
|
||||
g.combo = k;
|
||||
if (k != 3)
|
||||
rspeak(371);
|
||||
else {
|
||||
g.combo = 0;
|
||||
bitoff(SAFE, LOCKBT);
|
||||
biton(SAFE, OPENBT);
|
||||
g.prop[SAFE] = 1;
|
||||
if (g.prop[BOOK] < 0) {
|
||||
g.tally--;
|
||||
g.prop[BOOK] = 0;
|
||||
/* If remaining treasures too elusive, zap his lamp. this
|
||||
duplicates some code, must be done here since book is
|
||||
contained ins safe & tally stuff only works for thing
|
||||
deposited at a location. */
|
||||
if ((g.tally == g.tally2) && (g.tally != 0))
|
||||
g.limit = (g.limit < 35) ? g.limit : 35;
|
||||
}
|
||||
rspeak(365);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
ensure uniqueness as objects are searched
|
||||
out for an intransitive verb
|
||||
*/
|
||||
void addobj(obj)
|
||||
int obj;
|
||||
{
|
||||
if (!previous_obj) {
|
||||
if (object != 0)
|
||||
previous_obj = TRUE;
|
||||
else
|
||||
object = obj;
|
||||
}
|
||||
return;
|
||||
}
|
||||
199
commands/advent/score.c
Normal file
199
commands/advent/score.c
Normal file
@@ -0,0 +1,199 @@
|
||||
/**
|
||||
SCORE
|
||||
|
||||
Calculate what the player's score would be if he quit now.
|
||||
This may be the end of the game, or he may just be wondering
|
||||
how he is doing.
|
||||
|
||||
The present scoring algorithm is as follows:
|
||||
(treasure points are explained in a following comment)
|
||||
objective: points: present total possible:
|
||||
getting well into cave 25 25
|
||||
total possible for treasures (+mag) 426
|
||||
reaching "closing" 20 20
|
||||
"closed": quit/killed 10
|
||||
klutzed 20
|
||||
wrong way 25
|
||||
success 30 30
|
||||
total: 501
|
||||
(points can also be deducted for using hints or deaths.)
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "advent.h"
|
||||
#include "advdec.h"
|
||||
|
||||
void score(scorng)
|
||||
boolean scorng;
|
||||
{
|
||||
int cur_score, max_score, qk[3];
|
||||
int obj, num_treas, k, i;
|
||||
long t;
|
||||
char *kk2c;
|
||||
|
||||
cur_score = 0;
|
||||
max_score = 0;
|
||||
num_treas = 0;
|
||||
|
||||
/** First tally up the treasures. Must be in building and not broken.
|
||||
give the poor guy partial score just for finding each treasure.
|
||||
Gets full score, qk[3], for obj if:
|
||||
obj is at loc qk[1], and
|
||||
obj has prop value of qk[2]
|
||||
|
||||
weight total possible
|
||||
magazine 1 (absolute) 1
|
||||
|
||||
all the following are multiplied by 5 (range 5-25):
|
||||
book 2
|
||||
cask 3 (with wine only)
|
||||
chain 4 (must enter via styx)
|
||||
chest 5
|
||||
cloak 3
|
||||
clover 1
|
||||
coins 5
|
||||
crown 2
|
||||
crystal-ball 2
|
||||
diamonds 2
|
||||
eggs 3
|
||||
emerald 3
|
||||
grail 2
|
||||
horn 2
|
||||
jewels 1
|
||||
lyre 1
|
||||
nugget 2
|
||||
pearl 4
|
||||
pyramid 4
|
||||
radium 4
|
||||
ring 4
|
||||
rug 3
|
||||
sapphire 1
|
||||
shoes 3
|
||||
spices 1
|
||||
sword 4
|
||||
trident 2
|
||||
vase 2
|
||||
droplet 5
|
||||
tree 5
|
||||
total: 85 * 5 = 425 + 1 ==> 426
|
||||
*/
|
||||
|
||||
for (obj = 1; obj < MAXOBJ; obj++) {
|
||||
if (g.points[obj] == 0)
|
||||
continue;
|
||||
t = g.points[obj];
|
||||
qk[0] = (int) (t < 0L ? -((t = -t) % 1000) : (t % 1000));
|
||||
t /= 1000;
|
||||
qk[1] = (int) (t % 1000);
|
||||
qk[2] = (int) (t / 1000);
|
||||
k = 0;
|
||||
if (treasr(obj)) {
|
||||
num_treas++;
|
||||
k = qk[2] * 2;
|
||||
if (g.prop[obj] >= 0)
|
||||
cur_score += k;
|
||||
qk[2] *= 5;
|
||||
}
|
||||
if ((g.place[obj] == qk[0]) && (g.prop[obj] == qk[1])
|
||||
&& ((g.place[obj] != -CHEST) || (g.place[CHEST] == 3))
|
||||
&& ((g.place[obj] != -SHIELD) || (g.place[SHIELD] == -SAFE))
|
||||
)
|
||||
cur_score += qk[2] - k;
|
||||
max_score += qk[2];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Now look at how he finished and how far he got. Maxdie and numdie tell us
|
||||
how well he survived. Gaveup says whether he exited via quit. Dflag will
|
||||
tell us if he ever got suitably deep into the cave. Closing still indicates
|
||||
whether he reached the endgame. And if he got as far as "cave closed"
|
||||
(indicated by "closed"), then bonus is zero for mundane exits or 133, 134,
|
||||
135 if he blew it (so to speak).
|
||||
*/
|
||||
|
||||
if (g.dflag)
|
||||
cur_score += 25;
|
||||
max_score += 25;
|
||||
if (g.closing)
|
||||
cur_score += 20;
|
||||
max_score += 20;
|
||||
if (g.closed) {
|
||||
if (g.bonus == 0)
|
||||
cur_score += 10;
|
||||
else if (g.bonus == 135)
|
||||
cur_score += 20;
|
||||
else if (g.bonus == 134)
|
||||
cur_score += 25;
|
||||
else if (g.bonus == 133)
|
||||
cur_score += 30;
|
||||
}
|
||||
max_score += 30;
|
||||
|
||||
/* Deduct points for hints, deaths and quiting.
|
||||
hints < hntmin are special; see database description
|
||||
*/
|
||||
for (i = 1; i <= HNTMAX; i++)
|
||||
if (g.hinted[i])
|
||||
cur_score -= g.hints[i][2];
|
||||
cur_score -= g.numdie * 10;
|
||||
if (gaveup)
|
||||
cur_score -= 4;
|
||||
|
||||
fprintf(stdout, "You have found %3d out of %3d Treasures,",
|
||||
num_treas - g.tally, num_treas);
|
||||
fprintf(stdout, " using %4d turns\n", g.turns);
|
||||
fprintf(stdout, "For a score of: %4d", cur_score);
|
||||
fprintf(stdout, " out of a possible %4d\n", max_score);
|
||||
|
||||
if (cur_score < 110) {
|
||||
fprintf(stdout, "You are obviously a rank amateur.");
|
||||
if (!scorng)
|
||||
fprintf(stdout, " Better luck next time.");
|
||||
fputc('\n', stdout);
|
||||
k = 110 - cur_score;
|
||||
} else if (cur_score < 152) {
|
||||
fprintf(stdout,
|
||||
"Your score qualifies you as a Novice Class Adventurer.\n");
|
||||
k = 152 - cur_score;
|
||||
} else if (cur_score < 200) {
|
||||
fprintf(stdout,
|
||||
"You have achieved the rating: \"Experienced Adventurer\".\n");
|
||||
k = 200 - cur_score;
|
||||
} else if (cur_score < 277) {
|
||||
fprintf(stdout,
|
||||
"You may now consider yourself a \"Seasoned Adventurer\".\n");
|
||||
k = 277 - cur_score;
|
||||
} else if (cur_score < 345) {
|
||||
fprintf(stdout,
|
||||
"You have reached \"Junior Master\" status.\n");
|
||||
k = 345 - cur_score;
|
||||
} else if (cur_score < 451) {
|
||||
fprintf(stdout,
|
||||
"Your score puts you in Master Adventurer Class C.\n");
|
||||
k = 451 - cur_score;
|
||||
} else if (cur_score < 471) {
|
||||
fprintf(stdout,
|
||||
"Your score puts you in Master Adventurer Class B.\n");
|
||||
k = 471 - cur_score;
|
||||
} else if (cur_score < 501) {
|
||||
fprintf(stdout,
|
||||
"Your score puts you in Master Adventurer Class A.\n");
|
||||
k = 501 - cur_score;
|
||||
} else {
|
||||
fprintf(stdout,
|
||||
"All of Adventuredom gives tribute to you, Adventurer Grandmaster!\n");
|
||||
k = 0;
|
||||
}
|
||||
|
||||
if (!scorng) {
|
||||
kk2c = (k == 1) ? "." : "s.";
|
||||
printf("\nTo acheive the next higher rating,");
|
||||
if (cur_score == 501)
|
||||
printf(" would be a neat trick!\n\n CONGRATULATIONS!!\n");
|
||||
else
|
||||
printf(" you need %3d more point%s\n", k, kk2c);
|
||||
}
|
||||
return;
|
||||
}
|
||||
99
commands/advent/setup.c
Normal file
99
commands/advent/setup.c
Normal file
@@ -0,0 +1,99 @@
|
||||
/** program SETUP.C *
|
||||
* execution will read the four adventure text files *
|
||||
* files; "advent1.txt", "advent2.txt", "advent3.txt" & *
|
||||
* "advent4.txt". it will create the file "advtext.h" *
|
||||
* which is an Index Sequential Access Method (ISAM) *
|
||||
* header to be #included into "advent.c" before the *
|
||||
* header "advdec.h" is #included. */
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "advent.h"
|
||||
|
||||
_PROTOTYPE(int main, (void));
|
||||
_PROTOTYPE(void file_error, (char *));
|
||||
_PROTOTYPE(void encode, (unsigned char *));
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
FILE *isam, *src, *dest;
|
||||
char itxt[255];
|
||||
int cnt, i;
|
||||
long llen;
|
||||
char filename[12];
|
||||
static char *headername[] = {
|
||||
"idx1[MAXLOC]", "idx2[MAXLOC]", "idx3[MAXOBJ]", "idx4[MAXMSG]",
|
||||
};
|
||||
|
||||
long x29 = (1L << 29), x30 = (1L << 30);
|
||||
if (!(x30 / 2 == x29 && 0L < x30 && x29 < x30)) {
|
||||
fprintf(stderr, "Sorry, advent needs 32-bit `long int's.\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
isam = fopen("advtext.h", "w");
|
||||
if (!isam) {
|
||||
fprintf(stderr, "Sorry, I can't open advtext.h...\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
fprintf(isam, "\n/*\theader: ADVTEXT.H\t\t\t\t\t*/\n\n\n");
|
||||
|
||||
for (i = 1; i <= 4; i++) {
|
||||
cnt = -1;
|
||||
llen = 0L;
|
||||
sprintf(filename, "advent%d.txt", i);
|
||||
src = fopen(filename, "r");
|
||||
if (!src)
|
||||
file_error(filename);
|
||||
sprintf(filename, "advent%d.dat", i);
|
||||
dest = fopen(filename, "w");
|
||||
if (!dest)
|
||||
file_error(filename);
|
||||
fprintf(isam, "long\t%s = {\n\t", headername[i - 1]);
|
||||
while (fgets(itxt, 255, src)) {
|
||||
encode((unsigned char *) itxt);
|
||||
if (fprintf(dest, "%s\n", itxt) == EOF)
|
||||
file_error(filename);
|
||||
if (itxt[0] == '#') {
|
||||
if (llen)
|
||||
fprintf(isam, "%ld,%s\t", llen,
|
||||
&"\0\0\0\0\0\0\0\n"[++cnt & 7]);
|
||||
llen = ftell(dest);
|
||||
if (llen <= 0) {
|
||||
fprintf(stderr, "ftell err in %s\n", filename);
|
||||
exit(EXIT_FAILURE);
|
||||
} /* if (!llen) */
|
||||
} /* if (itxt[0]) */
|
||||
} /* while fgets */
|
||||
if (fprintf(isam, "%ld\n\t};\n\n", llen) == EOF)
|
||||
file_error("advtext.h");
|
||||
fclose(src);
|
||||
if (fclose(dest) == EOF)
|
||||
file_error(filename);
|
||||
}
|
||||
|
||||
if (fclose(isam) == EOF)
|
||||
file_error("advtext.h");
|
||||
return EXIT_SUCCESS;
|
||||
} /* main */
|
||||
|
||||
void file_error(filename)
|
||||
char *filename;
|
||||
{
|
||||
perror(filename);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
_CONST unsigned char key[4] = {'c' | 0x80, 'L' | 0x80, 'y' | 0x80, 'D' | 0x80};
|
||||
|
||||
void encode(msg)
|
||||
unsigned char *msg;
|
||||
{
|
||||
register int i;
|
||||
|
||||
for (i = 1; msg[i]; i++)
|
||||
msg[i] ^= key[i & 3];
|
||||
msg[--i] = '\0';
|
||||
return;
|
||||
}
|
||||
336
commands/advent/travel.c
Normal file
336
commands/advent/travel.c
Normal file
@@ -0,0 +1,336 @@
|
||||
/* module TRAVEL.C *
|
||||
* Routine to handle motion requests */
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "advent.h"
|
||||
#include "advdec.h"
|
||||
#include "advcave.h"
|
||||
|
||||
struct trav travel[MAXTRAV];
|
||||
static int kalflg;
|
||||
static int bcrossing = 0;
|
||||
static int phuce[2][4] = {158, 160, 167, 166,
|
||||
160, 158, 166, 167};
|
||||
|
||||
_PROTOTYPE(static void goback, (void));
|
||||
_PROTOTYPE(static void ck_kal, (void));
|
||||
_PROTOTYPE(static void dotrav, (void));
|
||||
_PROTOTYPE(static void badmove, (void));
|
||||
_PROTOTYPE(static void spcmove, (int rdest));
|
||||
|
||||
void domove()
|
||||
{
|
||||
gettrav(g.loc, travel);
|
||||
switch (motion) {
|
||||
case NULLX:
|
||||
break;
|
||||
case BACK:
|
||||
goback();
|
||||
break;
|
||||
case CAVE:
|
||||
if (outside(g.loc))
|
||||
rspeak(57);
|
||||
else
|
||||
rspeak(58);
|
||||
break;
|
||||
default:
|
||||
g.oldloc2 = g.oldloc;
|
||||
g.oldloc = g.loc;
|
||||
dotrav();
|
||||
}
|
||||
newtravel = TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
Routine to handle request to return
|
||||
from whence we came!
|
||||
*/
|
||||
static void goback()
|
||||
{
|
||||
int kk, k2, want, temp;
|
||||
struct trav strav[MAXTRAV];
|
||||
|
||||
want = forced(g.oldloc) ? g.oldloc2 : g.oldloc;
|
||||
g.oldloc2 = g.oldloc;
|
||||
g.oldloc = g.loc;
|
||||
k2 = 0;
|
||||
if (want == g.loc) {
|
||||
rspeak(91);
|
||||
ck_kal();
|
||||
return;
|
||||
}
|
||||
for (kk = 0; travel[kk].tdest != -1; ++kk) {
|
||||
if (!travel[kk].tcond && travel[kk].tdest == want) {
|
||||
motion = travel[kk].tverb;
|
||||
dotrav();
|
||||
return;
|
||||
}
|
||||
if (!travel[kk].tcond) {
|
||||
temp = travel[kk].tdest;
|
||||
gettrav(temp, strav);
|
||||
if (forced(temp) && strav[0].tdest == want)
|
||||
k2 = temp;
|
||||
}
|
||||
}
|
||||
if (k2) {
|
||||
motion = travel[k2].tverb;
|
||||
dotrav();
|
||||
} else
|
||||
rspeak(140);
|
||||
ck_kal();
|
||||
return;
|
||||
}
|
||||
|
||||
static void ck_kal()
|
||||
{
|
||||
if (g.newloc >= 242 && g.newloc <= 247) {
|
||||
if (g.newloc == 242)
|
||||
kalflg = 0;
|
||||
else if (g.newloc == (g.oldloc + 1))
|
||||
kalflg++;
|
||||
else
|
||||
kalflg = -10;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Routine to figure out a new location
|
||||
given current location and a motion.
|
||||
*/
|
||||
static void dotrav()
|
||||
{
|
||||
unsigned char mvflag, hitflag, kk;
|
||||
int rdest, rverb, rcond, robject;
|
||||
int pctt;
|
||||
|
||||
g.newloc = g.loc;
|
||||
mvflag = hitflag = 0;
|
||||
pctt = ranz(100);
|
||||
|
||||
for (kk = 0; travel[kk].tdest >= 0 && !mvflag; ++kk) {
|
||||
rdest = travel[kk].tdest;
|
||||
rverb = travel[kk].tverb;
|
||||
rcond = travel[kk].tcond;
|
||||
robject = rcond % 100;
|
||||
|
||||
if ((rverb != 1) && (rverb != motion) && !hitflag)
|
||||
continue;
|
||||
++hitflag;
|
||||
switch (rcond / 100) {
|
||||
case 0:
|
||||
if ((rcond == 0) || (pctt < rcond))
|
||||
++mvflag;
|
||||
break;
|
||||
case 1:
|
||||
if (robject == 0)
|
||||
++mvflag;
|
||||
else if (toting(robject))
|
||||
++mvflag;
|
||||
break;
|
||||
case 2:
|
||||
if (toting(robject) || at(robject))
|
||||
++mvflag;
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
case 7:
|
||||
if (g.prop[robject] != (rcond / 100) - 3)
|
||||
++mvflag;
|
||||
break;
|
||||
default:
|
||||
bug(37);
|
||||
}
|
||||
}
|
||||
if (!mvflag)
|
||||
badmove();
|
||||
else if (rdest > 500)
|
||||
rspeak(rdest - 500);
|
||||
else if (rdest > 300)
|
||||
spcmove(rdest);
|
||||
else {
|
||||
g.newloc = rdest;
|
||||
ck_kal();
|
||||
}
|
||||
newtravel = TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
The player tried a poor move option.
|
||||
*/
|
||||
static void badmove()
|
||||
{
|
||||
int msg;
|
||||
|
||||
msg = 12;
|
||||
if (motion >= 43 && motion <= 50)
|
||||
msg = 9;
|
||||
if (motion == 29 || motion == 30)
|
||||
msg = 9;
|
||||
if (motion == 7 || motion == 36 || motion == 37)
|
||||
msg = 10;
|
||||
if (motion == 11 || motion == 19)
|
||||
msg = 11;
|
||||
if (motion == 62 || motion == 65 || motion == 82)
|
||||
msg = 42;
|
||||
if (motion == 17)
|
||||
msg = 80;
|
||||
rspeak(msg);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
Routine to handle very special movement.
|
||||
*/
|
||||
static void spcmove(rdest)
|
||||
int rdest;
|
||||
{
|
||||
int load, obj, k;
|
||||
|
||||
switch (rdest - 300) {
|
||||
case 1: /* plover movement via alcove */
|
||||
load = burden(0);
|
||||
if (!load || (load == burden(EMERALD) && holding(EMERALD)))
|
||||
g.newloc = (99 + 100) - g.loc;
|
||||
else
|
||||
rspeak(117);
|
||||
break;
|
||||
case 2: /* trying to remove plover, bad
|
||||
route */
|
||||
if (enclosed(EMERALD))
|
||||
extract(EMERALD);
|
||||
drop(EMERALD, g.loc);
|
||||
g.newloc = 33;
|
||||
break;
|
||||
case 3: /* troll bridge */
|
||||
if (g.prop[TROLL] == 1) {
|
||||
pspeak(TROLL, 1);
|
||||
g.prop[TROLL] = 0;
|
||||
move(TROLL2, 0);
|
||||
move((TROLL2 + MAXOBJ), 0);
|
||||
move(TROLL, plac[TROLL]);
|
||||
move((TROLL + MAXOBJ), fixd[TROLL]);
|
||||
juggle(CHASM);
|
||||
g.newloc = g.loc;
|
||||
} else {
|
||||
g.newloc = plac[TROLL] + fixd[TROLL] - g.loc;
|
||||
if (g.prop[TROLL] == 0)
|
||||
g.prop[TROLL] = 1;
|
||||
if (toting(BEAR)) {
|
||||
rspeak(162);
|
||||
g.prop[CHASM] = 1;
|
||||
g.prop[TROLL] = 2;
|
||||
drop(BEAR, g.newloc);
|
||||
g.fixed[BEAR] = -1;
|
||||
g.prop[BEAR] = 3;
|
||||
if (g.prop[SPICES] < 0)
|
||||
++g.tally2;
|
||||
g.oldloc2 = g.newloc;
|
||||
death();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
/* Growing or shrinking in area of tiny door. Each time he
|
||||
does this, everything must be moved to the new loc.
|
||||
Presumably, all his possesions are shrunk or streched along
|
||||
with him. Phuce[2][4] is an array containg four pairs of
|
||||
"here" (K) and "there" (KK) locations. */
|
||||
k = phuce[0][g.loc - 161];
|
||||
g.newloc = phuce[1][g.loc - 161];
|
||||
for (obj = 1; obj < MAXOBJ; obj++) {
|
||||
if (obj == BOAT)
|
||||
continue;
|
||||
if (g.place[obj] == k && (g.fixed[obj] == 0 || g.fixed[obj] == -1))
|
||||
move(obj, g.newloc);
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
/* Phone booth in rotunda. Trying to shove past gnome, to get
|
||||
into phone booth. */
|
||||
if ((g.prop[BOOTH] == 0 && pct(35)) || g.visited[g.loc] == 1) {
|
||||
rspeak(263);
|
||||
g.prop[BOOTH] = 1;
|
||||
move(GNOME, 188);
|
||||
} else {
|
||||
if (g.prop[BOOTH] == 1)
|
||||
rspeak(253);
|
||||
else
|
||||
g.newloc = 189;
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
/* Collapsing clay bridge. He can cross with three (or fewer)
|
||||
thing. If more, of if carrying obviously heavy things, he
|
||||
may end up in the drink. */
|
||||
g.newloc = g.loc == 235 ? 190 : 235;
|
||||
bcrossing++;
|
||||
load = burden(0);
|
||||
if (load > 4) {
|
||||
k = (load + bcrossing) * 6 - 10;
|
||||
if (!pct(k))
|
||||
rspeak(318);
|
||||
else {
|
||||
rspeak(319);
|
||||
g.newloc = 236;
|
||||
if (holding(LAMP))
|
||||
move(LAMP, 236);
|
||||
if (toting(AXE) && enclosed(AXE))
|
||||
extract(AXE);
|
||||
if (holding(AXE))
|
||||
move(AXE, 208);
|
||||
for (obj = 1; obj < MAXOBJ; obj++)
|
||||
if (toting(obj))
|
||||
destroy(obj);
|
||||
g.prop[CHASM2] = 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 7:
|
||||
/* Kaleidoscope code is here. */
|
||||
if (kalflg == 5) {
|
||||
g.newloc = 248;
|
||||
g.oldloc = 247;
|
||||
} else {
|
||||
g.newloc = 242 + ranz(5);
|
||||
g.oldloc = g.newloc - 1;
|
||||
kalflg = g.newloc == 242 ? 0 : -10;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
bug(38);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
Routine to fill travel array for a given location
|
||||
*/
|
||||
void gettrav(loc, travel)
|
||||
int loc;
|
||||
struct trav *travel;
|
||||
{
|
||||
int i;
|
||||
long t, *lptr;
|
||||
|
||||
lptr = cave[loc - 1];
|
||||
for (i = 0; i < MAXTRAV; i++) {
|
||||
t = *lptr++;
|
||||
if (!(t)) {
|
||||
travel->tdest = -1; /* end of array */
|
||||
return; /* terminate for loop */
|
||||
}
|
||||
travel->tverb = (int) (t % 1000);
|
||||
t /= 1000;
|
||||
travel->tdest = (int) (t % 1000);
|
||||
t /= 1000;
|
||||
travel->tcond = (int) (t % 1000);
|
||||
travel++;
|
||||
}
|
||||
bug(25);
|
||||
return;
|
||||
}
|
||||
729
commands/advent/turn.c
Normal file
729
commands/advent/turn.c
Normal file
@@ -0,0 +1,729 @@
|
||||
/* program TURN.C */
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "advent.h"
|
||||
#include "advdec.h"
|
||||
|
||||
_PROTOTYPE(void descitem, (void));
|
||||
_PROTOTYPE(void domove, (void));
|
||||
_PROTOTYPE(void goback, (void));
|
||||
_PROTOTYPE(void copytrv, (struct trav *, struct trav *));
|
||||
_PROTOTYPE(void dotrav, (void));
|
||||
_PROTOTYPE(void badmove, (void));
|
||||
_PROTOTYPE(void spcmove, (int));
|
||||
_PROTOTYPE(void death, (void));
|
||||
_PROTOTYPE(void dwarves, (void));
|
||||
_PROTOTYPE(void dopirate, (void));
|
||||
_PROTOTYPE(int stimer, (void));
|
||||
_PROTOTYPE(void do_hint, (int));
|
||||
|
||||
|
||||
/*
|
||||
Routine to take 1 turn
|
||||
*/
|
||||
void turn()
|
||||
{
|
||||
int i, hint;
|
||||
static int waste = 0;
|
||||
|
||||
if (newtravel) {
|
||||
/* If closing, then he can't leave except via the main office. */
|
||||
if (outside(g.newloc) && g.newloc != 0 && g.closing) {
|
||||
rspeak(130);
|
||||
g.newloc = g.loc;
|
||||
if (!g.panic)
|
||||
g.clock2 = 15;
|
||||
g.panic = TRUE;
|
||||
}
|
||||
/* See if a dwarf has seen him and has come from where he wants
|
||||
to go. */
|
||||
if (g.newloc != g.loc && !forced(g.loc) && g.loc_attrib[g.loc] & NOPIRAT == 0)
|
||||
for (i = 1; i < (DWARFMAX - 1); ++i)
|
||||
if (g.odloc[i] == g.newloc && g.dseen[i]) {
|
||||
g.newloc = g.loc;
|
||||
rspeak(2);
|
||||
break;
|
||||
}
|
||||
|
||||
g.loc = g.newloc;
|
||||
dwarves(); /* & special dwarf(pirate who
|
||||
steals) */
|
||||
|
||||
/* Check for death */
|
||||
if (g.loc == 0) {
|
||||
death();
|
||||
return;
|
||||
}
|
||||
/* Check for forced move */
|
||||
if (forced(g.loc)) {
|
||||
desclg(g.loc);
|
||||
++g.visited[g.loc];
|
||||
domove();
|
||||
return;
|
||||
}
|
||||
/* Check for wandering in dark */
|
||||
if (g.wzdark && dark() && pct(35)) {
|
||||
rspeak(23);
|
||||
g.oldloc2 = g.loc;
|
||||
death();
|
||||
return;
|
||||
}
|
||||
/* see if he is wasting his batteies out in the open */
|
||||
if (outside(g.loc) && g.prop[LAMP]) {
|
||||
waste++;
|
||||
if (waste > 11) {
|
||||
rspeak(324);
|
||||
waste = 0;
|
||||
}
|
||||
} else
|
||||
waste = 0;
|
||||
|
||||
/* If wumpus is chasing stooge, see if wumpus gets him */
|
||||
if (g.chase) {
|
||||
g.chase++;
|
||||
g.prop[WUMPUS] = g.chase / 2;
|
||||
move(WUMPUS, g.loc);
|
||||
if (g.chase >= 10) {
|
||||
if (dark())
|
||||
rspeak(270);
|
||||
pspeak(WUMPUS, 5);
|
||||
death();
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* check for radiation poisoning. */
|
||||
g.health += (outside(g.loc)) ? 3 : 1;
|
||||
if (g.health > 100)
|
||||
g.health = 100;
|
||||
if (here(RADIUM) && (g.place[RADIUM] != -SHIELD || ajar(SHIELD)))
|
||||
g.health -= 7;
|
||||
if (g.health < 60) {
|
||||
rspeak(391 + (60 - g.health) / 10);
|
||||
if (g.health < 0) {
|
||||
death();
|
||||
return;
|
||||
}
|
||||
}
|
||||
if ((g.oldloc == 188) && (g.loc != 188 && g.loc != 189)
|
||||
&& (g.prop[BOOTH] == 1)) {
|
||||
move(GNOME, 0);
|
||||
g.prop[BOOTH] = 0;
|
||||
}
|
||||
/* Describe his situation */
|
||||
describe();
|
||||
if (!blind()) {
|
||||
++g.visited[g.loc];
|
||||
descitem();
|
||||
}
|
||||
} /* end of newtravel start for
|
||||
second entry point */
|
||||
/* Check if this location is eligible for any hints. If been here
|
||||
long enough, branch to help section. Ignore "hints" < HNTMIN
|
||||
(special stuff, see database notes. */
|
||||
for (hint = HNTMIN; hint <= HNTMAX; hint++) {
|
||||
if (g.hinted[hint])
|
||||
continue;
|
||||
if (g.loc_attrib[g.loc] / 256 != hint - 6)
|
||||
g.hintlc[hint] = -1;
|
||||
g.hintlc[hint]++;
|
||||
if (g.hintlc[hint] >= g.hints[hint][1])
|
||||
do_hint(hint);
|
||||
}
|
||||
|
||||
if (g.closed) {
|
||||
if (g.prop[OYSTER] < 0 && toting(OYSTER))
|
||||
pspeak(OYSTER, 1);
|
||||
for (i = 1; i < MAXOBJ; ++i)
|
||||
if (toting(i) && g.prop[i] < 0)
|
||||
g.prop[i] = -1 - g.prop[i];
|
||||
}
|
||||
g.wzdark = dark();
|
||||
if (g.knfloc > 0 && g.knfloc != g.loc)
|
||||
g.knfloc = 0;
|
||||
++g.turns;
|
||||
i = rand();
|
||||
|
||||
if (stimer()) /* as the grains of sand slip
|
||||
by */
|
||||
return;
|
||||
|
||||
while (!english()) /* retrieve player instructions */
|
||||
;
|
||||
|
||||
vrbx = 1;
|
||||
objx = objs[1] ? 1 : 0;
|
||||
iobx = iobjs[1] ? 1 : 0;
|
||||
verb = VAL(verbs[vrbx]);
|
||||
do {
|
||||
object = objx ? objs[objx] : 0;
|
||||
iobj = iobx ? iobjs[iobx] : 0;
|
||||
if (object && (objs[2] || iobjs[2])) {
|
||||
pspeak(object, -1);
|
||||
printf(" ");
|
||||
}
|
||||
switch (CLASS(verbs[vrbx])) {
|
||||
case MOTION:
|
||||
motion = verb;
|
||||
domove();
|
||||
break;
|
||||
case NOUN:
|
||||
bug(22);
|
||||
case ACTION:
|
||||
if (object || iobj)
|
||||
trverb();
|
||||
else
|
||||
itverb();
|
||||
break;
|
||||
case MISC:
|
||||
rspeak(verb);
|
||||
if (verb == 51)
|
||||
g.hinted[1] = TRUE;
|
||||
break;
|
||||
default:
|
||||
bug(22);
|
||||
}
|
||||
if (objx) {
|
||||
objx++;
|
||||
if (objs[objx] == 0)
|
||||
objx = 0;
|
||||
}
|
||||
if ((!objx || !objs[objx]) && iobx) {
|
||||
iobx++;
|
||||
if (iobjs[iobx] == 0)
|
||||
iobx = 0;
|
||||
if (iobx && iobjs[1])
|
||||
objx = 1;
|
||||
}
|
||||
} while (objx || iobx);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
Routine to describe current location
|
||||
*/
|
||||
void describe()
|
||||
{
|
||||
if (toting(BEAR))
|
||||
rspeak(141);
|
||||
if (dark())
|
||||
rspeak(16);
|
||||
else if ((g.terse && verb != LOOK) || g.visited[g.loc] % g.abbnum)
|
||||
descsh(g.loc);
|
||||
else
|
||||
desclg(g.loc);
|
||||
if (g.loc == 33 && pct(25) && !g.closing)
|
||||
rspeak(8);
|
||||
if (g.loc == 147 && !g.visited[g.loc])
|
||||
rspeak(216);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
Routine to describe visible items
|
||||
*/
|
||||
void descitem()
|
||||
{
|
||||
int i, state;
|
||||
|
||||
for (i = 1; i < MAXOBJ; ++i) {
|
||||
if (at(i)) {
|
||||
if (i == STEPS && toting(NUGGET))
|
||||
continue;
|
||||
if (g.prop[i] < 0) {
|
||||
if (g.closed)
|
||||
continue;
|
||||
else {
|
||||
g.prop[i] = 0;
|
||||
if (i == RUG || i == CHAIN
|
||||
|| i == SWORD || i == CASK)
|
||||
g.prop[i] = 1;
|
||||
if (i == CLOAK || i == RING)
|
||||
g.prop[i] = 2;
|
||||
--g.tally;
|
||||
}
|
||||
}
|
||||
if (i == STEPS && g.loc == g.fixed[STEPS])
|
||||
state = 1;
|
||||
else
|
||||
state = g.prop[i] % 8;
|
||||
pspeak(i, state);
|
||||
lookin(i);
|
||||
}
|
||||
}
|
||||
/* If remaining treasures too elusive, zap his lamp */
|
||||
if (g.tally == g.tally2 && g.tally != 0 && g.limit > 35)
|
||||
g.limit = 35;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
Routine to handle player's demise via
|
||||
waking up the dwarves...
|
||||
*/
|
||||
void dwarfend()
|
||||
{
|
||||
rspeak(136);
|
||||
normend();
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
normal end of game
|
||||
*/
|
||||
void normend()
|
||||
{
|
||||
score(FALSE);
|
||||
gaveup = TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
Routine to handle the passing on of one
|
||||
of the player's incarnations...
|
||||
*/
|
||||
void death()
|
||||
{
|
||||
int yea, j;
|
||||
|
||||
if (!g.closing) {
|
||||
if (g.limit < 0) {
|
||||
rspeak(185);
|
||||
normend();
|
||||
return;
|
||||
}
|
||||
yea = yes(81 + g.numdie * 2, 82 + g.numdie * 2, 54);
|
||||
if (++g.numdie >= MAXDIE || !yea)
|
||||
normend();
|
||||
if (g.chase) {
|
||||
g.chase = FALSE;
|
||||
g.prop[WUMPUS] = 0;
|
||||
move(WUMPUS, 174);
|
||||
}
|
||||
if (toting(LAMP))
|
||||
g.prop[LAMP] = 0;
|
||||
for (j = 1; j < MAXOBJ; ++j) {
|
||||
if (toting(j))
|
||||
drop(j, j == LAMP ? 1 : g.oldloc2);
|
||||
if (wearng(j)) {
|
||||
g.prop[j] = 0;
|
||||
bitoff(j, WEARBT);
|
||||
}
|
||||
}
|
||||
g.newloc = 3;
|
||||
g.oldloc = g.loc;
|
||||
g.health = 100;
|
||||
return;
|
||||
}
|
||||
/* Closing -- no resurrection... */
|
||||
rspeak(131);
|
||||
++g.numdie;
|
||||
normend();
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
dwarf stuff.
|
||||
*/
|
||||
void dwarves()
|
||||
{
|
||||
int i, j, k, attack, stick, dtotal;
|
||||
|
||||
/* See if dwarves allowed here */
|
||||
if (g.newloc == 0 || forced(g.newloc) || g.loc_attrib[g.newloc] & NOPIRAT)
|
||||
return;
|
||||
|
||||
/* See if dwarves are active. */
|
||||
if (!g.dflag) {
|
||||
if (inside(g.newloc))
|
||||
++g.dflag;
|
||||
return;
|
||||
}
|
||||
/* If first close encounter (of 3rd kind) */
|
||||
if (g.dflag == 1) {
|
||||
if (!inside(g.newloc) || pct(85))
|
||||
return;
|
||||
++g.dflag;
|
||||
|
||||
/* kill 0, 1 or 2 of the dwarfs */
|
||||
for (i = 1; i < 3; ++i)
|
||||
if (pct(50))
|
||||
g.dloc[(ranz(DWARFMAX - 1)) + 1] = 0;
|
||||
|
||||
/* If any of the survivors is at location, use alternate choise */
|
||||
for (i = 1; i <= DWARFMAX; ++i) {
|
||||
if (g.dloc[i] == g.newloc)
|
||||
g.dloc[i] = g.daltloc;
|
||||
g.odloc[i] = g.dloc[i];
|
||||
}
|
||||
rspeak(3);
|
||||
drop(AXE, g.newloc);
|
||||
return;
|
||||
}
|
||||
/* Things are in full swing. Move each dwarf at random, except if
|
||||
he's seen us then he sticks with us. Dwarfs never go to
|
||||
locations outside or meet the bear or following him into dead
|
||||
end in maze. And of couse, dead dwarves don't do much of
|
||||
anything. */
|
||||
|
||||
dtotal = attack = stick = 0;
|
||||
for (i = 1; i <= DWARFMAX; ++i) {
|
||||
if (g.dloc[i] == 0)
|
||||
continue;
|
||||
/* Move a dwarf at random. we don't have a matrix around to do
|
||||
it as in the original version... */
|
||||
do
|
||||
j = ranz(106) + 15;
|
||||
/* allowed area */
|
||||
while (j == g.odloc[i] || j == g.dloc[i]
|
||||
|| g.loc_attrib[j] & NOPIRAT);
|
||||
|
||||
if (j == 0)
|
||||
bug(36);
|
||||
g.odloc[i] = g.dloc[i];
|
||||
g.dloc[i] = j;
|
||||
|
||||
g.dseen[i] = ((g.dseen[i] && inside(g.newloc))
|
||||
|| g.dloc[i] == g.newloc
|
||||
|| g.odloc[i] == g.newloc);
|
||||
|
||||
if (g.dseen[i]) {
|
||||
g.dloc[i] = g.newloc;
|
||||
if (i == DWARFMAX)
|
||||
dopirate();
|
||||
else {
|
||||
++dtotal;
|
||||
if (g.odloc[i] == g.dloc[i]) {
|
||||
++attack;
|
||||
if (g.knfloc >= 0)
|
||||
g.knfloc = g.newloc;
|
||||
if (ranz(1000) < (45 * (g.dflag - 2)))
|
||||
++stick;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Now we know shat's happing, let's tell the poor sucker about it */
|
||||
if (dtotal == 0)
|
||||
return;
|
||||
if (dtotal > 1)
|
||||
printf("There are %d threatening little dwarves in the room with you!\n", dtotal);
|
||||
else
|
||||
rspeak(4);
|
||||
if (attack == 0)
|
||||
return;
|
||||
if (g.dflag == 2)
|
||||
++g.dflag;
|
||||
if (attack > 1) {
|
||||
printf("%d of them throw knives at you!!\n", attack);
|
||||
k = 6;
|
||||
} else {
|
||||
rspeak(5);
|
||||
k = 52;
|
||||
}
|
||||
if (stick <= 1) {
|
||||
rspeak(stick + k);
|
||||
if (stick == 0)
|
||||
return;
|
||||
} else
|
||||
printf("%d of them get you !!!\n", stick);
|
||||
g.oldloc2 = g.newloc;
|
||||
death();
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
pirate stuff
|
||||
*/
|
||||
void dopirate()
|
||||
{
|
||||
int j;
|
||||
boolean k;
|
||||
|
||||
if (g.newloc == g.chloc || g.prop[CHEST] >= 0)
|
||||
return;
|
||||
k = FALSE;
|
||||
/* Pirate won't take pyramid from plover room or dark room (too
|
||||
easy! ) */
|
||||
for (j = 1; j < MAXOBJ; ++j)
|
||||
if (treasr(j) && !(j == CASK && liq(CASK) == WINE)
|
||||
&& !(j == PYRAMID && (g.newloc == g.place[PYRAMID]
|
||||
|| g.newloc == g.place[EMERALD]))) {
|
||||
if (toting(j) && athand(j))
|
||||
goto stealit;
|
||||
if (here(j))
|
||||
k = TRUE;
|
||||
}
|
||||
if (g.tally == g.tally2 + 1 && k == FALSE && g.place[CHEST] == 0 &&
|
||||
athand(LAMP) && g.prop[LAMP] == 1) {
|
||||
rspeak(186);
|
||||
move(CHEST, g.chloc);
|
||||
move(MESSAGE, g.chloc2);
|
||||
g.dloc[DWARFMAX] = g.chloc;
|
||||
g.odloc[DWARFMAX] = g.chloc;
|
||||
g.dseen[DWARFMAX] = 0;
|
||||
return;
|
||||
}
|
||||
if (g.odloc[DWARFMAX] != g.dloc[DWARFMAX] && pct(30))
|
||||
rspeak(127);
|
||||
return;
|
||||
|
||||
stealit:
|
||||
|
||||
rspeak(128);
|
||||
/* don't steal chest back from troll! */
|
||||
if (g.place[MESSAGE] == 0)
|
||||
move(CHEST, g.chloc);
|
||||
move(MESSAGE, g.chloc2);
|
||||
for (j = 1; j < MAXOBJ; ++j) {
|
||||
if (!treasr(j) || !athand(j)
|
||||
|| (j == PYRAMID &&
|
||||
(g.newloc == plac[PYRAMID] || g.newloc == plac[EMERALD]))
|
||||
|| (j == CASK && (liq(CASK) != WINE)))
|
||||
continue;
|
||||
if (enclosed(j))
|
||||
extract(j);
|
||||
if (wearng(j)) {
|
||||
g.prop[j] = 0;
|
||||
bitoff(j, WEARBT);
|
||||
}
|
||||
insert(j, CHEST);
|
||||
}
|
||||
g.dloc[DWARFMAX] = g.chloc;
|
||||
g.odloc[DWARFMAX] = g.chloc;
|
||||
g.dseen[DWARFMAX] = FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
special time limit stuff...
|
||||
*/
|
||||
int stimer()
|
||||
{
|
||||
int i, spk;
|
||||
static int clock3;
|
||||
|
||||
g.foobar = g.foobar > 0 ? -g.foobar : 0;
|
||||
g.combo = g.combo > 0 ? -g.combo : 0;
|
||||
if (g.turns > 310 && g.abbnum != 10000 && !g.terse)
|
||||
rspeak(273);
|
||||
|
||||
/* Bump all the right clocks for reconning battery life and closing */
|
||||
if (g.closed) {
|
||||
clock3--;
|
||||
if (clock3 == 0) {
|
||||
g.prop[PHONE] = 0;
|
||||
g.prop[BOOTH] = 0;
|
||||
rspeak(284);
|
||||
} else if (clock3 < -7) {
|
||||
rspeak(254);
|
||||
normend();
|
||||
return (TRUE);
|
||||
}
|
||||
}
|
||||
if (g.tally == 0 && inside(g.loc) && g.loc != Y2)
|
||||
--g.clock;
|
||||
if (g.clock == 0) {
|
||||
/* Start closing the cave */
|
||||
g.prop[GRATE] = 0;
|
||||
biton(GRATE, LOCKBT);
|
||||
bitoff(GRATE, OPENBT);
|
||||
g.prop[FISSURE] = 0;
|
||||
g.prop[TDOOR] = 0;
|
||||
biton(TDOOR, LOCKBT);
|
||||
bitoff(TDOOR, OPENBT);
|
||||
g.prop[TDOOR2] = 0;
|
||||
biton(TDOOR2, LOCKBT);
|
||||
bitoff(TDOOR2, OPENBT);
|
||||
for (i = 1; i <= DWARFMAX; ++i) {
|
||||
g.dseen[i] = FALSE;
|
||||
g.dloc[i] = 0;
|
||||
}
|
||||
move(TROLL, 0);
|
||||
move((TROLL + MAXOBJ), 0);
|
||||
move(TROLL2, plac[TROLL]);
|
||||
move((TROLL2 + MAXOBJ), fixd[TROLL]);
|
||||
juggle(CHASM);
|
||||
if (g.prop[BEAR] != 3)
|
||||
destroy(BEAR);
|
||||
g.prop[CHAIN] = 0;
|
||||
g.fixed[CHAIN] = 0;
|
||||
g.prop[AXE] = 0;
|
||||
g.fixed[AXE] = 0;
|
||||
rspeak(129);
|
||||
g.clock = -1;
|
||||
g.closing = TRUE;
|
||||
return (FALSE);
|
||||
}
|
||||
if (g.clock < 0)
|
||||
--g.clock2;
|
||||
if (g.clock2 == 0) {
|
||||
/* Set up storage room... and close the cave... */
|
||||
g.prop[BOTTLE] = put(BOTTLE, 115, 8);
|
||||
g.holder[BOTTLE] = WATER;
|
||||
g.place[WATER] = -BOTTLE;
|
||||
g.hlink[WATER] = 0;
|
||||
bitoff(BOTTLE, OPENBT);
|
||||
g.prop[PLANT] = put(PLANT, 115, 0);
|
||||
g.prop[OYSTER] = put(OYSTER, 115, 0);
|
||||
g.prop[LAMP] = put(LAMP, 115, 0);
|
||||
g.prop[ROD] = put(ROD, 115, 0);
|
||||
g.prop[DWARF] = put(DWARF, 115, 0);
|
||||
g.loc = 115;
|
||||
g.oldloc = 115;
|
||||
g.newloc = 115;
|
||||
/* Leave the grate with normal (non-negative property). */
|
||||
put(GRATE, 116, 0);
|
||||
biton(GRATE, LOCKBT);
|
||||
bitoff(GRATE, OPENBT);
|
||||
g.prop[SNAKE] = put(SNAKE, 116, 1);
|
||||
g.prop[BIRD] = put(BIRD, 116, 1);
|
||||
g.prop[CAGE] = put(CAGE, 116, 0);
|
||||
g.prop[ROD2] = put(ROD2, 116, 0);
|
||||
g.prop[PILLOW] = put(PILLOW, 116, 0);
|
||||
|
||||
g.prop[BOOTH] = put(BOOTH, 116, -3);
|
||||
g.fixed[BOOTH] = 115;
|
||||
g.prop[PHONE] = put(PHONE, 212, -4);
|
||||
|
||||
g.prop[MIRROR] = put(MIRROR, 115, 0);
|
||||
g.fixed[MIRROR] = 116;
|
||||
g.prop[BOOK2] = put(BOOK2, 115, 0);
|
||||
|
||||
for (i = 1; i < MAXOBJ; ++i) {
|
||||
if (toting(i) && enclosed(i))
|
||||
extract(i);
|
||||
if (toting(i))
|
||||
destroy(i);
|
||||
}
|
||||
rspeak(132);
|
||||
g.closed = TRUE;
|
||||
clock3 = 20 + ranz(20);
|
||||
newtravel = TRUE;
|
||||
return (TRUE);
|
||||
}
|
||||
if (g.prop[LAMP] == 1)
|
||||
--g.limit;
|
||||
if (g.limit == 0) {
|
||||
--g.limit;
|
||||
g.prop[LAMP] = 0;
|
||||
if (here(LAMP))
|
||||
rspeak(184);
|
||||
return (FALSE);
|
||||
}
|
||||
if (g.limit < 0 && outside(g.loc)) {
|
||||
rspeak(185);
|
||||
normend();
|
||||
return (TRUE);
|
||||
}
|
||||
if (g.limit <= 40) {
|
||||
if (g.lmwarn || !here(LAMP))
|
||||
return (FALSE);
|
||||
g.lmwarn = TRUE;
|
||||
spk = 187;
|
||||
if (g.prop[BATTERIES] == 1)
|
||||
spk = 323;
|
||||
if (g.place[BATTERIES] == 0)
|
||||
spk = 183;
|
||||
if (g.prop[VEND] == 1)
|
||||
spk = 189;
|
||||
rspeak(spk);
|
||||
return (FALSE);
|
||||
}
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
/* HINTS
|
||||
come here if he's been long enough at required location(s)
|
||||
for some unused hint, hint number is in variable "hint".
|
||||
Branch to quick test for additional conditions, then
|
||||
do neet stuff. If conditions are met and we want to offer
|
||||
hint. Clear hintlc if no action is taken.
|
||||
*/
|
||||
|
||||
#define MASE 1
|
||||
#define DARK 2
|
||||
#define WITT 3
|
||||
#define H_SWORD 4
|
||||
#define SLIDE 5
|
||||
#define H_GRATE 6
|
||||
#define H_BIRD 7
|
||||
#define H_ELFIN 8
|
||||
#define RNBOW 9
|
||||
#define STYX 10
|
||||
#define H_SNAKE 11
|
||||
#define CASTLE 12
|
||||
|
||||
void do_hint(hint)
|
||||
int hint;
|
||||
{
|
||||
g.hintlc[hint] = 0;
|
||||
switch (hint + 1 - HNTMIN) {
|
||||
case MASE:
|
||||
if (!at(g.loc) && !at(g.oldloc)
|
||||
&& !at(g.loc) && burden(0) > 1)
|
||||
break;
|
||||
else
|
||||
return;
|
||||
case DARK:
|
||||
if (g.prop[EMERALD] != -1 && g.prop[PYRAMID] == -1)
|
||||
break;
|
||||
else
|
||||
return;
|
||||
case WITT:
|
||||
break;
|
||||
case H_SWORD:
|
||||
if ((g.prop[SWORD] == 1 || g.prop[SWORD] == 5)
|
||||
&& !toting(CROWN))
|
||||
break;
|
||||
else
|
||||
return;
|
||||
case SLIDE:
|
||||
break;
|
||||
case H_GRATE:
|
||||
if (g.prop[GRATE] == 0 && !athand(KEYS))
|
||||
break;
|
||||
else
|
||||
return;
|
||||
case H_BIRD:
|
||||
if (here(BIRD) && athand(ROD) && object == BIRD)
|
||||
break;
|
||||
else
|
||||
return;
|
||||
case H_ELFIN:
|
||||
if (!g.visited[159])
|
||||
break;
|
||||
else
|
||||
return;
|
||||
case RNBOW:
|
||||
if (!toting(SHOES) || g.visited[205])
|
||||
break;
|
||||
else
|
||||
return;
|
||||
case STYX:
|
||||
if (!athand(LYRE) && g.prop[DOG] != 1)
|
||||
break;
|
||||
else
|
||||
return;
|
||||
case H_SNAKE:
|
||||
if (here(SNAKE) && !here(BIRD))
|
||||
break;
|
||||
else
|
||||
return;
|
||||
case CASTLE:
|
||||
break;
|
||||
default:
|
||||
printf(" TRYING TO PRINT HINT # %d\n", hint);
|
||||
bug(27);
|
||||
}
|
||||
if (!yes(g.hints[hint][3], 0, 54))
|
||||
return;
|
||||
printf("\nI am prepared to give you a hint,");
|
||||
printf(" but it will cost you %2d points\n", g.hints[hint][2]);
|
||||
g.hinted[hint] = yes(175, g.hints[hint][4], 54);
|
||||
if (g.hinted[hint] && g.limit > 30)
|
||||
g.limit += 30 * g.hints[hint][2];
|
||||
return;
|
||||
}
|
||||
749
commands/advent/utility.c
Normal file
749
commands/advent/utility.c
Normal file
@@ -0,0 +1,749 @@
|
||||
/*
|
||||
Utility Routines
|
||||
the next logical funtions describe attributes of objects.
|
||||
(ajar, hinged, opaque, printd, treasr, vessel, wearng)
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include "advent.h"
|
||||
#include "advdec.h"
|
||||
|
||||
/*
|
||||
ajar .TRUE. if item is container and is open or unhinged
|
||||
*/
|
||||
boolean ajar(item)
|
||||
int item;
|
||||
{
|
||||
return ((bitset(g.obj_state[item], OPENBT))
|
||||
|| (vessel(item) && !hinged(item)));
|
||||
}
|
||||
|
||||
/*
|
||||
at .TRUE. To tell if player is on either side of a two sided object.
|
||||
*/
|
||||
boolean at(item)
|
||||
int item;
|
||||
{
|
||||
if (item < 1 || item > MAXOBJ)
|
||||
return (FALSE);
|
||||
else
|
||||
return (g.place[item] == g.loc || g.fixed[item] == g.loc);
|
||||
}
|
||||
|
||||
/*
|
||||
athand .TRUE. if item readily reachable
|
||||
it can be lying here, in hand or in open container.
|
||||
*/
|
||||
boolean athand(item)
|
||||
int item;
|
||||
{
|
||||
int contnr;
|
||||
boolean aaa;
|
||||
|
||||
contnr = -g.place[item];
|
||||
aaa = enclosed(item) && ajar(contnr);
|
||||
|
||||
return ((g.place[item] == g.loc) || holding(item)
|
||||
|| (aaa && ((g.place[contnr] == g.loc)
|
||||
|| (toting(item) && holding(contnr)))));
|
||||
}
|
||||
|
||||
/*
|
||||
bitoff turns off (sets to 0) a bit in obj_state word
|
||||
*/
|
||||
void bitoff(obj, bit)
|
||||
int obj, bit;
|
||||
{
|
||||
long val;
|
||||
|
||||
val = 1L << bit;
|
||||
g.obj_state[obj] &= ~val;
|
||||
}
|
||||
|
||||
/*
|
||||
biton turns on (sets to 1) a bit in obj_state word
|
||||
*/
|
||||
void biton(obj, bit)
|
||||
int obj, bit;
|
||||
{
|
||||
long val;
|
||||
|
||||
val = 1L << bit;
|
||||
g.obj_state[obj] |= val;
|
||||
}
|
||||
|
||||
/*
|
||||
bitset .TRUE. if object_state has bit N set
|
||||
*/
|
||||
boolean bitset(state, bit)
|
||||
long state;
|
||||
int bit;
|
||||
{
|
||||
return (((state >> bit) & 1) == 1);
|
||||
}
|
||||
|
||||
/*
|
||||
blind .TRUE. if you can't see at this loc, (darkness of glare)
|
||||
*/
|
||||
boolean blind()
|
||||
{
|
||||
return (dark() || (g.loc == 200
|
||||
&& athand(LAMP) && (g.prop[LAMP] == 1)));
|
||||
}
|
||||
|
||||
/*
|
||||
burden .. returns weight of items being carried
|
||||
|
||||
if obj=0, burden calculates the total weight of the adventurer's burden
|
||||
including everything in all containers (except the boat) that he is
|
||||
carring.
|
||||
|
||||
if object is a container, calculate the weight of everything inside
|
||||
the container (including the container itself). Since donkey FORTRAN
|
||||
isn't recursive, we will only calculate weight of contained containers
|
||||
one level down. The only serious contained container would be the sack
|
||||
The only thing we'll miss will be filled VS empty bottle or cage.
|
||||
|
||||
If object isn't a container, return its weight.
|
||||
*/
|
||||
int burden(obj)
|
||||
int obj;
|
||||
{
|
||||
int i, sum, temp;
|
||||
|
||||
sum = 0;
|
||||
if (obj == 0) {
|
||||
for (i = 1; i < MAXOBJ; i++) {
|
||||
if (toting(i) && (g.place[i] != -BOAT))
|
||||
sum += g.weight[i];
|
||||
}
|
||||
} else {
|
||||
if (obj != BOAT) {
|
||||
sum = g.weight[obj];
|
||||
temp = g.holder[obj];
|
||||
while (temp != 0) {
|
||||
sum += g.weight[temp];
|
||||
temp = g.hlink[temp];
|
||||
}
|
||||
}
|
||||
}
|
||||
return (sum);
|
||||
}
|
||||
|
||||
/*
|
||||
Routine to carry an object
|
||||
start toting an object, removing it from the list of things
|
||||
at its former location. If object > MAXOBJ ( moving "FIXED"
|
||||
or second loc), then don't change place.
|
||||
*/
|
||||
void carry(obj, where)
|
||||
int obj, where;
|
||||
{
|
||||
int temp;
|
||||
|
||||
if (obj < MAXOBJ) {
|
||||
if (g.place[obj] == -1)
|
||||
return;
|
||||
g.place[obj] = -1;
|
||||
}
|
||||
if (g.atloc[where] == obj)
|
||||
g.atloc[where] = g.link[obj];
|
||||
else {
|
||||
temp = g.atloc[where];
|
||||
while (g.link[temp] != obj) {
|
||||
temp = g.link[temp];
|
||||
if (temp == 0)
|
||||
bug(35);
|
||||
}
|
||||
g.link[temp] = g.link[obj];
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
confuz generates some variant of "Don't understand that" message.
|
||||
*/
|
||||
int confuz()
|
||||
{
|
||||
int msg;
|
||||
|
||||
msg = 60;
|
||||
if (pct(50))
|
||||
msg = 61;
|
||||
if (pct(33))
|
||||
msg = 13;
|
||||
if (pct(25))
|
||||
msg = 347;
|
||||
if (pct(20))
|
||||
msg = 195;
|
||||
return (msg);
|
||||
}
|
||||
|
||||
/*
|
||||
dark .TRUE. if there is no light here
|
||||
*/
|
||||
boolean dark()
|
||||
{
|
||||
return (!(g.loc_attrib[g.loc] & LIGHT) &&
|
||||
(!g.prop[LAMP] || !athand(LAMP)));
|
||||
}
|
||||
|
||||
/*
|
||||
Routine to check for presence
|
||||
of dwarves..
|
||||
*/
|
||||
int dcheck()
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 1; i < (DWARFMAX); ++i)
|
||||
if (g.dloc[i] == g.loc)
|
||||
return (i);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
dead .TRUE. if object is now dead
|
||||
*/
|
||||
boolean dead(obj)
|
||||
int obj;
|
||||
{
|
||||
return (bitset(g.obj_state[obj], 10));
|
||||
}
|
||||
|
||||
/*
|
||||
drop Place an object at a given loc, prefixing it onto the atloc list.
|
||||
*/
|
||||
void drop(obj, where)
|
||||
int obj, where;
|
||||
{
|
||||
if (obj > MAXOBJ)
|
||||
g.fixed[obj - MAXOBJ] = where;
|
||||
else
|
||||
g.place[obj] = where;
|
||||
if (where > 0) {
|
||||
g.link[obj] = g.atloc[where];
|
||||
g.atloc[where] = obj;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
destroy Permanently eliminate "object" by moving it to
|
||||
a non-existent location.
|
||||
*/
|
||||
void destroy(obj)
|
||||
int obj;
|
||||
{
|
||||
move(obj, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
edible .TRUE. if obj can be eaten.
|
||||
*/
|
||||
boolean edible(obj)
|
||||
int obj;
|
||||
{
|
||||
return (bitset(g.obj_state[obj], 7));
|
||||
}
|
||||
|
||||
/*
|
||||
enclosed .TRUE. If object is inside a container.
|
||||
*/
|
||||
boolean enclosed(item)
|
||||
int item;
|
||||
{
|
||||
if (item < 1 || item > MAXOBJ)
|
||||
return (FALSE);
|
||||
else
|
||||
return (g.place[item] < -1);
|
||||
}
|
||||
|
||||
/*
|
||||
extract remove "object" from a container.
|
||||
origionally name "remove" but rename to avoid conflict with stdio.h
|
||||
*/
|
||||
void extract(obj)
|
||||
int obj;
|
||||
{
|
||||
int contnr, temp;
|
||||
|
||||
contnr = -g.place[obj];
|
||||
g.place[obj] = -1;
|
||||
if (g.holder[contnr] == obj)
|
||||
g.holder[contnr] = g.hlink[obj];
|
||||
else {
|
||||
temp = g.holder[contnr];
|
||||
while (g.hlink[temp] != obj) {
|
||||
temp = g.hlink[temp];
|
||||
if (temp == 0)
|
||||
bug(35);
|
||||
}
|
||||
g.hlink[temp] = g.hlink[obj];
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
forced To tell if a location will causes a forced move.
|
||||
A forced location is one from which he is immediately bounced
|
||||
to another. Normal use is for death (forced to location zero)
|
||||
and for description of journey from on place to another.
|
||||
*/
|
||||
int forced(at_loc)
|
||||
int at_loc;
|
||||
{
|
||||
return ((g.loc_attrib[at_loc] & 10) == 2);
|
||||
}
|
||||
|
||||
/*
|
||||
here .TRUE. If an item is at location or is being carried.
|
||||
*/
|
||||
boolean here(item)
|
||||
int item;
|
||||
{
|
||||
return (g.place[item] == g.loc || toting(item));
|
||||
}
|
||||
|
||||
/*
|
||||
hinged .TRUE. If object can be opened or shut.
|
||||
*/
|
||||
boolean hinged(object)
|
||||
int object;
|
||||
{
|
||||
return (bitset(g.obj_state[object], 1));
|
||||
}
|
||||
|
||||
/*
|
||||
holding .TRUE. If the object is being carried in hand.
|
||||
*/
|
||||
boolean holding(item)
|
||||
int item;
|
||||
{
|
||||
if (item < 1 || item > MAXOBJ)
|
||||
return (FALSE);
|
||||
else
|
||||
return (g.place[item] == -1);
|
||||
}
|
||||
|
||||
/*
|
||||
insert
|
||||
*/
|
||||
void insert(obj, contnr)
|
||||
int obj, contnr;
|
||||
{
|
||||
int temp;
|
||||
|
||||
if (contnr == obj)
|
||||
bug(32);
|
||||
carry(obj, g.loc);
|
||||
|
||||
temp = g.holder[contnr];
|
||||
g.holder[contnr] = obj;
|
||||
g.hlink[obj] = temp;
|
||||
g.place[obj] = -contnr;
|
||||
}
|
||||
|
||||
/*
|
||||
inside = .TRUE. If location is well within cave
|
||||
*/
|
||||
boolean inside(loc)
|
||||
int loc;
|
||||
{
|
||||
return (!outside(loc) && !portal(loc));
|
||||
}
|
||||
|
||||
/*
|
||||
Juggle an object by picking it up and putting it down again,
|
||||
The purpose being to get the object to the front of the chain
|
||||
at its loc.
|
||||
*/
|
||||
void juggle(obj)
|
||||
int obj;
|
||||
{
|
||||
int i, j;
|
||||
|
||||
i = g.place[obj];
|
||||
j = g.fixed[obj];
|
||||
move(obj, i);
|
||||
move(obj + MAXOBJ, j);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
Determine liquid in the vessel
|
||||
*/
|
||||
int liq(item)
|
||||
int item;
|
||||
{
|
||||
int liquid;
|
||||
|
||||
if ((item == BOTTLE) || (item == CASK))
|
||||
liquid = liq2(((int) g.prop[item] >> 1) & 7);
|
||||
else
|
||||
liquid = 0;
|
||||
|
||||
return (liquid);
|
||||
}
|
||||
|
||||
/*
|
||||
Determine type of liquid in vessel
|
||||
*/
|
||||
int liq2(liquid)
|
||||
int liquid;
|
||||
{
|
||||
switch (liquid) {
|
||||
case 4:
|
||||
return (WATER);
|
||||
case 5:
|
||||
return (OIL);
|
||||
case 6:
|
||||
return (WINE);
|
||||
default:
|
||||
return (0); /* empty */
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Determine liquid at a location
|
||||
*/
|
||||
int liqloc(loc)
|
||||
int loc;
|
||||
{
|
||||
return (liq2((int) ((g.loc_attrib[loc] >> 1) & 7)));
|
||||
}
|
||||
|
||||
/*
|
||||
living .TRUE. If object is living, bear for example
|
||||
*/
|
||||
boolean living(obj)
|
||||
int obj;
|
||||
{
|
||||
return (bitset(g.obj_state[obj], 9));
|
||||
}
|
||||
|
||||
/*
|
||||
locked .TRUE. if lockable object is locked
|
||||
*/
|
||||
boolean locked(item)
|
||||
int item;
|
||||
{
|
||||
return (bitset(g.obj_state[item], 4));
|
||||
}
|
||||
|
||||
/*
|
||||
locks .TRUE. if you can lock this object
|
||||
*/
|
||||
boolean locks(item)
|
||||
int item;
|
||||
{
|
||||
return (bitset(g.obj_state[item], 3));
|
||||
}
|
||||
|
||||
/*
|
||||
LOOKIN list contents if obj is a container and is open or transparent.
|
||||
*/
|
||||
void lookin(contnr)
|
||||
int contnr;
|
||||
{
|
||||
int temp;
|
||||
boolean first_time;
|
||||
|
||||
if (vessel(contnr) && (ajar(contnr) || !opaque(contnr))) {
|
||||
temp = g.holder[contnr];
|
||||
first_time = TRUE;
|
||||
while (temp != 0) {
|
||||
if (first_time)
|
||||
rspeak(360);
|
||||
printf(" ");
|
||||
pspeak(temp, -1);
|
||||
temp = g.hlink[temp];
|
||||
first_time = FALSE;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
Routine to move an object
|
||||
*/
|
||||
void move(obj, where)
|
||||
int obj, where;
|
||||
{
|
||||
int from;
|
||||
|
||||
if (obj > MAXOBJ)
|
||||
from = g.fixed[obj - MAXOBJ];
|
||||
else {
|
||||
if (enclosed(obj))
|
||||
extract(obj);
|
||||
from = g.place[obj];
|
||||
}
|
||||
if ((from > 0) && (from < MAXOBJ * 2))
|
||||
carry(obj, from);
|
||||
drop(obj, where);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
noway, generate's some variant of "can't do that" message.
|
||||
*/
|
||||
int noway()
|
||||
{
|
||||
int msg;
|
||||
|
||||
msg = 14;
|
||||
if (pct(50))
|
||||
msg = 110;
|
||||
if (pct(33))
|
||||
msg = 147;
|
||||
if (pct(25))
|
||||
msg = 250;
|
||||
if (pct(20))
|
||||
msg = 262;
|
||||
if (pct(17))
|
||||
msg = 25;
|
||||
if (pct(14))
|
||||
msg = 345;
|
||||
if (pct(12))
|
||||
msg = 346;
|
||||
return (msg);
|
||||
}
|
||||
|
||||
/*
|
||||
opaque .TRUE. If obj is non-transparent container
|
||||
*/
|
||||
boolean opaque(obj)
|
||||
int obj;
|
||||
{
|
||||
return (bitset(g.obj_state[obj], 6));
|
||||
}
|
||||
|
||||
/*
|
||||
outsid .TRUE. If location is outside the cave
|
||||
*/
|
||||
boolean outside(loc)
|
||||
int loc;
|
||||
{
|
||||
return (bitset(g.loc_attrib[loc], 6));
|
||||
}
|
||||
|
||||
/*
|
||||
Routine true x% of the time. (x an integer from 0 to 100)
|
||||
*/
|
||||
int pct(x)
|
||||
int x;
|
||||
{
|
||||
return (ranz(100) < x);
|
||||
}
|
||||
|
||||
/*
|
||||
plural .TRUE. if object is multiple objects
|
||||
*/
|
||||
boolean plural(obj)
|
||||
int obj;
|
||||
{
|
||||
return (bitset(g.obj_state[obj], 13));
|
||||
}
|
||||
|
||||
/*
|
||||
portal .TRUE. If location is a cave entrance
|
||||
*/
|
||||
boolean portal(loc)
|
||||
int loc;
|
||||
{
|
||||
return (bitset(g.loc_attrib[loc], 5));
|
||||
}
|
||||
|
||||
/*
|
||||
printed .TRUE. If object can be read.
|
||||
*/
|
||||
boolean printed(obj)
|
||||
int obj;
|
||||
{
|
||||
return (bitset(g.obj_state[obj], 8));
|
||||
}
|
||||
|
||||
/*
|
||||
put is the same as move, except it returns a
|
||||
value used to set the negated prop values
|
||||
for the repository objects.
|
||||
*/
|
||||
int put(obj, where, pval)
|
||||
int obj, where, pval;
|
||||
{
|
||||
move(obj, where);
|
||||
return ((-1) - pval);
|
||||
}
|
||||
|
||||
/*
|
||||
RANZ
|
||||
*/
|
||||
int ranz(range)
|
||||
int range;
|
||||
{
|
||||
return (rand() % range);
|
||||
}
|
||||
|
||||
/*
|
||||
small .TRUE. If object fits in sack or small container
|
||||
*/
|
||||
boolean small(obj)
|
||||
int obj;
|
||||
{
|
||||
return (bitset(g.obj_state[obj], 5));
|
||||
}
|
||||
|
||||
/*
|
||||
toting .TRUE. If an item is being caried.
|
||||
*/
|
||||
int toting(item)
|
||||
int item;
|
||||
{
|
||||
boolean aaa, bbb, ccc;
|
||||
int contnr, outer, outer2;
|
||||
|
||||
contnr = -g.place[item];
|
||||
outer = -g.place[contnr];
|
||||
outer2 = -g.place[outer];
|
||||
|
||||
aaa = holding(contnr);
|
||||
bbb = enclosed(contnr) && holding(outer);
|
||||
ccc = enclosed(outer) && holding(outer2);
|
||||
|
||||
return (holding(item) || (enclosed(item) && (aaa || bbb || ccc)));
|
||||
}
|
||||
|
||||
/*
|
||||
treasr .TRUE. If object is valuable for points
|
||||
*/
|
||||
boolean treasr(obj)
|
||||
int obj;
|
||||
{
|
||||
return (bitset(g.obj_state[obj], 14));
|
||||
}
|
||||
|
||||
/*
|
||||
vessel .TRUE. if object can hold a liquid
|
||||
*/
|
||||
boolean vessel(obj)
|
||||
int obj;
|
||||
{
|
||||
return (bitset(g.obj_state[obj], 15));
|
||||
}
|
||||
|
||||
/*
|
||||
wearng .TRUE. If wearing obj
|
||||
*/
|
||||
boolean wearng(item)
|
||||
int item;
|
||||
{
|
||||
return (bitset(g.obj_state[item], WEARBT));
|
||||
}
|
||||
|
||||
/*
|
||||
worn .TRUE. if object is being worn
|
||||
*/
|
||||
boolean worn(obj)
|
||||
int obj;
|
||||
{
|
||||
return (bitset(g.obj_state[obj], 11));
|
||||
}
|
||||
|
||||
static char *e_msg[] = {
|
||||
"message line > 70 characters", /* 00 */
|
||||
"null line in message", /* 01 */
|
||||
"too many words of messages", /* 02 */
|
||||
"too many travel options", /* 03 */
|
||||
"too many vocabulary words", /* 04 */
|
||||
"required vocabulary word not found", /* 05 */
|
||||
"too many rtext or mtext messages", /* 06 */
|
||||
"too many hints", /* 07 */
|
||||
"location has loc_attrib bit being set twice", /* 08 */
|
||||
"invalid section number in database", /* 09 */
|
||||
"out of order locs or rspeak entries.", /* 10 */
|
||||
"illegal motion word in travel table", /* 11 */
|
||||
"** unused **.",/* 12 */
|
||||
"unknown or illegal word in adjective table.", /* 13 */
|
||||
"illegal word in prep/obj table", /* 14 */
|
||||
"too many entries in prep/obj table", /* 15 */
|
||||
"object has condition bit set twice", /* 16 */
|
||||
"object number too large", /* 17 */
|
||||
"too many entries in adjective/noun table.", /* 18 */
|
||||
"** unused **.",/* 19 */
|
||||
"special travel (500>l>300) exceeds goto list", /* 20 */
|
||||
"ran off end of vocabulary table", /* 21 */
|
||||
"verb class (n/1000) not between 1 and 3", /* 22 */
|
||||
"intransitive action verb exceeds goto list", /* 23 */
|
||||
"transitive action verb exceeds goto list", /* 24 */
|
||||
"conditional travel entry with no alternative", /* 25 */
|
||||
"location has no travel entries", /* 26 */
|
||||
"hint number exceeds goto list", /* 27 */
|
||||
"invalid month returned by date function", /* 28 */
|
||||
"action verb 'leave' has no object.", /* 29 */
|
||||
"preposition found in unexpected table", /* 30 */
|
||||
"received an unexpected word terminator from a1toa5", /* 31 */
|
||||
"trying to put a container into itself (tricky!)", /* 32 */
|
||||
"unknown word class in getwds", /* 33 */
|
||||
"** unused **.",/* 34 */
|
||||
"trying to carry a non-existent object"}; /* 35 */
|
||||
|
||||
/*
|
||||
Fatal error routine
|
||||
*/
|
||||
void bug(n)
|
||||
unsigned int n;
|
||||
{
|
||||
if (n < 36 && *e_msg[n] != '*')
|
||||
fprintf(stderr, "Fatal error, probable cause: %s\n", e_msg[n]);
|
||||
else
|
||||
fprintf(stderr, "Fatal error number %d - Unused error number!\n", n);
|
||||
panic((char *) 0, TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
Prompt for input, strip leading and trailing spaces,
|
||||
return &buf[first non-whitespace].
|
||||
Does not return if end of input.
|
||||
*/
|
||||
char *
|
||||
ask(prompt, buf, buflen)
|
||||
char *prompt, *buf;
|
||||
int buflen;
|
||||
{
|
||||
fputs(prompt, stdout);
|
||||
fflush(stdout);
|
||||
if (!fgets(buf, buflen, stdin))
|
||||
panic("end of input", FALSE);
|
||||
if (*buf) {
|
||||
int c;
|
||||
char *end = buf + strlen(buf);
|
||||
if (end[-1] != '\n')
|
||||
/* Skip to end of line */
|
||||
while ((c = getchar()) != '\n' && c != EOF);
|
||||
while (*buf && isspace(*buf))
|
||||
buf++;
|
||||
while (buf <= --end && isspace(*end))
|
||||
*end = '\0';
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
/*
|
||||
save and abort
|
||||
*/
|
||||
|
||||
void panic(msg, save)
|
||||
char *msg;
|
||||
boolean save;
|
||||
{
|
||||
fprintf(stderr, "\nPANIC: %s%s\n",
|
||||
msg ? msg : "", save ? ". Save..." : msg ? "" : "aborting.");
|
||||
if (save)
|
||||
saveadv("advpanic.sav");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
2142
commands/advent/verb.c
Normal file
2142
commands/advent/verb.c
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user