Initial revision
This commit is contained in:
parent
5f7d5e8d18
commit
b2cfc4e2e7
242 changed files with 18177 additions and 0 deletions
258
src/lib9/LICENSE
Normal file
258
src/lib9/LICENSE
Normal file
|
|
@ -0,0 +1,258 @@
|
|||
The Plan 9 software is provided under the terms of the
|
||||
Lucent Public License, Version 1.02, reproduced below,
|
||||
with the following exceptions:
|
||||
|
||||
1. No right is granted to create derivative works of or
|
||||
to redistribute (other than with the Plan 9 Operating System)
|
||||
the screen imprinter fonts identified in subdirectory
|
||||
/lib/font/bit/lucida and printer fonts (Lucida Sans Unicode, Lucida
|
||||
Sans Italic, Lucida Sans Demibold, Lucida Typewriter, Lucida Sans
|
||||
Typewriter83), identified in subdirectory /sys/lib/postscript/font.
|
||||
These directories contain material copyrights by B&H Inc. and Y&Y Inc.
|
||||
|
||||
2. The printer fonts identified in subdirectory /sys/lib/ghostscript/font
|
||||
are subject to the GNU GPL, reproduced in the file /LICENSE.gpl.
|
||||
|
||||
3. The ghostscript program in the subdirectory /sys/src/cmd/gs is
|
||||
covered by the Aladdin Free Public License, reproduced in the file
|
||||
/LICENSE.afpl.
|
||||
|
||||
===================================================================
|
||||
|
||||
Lucent Public License Version 1.02
|
||||
|
||||
THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS PUBLIC
|
||||
LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE
|
||||
PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
|
||||
|
||||
1. DEFINITIONS
|
||||
|
||||
"Contribution" means:
|
||||
|
||||
a. in the case of Lucent Technologies Inc. ("LUCENT"), the Original
|
||||
Program, and
|
||||
b. in the case of each Contributor,
|
||||
|
||||
i. changes to the Program, and
|
||||
ii. additions to the Program;
|
||||
|
||||
where such changes and/or additions to the Program were added to the
|
||||
Program by such Contributor itself or anyone acting on such
|
||||
Contributor's behalf, and the Contributor explicitly consents, in
|
||||
accordance with Section 3C, to characterization of the changes and/or
|
||||
additions as Contributions.
|
||||
|
||||
"Contributor" means LUCENT and any other entity that has Contributed a
|
||||
Contribution to the Program.
|
||||
|
||||
"Distributor" means a Recipient that distributes the Program,
|
||||
modifications to the Program, or any part thereof.
|
||||
|
||||
"Licensed Patents" mean patent claims licensable by a Contributor
|
||||
which are necessarily infringed by the use or sale of its Contribution
|
||||
alone or when combined with the Program.
|
||||
|
||||
"Original Program" means the original version of the software
|
||||
accompanying this Agreement as released by LUCENT, including source
|
||||
code, object code and documentation, if any.
|
||||
|
||||
"Program" means the Original Program and Contributions or any part
|
||||
thereof
|
||||
|
||||
"Recipient" means anyone who receives the Program under this
|
||||
Agreement, including all Contributors.
|
||||
|
||||
2. GRANT OF RIGHTS
|
||||
|
||||
a. Subject to the terms of this Agreement, each Contributor hereby
|
||||
grants Recipient a non-exclusive, worldwide, royalty-free copyright
|
||||
license to reproduce, prepare derivative works of, publicly display,
|
||||
publicly perform, distribute and sublicense the Contribution of such
|
||||
Contributor, if any, and such derivative works, in source code and
|
||||
object code form.
|
||||
|
||||
b. Subject to the terms of this Agreement, each Contributor hereby
|
||||
grants Recipient a non-exclusive, worldwide, royalty-free patent
|
||||
license under Licensed Patents to make, use, sell, offer to sell,
|
||||
import and otherwise transfer the Contribution of such Contributor, if
|
||||
any, in source code and object code form. The patent license granted
|
||||
by a Contributor shall also apply to the combination of the
|
||||
Contribution of that Contributor and the Program if, at the time the
|
||||
Contribution is added by the Contributor, such addition of the
|
||||
Contribution causes such combination to be covered by the Licensed
|
||||
Patents. The patent license granted by a Contributor shall not apply
|
||||
to (i) any other combinations which include the Contribution, nor to
|
||||
(ii) Contributions of other Contributors. No hardware per se is
|
||||
licensed hereunder.
|
||||
|
||||
c. Recipient understands that although each Contributor grants the
|
||||
licenses to its Contributions set forth herein, no assurances are
|
||||
provided by any Contributor that the Program does not infringe the
|
||||
patent or other intellectual property rights of any other entity. Each
|
||||
Contributor disclaims any liability to Recipient for claims brought by
|
||||
any other entity based on infringement of intellectual property rights
|
||||
or otherwise. As a condition to exercising the rights and licenses
|
||||
granted hereunder, each Recipient hereby assumes sole responsibility
|
||||
to secure any other intellectual property rights needed, if any. For
|
||||
example, if a third party patent license is required to allow
|
||||
Recipient to distribute the Program, it is Recipient's responsibility
|
||||
to acquire that license before distributing the Program.
|
||||
|
||||
d. Each Contributor represents that to its knowledge it has sufficient
|
||||
copyright rights in its Contribution, if any, to grant the copyright
|
||||
license set forth in this Agreement.
|
||||
|
||||
3. REQUIREMENTS
|
||||
|
||||
A. Distributor may choose to distribute the Program in any form under
|
||||
this Agreement or under its own license agreement, provided that:
|
||||
|
||||
a. it complies with the terms and conditions of this Agreement;
|
||||
|
||||
b. if the Program is distributed in source code or other tangible
|
||||
form, a copy of this Agreement or Distributor's own license agreement
|
||||
is included with each copy of the Program; and
|
||||
|
||||
c. if distributed under Distributor's own license agreement, such
|
||||
license agreement:
|
||||
|
||||
i. effectively disclaims on behalf of all Contributors all warranties
|
||||
and conditions, express and implied, including warranties or
|
||||
conditions of title and non-infringement, and implied warranties or
|
||||
conditions of merchantability and fitness for a particular purpose;
|
||||
ii. effectively excludes on behalf of all Contributors all liability
|
||||
for damages, including direct, indirect, special, incidental and
|
||||
consequential damages, such as lost profits; and
|
||||
iii. states that any provisions which differ from this Agreement are
|
||||
offered by that Contributor alone and not by any other party.
|
||||
|
||||
B. Each Distributor must include the following in a conspicuous
|
||||
location in the Program:
|
||||
|
||||
Copyright (C) 2003, Lucent Technologies Inc. and others. All Rights
|
||||
Reserved.
|
||||
|
||||
C. In addition, each Contributor must identify itself as the
|
||||
originator of its Contribution in a manner that reasonably allows
|
||||
subsequent Recipients to identify the originator of the Contribution.
|
||||
Also, each Contributor must agree that the additions and/or changes
|
||||
are intended to be a Contribution. Once a Contribution is contributed,
|
||||
it may not thereafter be revoked.
|
||||
|
||||
4. COMMERCIAL DISTRIBUTION
|
||||
|
||||
Commercial distributors of software may accept certain
|
||||
responsibilities with respect to end users, business partners and the
|
||||
like. While this license is intended to facilitate the commercial use
|
||||
of the Program, the Distributor who includes the Program in a
|
||||
commercial product offering should do so in a manner which does not
|
||||
create potential liability for Contributors. Therefore, if a
|
||||
Distributor includes the Program in a commercial product offering,
|
||||
such Distributor ("Commercial Distributor") hereby agrees to defend
|
||||
and indemnify every Contributor ("Indemnified Contributor") against
|
||||
any losses, damages and costs (collectively"Losses") arising from
|
||||
claims, lawsuits and other legal actions brought by a third party
|
||||
against the Indemnified Contributor to the extent caused by the acts
|
||||
or omissions of such Commercial Distributor in connection with its
|
||||
distribution of the Program in a commercial product offering. The
|
||||
obligations in this section do not apply to any claims or Losses
|
||||
relating to any actual or alleged intellectual property infringement.
|
||||
In order to qualify, an Indemnified Contributor must: a) promptly
|
||||
notify the Commercial Distributor in writing of such claim, and b)
|
||||
allow the Commercial Distributor to control, and cooperate with the
|
||||
Commercial Distributor in, the defense and any related settlement
|
||||
negotiations. The Indemnified Contributor may participate in any such
|
||||
claim at its own expense.
|
||||
|
||||
For example, a Distributor might include the Program in a commercial
|
||||
product offering, Product X. That Distributor is then a Commercial
|
||||
Distributor. If that Commercial Distributor then makes performance
|
||||
claims, or offers warranties related to Product X, those performance
|
||||
claims and warranties are such Commercial Distributor's responsibility
|
||||
alone. Under this section, the Commercial Distributor would have to
|
||||
defend claims against the Contributors related to those performance
|
||||
claims and warranties, and if a court requires any Contributor to pay
|
||||
any damages as a result, the Commercial Distributor must pay those
|
||||
damages.
|
||||
|
||||
5. NO WARRANTY
|
||||
|
||||
EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS
|
||||
PROVIDED ON AN"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
|
||||
WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY
|
||||
OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely
|
||||
responsible for determining the appropriateness of using and
|
||||
distributing the Program and assumes all risks associated with its
|
||||
exercise of rights under this Agreement, including but not limited to
|
||||
the risks and costs of program errors, compliance with applicable
|
||||
laws, damage to or loss of data, programs or equipment, and
|
||||
unavailability or interruption of operations.
|
||||
|
||||
6. DISCLAIMER OF LIABILITY
|
||||
|
||||
EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR
|
||||
ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING
|
||||
WITHOUT LIMITATION LOST PROFITS), 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 OR
|
||||
DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
|
||||
HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
7. EXPORT CONTROL
|
||||
|
||||
Recipient agrees that Recipient alone is responsible for compliance
|
||||
with the United States export administration regulations (and the
|
||||
export control laws and regulation of any other countries).
|
||||
|
||||
8. GENERAL
|
||||
|
||||
If any provision of this Agreement is invalid or unenforceable under
|
||||
applicable law, it shall not affect the validity or enforceability of
|
||||
the remainder of the terms of this Agreement, and without further
|
||||
action by the parties hereto, such provision shall be reformed to the
|
||||
minimum extent necessary to make such provision valid and enforceable.
|
||||
|
||||
If Recipient institutes patent litigation against a Contributor with
|
||||
respect to a patent applicable to software (including a cross-claim or
|
||||
counterclaim in a lawsuit), then any patent licenses granted by that
|
||||
Contributor to such Recipient under this Agreement shall terminate as
|
||||
of the date such litigation is filed. In addition, if Recipient
|
||||
institutes patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Program
|
||||
itself (excluding combinations of the Program with other software or
|
||||
hardware) infringes such Recipient's patent(s), then such Recipient's
|
||||
rights granted under Section 2(b) shall terminate as of the date such
|
||||
litigation is filed.
|
||||
|
||||
All Recipient's rights under this Agreement shall terminate if it
|
||||
fails to comply with any of the material terms or conditions of this
|
||||
Agreement and does not cure such failure in a reasonable period of
|
||||
time after becoming aware of such noncompliance. If all Recipient's
|
||||
rights under this Agreement terminate, Recipient agrees to cease use
|
||||
and distribution of the Program as soon as reasonably practicable.
|
||||
However, Recipient's obligations under this Agreement and any licenses
|
||||
granted by Recipient relating to the Program shall continue and
|
||||
survive.
|
||||
|
||||
LUCENT may publish new versions (including revisions) of this
|
||||
Agreement from time to time. Each new version of the Agreement will be
|
||||
given a distinguishing version number. The Program (including
|
||||
Contributions) may always be distributed subject to the version of the
|
||||
Agreement under which it was received. In addition, after a new
|
||||
version of the Agreement is published, Contributor may elect to
|
||||
distribute the Program (including its Contributions) under the new
|
||||
version. No one other than LUCENT has the right to modify this
|
||||
Agreement. Except as expressly stated in Sections 2(a) and 2(b) above,
|
||||
Recipient receives no rights or licenses to the intellectual property
|
||||
of any Contributor under this Agreement, whether expressly, by
|
||||
implication, estoppel or otherwise. All rights in the Program not
|
||||
expressly granted under this Agreement are reserved.
|
||||
|
||||
This Agreement is governed by the laws of the State of New York and
|
||||
the intellectual property laws of the United States of America. No
|
||||
party to this Agreement will bring a legal action under this Agreement
|
||||
more than one year after the cause of action arose. Each party waives
|
||||
its rights to a jury trial in any resulting litigation.
|
||||
|
||||
6
src/lib9/Make.Darwin-PowerMacintosh
Normal file
6
src/lib9/Make.Darwin-PowerMacintosh
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
CC=gcc
|
||||
CFLAGS+=-Wall -Wno-missing-braces -Wno-parentheses -Wno-switch -O2 -g -c -I. -I${PREFIX}/include
|
||||
O=o
|
||||
AR=ar
|
||||
ARFLAGS=rvc
|
||||
NAN=nan64.$O
|
||||
7
src/lib9/Make.FreeBSD-386
Normal file
7
src/lib9/Make.FreeBSD-386
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
CC=gcc
|
||||
CFLAGS+=-Wall -Wno-missing-braces -Wno-parentheses -Wno-switch -O2 -g -c -I. -I$(PREFIX)/include
|
||||
O=o
|
||||
AR=ar
|
||||
ARFLAGS=rvc
|
||||
NAN=nan64.$O # default, can be overriden by Make.$(SYSNAME)
|
||||
NAN=nan64.$O
|
||||
6
src/lib9/Make.HP-UX-9000
Normal file
6
src/lib9/Make.HP-UX-9000
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
CC=cc
|
||||
CFLAGS=-O -c -Ae -I.
|
||||
O=o
|
||||
AR=ar
|
||||
ARFLAGS=rvc
|
||||
NAN=nan64.$O
|
||||
7
src/lib9/Make.Linux-386
Normal file
7
src/lib9/Make.Linux-386
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
CC=gcc
|
||||
CFLAGS+=-Wall -Wno-missing-braces -Wno-parentheses -Wno-switch -O2 -g -c -I.
|
||||
O=o
|
||||
AR=ar
|
||||
ARFLAGS=rvc
|
||||
NAN=nan64.$O # default, can be overriden by Make.$(SYSNAME)
|
||||
NAN=nan64.$O
|
||||
7
src/lib9/Make.NetBSD-386
Normal file
7
src/lib9/Make.NetBSD-386
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
CC=gcc
|
||||
CFLAGS+=-Wall -Wno-missing-braces -Wno-parentheses -Wno-switch -O2 -g -c -I. -I$(PREFIX)/include
|
||||
O=o
|
||||
AR=ar
|
||||
ARFLAGS=rvc
|
||||
NAN=nan64.$O # default, can be overriden by Make.$(SYSNAME)
|
||||
NAN=nan64.$O
|
||||
6
src/lib9/Make.OSF1-alpha
Normal file
6
src/lib9/Make.OSF1-alpha
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
CC=cc
|
||||
CFLAGS+=-g -c -I.
|
||||
O=o
|
||||
AR=ar
|
||||
ARFLAGS=rvc
|
||||
NAN=nan64.$O
|
||||
2
src/lib9/Make.SunOS-sun4u
Normal file
2
src/lib9/Make.SunOS-sun4u
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
include Make.SunOS-sun4u-$(CC)
|
||||
NAN=nan64.$O
|
||||
6
src/lib9/Make.SunOS-sun4u-cc
Normal file
6
src/lib9/Make.SunOS-sun4u-cc
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
CC=cc
|
||||
CFLAGS+=-g -c -I. -O
|
||||
O=o
|
||||
AR=ar
|
||||
ARFLAGS=rvc
|
||||
NAN=nan64.$O
|
||||
6
src/lib9/Make.SunOS-sun4u-gcc
Normal file
6
src/lib9/Make.SunOS-sun4u-gcc
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
CC=gcc
|
||||
CFLAGS+=-Wall -Wno-missing-braces -Wno-parentheses -Wno-switch -O2 -g -c
|
||||
O=o
|
||||
AR=ar
|
||||
ARFLAGS=rvc
|
||||
NAN=nan64.$O
|
||||
120
src/lib9/Makefile
Normal file
120
src/lib9/Makefile
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
|
||||
# this works in gnu make
|
||||
SYSNAME:=${shell uname}
|
||||
OBJTYPE:=${shell uname -m | sed 's;i.86;386;; s;/.*;;; s; ;;g'}
|
||||
|
||||
# this works in bsd make
|
||||
SYSNAME!=uname
|
||||
OBJTYPE!=uname -m | sed 's;i.86;386;; s;/.*;;; s; ;;g'
|
||||
|
||||
# the gnu rules will mess up bsd but not vice versa,
|
||||
# hence the gnu rules come first.
|
||||
|
||||
include Make.$(SYSNAME)-$(OBJTYPE)
|
||||
|
||||
PREFIX=/usr/local
|
||||
|
||||
NUKEFILES=
|
||||
|
||||
TGZFILES=
|
||||
|
||||
LIB=lib9.a
|
||||
VERSION=2.0
|
||||
PORTPLACE=devel/lib9
|
||||
NAME=lib9
|
||||
|
||||
OFILES=\
|
||||
_exits.$O\
|
||||
argv0.$O\
|
||||
await.$O\
|
||||
encodefmt.$O\
|
||||
errstr.$O\
|
||||
exits.$O\
|
||||
ffork-$(SYSNAME).$O\
|
||||
getcallerpc-$(OBJTYPE).$O\
|
||||
getfields.$O\
|
||||
lock.$O\
|
||||
malloctag.$O\
|
||||
mallocz.$O\
|
||||
nrand.$O\
|
||||
qlock.$O\
|
||||
readn.$O\
|
||||
rendez.$O\
|
||||
strecpy.$O\
|
||||
sysfatal.$O\
|
||||
tas-$(OBJTYPE).$O\
|
||||
tokenize.$O\
|
||||
u16.$O\
|
||||
u32.$O\
|
||||
u64.$O\
|
||||
wait.$O\
|
||||
werrstr.$O\
|
||||
|
||||
HFILES=\
|
||||
lib9.h\
|
||||
|
||||
all: $(LIB)
|
||||
|
||||
install: $(LIB)
|
||||
test -d $(PREFIX)/man/man3 || mkdir $(PREFIX)/man/man3
|
||||
# install -m 0644 lib9.3 $(PREFIX)/man/man3/lib9.3
|
||||
install -m 0644 lib9.h $(PREFIX)/include/lib9.h
|
||||
install -m 0644 $(LIB) $(PREFIX)/lib/$(LIB)
|
||||
|
||||
test: $(LIB) test.$O
|
||||
$(CC) -o test test.$O $(LIB) -L$(PREFIX)/lib -lfmt -lutf
|
||||
|
||||
testfork: $(LIB) testfork.$O
|
||||
$(CC) -o testfork testfork.$O $(LIB) -L$(PREFIX)/lib -lfmt -lutf
|
||||
|
||||
$(LIB): $(OFILES)
|
||||
$(AR) $(ARFLAGS) $(LIB) $(OFILES)
|
||||
|
||||
NUKEFILES+=$(LIB)
|
||||
.c.$O:
|
||||
$(CC) $(CFLAGS) -I$(PREFIX)/include $*.c
|
||||
|
||||
%.$O: %.c
|
||||
$(CC) $(CFLAGS) -I$(PREFIX)/include $*.c
|
||||
|
||||
|
||||
$(OFILES): $(HFILES)
|
||||
|
||||
tgz:
|
||||
rm -rf $(NAME)-$(VERSION)
|
||||
mkdir $(NAME)-$(VERSION)
|
||||
cp Makefile Make.* README LICENSE NOTICE *.[ch137] rpm.spec bundle.ports $(TGZFILES) $(NAME)-$(VERSION)
|
||||
tar cf - $(NAME)-$(VERSION) | gzip >$(NAME)-$(VERSION).tgz
|
||||
rm -rf $(NAME)-$(VERSION)
|
||||
|
||||
clean:
|
||||
rm -f $(OFILES) $(LIB)
|
||||
|
||||
nuke:
|
||||
rm -f $(OFILES) *.tgz *.rpm $(NUKEFILES)
|
||||
|
||||
rpm:
|
||||
make tgz
|
||||
cp $(NAME)-$(VERSION).tgz /usr/src/RPM/SOURCES
|
||||
rpm -ba rpm.spec
|
||||
cp /usr/src/RPM/SRPMS/$(NAME)-$(VERSION)-1.src.rpm .
|
||||
cp /usr/src/RPM/RPMS/i586/$(NAME)-$(VERSION)-1.i586.rpm .
|
||||
scp *.rpm rsc@amsterdam.lcs.mit.edu:public_html/software
|
||||
|
||||
PORTDIR=/usr/ports/$(PORTPLACE)
|
||||
|
||||
ports:
|
||||
make tgz
|
||||
rm -rf $(PORTDIR)
|
||||
mkdir $(PORTDIR)
|
||||
cp $(NAME)-$(VERSION).tgz /usr/ports/distfiles
|
||||
cat bundle.ports | (cd $(PORTDIR) && awk '$$1=="---" && $$3=="---" { ofile=$$2; next} {if(ofile) print >ofile}')
|
||||
(cd $(PORTDIR); make makesum)
|
||||
(cd $(PORTDIR); make)
|
||||
(cd $(PORTDIR); /usr/local/bin/portlint)
|
||||
rm -rf $(PORTDIR)/work
|
||||
shar `find $(PORTDIR)` > ports.shar
|
||||
(cd $(PORTDIR); tar cf - *) | gzip >$(NAME)-$(VERSION)-ports.tgz
|
||||
scp *.tgz rsc@amsterdam.lcs.mit.edu:public_html/software
|
||||
|
||||
.phony: all clean nuke install tgz rpm ports
|
||||
49
src/lib9/Makefile.MID
Normal file
49
src/lib9/Makefile.MID
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
LIB=lib9.a
|
||||
VERSION=2.0
|
||||
PORTPLACE=devel/lib9
|
||||
NAME=lib9
|
||||
|
||||
OFILES=\
|
||||
_exits.$O\
|
||||
argv0.$O\
|
||||
await.$O\
|
||||
encodefmt.$O\
|
||||
errstr.$O\
|
||||
exits.$O\
|
||||
ffork-$(SYSNAME).$O\
|
||||
getcallerpc-$(OBJTYPE).$O\
|
||||
getfields.$O\
|
||||
lock.$O\
|
||||
malloctag.$O\
|
||||
mallocz.$O\
|
||||
nrand.$O\
|
||||
qlock.$O\
|
||||
readn.$O\
|
||||
rendez.$O\
|
||||
strecpy.$O\
|
||||
sysfatal.$O\
|
||||
tas-$(OBJTYPE).$O\
|
||||
tokenize.$O\
|
||||
u16.$O\
|
||||
u32.$O\
|
||||
u64.$O\
|
||||
wait.$O\
|
||||
werrstr.$O\
|
||||
|
||||
HFILES=\
|
||||
lib9.h\
|
||||
|
||||
all: $(LIB)
|
||||
|
||||
install: $(LIB)
|
||||
test -d $(PREFIX)/man/man3 || mkdir $(PREFIX)/man/man3
|
||||
# install -m 0644 lib9.3 $(PREFIX)/man/man3/lib9.3
|
||||
install -m 0644 lib9.h $(PREFIX)/include/lib9.h
|
||||
install -m 0644 $(LIB) $(PREFIX)/lib/$(LIB)
|
||||
|
||||
test: $(LIB) test.$O
|
||||
$(CC) -o test test.$O $(LIB) -L$(PREFIX)/lib -lfmt -lutf
|
||||
|
||||
testfork: $(LIB) testfork.$O
|
||||
$(CC) -o testfork testfork.$O $(LIB) -L$(PREFIX)/lib -lfmt -lutf
|
||||
|
||||
9
src/lib9/_exits.c
Normal file
9
src/lib9/_exits.c
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
#include <lib9.h>
|
||||
|
||||
void
|
||||
_exits(char *s)
|
||||
{
|
||||
if(s && *s)
|
||||
_exit(1);
|
||||
_exit(0);
|
||||
}
|
||||
4
src/lib9/argv0.c
Normal file
4
src/lib9/argv0.c
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
#include <lib9.h>
|
||||
|
||||
char *argv0;
|
||||
|
||||
105
src/lib9/await.c
Normal file
105
src/lib9/await.c
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
#include <signal.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/time.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <lib9.h>
|
||||
|
||||
static struct {
|
||||
int sig;
|
||||
char *str;
|
||||
} tab[] = {
|
||||
SIGHUP, "hangup",
|
||||
SIGINT, "interrupt",
|
||||
SIGQUIT, "quit",
|
||||
SIGILL, "sys: trap: illegal instruction",
|
||||
SIGTRAP, "sys: trace trap",
|
||||
SIGABRT, "sys: abort",
|
||||
#ifdef SIGEMT
|
||||
SIGEMT, "sys: emulate instruction executed",
|
||||
#endif
|
||||
SIGFPE, "sys: fp: trap",
|
||||
SIGKILL, "sys: kill",
|
||||
SIGBUS, "sys: bus error",
|
||||
SIGSEGV, "sys: segmentation violation",
|
||||
SIGALRM, "alarm",
|
||||
SIGTERM, "kill",
|
||||
SIGURG, "sys: urgent condition on socket",
|
||||
SIGSTOP, "sys: stop",
|
||||
SIGTSTP, "sys: tstp",
|
||||
SIGCONT, "sys: cont",
|
||||
SIGCHLD, "sys: child",
|
||||
SIGTTIN, "sys: ttin",
|
||||
SIGTTOU, "sys: ttou",
|
||||
SIGIO, "sys: i/o possible on fd",
|
||||
SIGXCPU, "sys: cpu time limit exceeded",
|
||||
SIGXFSZ, "sys: file size limit exceeded",
|
||||
SIGVTALRM, "sys: virtual time alarm",
|
||||
SIGPROF, "sys: profiling timer alarm",
|
||||
SIGWINCH, "sys: window size change",
|
||||
#ifdef SIGINFO
|
||||
SIGINFO, "sys: status request",
|
||||
#endif
|
||||
SIGUSR1, "sys: usr1",
|
||||
SIGUSR2, "sys: usr2",
|
||||
};
|
||||
|
||||
static char*
|
||||
_p9sigstr(int sig, char *tmp)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0; i<nelem(tab); i++)
|
||||
if(tab[i].sig == sig)
|
||||
return tab[i].str;
|
||||
sprint(tmp, "sys: signal %d", sig);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
static int
|
||||
_p9strsig(char *s)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0; i<nelem(tab); i++)
|
||||
if(strcmp(s, tab[i].str) == 0)
|
||||
return tab[i].sig;
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
||||
int
|
||||
await(char *str, int n)
|
||||
{
|
||||
int pid, status, cd;
|
||||
struct rusage ru;
|
||||
char buf[128], tmp[64];
|
||||
ulong u, s;
|
||||
|
||||
for(;;){
|
||||
pid = wait3(&status, 0, &ru);
|
||||
if(pid < 0)
|
||||
return -1;
|
||||
u = ru.ru_utime.tv_sec*1000+((ru.ru_utime.tv_usec+500)/1000);
|
||||
s = ru.ru_stime.tv_sec*1000+((ru.ru_stime.tv_usec+500)/1000);
|
||||
if(WIFEXITED(status)){
|
||||
status = WEXITSTATUS(status);
|
||||
if(status)
|
||||
snprint(buf, sizeof buf, "%d %lu %lu %lu %d", pid, u, s, u+s, status);
|
||||
else
|
||||
snprint(buf, sizeof buf, "%d %lu %lu %lu ''", pid, u, s, u+s);
|
||||
strecpy(str, str+n, buf);
|
||||
return strlen(str);
|
||||
}
|
||||
if(WIFSIGNALED(status)){
|
||||
cd = WCOREDUMP(status);
|
||||
USED(cd);
|
||||
snprint(buf, sizeof buf, "%d %lu %lu %lu '%s'", pid, u, s, u+s, _p9sigstr(WTERMSIG(status), tmp));
|
||||
strecpy(str, str+n, buf);
|
||||
return strlen(str);
|
||||
}
|
||||
}
|
||||
}
|
||||
69
src/lib9/encodefmt.c
Normal file
69
src/lib9/encodefmt.c
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
#include <lib9.h>
|
||||
|
||||
int
|
||||
encodefmt(Fmt *f)
|
||||
{
|
||||
char *out;
|
||||
char *buf;
|
||||
int len;
|
||||
int ilen;
|
||||
int rv;
|
||||
uchar *b;
|
||||
char obuf[64]; // rsc optimization
|
||||
|
||||
if(!(f->flags&FmtPrec) || f->prec < 1)
|
||||
goto error;
|
||||
|
||||
b = va_arg(f->args, uchar*);
|
||||
|
||||
ilen = f->prec;
|
||||
f->prec = 0;
|
||||
f->flags &= ~FmtPrec;
|
||||
switch(f->r){
|
||||
case '<':
|
||||
len = (8*ilen+4)/5 + 3;
|
||||
break;
|
||||
case '[':
|
||||
len = (8*ilen+5)/6 + 4;
|
||||
break;
|
||||
case 'H':
|
||||
len = 2*ilen + 1;
|
||||
break;
|
||||
default:
|
||||
goto error;
|
||||
}
|
||||
|
||||
if(len > sizeof(obuf)){
|
||||
buf = malloc(len);
|
||||
if(buf == nil)
|
||||
goto error;
|
||||
} else
|
||||
buf = obuf;
|
||||
|
||||
// convert
|
||||
out = buf;
|
||||
switch(f->r){
|
||||
case '<':
|
||||
rv = enc32(out, len, b, ilen);
|
||||
break;
|
||||
case '[':
|
||||
rv = enc64(out, len, b, ilen);
|
||||
break;
|
||||
case 'H':
|
||||
rv = enc16(out, len, b, ilen);
|
||||
break;
|
||||
default:
|
||||
rv = -1;
|
||||
break;
|
||||
}
|
||||
if(rv < 0)
|
||||
goto error;
|
||||
|
||||
fmtstrcpy(f, buf);
|
||||
if(buf != obuf)
|
||||
free(buf);
|
||||
return 0;
|
||||
|
||||
error:
|
||||
return fmtstrcpy(f, "<encodefmt>");
|
||||
}
|
||||
68
src/lib9/errstr.c
Normal file
68
src/lib9/errstr.c
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* We assume there's only one error buffer for the whole system.
|
||||
* If you use ffork, you need to provide a _syserrstr. Since most
|
||||
* people will use libthread (which provides a _syserrstr), this is
|
||||
* okay.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <lib9.h>
|
||||
|
||||
enum
|
||||
{
|
||||
EPLAN9 = 0x19283745,
|
||||
};
|
||||
|
||||
char *(*_syserrstr)(void);
|
||||
static char xsyserr[ERRMAX];
|
||||
static char*
|
||||
getsyserr(void)
|
||||
{
|
||||
char *s;
|
||||
|
||||
s = nil;
|
||||
if(_syserrstr)
|
||||
s = (*_syserrstr)();
|
||||
if(s == nil)
|
||||
s = xsyserr;
|
||||
return s;
|
||||
}
|
||||
|
||||
int
|
||||
errstr(char *err, uint n)
|
||||
{
|
||||
char tmp[ERRMAX];
|
||||
char *syserr;
|
||||
|
||||
syserr = getsyserr();
|
||||
if(errno != EPLAN9)
|
||||
strcpy(syserr, strerror(errno));
|
||||
|
||||
strecpy(tmp, tmp+ERRMAX, syserr);
|
||||
strecpy(syserr, syserr+ERRMAX, err);
|
||||
strecpy(err, err+n, tmp);
|
||||
errno = EPLAN9;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
rerrstr(char *err, uint n)
|
||||
{
|
||||
char *syserr;
|
||||
|
||||
syserr = getsyserr();
|
||||
if(errno != EPLAN9)
|
||||
strcpy(syserr, strerror(errno));
|
||||
strecpy(err, err+n, syserr);
|
||||
}
|
||||
|
||||
/* replaces __errfmt in libfmt */
|
||||
|
||||
int
|
||||
__errfmt(Fmt *f)
|
||||
{
|
||||
if(errno == EPLAN9)
|
||||
return fmtstrcpy(f, getsyserr());
|
||||
return fmtstrcpy(f, strerror(errno));
|
||||
}
|
||||
10
src/lib9/exits.c
Normal file
10
src/lib9/exits.c
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
#include <lib9.h>
|
||||
|
||||
void
|
||||
exits(char *s)
|
||||
{
|
||||
if(s && *s)
|
||||
exit(1);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
33
src/lib9/ffork-FreeBSD.c
Normal file
33
src/lib9/ffork-FreeBSD.c
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
#include <lib9.h>
|
||||
|
||||
extern int __isthreaded;
|
||||
int
|
||||
ffork(int flags, void(*fn)(void*), void *arg)
|
||||
{
|
||||
void *p;
|
||||
|
||||
__isthreaded = 1;
|
||||
p = malloc(16384);
|
||||
if(p == nil)
|
||||
return -1;
|
||||
memset(p, 0xFE, 16384);
|
||||
return rfork_thread(RFPROC|flags, (char*)p+16000, (int(*)(void*))fn, arg);
|
||||
}
|
||||
|
||||
/*
|
||||
* For FreeBSD libc.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
volatile long access_lock;
|
||||
volatile long lock_owner;
|
||||
volatile char *fname;
|
||||
volatile int lineno;
|
||||
} spinlock_t;
|
||||
|
||||
void
|
||||
_spinlock(spinlock_t *lk)
|
||||
{
|
||||
lock((Lock*)&lk->access_lock);
|
||||
}
|
||||
|
||||
39
src/lib9/ffork-Linux.c
Normal file
39
src/lib9/ffork-Linux.c
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
#include <sched.h>
|
||||
#include <signal.h>
|
||||
#include <lib9.h>
|
||||
|
||||
int fforkstacksize = 16384;
|
||||
|
||||
int
|
||||
ffork(int flags, void (*fn)(void*), void *arg)
|
||||
{
|
||||
char *p;
|
||||
int cloneflag, pid;
|
||||
|
||||
p = malloc(fforkstacksize);
|
||||
if(p == nil)
|
||||
return -1;
|
||||
cloneflag = 0;
|
||||
flags &= ~RFPROC;
|
||||
if(flags&RFMEM){
|
||||
cloneflag |= CLONE_VM;
|
||||
flags &= ~RFMEM;
|
||||
}
|
||||
if(!(flags&RFFDG))
|
||||
cloneflag |= CLONE_FILES;
|
||||
else
|
||||
flags &= ~RFFDG;
|
||||
if(!(flags&RFNOWAIT))
|
||||
cloneflag |= SIGCHLD;
|
||||
else
|
||||
flags &= ~RFNOWAIT;
|
||||
if(flags){
|
||||
fprint(2, "unknown rfork flags %x\n", flags);
|
||||
return -1;
|
||||
}
|
||||
pid = clone((int(*)(void*))fn, p+fforkstacksize-16, cloneflag, arg);
|
||||
if(pid < 0)
|
||||
free(p);
|
||||
return pid;
|
||||
}
|
||||
|
||||
7
src/lib9/getcallerpc-386.c
Normal file
7
src/lib9/getcallerpc-386.c
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
#include <lib9.h>
|
||||
|
||||
ulong
|
||||
getcallerpc(void *x)
|
||||
{
|
||||
return (((ulong*)(x))[-1]);
|
||||
}
|
||||
36
src/lib9/getfields.c
Normal file
36
src/lib9/getfields.c
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
#include <lib9.h>
|
||||
|
||||
int
|
||||
getfields(char *str, char **args, int max, int mflag, char *set)
|
||||
{
|
||||
Rune r;
|
||||
int nr, intok, narg;
|
||||
|
||||
if(max <= 0)
|
||||
return 0;
|
||||
|
||||
narg = 0;
|
||||
args[narg] = str;
|
||||
if(!mflag)
|
||||
narg++;
|
||||
intok = 0;
|
||||
for(;; str += nr) {
|
||||
nr = chartorune(&r, str);
|
||||
if(r == 0)
|
||||
break;
|
||||
if(utfrune(set, r)) {
|
||||
if(narg >= max)
|
||||
break;
|
||||
*str = 0;
|
||||
intok = 0;
|
||||
args[narg] = str + nr;
|
||||
if(!mflag)
|
||||
narg++;
|
||||
} else {
|
||||
if(!intok && mflag)
|
||||
narg++;
|
||||
intok = 1;
|
||||
}
|
||||
}
|
||||
return narg;
|
||||
}
|
||||
246
src/lib9/lib9.h
Normal file
246
src/lib9/lib9.h
Normal file
|
|
@ -0,0 +1,246 @@
|
|||
/*
|
||||
* Lib9 is miscellany from the Plan 9 C library that doesn't
|
||||
* fit into libutf or into libfmt, but is still missing from traditional
|
||||
* Unix C libraries.
|
||||
*/
|
||||
#ifndef _LIB9H_
|
||||
#define _LIB9H_ 1
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <fcntl.h>
|
||||
#include <assert.h>
|
||||
|
||||
#ifndef _FMTH_
|
||||
# include <fmt.h>
|
||||
#endif
|
||||
|
||||
#define nil ((void*)0)
|
||||
#define nelem(x) (sizeof(x)/sizeof((x)[0]))
|
||||
|
||||
#define _NEEDUCHAR 1
|
||||
#define _NEEDUSHORT 1
|
||||
#define _NEEDUINT 1
|
||||
#define _NEEDULONG 1
|
||||
|
||||
#if defined(__linux__)
|
||||
# include <sys/types.h>
|
||||
# if defined(__USE_MISC)
|
||||
# undef _NEEDUSHORT
|
||||
# undef _NEEDUINT
|
||||
# undef _NEEDULONG
|
||||
# endif
|
||||
#endif
|
||||
#if defined(__FreeBSD__)
|
||||
# include <sys/types.h>
|
||||
# if !defined(_POSIX_SOURCE)
|
||||
# undef _NEEDUSHORT
|
||||
# undef _NEEDUINT
|
||||
# endif
|
||||
#endif
|
||||
|
||||
typedef signed char schar;
|
||||
typedef unsigned int u32int;
|
||||
#ifdef _NEEDUCHAR
|
||||
typedef unsigned char uchar;
|
||||
#endif
|
||||
#ifdef _NEEDUSHORT
|
||||
typedef unsigned short ushort;
|
||||
#endif
|
||||
#ifdef _NEEDUINT
|
||||
typedef unsigned int uint;
|
||||
#endif
|
||||
#ifdef _NEEDULONG
|
||||
typedef unsigned long ulong;
|
||||
#endif
|
||||
typedef unsigned long long uvlong;
|
||||
typedef long long vlong;
|
||||
|
||||
/* rfork to create new process running fn(arg) */
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
#undef RFFDG
|
||||
#undef RFNOTEG
|
||||
#undef RFPROC
|
||||
#undef RFMEM
|
||||
#undef RFNOWAIT
|
||||
#undef RFCFDG
|
||||
#endif
|
||||
|
||||
enum
|
||||
{
|
||||
/* RFNAMEG = (1<<0), */
|
||||
/* RFENVG = (1<<1), */
|
||||
RFFDG = (1<<2),
|
||||
RFNOTEG = (1<<3),
|
||||
RFPROC = (1<<4),
|
||||
RFMEM = (1<<5),
|
||||
RFNOWAIT = (1<<6),
|
||||
/* RFCNAMEG = (1<<10), */
|
||||
/* RFCENVG = (1<<11), */
|
||||
RFCFDG = (1<<12),
|
||||
/* RFREND = (1<<13), */
|
||||
/* RFNOMNT = (1<<14) */
|
||||
};
|
||||
extern int ffork(int, void(*)(void*), void*);
|
||||
|
||||
/* wait for processes */
|
||||
#define wait _p9wait
|
||||
typedef struct Waitmsg Waitmsg;
|
||||
struct Waitmsg
|
||||
{
|
||||
int pid; /* of loved one */
|
||||
ulong time[3]; /* of loved one & descendants */
|
||||
char *msg;
|
||||
};
|
||||
extern int await(char*, int);
|
||||
extern Waitmsg* wait(void);
|
||||
|
||||
/* synchronization */
|
||||
typedef struct Lock Lock;
|
||||
struct Lock
|
||||
{
|
||||
int val;
|
||||
};
|
||||
|
||||
extern int _tas(void*);
|
||||
extern void lock(Lock*);
|
||||
extern void unlock(Lock*);
|
||||
extern int canlock(Lock*);
|
||||
|
||||
typedef struct QLp QLp;
|
||||
struct QLp
|
||||
{
|
||||
int inuse;
|
||||
QLp *next;
|
||||
int state;
|
||||
};
|
||||
|
||||
typedef struct QLock QLock;
|
||||
struct QLock
|
||||
{
|
||||
Lock lock;
|
||||
int locked;
|
||||
QLp *head;
|
||||
QLp *tail;
|
||||
};
|
||||
|
||||
extern void qlock(QLock*);
|
||||
extern void qunlock(QLock*);
|
||||
extern int canqlock(QLock*);
|
||||
extern void _qlockinit(ulong (*)(ulong, ulong));
|
||||
|
||||
typedef struct RWLock RWLock;
|
||||
struct RWLock
|
||||
{
|
||||
Lock lock;
|
||||
int readers;
|
||||
int writer;
|
||||
QLp *head;
|
||||
QLp *tail;
|
||||
};
|
||||
|
||||
extern void rlock(RWLock*);
|
||||
extern void runlock(RWLock*);
|
||||
extern int canrlock(RWLock*);
|
||||
extern void wlock(RWLock*);
|
||||
extern void wunlock(RWLock*);
|
||||
extern int canwlock(RWLock*);
|
||||
|
||||
typedef struct Rendez Rendez;
|
||||
struct Rendez
|
||||
{
|
||||
QLock *l;
|
||||
QLp *head;
|
||||
QLp *tail;
|
||||
};
|
||||
|
||||
extern void rsleep(Rendez*);
|
||||
extern int rwakeup(Rendez*);
|
||||
extern int rwakeupall(Rendez*);
|
||||
|
||||
extern ulong rendezvous(ulong, ulong);
|
||||
|
||||
/* one of a kind */
|
||||
extern void sysfatal(char*, ...);
|
||||
extern int nrand(int);
|
||||
extern void setmalloctag(void*, ulong);
|
||||
extern void setrealloctag(void*, ulong);
|
||||
extern void *mallocz(ulong, int);
|
||||
extern long readn(int, void*, long);
|
||||
extern void exits(char*);
|
||||
extern void _exits(char*);
|
||||
extern ulong getcallerpc(void*);
|
||||
|
||||
/* string routines */
|
||||
extern char* strecpy(char*, char*, char*);
|
||||
extern int tokenize(char*, char**, int);
|
||||
extern int cistrncmp(char*, char*, int);
|
||||
extern int cistrcmp(char*, char*);
|
||||
extern char* cistrstr(char*, char*);
|
||||
extern int getfields(char*, char**, int, int, char*);
|
||||
extern int gettokens(char *, char **, int, char *);
|
||||
|
||||
/* formatting helpers */
|
||||
extern int dec64(uchar*, int, char*, int);
|
||||
extern int enc64(char*, int, uchar*, int);
|
||||
extern int dec32(uchar*, int, char*, int);
|
||||
extern int enc32(char*, int, uchar*, int);
|
||||
extern int dec16(uchar*, int, char*, int);
|
||||
extern int enc16(char*, int, uchar*, int);
|
||||
extern int encodefmt(Fmt*);
|
||||
|
||||
/* error string */
|
||||
enum
|
||||
{
|
||||
ERRMAX = 128
|
||||
};
|
||||
extern void rerrstr(char*, uint);
|
||||
extern void werrstr(char*, ...);
|
||||
extern int errstr(char*, uint);
|
||||
|
||||
/* compiler directives on plan 9 */
|
||||
#define USED(x) if(x){}else{}
|
||||
#define SET(x) ((x)=0)
|
||||
|
||||
/* command line */
|
||||
extern char *argv0;
|
||||
#define ARGBEGIN for((argv0||(argv0=*argv)),argv++,argc--;\
|
||||
argv[0] && argv[0][0]=='-' && argv[0][1];\
|
||||
argc--, argv++) {\
|
||||
char *_args, *_argt;\
|
||||
Rune _argc;\
|
||||
_args = &argv[0][1];\
|
||||
if(_args[0]=='-' && _args[1]==0){\
|
||||
argc--; argv++; break;\
|
||||
}\
|
||||
_argc = 0;\
|
||||
while(*_args && (_args += chartorune(&_argc, _args)))\
|
||||
switch(_argc)
|
||||
#define ARGEND SET(_argt);USED(_argt);USED(_argc);USED(_args);}USED(argv);USED(argc);
|
||||
#define ARGF() (_argt=_args, _args="",\
|
||||
(*_argt? _argt: argv[1]? (argc--, *++argv): 0))
|
||||
#define EARGF(x) (_argt=_args, _args="",\
|
||||
(*_argt? _argt: argv[1]? (argc--, *++argv): ((x), abort(), (char*)0)))
|
||||
|
||||
#define ARGC() _argc
|
||||
|
||||
#define OREAD O_RDONLY
|
||||
#define OWRITE O_WRONLY
|
||||
#define AEXIST 0
|
||||
#define AREAD 4
|
||||
#define AWRITE 2
|
||||
#define AEXEC 1
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _LIB9H_ */
|
||||
54
src/lib9/lock.c
Normal file
54
src/lib9/lock.c
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
#include <unistd.h>
|
||||
#include <sched.h>
|
||||
#include <lib9.h>
|
||||
|
||||
int _ntas;
|
||||
static int
|
||||
_xtas(void *v)
|
||||
{
|
||||
int x;
|
||||
|
||||
_ntas++;
|
||||
x = _tas(v);
|
||||
if(x == 0 || x == 0xCAFEBABE)
|
||||
return x;
|
||||
fprint(2, "%d: tas %p got %ux\n", getpid(), v, x);
|
||||
abort();
|
||||
}
|
||||
|
||||
int
|
||||
canlock(Lock *l)
|
||||
{
|
||||
return !_xtas(&l->val);
|
||||
}
|
||||
|
||||
void
|
||||
unlock(Lock *l)
|
||||
{
|
||||
l->val = 0;
|
||||
}
|
||||
|
||||
void
|
||||
lock(Lock *lk)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* once fast */
|
||||
if(!_xtas(&lk->val))
|
||||
return;
|
||||
/* a thousand times pretty fast */
|
||||
for(i=0; i<1000; i++){
|
||||
if(!_xtas(&lk->val))
|
||||
return;
|
||||
sched_yield();
|
||||
}
|
||||
/* now nice and slow */
|
||||
for(i=0; i<1000; i++){
|
||||
if(!_xtas(&lk->val))
|
||||
return;
|
||||
usleep(100*1000);
|
||||
}
|
||||
/* take your time */
|
||||
while(_xtas(&lk->val))
|
||||
usleep(1000*1000);
|
||||
}
|
||||
15
src/lib9/malloctag.c
Normal file
15
src/lib9/malloctag.c
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
#include <lib9.h>
|
||||
|
||||
void
|
||||
setmalloctag(void *v, ulong t)
|
||||
{
|
||||
USED(v);
|
||||
USED(t);
|
||||
}
|
||||
|
||||
void
|
||||
setrealloctag(void *v, ulong t)
|
||||
{
|
||||
USED(v);
|
||||
USED(t);
|
||||
}
|
||||
14
src/lib9/mallocz.c
Normal file
14
src/lib9/mallocz.c
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <lib9.h>
|
||||
|
||||
void*
|
||||
mallocz(unsigned long n, int clr)
|
||||
{
|
||||
void *v;
|
||||
|
||||
v = malloc(n);
|
||||
if(clr && v)
|
||||
memset(v, 0, n);
|
||||
return v;
|
||||
}
|
||||
2
src/lib9/mkfile
Normal file
2
src/lib9/mkfile
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
<../libutf/mkfile
|
||||
|
||||
17
src/lib9/nrand.c
Normal file
17
src/lib9/nrand.c
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
#include <lib9.h>
|
||||
|
||||
#define MASK 0x7fffffffL
|
||||
|
||||
int
|
||||
nrand(int n)
|
||||
{
|
||||
long slop, v;
|
||||
|
||||
if(n < 0)
|
||||
return n;
|
||||
slop = MASK % n;
|
||||
do
|
||||
v = lrand();
|
||||
while(v <= slop);
|
||||
return v % n;
|
||||
}
|
||||
360
src/lib9/qlock.c
Normal file
360
src/lib9/qlock.c
Normal file
|
|
@ -0,0 +1,360 @@
|
|||
#include <lib9.h>
|
||||
|
||||
static struct {
|
||||
QLp *p;
|
||||
QLp x[1024];
|
||||
} ql = {
|
||||
ql.x
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
Queuing,
|
||||
QueuingR,
|
||||
QueuingW,
|
||||
Sleeping,
|
||||
};
|
||||
|
||||
static ulong (*_rendezvousp)(ulong, ulong) = rendezvous;
|
||||
|
||||
/* this gets called by the thread library ONLY to get us to use its rendezvous */
|
||||
void
|
||||
_qlockinit(ulong (*r)(ulong, ulong))
|
||||
{
|
||||
_rendezvousp = r;
|
||||
}
|
||||
|
||||
/* find a free shared memory location to queue ourselves in */
|
||||
static QLp*
|
||||
getqlp(void)
|
||||
{
|
||||
QLp *p, *op;
|
||||
|
||||
op = ql.p;
|
||||
for(p = op+1; ; p++){
|
||||
if(p == &ql.x[nelem(ql.x)])
|
||||
p = ql.x;
|
||||
if(p == op)
|
||||
abort();
|
||||
if(_tas(&(p->inuse)) == 0){
|
||||
ql.p = p;
|
||||
p->next = nil;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
void
|
||||
qlock(QLock *q)
|
||||
{
|
||||
QLp *p, *mp;
|
||||
|
||||
lock(&q->lock);
|
||||
if(!q->locked){
|
||||
q->locked = 1;
|
||||
unlock(&q->lock);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* chain into waiting list */
|
||||
mp = getqlp();
|
||||
p = q->tail;
|
||||
if(p == nil)
|
||||
q->head = mp;
|
||||
else
|
||||
p->next = mp;
|
||||
q->tail = mp;
|
||||
mp->state = Queuing;
|
||||
unlock(&q->lock);
|
||||
|
||||
/* wait */
|
||||
while((*_rendezvousp)((ulong)mp, 1) == ~0)
|
||||
;
|
||||
mp->inuse = 0;
|
||||
}
|
||||
|
||||
void
|
||||
qunlock(QLock *q)
|
||||
{
|
||||
QLp *p;
|
||||
|
||||
lock(&q->lock);
|
||||
p = q->head;
|
||||
if(p != nil){
|
||||
/* wakeup head waiting process */
|
||||
q->head = p->next;
|
||||
if(q->head == nil)
|
||||
q->tail = nil;
|
||||
unlock(&q->lock);
|
||||
while((*_rendezvousp)((ulong)p, 0x12345) == ~0)
|
||||
;
|
||||
return;
|
||||
}
|
||||
q->locked = 0;
|
||||
unlock(&q->lock);
|
||||
}
|
||||
|
||||
int
|
||||
canqlock(QLock *q)
|
||||
{
|
||||
if(!canlock(&q->lock))
|
||||
return 0;
|
||||
if(!q->locked){
|
||||
q->locked = 1;
|
||||
unlock(&q->lock);
|
||||
return 1;
|
||||
}
|
||||
unlock(&q->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
rlock(RWLock *q)
|
||||
{
|
||||
QLp *p, *mp;
|
||||
|
||||
lock(&q->lock);
|
||||
if(q->writer == 0 && q->head == nil){
|
||||
/* no writer, go for it */
|
||||
q->readers++;
|
||||
unlock(&q->lock);
|
||||
return;
|
||||
}
|
||||
|
||||
mp = getqlp();
|
||||
p = q->tail;
|
||||
if(p == 0)
|
||||
q->head = mp;
|
||||
else
|
||||
p->next = mp;
|
||||
q->tail = mp;
|
||||
mp->next = nil;
|
||||
mp->state = QueuingR;
|
||||
unlock(&q->lock);
|
||||
|
||||
/* wait in kernel */
|
||||
while((*_rendezvousp)((ulong)mp, 1) == ~0)
|
||||
;
|
||||
mp->inuse = 0;
|
||||
}
|
||||
|
||||
int
|
||||
canrlock(RWLock *q)
|
||||
{
|
||||
lock(&q->lock);
|
||||
if (q->writer == 0 && q->head == nil) {
|
||||
/* no writer; go for it */
|
||||
q->readers++;
|
||||
unlock(&q->lock);
|
||||
return 1;
|
||||
}
|
||||
unlock(&q->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
runlock(RWLock *q)
|
||||
{
|
||||
QLp *p;
|
||||
|
||||
lock(&q->lock);
|
||||
if(q->readers <= 0)
|
||||
abort();
|
||||
p = q->head;
|
||||
if(--(q->readers) > 0 || p == nil){
|
||||
unlock(&q->lock);
|
||||
return;
|
||||
}
|
||||
|
||||
/* start waiting writer */
|
||||
if(p->state != QueuingW)
|
||||
abort();
|
||||
q->head = p->next;
|
||||
if(q->head == 0)
|
||||
q->tail = 0;
|
||||
q->writer = 1;
|
||||
unlock(&q->lock);
|
||||
|
||||
/* wakeup waiter */
|
||||
while((*_rendezvousp)((ulong)p, 0) == ~0)
|
||||
;
|
||||
}
|
||||
|
||||
void
|
||||
wlock(RWLock *q)
|
||||
{
|
||||
QLp *p, *mp;
|
||||
|
||||
lock(&q->lock);
|
||||
if(q->readers == 0 && q->writer == 0){
|
||||
/* noone waiting, go for it */
|
||||
q->writer = 1;
|
||||
unlock(&q->lock);
|
||||
return;
|
||||
}
|
||||
|
||||
/* wait */
|
||||
p = q->tail;
|
||||
mp = getqlp();
|
||||
if(p == nil)
|
||||
q->head = mp;
|
||||
else
|
||||
p->next = mp;
|
||||
q->tail = mp;
|
||||
mp->next = nil;
|
||||
mp->state = QueuingW;
|
||||
unlock(&q->lock);
|
||||
|
||||
/* wait in kernel */
|
||||
while((*_rendezvousp)((ulong)mp, 1) == ~0)
|
||||
;
|
||||
mp->inuse = 0;
|
||||
}
|
||||
|
||||
int
|
||||
canwlock(RWLock *q)
|
||||
{
|
||||
lock(&q->lock);
|
||||
if (q->readers == 0 && q->writer == 0) {
|
||||
/* no one waiting; go for it */
|
||||
q->writer = 1;
|
||||
unlock(&q->lock);
|
||||
return 1;
|
||||
}
|
||||
unlock(&q->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
wunlock(RWLock *q)
|
||||
{
|
||||
QLp *p;
|
||||
|
||||
lock(&q->lock);
|
||||
if(q->writer == 0)
|
||||
abort();
|
||||
p = q->head;
|
||||
if(p == nil){
|
||||
q->writer = 0;
|
||||
unlock(&q->lock);
|
||||
return;
|
||||
}
|
||||
if(p->state == QueuingW){
|
||||
/* start waiting writer */
|
||||
q->head = p->next;
|
||||
if(q->head == nil)
|
||||
q->tail = nil;
|
||||
unlock(&q->lock);
|
||||
while((*_rendezvousp)((ulong)p, 0) == ~0)
|
||||
;
|
||||
return;
|
||||
}
|
||||
|
||||
if(p->state != QueuingR)
|
||||
abort();
|
||||
|
||||
/* wake waiting readers */
|
||||
while(q->head != nil && q->head->state == QueuingR){
|
||||
p = q->head;
|
||||
q->head = p->next;
|
||||
q->readers++;
|
||||
while((*_rendezvousp)((ulong)p, 0) == ~0)
|
||||
;
|
||||
}
|
||||
if(q->head == nil)
|
||||
q->tail = nil;
|
||||
q->writer = 0;
|
||||
unlock(&q->lock);
|
||||
}
|
||||
|
||||
void
|
||||
rsleep(Rendez *r)
|
||||
{
|
||||
QLp *t, *me;
|
||||
|
||||
if(!r->l)
|
||||
abort();
|
||||
lock(&r->l->lock);
|
||||
/* we should hold the qlock */
|
||||
if(!r->l->locked)
|
||||
abort();
|
||||
|
||||
/* add ourselves to the wait list */
|
||||
me = getqlp();
|
||||
me->state = Sleeping;
|
||||
if(r->head == nil)
|
||||
r->head = me;
|
||||
else
|
||||
r->tail->next = me;
|
||||
me->next = nil;
|
||||
r->tail = me;
|
||||
|
||||
/* pass the qlock to the next guy */
|
||||
t = r->l->head;
|
||||
if(t){
|
||||
r->l->head = t->next;
|
||||
if(r->l->head == nil)
|
||||
r->l->tail = nil;
|
||||
unlock(&r->l->lock);
|
||||
while((*_rendezvousp)((ulong)t, 0x12345) == ~0)
|
||||
;
|
||||
}else{
|
||||
r->l->locked = 0;
|
||||
unlock(&r->l->lock);
|
||||
}
|
||||
|
||||
/* wait for a wakeup */
|
||||
while((*_rendezvousp)((ulong)me, 0x23456) == ~0)
|
||||
;
|
||||
me->inuse = 0;
|
||||
if(!r->l->locked)
|
||||
abort();
|
||||
}
|
||||
|
||||
int
|
||||
rwakeup(Rendez *r)
|
||||
{
|
||||
QLp *t;
|
||||
|
||||
/*
|
||||
* take off wait and put on front of queue
|
||||
* put on front so guys that have been waiting will not get starved
|
||||
*/
|
||||
|
||||
if(!r->l)
|
||||
abort();
|
||||
lock(&r->l->lock);
|
||||
if(!r->l->locked)
|
||||
abort();
|
||||
|
||||
t = r->head;
|
||||
if(t == nil){
|
||||
unlock(&r->l->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
r->head = t->next;
|
||||
if(r->head == nil)
|
||||
r->tail = nil;
|
||||
|
||||
t->next = r->l->head;
|
||||
r->l->head = t;
|
||||
if(r->l->tail == nil)
|
||||
r->l->tail = t;
|
||||
|
||||
t->state = Queuing;
|
||||
unlock(&r->l->lock);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
rwakeupall(Rendez *r)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0; rwakeup(r); i++)
|
||||
;
|
||||
return i;
|
||||
}
|
||||
89
src/lib9/rand.c
Normal file
89
src/lib9/rand.c
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
#include <lib9.h>
|
||||
|
||||
/*
|
||||
* algorithm by
|
||||
* D. P. Mitchell & J. A. Reeds
|
||||
*/
|
||||
|
||||
#define LEN 607
|
||||
#define TAP 273
|
||||
#define MASK 0x7fffffffL
|
||||
#define A 48271
|
||||
#define M 2147483647
|
||||
#define Q 44488
|
||||
#define R 3399
|
||||
#define NORM (1.0/(1.0+MASK))
|
||||
|
||||
static ulong rng_vec[LEN];
|
||||
static ulong* rng_tap = rng_vec;
|
||||
static ulong* rng_feed = 0;
|
||||
static Lock lk;
|
||||
|
||||
static void
|
||||
isrand(long seed)
|
||||
{
|
||||
long lo, hi, x;
|
||||
int i;
|
||||
|
||||
rng_tap = rng_vec;
|
||||
rng_feed = rng_vec+LEN-TAP;
|
||||
seed = seed%M;
|
||||
if(seed < 0)
|
||||
seed += M;
|
||||
if(seed == 0)
|
||||
seed = 89482311;
|
||||
x = seed;
|
||||
/*
|
||||
* Initialize by x[n+1] = 48271 * x[n] mod (2**31 - 1)
|
||||
*/
|
||||
for(i = -20; i < LEN; i++) {
|
||||
hi = x / Q;
|
||||
lo = x % Q;
|
||||
x = A*lo - R*hi;
|
||||
if(x < 0)
|
||||
x += M;
|
||||
if(i >= 0)
|
||||
rng_vec[i] = x;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
srand(long seed)
|
||||
{
|
||||
lock(&lk);
|
||||
isrand(seed);
|
||||
unlock(&lk);
|
||||
}
|
||||
|
||||
long
|
||||
lrand(void)
|
||||
{
|
||||
ulong x;
|
||||
|
||||
lock(&lk);
|
||||
|
||||
rng_tap--;
|
||||
if(rng_tap < rng_vec) {
|
||||
if(rng_feed == 0) {
|
||||
isrand(1);
|
||||
rng_tap--;
|
||||
}
|
||||
rng_tap += LEN;
|
||||
}
|
||||
rng_feed--;
|
||||
if(rng_feed < rng_vec)
|
||||
rng_feed += LEN;
|
||||
x = (*rng_feed + *rng_tap) & MASK;
|
||||
*rng_feed = x;
|
||||
|
||||
unlock(&lk);
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
int
|
||||
rand(void)
|
||||
{
|
||||
return lrand() & 0x7fff;
|
||||
}
|
||||
|
||||
21
src/lib9/readn.c
Normal file
21
src/lib9/readn.c
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
#include <lib9.h>
|
||||
|
||||
long
|
||||
readn(int f, void *av, long n)
|
||||
{
|
||||
char *a;
|
||||
long m, t;
|
||||
|
||||
a = av;
|
||||
t = 0;
|
||||
while(t < n){
|
||||
m = read(f, a+t, n-t);
|
||||
if(m <= 0){
|
||||
if(t == 0)
|
||||
return m;
|
||||
break;
|
||||
}
|
||||
t += m;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
180
src/lib9/rendez.c
Normal file
180
src/lib9/rendez.c
Normal file
|
|
@ -0,0 +1,180 @@
|
|||
/*
|
||||
NAME
|
||||
rendezvous - user level process synchronization
|
||||
|
||||
SYNOPSIS
|
||||
ulong rendezvous(ulong tag, ulong value)
|
||||
|
||||
DESCRIPTION
|
||||
The rendezvous system call allows two processes to synchro-
|
||||
nize and exchange a value. In conjunction with the shared
|
||||
memory system calls (see segattach(2) and fork(2)), it
|
||||
enables parallel programs to control their scheduling.
|
||||
|
||||
Two processes wishing to synchronize call rendezvous with a
|
||||
common tag, typically an address in memory they share. One
|
||||
process will arrive at the rendezvous first; it suspends
|
||||
execution until a second arrives. When a second process
|
||||
meets the rendezvous the value arguments are exchanged
|
||||
between the processes and returned as the result of the
|
||||
respective rendezvous system calls. Both processes are
|
||||
awakened when the rendezvous succeeds.
|
||||
|
||||
The set of tag values which two processes may use to
|
||||
rendezvous-their tag space-is inherited when a process
|
||||
forks, unless RFREND is set in the argument to rfork; see
|
||||
fork(2).
|
||||
|
||||
If a rendezvous is interrupted the return value is ~0, so
|
||||
that value should not be used in normal communication.
|
||||
|
||||
* This simulates rendezvous with shared memory, pause, and SIGUSR1.
|
||||
*/
|
||||
|
||||
#include <signal.h>
|
||||
#include <lib9.h>
|
||||
|
||||
enum
|
||||
{
|
||||
VOUSHASH = 257,
|
||||
};
|
||||
|
||||
typedef struct Vous Vous;
|
||||
struct Vous
|
||||
{
|
||||
Vous *link;
|
||||
Lock lk;
|
||||
int pid;
|
||||
ulong val;
|
||||
ulong tag;
|
||||
};
|
||||
|
||||
static void
|
||||
ign(int x)
|
||||
{
|
||||
USED(x);
|
||||
}
|
||||
|
||||
void /*__attribute__((constructor))*/
|
||||
ignusr1(void)
|
||||
{
|
||||
signal(SIGUSR1, ign);
|
||||
}
|
||||
|
||||
static Vous vouspool[2048];
|
||||
static int nvousused;
|
||||
static Vous *vousfree;
|
||||
static Vous *voushash[VOUSHASH];
|
||||
static Lock vouslock;
|
||||
|
||||
static Vous*
|
||||
getvous(void)
|
||||
{
|
||||
Vous *v;
|
||||
|
||||
if(vousfree){
|
||||
v = vousfree;
|
||||
vousfree = v->link;
|
||||
}else if(nvousused < nelem(vouspool))
|
||||
v = &vouspool[nvousused++];
|
||||
else
|
||||
abort();
|
||||
return v;
|
||||
}
|
||||
|
||||
static void
|
||||
putvous(Vous *v)
|
||||
{
|
||||
lock(&vouslock);
|
||||
v->link = vousfree;
|
||||
vousfree = v;
|
||||
unlock(&vouslock);
|
||||
}
|
||||
|
||||
static Vous*
|
||||
findvous(ulong tag, ulong val, int pid)
|
||||
{
|
||||
int h;
|
||||
Vous *v, **l;
|
||||
|
||||
lock(&vouslock);
|
||||
h = tag%VOUSHASH;
|
||||
for(l=&voushash[h], v=*l; v; l=&(*l)->link, v=*l){
|
||||
if(v->tag == tag){
|
||||
*l = v->link;
|
||||
unlock(&vouslock);
|
||||
return v;
|
||||
}
|
||||
}
|
||||
v = getvous();
|
||||
v->pid = pid;
|
||||
v->link = voushash[h];
|
||||
v->val = val;
|
||||
v->tag = tag;
|
||||
lock(&v->lk);
|
||||
voushash[h] = v;
|
||||
unlock(&vouslock);
|
||||
return v;
|
||||
}
|
||||
|
||||
#define DBG 0
|
||||
ulong
|
||||
rendezvous(ulong tag, ulong val)
|
||||
{
|
||||
int me, vpid;
|
||||
ulong rval;
|
||||
Vous *v;
|
||||
sigset_t mask;
|
||||
|
||||
me = getpid();
|
||||
v = findvous(tag, val, me);
|
||||
if(v->pid == me){
|
||||
if(DBG)fprint(2, "pid is %d tag %lux, sleeping\n", me, tag);
|
||||
/*
|
||||
* No rendezvous partner was found; the next guy
|
||||
* through will find v and wake us, so we must go
|
||||
* to sleep.
|
||||
*
|
||||
* To go to sleep:
|
||||
* 1. disable USR1 signals.
|
||||
* 2. unlock v->lk (tells waker okay to signal us).
|
||||
* 3. atomically suspend and enable USR1 signals.
|
||||
*
|
||||
* The call to ignusr1() could be done once at
|
||||
* process creation instead of every time through rendezvous.
|
||||
*/
|
||||
v->val = val;
|
||||
ignusr1();
|
||||
sigprocmask(SIG_SETMASK, NULL, &mask);
|
||||
sigaddset(&mask, SIGUSR1);
|
||||
sigprocmask(SIG_SETMASK, &mask, NULL);
|
||||
sigdelset(&mask, SIGUSR1);
|
||||
unlock(&v->lk);
|
||||
sigsuspend(&mask);
|
||||
rval = v->val;
|
||||
if(DBG)fprint(2, "pid is %d, awake\n", me);
|
||||
putvous(v);
|
||||
}else{
|
||||
/*
|
||||
* Found someone to meet. Wake him:
|
||||
*
|
||||
* A. lock v->lk (waits for him to get to his step 2)
|
||||
* B. send a USR1
|
||||
*
|
||||
* He won't get the USR1 until he suspends, which
|
||||
* means it must wake him up (it can't get delivered
|
||||
* before he sleeps).
|
||||
*/
|
||||
vpid = v->pid;
|
||||
lock(&v->lk);
|
||||
rval = v->val;
|
||||
v->val = val;
|
||||
unlock(&v->lk);
|
||||
if(kill(vpid, SIGUSR1) < 0){
|
||||
if(DBG)fprint(2, "pid is %d, kill %d failed: %r\n", me, vpid);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
|
||||
16
src/lib9/strecpy.c
Normal file
16
src/lib9/strecpy.c
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
#include <lib9.h>
|
||||
|
||||
char*
|
||||
strecpy(char *to, char *e, char *from)
|
||||
{
|
||||
if(to >= e)
|
||||
return to;
|
||||
to = memccpy(to, from, '\0', e - to);
|
||||
if(to == nil){
|
||||
to = e - 1;
|
||||
*to = '\0';
|
||||
}else{
|
||||
to--;
|
||||
}
|
||||
return to;
|
||||
}
|
||||
20
src/lib9/sysfatal.c
Normal file
20
src/lib9/sysfatal.c
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
#include <lib9.h>
|
||||
|
||||
void (*_sysfatal)(char*, ...);
|
||||
|
||||
void
|
||||
sysfatal(char *fmt, ...)
|
||||
{
|
||||
char buf[256];
|
||||
va_list arg;
|
||||
|
||||
va_start(arg, fmt);
|
||||
if(_sysfatal)
|
||||
(*_sysfatal)(fmt, arg);
|
||||
vseprint(buf, buf+sizeof buf, fmt, arg);
|
||||
va_end(arg);
|
||||
|
||||
fprint(2, "%s; %s\n", argv0 ? argv0 : "<prog>", buf);
|
||||
exits("fatal");
|
||||
}
|
||||
|
||||
6
src/lib9/tas-386.s
Normal file
6
src/lib9/tas-386.s
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
.globl _tas
|
||||
_tas:
|
||||
movl $0xCAFEBABE, %eax
|
||||
movl 4(%esp), %ecx
|
||||
xchgl %eax, 0(%ecx)
|
||||
ret
|
||||
8
src/lib9/test.c
Normal file
8
src/lib9/test.c
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
#include <lib9.h>
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
werrstr("hello world");
|
||||
print("%r\n");
|
||||
}
|
||||
21
src/lib9/testfork.c
Normal file
21
src/lib9/testfork.c
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
#include <lib9.h>
|
||||
|
||||
void
|
||||
sayhi(void *v)
|
||||
{
|
||||
USED(v);
|
||||
|
||||
print("hello from subproc\n");
|
||||
print("rendez got %lu from main\n", rendezvous(0x1234, 1234));
|
||||
exits(0);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
print("hello from main\n");
|
||||
ffork(RFMEM|RFPROC, sayhi, nil);
|
||||
|
||||
print("rendez got %lu from subproc\n", rendezvous(0x1234, 0));
|
||||
exits(0);
|
||||
}
|
||||
106
src/lib9/tokenize.c
Normal file
106
src/lib9/tokenize.c
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
#include <lib9.h>
|
||||
|
||||
static char qsep[] = " \t\r\n";
|
||||
|
||||
static char*
|
||||
qtoken(char *s, char *sep)
|
||||
{
|
||||
int quoting;
|
||||
char *t;
|
||||
|
||||
quoting = 0;
|
||||
t = s; /* s is output string, t is input string */
|
||||
while(*t!='\0' && (quoting || utfrune(sep, *t)==nil)){
|
||||
if(*t != '\''){
|
||||
*s++ = *t++;
|
||||
continue;
|
||||
}
|
||||
/* *t is a quote */
|
||||
if(!quoting){
|
||||
quoting = 1;
|
||||
t++;
|
||||
continue;
|
||||
}
|
||||
/* quoting and we're on a quote */
|
||||
if(t[1] != '\''){
|
||||
/* end of quoted section; absorb closing quote */
|
||||
t++;
|
||||
quoting = 0;
|
||||
continue;
|
||||
}
|
||||
/* doubled quote; fold one quote into two */
|
||||
t++;
|
||||
*s++ = *t++;
|
||||
}
|
||||
if(*s != '\0'){
|
||||
*s = '\0';
|
||||
if(t == s)
|
||||
t++;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
static char*
|
||||
etoken(char *t, char *sep)
|
||||
{
|
||||
int quoting;
|
||||
|
||||
/* move to end of next token */
|
||||
quoting = 0;
|
||||
while(*t!='\0' && (quoting || utfrune(sep, *t)==nil)){
|
||||
if(*t != '\''){
|
||||
t++;
|
||||
continue;
|
||||
}
|
||||
/* *t is a quote */
|
||||
if(!quoting){
|
||||
quoting = 1;
|
||||
t++;
|
||||
continue;
|
||||
}
|
||||
/* quoting and we're on a quote */
|
||||
if(t[1] != '\''){
|
||||
/* end of quoted section; absorb closing quote */
|
||||
t++;
|
||||
quoting = 0;
|
||||
continue;
|
||||
}
|
||||
/* doubled quote; fold one quote into two */
|
||||
t += 2;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
int
|
||||
gettokens(char *s, char **args, int maxargs, char *sep)
|
||||
{
|
||||
int nargs;
|
||||
|
||||
for(nargs=0; nargs<maxargs; nargs++){
|
||||
while(*s!='\0' && utfrune(sep, *s)!=nil)
|
||||
*s++ = '\0';
|
||||
if(*s == '\0')
|
||||
break;
|
||||
args[nargs] = s;
|
||||
s = etoken(s, sep);
|
||||
}
|
||||
|
||||
return nargs;
|
||||
}
|
||||
|
||||
int
|
||||
tokenize(char *s, char **args, int maxargs)
|
||||
{
|
||||
int nargs;
|
||||
|
||||
for(nargs=0; nargs<maxargs; nargs++){
|
||||
while(*s!='\0' && utfrune(qsep, *s)!=nil)
|
||||
s++;
|
||||
if(*s == '\0')
|
||||
break;
|
||||
args[nargs] = s;
|
||||
s = qtoken(s, qsep);
|
||||
}
|
||||
|
||||
return nargs;
|
||||
}
|
||||
52
src/lib9/u16.c
Normal file
52
src/lib9/u16.c
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
#include <lib9.h>
|
||||
static char t16e[] = "0123456789ABCDEF";
|
||||
|
||||
int
|
||||
dec16(uchar *out, int lim, char *in, int n)
|
||||
{
|
||||
int c, w = 0, i = 0;
|
||||
uchar *start = out;
|
||||
uchar *eout = out + lim;
|
||||
|
||||
while(n-- > 0){
|
||||
c = *in++;
|
||||
if('0' <= c && c <= '9')
|
||||
c = c - '0';
|
||||
else if('a' <= c && c <= 'z')
|
||||
c = c - 'a' + 10;
|
||||
else if('A' <= c && c <= 'Z')
|
||||
c = c - 'A' + 10;
|
||||
else
|
||||
continue;
|
||||
w = (w<<4) + c;
|
||||
i++;
|
||||
if(i == 2){
|
||||
if(out + 1 > eout)
|
||||
goto exhausted;
|
||||
*out++ = w;
|
||||
w = 0;
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
exhausted:
|
||||
return out - start;
|
||||
}
|
||||
|
||||
int
|
||||
enc16(char *out, int lim, uchar *in, int n)
|
||||
{
|
||||
uint c;
|
||||
char *eout = out + lim;
|
||||
char *start = out;
|
||||
|
||||
while(n-- > 0){
|
||||
c = *in++;
|
||||
if(out + 2 >= eout)
|
||||
goto exhausted;
|
||||
*out++ = t16e[c>>4];
|
||||
*out++ = t16e[c&0xf];
|
||||
}
|
||||
exhausted:
|
||||
*out = 0;
|
||||
return out - start;
|
||||
}
|
||||
109
src/lib9/u32.c
Normal file
109
src/lib9/u32.c
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
#include <lib9.h>
|
||||
|
||||
int
|
||||
dec32(uchar *dest, int ndest, char *src, int nsrc)
|
||||
{
|
||||
char *s, *tab;
|
||||
uchar *start;
|
||||
int i, u[8];
|
||||
|
||||
if(ndest+1 < (5*nsrc+7)/8)
|
||||
return -1;
|
||||
start = dest;
|
||||
tab = "23456789abcdefghijkmnpqrstuvwxyz";
|
||||
while(nsrc>=8){
|
||||
for(i=0; i<8; i++){
|
||||
s = strchr(tab,(int)src[i]);
|
||||
u[i] = s ? s-tab : 0;
|
||||
}
|
||||
*dest++ = (u[0]<<3) | (0x7 & (u[1]>>2));
|
||||
*dest++ = ((0x3 & u[1])<<6) | (u[2]<<1) | (0x1 & (u[3]>>4));
|
||||
*dest++ = ((0xf & u[3])<<4) | (0xf & (u[4]>>1));
|
||||
*dest++ = ((0x1 & u[4])<<7) | (u[5]<<2) | (0x3 & (u[6]>>3));
|
||||
*dest++ = ((0x7 & u[6])<<5) | u[7];
|
||||
src += 8;
|
||||
nsrc -= 8;
|
||||
}
|
||||
if(nsrc > 0){
|
||||
if(nsrc == 1 || nsrc == 3 || nsrc == 6)
|
||||
return -1;
|
||||
for(i=0; i<nsrc; i++){
|
||||
s = strchr(tab,(int)src[i]);
|
||||
u[i] = s ? s-tab : 0;
|
||||
}
|
||||
*dest++ = (u[0]<<3) | (0x7 & (u[1]>>2));
|
||||
if(nsrc == 2)
|
||||
goto out;
|
||||
*dest++ = ((0x3 & u[1])<<6) | (u[2]<<1) | (0x1 & (u[3]>>4));
|
||||
if(nsrc == 4)
|
||||
goto out;
|
||||
*dest++ = ((0xf & u[3])<<4) | (0xf & (u[4]>>1));
|
||||
if(nsrc == 5)
|
||||
goto out;
|
||||
*dest++ = ((0x1 & u[4])<<7) | (u[5]<<2) | (0x3 & (u[6]>>3));
|
||||
}
|
||||
out:
|
||||
return dest-start;
|
||||
}
|
||||
|
||||
int
|
||||
enc32(char *dest, int ndest, uchar *src, int nsrc)
|
||||
{
|
||||
char *tab, *start;
|
||||
int j;
|
||||
|
||||
if(ndest <= (8*nsrc+4)/5 )
|
||||
return -1;
|
||||
start = dest;
|
||||
tab = "23456789abcdefghijkmnpqrstuvwxyz";
|
||||
while(nsrc>=5){
|
||||
j = (0x1f & (src[0]>>3));
|
||||
*dest++ = tab[j];
|
||||
j = (0x1c & (src[0]<<2)) | (0x03 & (src[1]>>6));
|
||||
*dest++ = tab[j];
|
||||
j = (0x1f & (src[1]>>1));
|
||||
*dest++ = tab[j];
|
||||
j = (0x10 & (src[1]<<4)) | (0x0f & (src[2]>>4));
|
||||
*dest++ = tab[j];
|
||||
j = (0x1e & (src[2]<<1)) | (0x01 & (src[3]>>7));
|
||||
*dest++ = tab[j];
|
||||
j = (0x1f & (src[3]>>2));
|
||||
*dest++ = tab[j];
|
||||
j = (0x18 & (src[3]<<3)) | (0x07 & (src[4]>>5));
|
||||
*dest++ = tab[j];
|
||||
j = (0x1f & (src[4]));
|
||||
*dest++ = tab[j];
|
||||
src += 5;
|
||||
nsrc -= 5;
|
||||
}
|
||||
if(nsrc){
|
||||
j = (0x1f & (src[0]>>3));
|
||||
*dest++ = tab[j];
|
||||
j = (0x1c & (src[0]<<2));
|
||||
if(nsrc == 1)
|
||||
goto out;
|
||||
j |= (0x03 & (src[1]>>6));
|
||||
*dest++ = tab[j];
|
||||
j = (0x1f & (src[1]>>1));
|
||||
if(nsrc == 2)
|
||||
goto out;
|
||||
*dest++ = tab[j];
|
||||
j = (0x10 & (src[1]<<4));
|
||||
if(nsrc == 3)
|
||||
goto out;
|
||||
j |= (0x0f & (src[2]>>4));
|
||||
*dest++ = tab[j];
|
||||
j = (0x1e & (src[2]<<1));
|
||||
if(nsrc == 4)
|
||||
goto out;
|
||||
j |= (0x01 & (src[3]>>7));
|
||||
*dest++ = tab[j];
|
||||
j = (0x1f & (src[3]>>2));
|
||||
*dest++ = tab[j];
|
||||
j = (0x18 & (src[3]<<3));
|
||||
out:
|
||||
*dest++ = tab[j];
|
||||
}
|
||||
*dest = 0;
|
||||
return dest-start;
|
||||
}
|
||||
126
src/lib9/u64.c
Normal file
126
src/lib9/u64.c
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
#include <lib9.h>
|
||||
|
||||
enum {
|
||||
INVAL= 255
|
||||
};
|
||||
|
||||
static uchar t64d[256] = {
|
||||
INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
|
||||
INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
|
||||
INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL, 62,INVAL,INVAL,INVAL, 63,
|
||||
52, 53, 54, 55, 56, 57, 58, 59, 60, 61,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
|
||||
INVAL, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
|
||||
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,INVAL,INVAL,INVAL,INVAL,INVAL,
|
||||
INVAL, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
|
||||
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,INVAL,INVAL,INVAL,INVAL,INVAL,
|
||||
INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
|
||||
INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
|
||||
INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
|
||||
INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
|
||||
INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
|
||||
INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
|
||||
INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
|
||||
INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL
|
||||
};
|
||||
static char t64e[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
int
|
||||
dec64(uchar *out, int lim, char *in, int n)
|
||||
{
|
||||
ulong b24;
|
||||
uchar *start = out;
|
||||
uchar *e = out + lim;
|
||||
int i, c;
|
||||
|
||||
b24 = 0;
|
||||
i = 0;
|
||||
while(n-- > 0){
|
||||
|
||||
c = t64d[*(uchar*)in++];
|
||||
if(c == INVAL)
|
||||
continue;
|
||||
switch(i){
|
||||
case 0:
|
||||
b24 = c<<18;
|
||||
break;
|
||||
case 1:
|
||||
b24 |= c<<12;
|
||||
break;
|
||||
case 2:
|
||||
b24 |= c<<6;
|
||||
break;
|
||||
case 3:
|
||||
if(out + 3 > e)
|
||||
goto exhausted;
|
||||
|
||||
b24 |= c;
|
||||
*out++ = b24>>16;
|
||||
*out++ = b24>>8;
|
||||
*out++ = b24;
|
||||
i = -1;
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
switch(i){
|
||||
case 2:
|
||||
if(out + 1 > e)
|
||||
goto exhausted;
|
||||
*out++ = b24>>16;
|
||||
break;
|
||||
case 3:
|
||||
if(out + 2 > e)
|
||||
goto exhausted;
|
||||
*out++ = b24>>16;
|
||||
*out++ = b24>>8;
|
||||
break;
|
||||
}
|
||||
exhausted:
|
||||
return out - start;
|
||||
}
|
||||
|
||||
int
|
||||
enc64(char *out, int lim, uchar *in, int n)
|
||||
{
|
||||
int i;
|
||||
ulong b24;
|
||||
char *start = out;
|
||||
char *e = out + lim;
|
||||
|
||||
for(i = n/3; i > 0; i--){
|
||||
b24 = (*in++)<<16;
|
||||
b24 |= (*in++)<<8;
|
||||
b24 |= *in++;
|
||||
if(out + 4 >= e)
|
||||
goto exhausted;
|
||||
*out++ = t64e[(b24>>18)];
|
||||
*out++ = t64e[(b24>>12)&0x3f];
|
||||
*out++ = t64e[(b24>>6)&0x3f];
|
||||
*out++ = t64e[(b24)&0x3f];
|
||||
}
|
||||
|
||||
switch(n%3){
|
||||
case 2:
|
||||
b24 = (*in++)<<16;
|
||||
b24 |= (*in)<<8;
|
||||
if(out + 4 >= e)
|
||||
goto exhausted;
|
||||
*out++ = t64e[(b24>>18)];
|
||||
*out++ = t64e[(b24>>12)&0x3f];
|
||||
*out++ = t64e[(b24>>6)&0x3f];
|
||||
*out++ = '=';
|
||||
break;
|
||||
case 1:
|
||||
b24 = (*in)<<16;
|
||||
if(out + 4 >= e)
|
||||
goto exhausted;
|
||||
*out++ = t64e[(b24>>18)];
|
||||
*out++ = t64e[(b24>>12)&0x3f];
|
||||
*out++ = '=';
|
||||
*out++ = '=';
|
||||
break;
|
||||
}
|
||||
exhausted:
|
||||
*out = 0;
|
||||
return out - start;
|
||||
}
|
||||
30
src/lib9/wait.c
Normal file
30
src/lib9/wait.c
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
#include <lib9.h>
|
||||
|
||||
Waitmsg*
|
||||
wait(void)
|
||||
{
|
||||
int n, l;
|
||||
char buf[512], *fld[5];
|
||||
Waitmsg *w;
|
||||
|
||||
n = await(buf, sizeof buf-1);
|
||||
if(n < 0)
|
||||
return nil;
|
||||
buf[n] = '\0';
|
||||
if(tokenize(buf, fld, nelem(fld)) != nelem(fld)){
|
||||
werrstr("couldn't parse wait message");
|
||||
return nil;
|
||||
}
|
||||
l = strlen(fld[4])+1;
|
||||
w = malloc(sizeof(Waitmsg)+l);
|
||||
if(w == nil)
|
||||
return nil;
|
||||
w->pid = atoi(fld[0]);
|
||||
w->time[0] = atoi(fld[1]);
|
||||
w->time[1] = atoi(fld[2]);
|
||||
w->time[2] = atoi(fld[3]);
|
||||
w->msg = (char*)&w[1];
|
||||
memmove(w->msg, fld[4], l);
|
||||
return w;
|
||||
}
|
||||
|
||||
13
src/lib9/werrstr.c
Normal file
13
src/lib9/werrstr.c
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
#include <lib9.h>
|
||||
|
||||
void
|
||||
werrstr(char *fmt, ...)
|
||||
{
|
||||
va_list arg;
|
||||
char buf[ERRMAX];
|
||||
|
||||
va_start(arg, fmt);
|
||||
vseprint(buf, buf+ERRMAX, fmt, arg);
|
||||
va_end(arg);
|
||||
errstr(buf, ERRMAX);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue