add directory study

This commit is contained in:
gohigh
2024-02-19 00:25:23 -05:00
parent b1306b38b1
commit f3774e2f8c
4001 changed files with 2285787 additions and 0 deletions

View File

@@ -0,0 +1,9 @@
all:
@echo /usr/lib/cpp needs 50000 bytes of stack space. Current size is:
@size /usr/lib/cpp
@echo If it has less than 50K, het DEL and use chmem to change it.
cd kernel; make
cd fs; make
cd mm; make
cd ../tools; make net

View File

@@ -0,0 +1,23 @@
CFLAGS=-F
all: client1 server1 client2 server2 client3 server3
client1: header.h client1.s
cc -o client1 client1.s
client2: header.h client2.s
cc -o client2 client2.s
client3: header.h client3.s
cc -o client3 client3.s
server1: header.h server1.s
cc -o server1 server1.s
chmem =1000 server1
server2: header.h server2.s
cc -o server2 server2.s
chmem =1000 server2
server3: header.h server3.s
cc -o server3 server3.s
chmem =1000 server3

View File

@@ -0,0 +1,59 @@
This directory contains several examples of networking code. These examples
also serve as programs to test the correctness and performance of the
networking and to provide some useful utility functions. In all the tests,
the client and server may run on the same machine, or if an Ethernet is
installed, on different machines. The ports 'xyz' used in tests 1 and 2
are examples. It is possible to run multiple tests at the same time (e.g.,
n1 sets of (client1, server1) and n2 sets of (client2, server2), provided
that each pair of (clientX, serverX) uses a port not used by any other process.
1. Test 1 consists of two programs, server1.c and client1.c. This test
transfers 1 megabyte from the client to the server in 1K chunks, has the
server transform the data and send it back. The client then verifies if
the returned data is correct. To run the test, type the following lines:
make client1 server1
server1 xyz &
client1 xyz
If an Ethernet is installed and the kernel has been compiled with
-DAM_KERNEL, the server and client may either be on the same machine or
one different ones. If there is no Ethernet and the kernel has been
compiled with _DAM_KERNEL -DNONET, both processes must be on the same CPU.
At the end of the test, "ok" is printed if no errors occurred. Otherwise
the number of bad transactions is printed. Both the client and server exit
by themselves after the test has been completed.
2. Test 2 consists of two programs, server2.c and client2.c. This test
measures the performance of the transactions. Like test 1, it can be run
either locally or remotely. The test consists of having the client request
n bytes of data from the server, where n grows from 1 to 30,000 bytes per
transaction. For each value of n, the test is run 1000 times to increase
the statistical accuracy. For each value of n, the value of n, the delay
(transaction time in milliseconds), and the throughput (bytes/sec moved)
is reported. To run the test, type:
make client2 server2
server2 xyz &
client2 xyz
3. Test 3 is an example of how one might go about making a remote file server
for MINIX to service diskless PCs. In this approach, one writes a server,
server3.c in this example, and a set of library routines, contained in
client3.c. These library routines should have the same names as the MINIX
system calls, such as open(), read(), and write(). When programs are linked
with these routines instead of the usual ones, the routines make calls to
the remote file server instead of FS. The file client3.c contains not only
a few of these library routines, but also a short main program to test them.
The main program fetches a file from the remote file server and copies it to
stdout. To test the program, type:
make client3 server3
server3 &
client3 <filename>
where <filename> is the name of a file on the same machine as server3. The
result of this command will be that <filename> is written to client3's
standard output.

View File

@@ -0,0 +1,56 @@
/* This program tests the basic RPC to see if it works. */
#include <amoeba.h>
#include "header.h"
#define MAX_TRIALS 1000
char buffer1[BUF_SIZE], buffer2[BUF_SIZE];
main(argc, argv)
int argc;
char *argv[];
{
header hdr1, hdr2;
int cnt, i, base = 0, size, errors, blocks, iterations = 0;
long bad_trans = 0;
if (argc != 2) {
printf("Usage: client1 portname\n");
exit(1);
}
/* Copy the filename into the start of the buffer. */
strncpy(&hdr1.h_port, argv[1], PORTSIZE);
hdr1.h_command = WORK;
printf("Number of tests performed = %5d ", 0);
while (iterations < MAX_TRIALS) {
/* Initialize the buffer. */
for (i = 0; i < BUF_SIZE; i++) buffer1[i] = base + i;
size = trans(&hdr1, buffer1, BUF_SIZE, &hdr2, buffer2, BUF_SIZE);
if (size < 0) {
printf("\nTransaction failed. Error = %d. ", size);
printf("Hit F1 to see if AMTASK running.\n");
exit(1);
}
/* Check reply. */
errors = 0;
for (i = 0; i < BUF_SIZE; i++)
if ( (buffer2[i]&0377) != ( (buffer1[i]+1)&0377)) errors++;
if (errors > 0) bad_trans++;
blocks++;
base++;
iterations++;
if (iterations % 10 == 0) printf("\b\b\b\b\b\b%5d ", iterations);
}
/* Test done. Send null trans to tell server. Report on errors. */
hdr1.h_command = QUIT;
trans(&hdr1, buffer1, 0, &hdr2, buffer2, BUF_SIZE);
printf("\b. Number of errors = %d.\n", bad_trans);
}

View File

@@ -0,0 +1,76 @@
/* This file is the client of a test program for measuring RPC speed. */
#include <amoeba.h>
#include <minix/callnr.h>
#include "header.h"
#define TRIALS 1000
char buffer[MAX_TRANS];
int bytes[] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096,
8192, 16384, 30000, 0};
header hdr1, hdr2;
main(argc, argv)
int argc;
char *argv[];
{
int i, cnt;
if (argc != 2) {
printf("Usage: client2 portname\n");
exit(1);
}
/* Copy the filename into the start of the buffer. */
strncpy(&hdr1.h_port, argv[1], PORTSIZE);
hdr1.h_command = READ;
printf("Buf size Delay Throughput (Each test repeated %d times)\n", TRIALS);
printf(" (msec/trans) (bytes/sec)\n");
printf("-------- ------------ -----------\n");
i = 0;
while (bytes[i] != 0) {
run_test(bytes[i], TRIALS);
i++;
}
hdr1.h_command = QUIT;
trans(&hdr1, buffer, 0, &hdr2, buffer, 0);
exit(0);
}
run_test(count, trials)
int count, trials;
{
/* Run a performance test. */
int i, n;
long start, finish, traffic, sec, msec, delay, throughput;
time(&start); /* record starting time */
for (i = 0; i < trials; i++) {
hdr1.h_command = READ;
hdr1.h_size = (unshort) count;
n = trans(&hdr1, buffer, 0, &hdr2, buffer, MAX_TRANS);
if (n < 0) {
printf("Transaction failed. Error = %d. ", n);
printf("Hit F1 to see if AMTASK running.\n");
exit(1);
}
}
time(&finish);
sec = finish - start; /* time for this trial in seconds */
msec = 1000L * sec;
traffic = (long) trials * (long) count;
delay = msec/trials; /* msec per transaction */
if (sec != 0L)
throughput = traffic/sec;
else
throughput = 0L;
printf(" %5d %4D %7D\n", count, delay, throughput);
}

View File

@@ -0,0 +1,236 @@
/* This file shows how one could build a remote file server for MINIX.
* In this file there are several library routines for the basic system
* calls. Unlike the "real" ones, these call a remote file server instead
* of the local kernel. On client machines, one would replace the library
* routines with these routines, and then recompile programs. In this way,
* clients will then call the remote file server. It should be obvious that
* this file is just an example, and that a productio version would have to
* be much more complete.
*
* The file server3.c contains the start of a stateless file server. Because
* MINIX is not stateless, the conversion must be done in this library. For
* example, when an open() is done, the library records the name, but no
* operation is performed on the file server.
*
* An alternative approach to making a remote file systems is to replace FS,
* the local file server, with one that makes the calls to the remote file
* server itself. This approach is less efficient, because a call then
* consists of a local FS call plus a remote one, but it is more transparent
* because no programs need to recompiled.
*/
#include <amoeba.h>
#include <errno.h>
#include <minix/callnr.h>
#include "header.h"
#define MAX_FD 20
#define LOCAL 100
#define HEAPSIZE 512 /* space for file names */
#define WRITING 2
#define ER -1
#define FS 1
#define NIL_PTR (char*) 0
/* The local array is indexed by file descriptor. Those entries containing
* LOCAL are local (e.g., stdin), those containing REMOTE are remote, and
* those containing 0 are unassigned.
*/
char where[MAX_FD] = {LOCAL, LOCAL, LOCAL};
long pos[MAX_FD]; /* current offset */
char *server_name = "filsrv";
char *file_name[MAX_FD];
char heap[HEAPSIZE];
char *heap_ptr = heap;
header hdr1, hdr2;
char buffer[BUF_SIZE+NAME_SIZE];
extern int errno;
/*============================= Remote Library ==============================*/
int open(name, how)
char *name;
int how;
{
/* Open is entirely local. */
int i, len;
if (how < 0 || how > 2) { errno = EINVAL; return(ER);}
/* Find a free file descriptor. */
for (i = 0; i < MAX_FD; i++) {
if (where[i] == 0) {
len = strlen(name);
file_name[i] = heap_ptr;
bcopy(name, heap_ptr, len);
heap_ptr += len;
*heap_ptr++ = 0;
where[i] = how+1;
return(i);
}
}
errno = EMFILE;
return(ER);
}
int creat(name, mode)
char *name;
int mode;
{
/* Create a file. */
int i, len, n;
/* Find a free file descriptor. */
for (i = 0; i < MAX_FD; i++) {
if (where[i] == 0) {
len = strlen(name);
file_name[i] = heap_ptr;
bcopy(name, heap_ptr, len);
heap_ptr += len;
*heap_ptr++ = 0;
where[i] = WRITING;
strncpy(&hdr1.h_port, server_name, PORTSIZE);
hdr1.h_command = CREAT;
hdr1.h_size = mode;
n = trans(&hdr1, file_name[i], len+1, &hdr2, buffer, 0);
if (n < 0) {errno = EIO; return(ER);}
return(hdr2.h_status);
}
}
errno = EMFILE;
return(ER);
}
/* int close(fd)
int fd;
{
if (where[fd] == LOCAL) return(Xclose(fd));
if (where[fd] == 0) {errno = EBADF; return(ER);}
where[fd] = 0;
return(OK);
}
*/
int read(fd, buf, bytes)
int fd, bytes;
char buf[];
{
/* Primitive read() routine for reads up to 1K. */
int n;
if (where[fd] == LOCAL) return (Xread(fd, buf, bytes));
if ((where[fd]&1) == 0) {errno = EBADF; return(ER);}
if (bytes > BUF_SIZE) return(EINVAL); /* in a real version, fix this */
strncpy(&hdr1.h_port, server_name, PORTSIZE);
hdr1.h_command = READ;
hdr1.h_size = bytes;
hdr1.h_offset = pos[fd];
n = trans(&hdr1, file_name[fd], strlen(file_name[fd])+1, &hdr2, buf, bytes);
if (n < 0) {errno = EIO; return(ER);}
if (hdr2.h_extra != 0) errno = hdr2.h_extra;
pos[fd] += hdr2.h_status; /* advance file position */
return(hdr2.h_status);
}
int write(fd, buf, bytes)
int fd, bytes;
char buf[];
{
/* Primitive write() routine for writes up to 1K. This is a very simple
* routine. Because the server is stateless, for a write we must send both
* the data and the file name. In this example, the first 1K of the buffer
* is reserved for the data, with the file name starting at position 1024.
*/
int n, len;
if (where[fd] == LOCAL) return (Xwrite(fd, buf, bytes));
if ((where[fd]&02) == 0) {errno = EBADF; return(ER);}
if (bytes > BUF_SIZE) return(EINVAL); /* in a real version, fix this */
strncpy(&hdr1.h_port, server_name, PORTSIZE);
len = strlen(file_name[fd]);
hdr1.h_command = WRITE;
hdr1.h_size = bytes;
hdr1.h_offset = pos[fd];
bcopy(buf, buffer, bytes); /* copy data to message */
bcopy(file_name[fd], &buffer[BUF_SIZE], len+1);
n = trans(&hdr1, buffer, BUF_SIZE+len+1, &hdr2, buf, 0);
if(n < 0) {errno = EIO; return(ER);}
if (hdr2.h_extra != 0) errno = hdr2.h_extra;
pos[fd] += hdr2.h_status;
return(hdr2.h_status);
}
/* Below are the real calls, which are sometimes needed. */
int Xread(fd, buffer, nbytes)
int fd;
char *buffer;
int nbytes;
{
int n;
n = callm1(FS, READ, fd, nbytes, 0, buffer, NIL_PTR, NIL_PTR);
return(n);
}
int Xwrite(fd, buffer, nbytes)
char *buffer;
int nbytes;
{
return callm1(FS, WRITE, fd, nbytes, 0, buffer, NIL_PTR, NIL_PTR);
}
int Xclose(fd)
int fd;
{
return callm1(FS, CLOSE, fd, 0, 0, NIL_PTR, NIL_PTR, NIL_PTR);
}
/* ========================= test program =============================*/
main(argc, argv)
int argc;
char *argv[];
{
int fd1, n;
char b[1024];
if (argc != 2) {
printf("Usage: client3 file\n");
exit(1);
}
fd1 = open(argv[1], 0);
if (fd1 < 0) {
printf("Open of %s failed\n", argv[1]);
exit(1);
}
do {
if ((n=read(fd1, b, 1024) < 0)) {
printf("Cannot read %s\n", argv[1]);
exit(1);
}
if (write(1, b, n) < 0) {
printf("Cannot write stdout\n");
exit(1);
}
} while (n > 0);
}

View File

@@ -0,0 +1,11 @@
/* Some declarations need by the example clients and servers. */
char *file_server = "filsrv";
#define BUF_SIZE 1024
#define NAME_SIZE 512
#define WORK 1
#define QUIT 999
#define MAX_TRANS 30000

View File

@@ -0,0 +1,44 @@
#include <amoeba.h>
#include "header.h"
char buffer[BUF_SIZE];
main(argc, argv)
int argc;
char *argv[];
{
unshort getreq(), putrep();
header hdr;
int cnt, i, iterations = 0;
if (argc != 2) {
printf("Usage: server1 portname\n");
exit(1);
}
strncpy( (char *) &hdr.h_port, argv[1], PORTSIZE); /* init port */
while (1) {
/* Wait for a request to arrive. */
if ((cnt = (short) getreq(&hdr, buffer, BUF_SIZE)) < 0) {
printf("Server's getreq failed. Error = %d. ", cnt);
printf("Hit F1 to see if AMTASK running.\n");
exit(1);
}
/* Opcode QUIT indicates that we are done. */
if (hdr.h_command == QUIT) {
putrep(&hdr, buffer, 0);
exit(0);
}
/* We have a request. Increment each byte. */
for (i = 0; i < cnt; i++) buffer[i]++;
/* Send back reply. */
hdr.h_status = 0;
putrep(&hdr, buffer, cnt);
}
}

View File

@@ -0,0 +1,40 @@
#include <amoeba.h>
#include "header.h"
char buffer[MAX_TRANS];
main(argc, argv)
int argc;
char *argv[];
{
header hdr;
int count;
if (argc != 2) {
printf("Usage: server2 portname\n");
exit(1);
}
strncpy( (char *) &hdr.h_port, argv[1], PORTSIZE); /* init port */
while (1) {
/* Wait for a request to arrive. */
count = (short) getreq(&hdr, buffer, MAX_TRANS);
if (count < 0) {
printf("Server's getreq failed. Error = %d. ", count);
printf("Hit F1 to see if AMTASK running.\n");
exit(1);
}
/* Opcode QUIT indicates that we are done. */
if (hdr.h_command == QUIT) {
putrep(&hdr, buffer, 0);
exit(0);
}
/* We have a request. Reply. */
count = hdr.h_size;
putrep(&hdr, buffer, count);
}
}

View File

@@ -0,0 +1,104 @@
#include <amoeba.h>
#include <minix/callnr.h>
#include <errno.h>
#include "header.h"
header hdr; /* header for incoming messages */
char buffer[BUF_SIZE+NAME_SIZE]; /* buffer for incoming messages */
char *server_name = "filsrv";
int repsize;
extern int errno;
main()
{
/* This is a primitive file server. The client runs with a special set of
* routines for read(), write(), etc. that call this server. The server is
* stateless.
*/
int s;
int count;
unshort opcode, size;
strncpy( (char *) &hdr.h_port, server_name, PORTSIZE); /* init port */
while (1) {
/* Wait for a request to arrive. */
count = (short) getreq(&hdr, buffer, MAX_TRANS);
if (count < 0) {
printf("Server's getreq failed. Error = %d. ", count);
printf("Hit F1 to see if AMTASK running.\n");
exit(1);
}
/* Dispatch on opcode. */
opcode = hdr.h_command;
repsize = 0;
errno = 0;
switch(opcode) {
case CREAT: s = do_creat(); break;
case READ: s = do_read(); break;
case WRITE: s = do_write(); break;
default: s = EINVAL; break;
}
/* Work done. Send a reply. */
hdr.h_status = (unshort) s;
hdr.h_extra = (unshort) errno;
putrep(&hdr, buffer, repsize);
}
}
int do_read()
{
/* Stateless read. */
int fd, n;
long offset;
unshort count;
offset = hdr.h_offset;
count = hdr.h_size;
if (count > MAX_TRANS) count = MAX_TRANS;
fd = open(buffer, 0); /* open the file for reading */
if (fd < 0) return(errno);
lseek(fd, offset, 0);
n = read(fd, buffer, count);
close(fd);
repsize = n;
return(n);
}
int do_write()
{
/* Stateless write. */
int fd, n;
long offset;
unshort count;
offset = hdr.h_offset;
count = hdr.h_size;
if (count > MAX_TRANS) count = MAX_TRANS;
fd = open(&buffer[BUF_SIZE], 2); /* open the file for writing */
if (fd < 0) return(errno);
lseek(fd, offset, 0);
n = write(fd, buffer, count);
close(fd);
return(n);
}
int do_creat()
{
/* Stateless creat. */
int fd, n, mode;
mode = hdr.h_size;
fd = creat(buffer, mode); /* creat the file */
close(fd);
return(fd);
}

View File

@@ -0,0 +1,236 @@
CFLAGS= -DAM_KERNEL -I../../fs -I. -F
f=../../fs
i=/usr/include
s=/usr/include/sys
h=/usr/include/minix
l=/usr/lib
a=$f/fs.h $h/config.h $h/const.h $h/type.h $s/types.h $i/limits.h $i/errno.h \
$f/const.h $f/type.h $f/proto.h $f/glo.h
obj = main.s open.s read.s write.s pipe.s device.s \
path.s mount.s link.s super.s inode.s cache.s filedes.s \
stadir.s protect.s time.s misc.s utility.s table.s \
putc.s
fs: Makefile $l/head.s $(obj) $l/libc.a $l/end.s
asld -i -o fs $l/head.s $(obj) $l/libc.a $l/end.s
clean:
@rm -f $(obj) fs *.bak
cache.s: $a
cache.s: $h/com.h
cache.s: $h/boot.h
cache.s: $f/buf.h
cache.s: $f/file.h
cache.s: $f/fproc.h
cache.s: $f/inode.h
cache.s: $f/super.h
cache.s: $f/cache.c
$(CC) $(CFLAGS) -c $f/cache.c
device.s: $a
device.s: $h/com.h
device.s: $f/dev.h
device.s: $f/file.h
device.s: $f/fproc.h
device.s: $f/inode.h
device.s: $f/param.h
device.s: $f/device.c
$(CC) $(CFLAGS) -c $f/device.c
filedes.s: $a
filedes.s: $f/file.h
filedes.s: $f/fproc.h
filedes.s: $f/inode.h
filedes.s: $f/filedes.c
$(CC) $(CFLAGS) -c $f/filedes.c
inode.s: $a
inode.s: $s/stat.h
inode.s: $h/boot.h
inode.s: $f/buf.h
inode.s: $f/file.h
inode.s: $f/fproc.h
inode.s: $f/inode.h
inode.s: $f/super.h
inode.s: $f/inode.c
$(CC) $(CFLAGS) -c $f/inode.c
link.s: $a
link.s: $s/stat.h
link.s: $f/buf.h
link.s: $f/file.h
link.s: $f/fproc.h
link.s: $f/inode.h
link.s: $f/param.h
link.s: $f/link.c
$(CC) $(CFLAGS) -c $f/link.c
main.s: $a
main.s: $h/callnr.h
main.s: $h/com.h
main.s: $h/boot.h
main.s: $f/buf.h
main.s: $f/file.h
main.s: $f/fproc.h
main.s: $f/inode.h
main.s: $f/param.h
main.s: $f/super.h
main.s: $f/main.c
$(CC) $(CFLAGS) -c $f/main.c
misc.s: $a
misc.s: $i/fcntl.h
misc.s: $h/callnr.h
misc.s: $h/com.h
misc.s: $h/boot.h
misc.s: $f/buf.h
misc.s: $f/file.h
misc.s: $f/fproc.h
misc.s: $f/inode.h
misc.s: $f/param.h
misc.s: $f/super.h
misc.s: $f/misc.c
$(CC) $(CFLAGS) -c $f/misc.c
mount.s: $a
mount.s: $s/stat.h
mount.s: $f/buf.h
mount.s: $f/file.h
mount.s: $f/fproc.h
mount.s: $f/inode.h
mount.s: $f/param.h
mount.s: $f/super.h
mount.s: $f/mount.c
$(CC) $(CFLAGS) -c $f/mount.c
open.s: $a
open.s: $i/fcntl.h
open.s: $h/callnr.h
open.s: $f/buf.h
open.s: $f/file.h
open.s: $f/fproc.h
open.s: $f/inode.h
open.s: $f/param.h
open.s: $f/open.c
$(CC) $(CFLAGS) -c $f/open.c
path.s: $a
path.s: $f/buf.h
path.s: $f/file.h
path.s: $f/fproc.h
path.s: $f/inode.h
path.s: $f/super.h
path.s: $f/path.c
$(CC) $(CFLAGS) -c $f/path.c
pipe.s: $a
pipe.s: $i/fcntl.h
pipe.s: $i/signal.h
pipe.s: $h/callnr.h
pipe.s: $h/com.h
pipe.s: $f/dev.h
pipe.s: $f/file.h
pipe.s: $f/fproc.h
pipe.s: $f/inode.h
pipe.s: $f/param.h
pipe.s: $f/pipe.c
$(CC) $(CFLAGS) -c $f/pipe.c
protect.s: $a
protect.s: $f/buf.h
protect.s: $f/file.h
protect.s: $f/fproc.h
protect.s: $f/inode.h
protect.s: $f/param.h
protect.s: $f/super.h
protect.s: $f/protect.c
$(CC) $(CFLAGS) -c $f/protect.c
putc.s: $a
putc.s: $h/com.h
putc.s: $f/putc.c
$(CC) $(CFLAGS) -c $f/putc.c
read.s: $a
read.s: $i/fcntl.h
read.s: $h/com.h
read.s: $f/buf.h
read.s: $f/file.h
read.s: $f/fproc.h
read.s: $f/inode.h
read.s: $f/param.h
read.s: $f/super.h
read.s: $f/read.c
$(CC) $(CFLAGS) -c $f/read.c
stadir.s: $a
stadir.s: $s/stat.h
stadir.s: $f/file.h
stadir.s: $f/fproc.h
stadir.s: $f/inode.h
stadir.s: $f/param.h
stadir.s: $f/stadir.c
$(CC) $(CFLAGS) -c $f/stadir.c
super.s: $a
super.s: $h/boot.h
super.s: $f/buf.h
super.s: $f/inode.h
super.s: $f/super.h
super.s: $f/super.c
$(CC) $(CFLAGS) -c $f/super.c
table.s: $a
table.s: $s/stat.h
table.s: $h/callnr.h
table.s: $h/com.h
table.s: $f/buf.h
table.s: $f/dev.h
table.s: $f/file.h
table.s: $f/fproc.h
table.s: $f/inode.h
table.s: $f/super.h
table.s: $f/table.c
$(CC) $(CFLAGS) -c $f/table.c
time.s: $a
time.s: $h/callnr.h
time.s: $h/com.h
time.s: $f/file.h
time.s: $f/fproc.h
time.s: $f/inode.h
time.s: $f/param.h
time.s: $f/time.c
$(CC) $(CFLAGS) -c $f/time.c
utility.s: $a
utility.s: $h/com.h
utility.s: $h/boot.h
utility.s: $f/buf.h
utility.s: $f/file.h
utility.s: $f/fproc.h
utility.s: $f/inode.h
utility.s: $f/param.h
utility.s: $f/super.h
utility.s: $f/utility.c
$(CC) $(CFLAGS) -c $f/utility.c
write.s: $a
write.s: $f/buf.h
write.s: $f/file.h
write.s: $f/fproc.h
write.s: $f/inode.h
write.s: $f/super.h
write.s: $f/write.c
$(CC) $(CFLAGS) -c $f/write.c

View File

@@ -0,0 +1,300 @@
# Makefile for networking kernel using standard Minix directory
# layout and compiler.
# CPP may need changing to /usr/lib/cpp.
# The following nonstandard flags are used:
# -F: run cpp and cem sequentially (used when memory is tight)
# -T.: put temporaries in working directory (when RAM disk is small)
#
# Define AM_KERNEL and NONET to get a networking kernel without
# a network interface (only local transactions). Define
# AM_KERNEL if you have a Western Digital Etherplus card and
# want remote transactions. Define STATISTICS to keep track of
# Amoeba transaction statistics and to bind function key F5 to
# dump them.
#
BIN =.
CC =cc
#CFLAGS =-F -T.
CFLAGS =-DAM_KERNEL -DSTATISTICS -I../../kernel -I. -DNO_NET
CPP =/lib/cpp
CPPFLAGS =-DASLD -P
END =/lib/end.s
LD =asld
LDFLAGS =-i
LIBS =/lib/libc.a
START =start.s
a =$k/kernel.h $h/config.h $h/const.h $h/type.h \
$s/types.h $i/limits.h $i/errno.h \
$k/const.h $k/type.h $k/proto.h $k/glo.h
h =/usr/include/minix
i =/usr/include
k =../../kernel
s =/usr/include/sys
KEROBJS =cstart.s protect.s protect1.s klib.s mpx.s wini.s \
table.s main.s tty.s floppy.s system.s proc.s \
clock.s memory.s console.s rs232.s rs2.s printer.s \
amoeba.s conf.s dp8390.s util.s etherplus.s portcache.s \
trans.s dmp.s exception.s i8259.s misc.s keyboard.s
SOBJS =start.s klib.s mpx.s rs2.s
# Rules.
.SUFFIXES: .x # .x files are .s files which need C-preprocessing
.x.s:
$(CPP) $(CPPFLAGS) $k/$< >$@
# What to make.
dummy: $(BIN)/kernel # this line fixes a bug in RAL's latest make
$(BIN)/kernel: $(START) $(KEROBJS) $(LIBS) $(END)
$(LD) $(LDFLAGS) -o $(BIN)/kernel \
$(START) $(KEROBJS) \
$(LIBS) $(END)
clean:
rm -f $(START) $(KEROBJS) $(SOBJS) *.bak
klib.s: $h/config.h $h/const.h $k/const.h $k/protect.h $k/sconst.h
klib.s: $k/klib.x
$(CPP) $(CPPFLAGS) $k/klib.x >$@
mpx.s: $h/config.h $h/const.h $h/com.h $k/const.h $k/protect.h $k/sconst.h
mpx.s: $k/mpx.x
$(CPP) $(CPPFLAGS) $k/mpx.x >$@
rs2.s: $h/config.h $h/const.h $k/const.h $k/sconst.h
rs2.s: $k/rs2.x
$(CPP) $(CPPFLAGS) $k/rs2.x >$@
start.s: $h/config.h $h/const.h $h/com.h $k/const.h $k/protect.h $k/sconst.h
start.s: $k/start.x
$(CPP) $(CPPFLAGS) $k/start.x >$@
clock.s: $a
clock.s: $i/signal.h
clock.s: $h/callnr.h
clock.s: $h/com.h
clock.s: $k/proc.h
clock.s: $k/clock.c
$(CC) $(CFLAGS) -c $k/clock.c
console.s: $a
console.s: $i/sgtty.h
console.s: $h/callnr.h
console.s: $h/com.h
console.s: $k/protect.h
console.s: $k/tty.h
console.s: $k/console.c
$(CC) $(CFLAGS) -c $k/console.c
cstart.s: $a
cstart.s: $h/boot.h
cstart.s: $k/cstart.c
$(CC) $(CFLAGS) -c $k/cstart.c
dmp.s: $a
dmp.s: $h/callnr.h
dmp.s: $h/com.h
dmp.s: $k/proc.h
dmp.s: $k/dmp.c
$(CC) $(CFLAGS) -c $k/dmp.c
exception.s: $a
exception.s: $i/signal.h
exception.s: $k/proc.h
exception.s: $k/exception.c
$(CC) $(CFLAGS) -c $k/exception.c
floppy.s: $a
floppy.s: $h/callnr.h
floppy.s: $h/com.h
floppy.s: $k/floppy.c
$(CC) $(CFLAGS) -c $k/floppy.c
i8259.s: $a
i8259.s: $k/i8259.c
$(CC) $(CFLAGS) -c $k/i8259.c
keyboard.s: $a
keyboard.s: $i/sgtty.h
keyboard.s: $i/signal.h
keyboard.s: $h/callnr.h
keyboard.s: $h/com.h
keyboard.s: $k/tty.h
keyboard.s: $k/keyboard.c
$(CC) $(CFLAGS) -c $k/keyboard.c
main.s: $a
main.s: $i/signal.h
main.s: $h/callnr.h
main.s: $h/com.h
main.s: $k/proc.h
main.s: $k/main.c
$(CC) $(CFLAGS) -c $k/main.c
memory.s: $a
memory.s: $h/callnr.h
memory.s: $h/com.h
memory.s: $k/memory.c
$(CC) $(CFLAGS) -c $k/memory.c
misc.s: $a
misc.s: $h/com.h
misc.s: $k/misc.c
$(CC) $(CFLAGS) -c $k/misc.c
printer.s: $a
printer.s: $h/callnr.h
printer.s: $h/com.h
printer.s: $k/printer.c
$(CC) $(CFLAGS) -c $k/printer.c
proc.s: $a
proc.s: $h/callnr.h
proc.s: $h/com.h
proc.s: $k/proc.h
proc.s: $k/proc.c
$(CC) $(CFLAGS) -c $k/proc.c
protect.s: $a
protect.s: $k/protect.h
protect.s: $k/protect1.c
protect.s: $k/protect.c
$(CC) $(CFLAGS) -c $k/protect.c
protect1.s: $a
protect1.s: $k/proc.h
protect1.s: $k/protect.h
protect1.s: $k/protect1.c
$(CC) $(CFLAGS) -c $k/protect1.c
rs232.s: $a
rs232.s: $i/sgtty.h
rs232.s: $k/tty.h
rs232.s: $k/rs232.c
$(CC) $(CFLAGS) -c $k/rs232.c
system.s: $a
system.s: $i/signal.h
system.s: $h/boot.h
system.s: $h/callnr.h
system.s: $h/com.h
system.s: $k/proc.h
system.s: $k/protect.h
system.s: $k/system.c
$(CC) $(CFLAGS) -c $k/system.c
table.s: $a
table.s: $h/com.h
table.s: $k/proc.h
table.s: $k/tty.h
table.s: $k/table.c
$(CC) $(CFLAGS) -c $k/table.c
tty.s: $a
tty.s: $i/sgtty.h
tty.s: $i/signal.h
tty.s: $h/callnr.h
tty.s: $h/com.h
tty.s: $k/tty.h
tty.s: $k/tty.c
$(CC) $(CFLAGS) -c $k/tty.c
wini.s: $a
wini.s: $h/callnr.h
wini.s: $h/com.h
wini.s: $h/partition.h
wini.s: $k/wini.c
$(CC) $(CFLAGS) -c $k/wini.c
amoeba.s: $a
amoeba.s: $i/amoeba.h
amoeba.s: $i/host_os.h
amoeba.s: $i/amparam.h
amoeba.s: $i/signal.h
amoeba.s: $i/assert.h
amoeba.s: ./byteorder.h
amoeba.s: ./dp8390info.h
amoeba.s: ./etherformat.h
amoeba.s: ./global.h
amoeba.s: ./internet.h
amoeba.s: ./mpx.H
amoeba.s: ./portcache.H
amoeba.s: $k/proc.h
amoeba.s: ./task.h
amoeba.s: ./trans.H
amoeba.s: amoeba.c
conf.s: $a
conf.s: $i/amoeba.h
conf.s: ./conf.h
conf.s: ./global.h
conf.s: ./mpx.H
conf.s: ./portcache.H
conf.s: ./task.h
conf.s: ./trans.H
conf.s: conf.c
dp8390.s: $a
dp8390.s: $h/com.h
dp8390.s: $i/assert.h
dp8390.s: ./dp8390.h
dp8390.s: ./dp8390info.h
dp8390.s: ./dp8390stat.h
dp8390.s: ./etherformat.h
dp8390.s: ./internet.h
dp8390.s: dp8390.c
etherplus.s: $a
etherplus.s: $h/com.h
etherplus.s: $i/assert.h
etherplus.s: ./dp8390.h
etherplus.s: ./dp8390info.h
etherplus.s: ./eplinfo.h
etherplus.s: ./etherformat.h
etherplus.s: ./etherplus.h
etherplus.s: ./internet.h
etherplus.s: etherplus.c
portcache.s: $a
portcache.s: $i/amoeba.h
portcache.s: $i/host_os.h
portcache.s: ./assert.h
portcache.s: ./conf.h
portcache.s: ./global.h
portcache.s: ./internet.h
portcache.s: ./mpx.H
portcache.s: ./portcache.H
portcache.s: ./task.h
portcache.s: ./trans.H
portcache.s: portcache.c
trans.s: $a
trans.s: $i/amoeba.h
trans.s: $i/host_os.h
trans.s: ./amstat.h
trans.s: ./assert.h
trans.s: ./byteorder.h
trans.s: ./exception.h
trans.s: ./global.h
trans.s: ./internet.h
trans.s: ./mpx.H
trans.s: ./portcache.H
trans.s: ./task.h
trans.s: ./trans.H
trans.s: trans.c
util.s: $a
util.s: $h/com.h
util.s: ./assert.h
util.s: ./dp8390.h
util.s: ./dp8390info.h
util.s: ./eplinfo.h
util.s: $k/proc.h
util.s: util.c

View File

@@ -0,0 +1,302 @@
# Makefile for networking kernel using standard Minix directory
# layout and compiler.
#
# /usr/lib/cpp needs about 50K of stack, which is more than usual
#
# The following nonstandard flags are used:
# -F: run cpp and cem sequentially (used when memory is tight)
# -T.: put temporaries in working directory (when RAM disk is small)
#
# Define AM_KERNEL and NONET to get a networking kernel without
# a network interface (only local transactions). Define
# AM_KERNEL if you have a Western Digital Etherplus card and
# want remote transactions. Define STATISTICS to keep track of
# Amoeba transaction statistics and to bind function key F5 to
# dump them.
#
BIN =.
CC =cc
#CFLAGS =-F -T.
CFLAGS =-DAM_KERNEL -DSTATISTICS -I../../kernel -I. -F
CPP =/usr/lib/cpp
CPPFLAGS =-DASLD -P
END =/usr/lib/end.s
LD =asld
LDFLAGS =-i
LIBS =/usr/lib/libc.a
START =start.s
a =$k/kernel.h $h/config.h $h/const.h $h/type.h \
$s/types.h $i/limits.h $i/errno.h \
$k/const.h $k/type.h $k/proto.h $k/glo.h
h =/usr/include/minix
i =/usr/include
k =../../kernel
s =/usr/include/sys
KEROBJS =cstart.s protect.s protect1.s klib.s mpx.s wini.s \
table.s main.s tty.s floppy.s system.s proc.s \
clock.s memory.s console.s rs232.s rs2.s printer.s \
amoeba.s conf.s dp8390.s util.s etherplus.s portcache.s \
trans.s dmp.s exception.s i8259.s misc.s keyboard.s
SOBJS =start.s klib.s mpx.s rs2.s
# Rules.
.SUFFIXES: .x # .x files are .s files which need C-preprocessing
.x.s:
$(CPP) $(CPPFLAGS) $k/$< >$@
# What to make.
dummy: $(BIN)/kernel # this line fixes a bug in RAL's latest make
$(BIN)/kernel: $(START) $(KEROBJS) $(LIBS) $(END)
$(LD) $(LDFLAGS) -o $(BIN)/kernel \
$(START) $(KEROBJS) \
$(LIBS) $(END)
clean:
rm -f $(START) $(KEROBJS) $(SOBJS) *.bak
klib.s: $h/config.h $h/const.h $k/const.h $k/protect.h $k/sconst.h
klib.s: $k/klib.x
$(CPP) $(CPPFLAGS) $k/klib.x >$@
mpx.s: $h/config.h $h/const.h $h/com.h $k/const.h $k/protect.h $k/sconst.h
mpx.s: $k/mpx.x
$(CPP) $(CPPFLAGS) $k/mpx.x >$@
rs2.s: $h/config.h $h/const.h $k/const.h $k/sconst.h
rs2.s: $k/rs2.x
$(CPP) $(CPPFLAGS) $k/rs2.x >$@
start.s: $h/config.h $h/const.h $h/com.h $k/const.h $k/protect.h $k/sconst.h
start.s: $k/start.x
$(CPP) $(CPPFLAGS) $k/start.x >$@
clock.s: $a
clock.s: $i/signal.h
clock.s: $h/callnr.h
clock.s: $h/com.h
clock.s: $k/proc.h
clock.s: $k/clock.c
$(CC) $(CFLAGS) -c $k/clock.c
console.s: $a
console.s: $i/sgtty.h
console.s: $h/callnr.h
console.s: $h/com.h
console.s: $k/protect.h
console.s: $k/tty.h
console.s: $k/console.c
$(CC) $(CFLAGS) -c $k/console.c
cstart.s: $a
cstart.s: $h/boot.h
cstart.s: $k/cstart.c
$(CC) $(CFLAGS) -c $k/cstart.c
dmp.s: $a
dmp.s: $h/callnr.h
dmp.s: $h/com.h
dmp.s: $k/proc.h
dmp.s: $k/dmp.c
$(CC) $(CFLAGS) -c $k/dmp.c
exception.s: $a
exception.s: $i/signal.h
exception.s: $k/proc.h
exception.s: $k/exception.c
$(CC) $(CFLAGS) -c $k/exception.c
floppy.s: $a
floppy.s: $h/callnr.h
floppy.s: $h/com.h
floppy.s: $k/floppy.c
$(CC) $(CFLAGS) -c $k/floppy.c
i8259.s: $a
i8259.s: $k/i8259.c
$(CC) $(CFLAGS) -c $k/i8259.c
keyboard.s: $a
keyboard.s: $i/sgtty.h
keyboard.s: $i/signal.h
keyboard.s: $h/callnr.h
keyboard.s: $h/com.h
keyboard.s: $k/tty.h
keyboard.s: $k/keyboard.c
$(CC) $(CFLAGS) -c $k/keyboard.c
main.s: $a
main.s: $i/signal.h
main.s: $h/callnr.h
main.s: $h/com.h
main.s: $k/proc.h
main.s: $k/main.c
$(CC) $(CFLAGS) -c $k/main.c
memory.s: $a
memory.s: $h/callnr.h
memory.s: $h/com.h
memory.s: $k/memory.c
$(CC) $(CFLAGS) -c $k/memory.c
misc.s: $a
misc.s: $h/com.h
misc.s: $k/misc.c
$(CC) $(CFLAGS) -c $k/misc.c
printer.s: $a
printer.s: $h/callnr.h
printer.s: $h/com.h
printer.s: $k/printer.c
$(CC) $(CFLAGS) -c $k/printer.c
proc.s: $a
proc.s: $h/callnr.h
proc.s: $h/com.h
proc.s: $k/proc.h
proc.s: $k/proc.c
$(CC) $(CFLAGS) -c $k/proc.c
protect.s: $a
protect.s: $k/protect.h
protect.s: $k/protect1.c
protect.s: $k/protect.c
$(CC) $(CFLAGS) -c $k/protect.c
protect1.s: $a
protect1.s: $k/proc.h
protect1.s: $k/protect.h
protect1.s: $k/protect1.c
$(CC) $(CFLAGS) -c $k/protect1.c
rs232.s: $a
rs232.s: $i/sgtty.h
rs232.s: $k/tty.h
rs232.s: $k/rs232.c
$(CC) $(CFLAGS) -c $k/rs232.c
system.s: $a
system.s: $i/signal.h
system.s: $h/boot.h
system.s: $h/callnr.h
system.s: $h/com.h
system.s: $k/proc.h
system.s: $k/protect.h
system.s: $k/system.c
$(CC) $(CFLAGS) -c $k/system.c
table.s: $a
table.s: $h/com.h
table.s: $k/proc.h
table.s: $k/tty.h
table.s: $k/table.c
$(CC) $(CFLAGS) -c $k/table.c
tty.s: $a
tty.s: $i/sgtty.h
tty.s: $i/signal.h
tty.s: $h/callnr.h
tty.s: $h/com.h
tty.s: $k/tty.h
tty.s: $k/tty.c
$(CC) $(CFLAGS) -c $k/tty.c
wini.s: $a
wini.s: $h/callnr.h
wini.s: $h/com.h
wini.s: $h/partition.h
wini.s: $k/wini.c
$(CC) $(CFLAGS) -c $k/wini.c
amoeba.s: $a
amoeba.s: $i/amoeba.h
amoeba.s: $i/host_os.h
amoeba.s: $i/amparam.h
amoeba.s: $i/signal.h
amoeba.s: $i/assert.h
amoeba.s: ./byteorder.h
amoeba.s: ./dp8390info.h
amoeba.s: ./etherformat.h
amoeba.s: ./global.h
amoeba.s: ./internet.h
amoeba.s: ./mpx.H
amoeba.s: ./portcache.H
amoeba.s: $k/proc.h
amoeba.s: ./task.h
amoeba.s: ./trans.H
amoeba.s: amoeba.c
conf.s: $a
conf.s: $i/amoeba.h
conf.s: ./conf.h
conf.s: ./global.h
conf.s: ./mpx.H
conf.s: ./portcache.H
conf.s: ./task.h
conf.s: ./trans.H
conf.s: conf.c
dp8390.s: $a
dp8390.s: $h/com.h
dp8390.s: $i/assert.h
dp8390.s: ./dp8390.h
dp8390.s: ./dp8390info.h
dp8390.s: ./dp8390stat.h
dp8390.s: ./etherformat.h
dp8390.s: ./internet.h
dp8390.s: dp8390.c
etherplus.s: $a
etherplus.s: $h/com.h
etherplus.s: $i/assert.h
etherplus.s: ./dp8390.h
etherplus.s: ./dp8390info.h
etherplus.s: ./eplinfo.h
etherplus.s: ./etherformat.h
etherplus.s: ./etherplus.h
etherplus.s: ./internet.h
etherplus.s: etherplus.c
portcache.s: $a
portcache.s: $i/amoeba.h
portcache.s: $i/host_os.h
portcache.s: ./assert.h
portcache.s: ./conf.h
portcache.s: ./global.h
portcache.s: ./internet.h
portcache.s: ./mpx.H
portcache.s: ./portcache.H
portcache.s: ./task.h
portcache.s: ./trans.H
portcache.s: portcache.c
trans.s: $a
trans.s: $i/amoeba.h
trans.s: $i/host_os.h
trans.s: ./amstat.h
trans.s: ./assert.h
trans.s: ./byteorder.h
trans.s: ./exception.h
trans.s: ./global.h
trans.s: ./internet.h
trans.s: ./mpx.H
trans.s: ./portcache.H
trans.s: ./task.h
trans.s: ./trans.H
trans.s: trans.c
util.s: $a
util.s: $h/com.h
util.s: ./assert.h
util.s: ./dp8390.h
util.s: ./dp8390info.h
util.s: ./eplinfo.h
util.s: $k/proc.h
util.s: util.c

View File

@@ -0,0 +1,13 @@
struct amstat {
long ams_clfail;
long ams_svfail;
long ams_clcrash;
long ams_rxcl;
long ams_rxsv;
long ams_trans;
long ams_loctrans;
long ams_remtrans;
long ams_getreq;
long ams_putrep;
long ams_naks;
};

View File

@@ -0,0 +1,43 @@
/****************************************************************************
* *
* (c) Copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands *
* *
* This product is part of the Amoeba distributed operating system. *
* Permission is hereby granted to use it exclusively for educational *
* and research purposes. It may also be freely duplicated and given *
* to others for educational and research purposes only. All other use *
* requires written permission from the copyright owner. *
* *
* Requests for such permissions may be sent to *
* *
* *
* Dr. Andrew S. Tanenbaum *
* Dept. of Mathematics and Computer Science *
* Vrije Universiteit *
* De Boelelaan 1081 *
* 1081 HV Amsterdam *
* The Netherlands *
* *
/****************************************************************************/
#define NDEBUG
#ifdef NDEBUG
#define assert(e) /* NOTHING */
#define compare(a,t,b) /* NOTHING */
#else
#ifdef lint
#define assert(e) use(e)
#define compare(a,t,b) use(a, b)
#else lint
#define assert(x) if (!(x)) printf("assertion failed in %s at %d\n", __FILE__, __LINE__)
#define compare(a,t,b) if (!((a) t (b))) \
printf("comparison failed in %s at %d (%D)\n", \
__FILE__, __LINE__, a)
/*
#define assert(e) do if (!(e)) badassertion(__FILE__,__LINE__); while (0)
#define compare(a,t,b) do if (!((a) t (b))) \
badcompare(__FILE__,__LINE__, (long) (a)); \
while (0)
*/
#endif lint
#endif NDEBUG

View File

@@ -0,0 +1,21 @@
/*
* set of macros to do inplace byteorder changes
* The dec_* routines decode a short (_s) or long (_l) from little endian(_le)
* or bigendian(_be) to native format.
* The enc_* are similar for native to net format
*/
/* littleendian version for ibm pc */
#define dec_s_le(s) /* nothing */
#define dec_s_be(s) (*(s))=((((*(s))>>8)&0xFF)|(((*(s))&0xFF)<<8))
#define dec_l_le(l) /* nothing */
#define dec_l_be(l) (*(l))=((((*(l))>>24)&0xFF)|(((*(l))>>8)&0xFF00)|(((*(l))<<8)&0xFF0000)|(((*(l))<<24)&0xFF000000))
#define enc_s_le(s) /* nothing */
#define enc_s_be(s) dec_s_be(s)
#define enc_l_le(l) /* nothing */
#define enc_l_be(l) dec_l_be(l)

View File

@@ -0,0 +1,40 @@
#include "kernel.h"
#include "amoeba.h"
#include "global.h"
#include "conf.h"
/*
** the following hack is imported from task.c under Amoeba to declare
** a few pointers to the task table
*/
#define extern
#include "task.h"
#undef extern
/************************************************************************/
/* TRANS CONFIGURATION */
/************************************************************************/
/*
** various variables used for transactions
*/
port NULLPORT; /* used in trans.c, declared here for compatability */
long ticker; /* bogus global used by trans.c for statistics */
#ifndef NONET
unshort minloccnt = MINLOCCNT;
unshort maxloccnt = MAXLOCCNT;
unshort retranstime = RETRANSTIME;
unshort crashtime = CRASHTIME;
unshort clientcrash = CLIENTCRASH;
unshort maxretrans = MAXRETRANS;
unshort mincrash = MINCRASH;
unshort maxcrash = MAXCRASH;
#endif NONET

View File

@@ -0,0 +1,15 @@
/*
** constants used for configuring amoeba transactions
*/
#define MINLOCCNT 5 /* locate message sent every dsec */
#define MAXLOCCNT 100 /* locate message sent every MAXLOCCNT dsec */
#define RETRANSTIME 5 /* retransmission time in dsec */
#define CRASHTIME 100 /* crash timer in dsec */
#define CLIENTCRASH 500 /* client must probe within this time */
#define MAXRETRANS 10 /* max. number of transmissions */
#define MINCRASH 5 /* enquiry sent MINCRASH times during recv */
#define MAXCRASH 10 /* enquiry sent MAXCRASH times during serv */
#define NPORTS 16 /* # ports in portcache */

View File

@@ -0,0 +1,344 @@
#include "kernel.h"
#ifndef NONET
#include "minix/com.h"
#include "internet.h"
#include "etherformat.h"
#include "dp8390.h"
#include "dp8390info.h"
#include "dp8390stat.h"
#include "assert.h"
/* macros for device I/O */
#define input(devaddr, dp_register) \
in_byte((vir_bytes)&((union dp8390reg *) devaddr)->dp_pg0rd.dp_register)
#define input1(devaddr, dp_register) \
in_byte((vir_bytes)&((union dp8390reg *) devaddr)->dp_pg1rdwr.dp_register)
#define output(devaddr, dp_register, value) \
out_byte((vir_bytes)&((union dp8390reg *) devaddr)->dp_pg0wr.dp_register, value)
#define output1(devaddr, dp_register, value) \
out_byte((vir_bytes)&((union dp8390reg *) devaddr)->dp_pg1rdwr.dp_register, value)
#define MAX_WAIT 10000
#ifdef DPSTAT
struct dpstat dpstat;
#endif
static int (*bufread)(); /* call when packet came in */
static int (*bufwritten)(); /* call when packet has been written */
static disabled;
static phys_bytes curopacket; /* packet being transmitted */
static phys_bytes Curbuff; /* address of next read buffer to release */
static
chipinit(myaddr)
Eth_addr *myaddr;
{
register vir_bytes device;
device = dp8390info.dpi_devaddr;
output(device, dp_cr, CR_PS_P0|CR_DM_ABORT); /* back to main register set */
output(device, dp_pstart, dp8390info.dpi_pstart);
output(device, dp_pstop, dp8390info.dpi_pstop);
output(device, dp_bnry, dp8390info.dpi_pstart);
output(device, dp_rcr, RCR_MON);
output(device, dp_tcr, TCR_NORMAL);
output(device, dp_dcr, DCR_BYTEWIDE|DCR_8BYTES);
output(device, dp_rbcr0, 0);
output(device, dp_rbcr1, 0);
output(device, dp_isr, 0xFF);
output(device, dp_cr, CR_PS_P1|CR_DM_ABORT); /* switch to register set 1 */
output1(device, dp_par0, myaddr->e[0]);
output1(device, dp_par1, myaddr->e[1]);
output1(device, dp_par2, myaddr->e[2]);
output1(device, dp_par3, myaddr->e[3]);
output1(device, dp_par4, myaddr->e[4]);
output1(device, dp_par5, myaddr->e[5]);
output1(device, dp_curr, dp8390info.dpi_pstart+1);
output1(device, dp_cr, CR_PS_P0|CR_DM_ABORT);
output(device, dp_rcr, RCR_AB);
input(device, dp_cntr0);
input(device, dp_cntr1);
input(device, dp_cntr2);
#ifdef TRMTINT
output(device, dp_imr, IMR_TXEE|IMR_PTXE|IMR_PRXE|IMR_CNTE|IMR_OVWE);
#endif
output(device, dp_imr, IMR_PRXE|IMR_CNTE|IMR_OVWE);
output(device, dp_cr, CR_STA|CR_DM_ABORT); /* fire it up */
}
/*
* Interrupt handling
*/
static
dp_xmit_intr()
#ifdef TRMTINT
{
register tsr;
if (curopacket == 0) {
printf("Bogus transmit interrupt\n");
STINC(ds_btint);
return;
}
tsr = input(dp8390info.dpi_devaddr, dp_tsr);
if (tsr&TSR_PTX)
STINC(ds_written); /* It went OK! */
if (tsr&TSR_DFR)
STINC(ds_deferred);
if (tsr&TSR_COL)
STINC(ds_collisions);
if (tsr&TSR_ABT)
STINC(ds_xcollisions);
if (tsr&TSR_CRS) {
printf("Ethernet carrier sense lost\n");
STINC(ds_carlost);
}
if (tsr&TSR_FU) {
printf("Ethernet Fifo Underrun\n");
STINC(ds_fifo);
}
if (tsr&TSR_CDH) {
printf("Ethernet Heartbeat failure\n");
STINC(ds_heartbeat);
}
if (tsr&TSR_OWC) {
printf("Ethernet late collision\n");
STINC(ds_lcol);
}
(*bufwritten)(curopacket);
curopacket = 0;
}
#else
{}
#endif
static
recvintr()
{
register vir_bytes device;
register phys_bytes paddr;
struct rcvdheader pkthead;
char pageno, curr, next;
int length;
device = dp8390info.dpi_devaddr;
pageno=input(device, dp_bnry)+1;
if (pageno == dp8390info.dpi_pstop)
pageno = dp8390info.dpi_pstart;
while (!(disabled)) {
output(device, dp_cr, CR_PS_P1);/* switch to register set 1 */
curr = input1(device, dp_curr);
output1(device, dp_cr, CR_PS_P0);/* back to main register set*/
if (pageno==curr){
break;
}
STINC(ds_read);
paddr = dp8390info.dpi_membase+(pageno<<8);
getheader(paddr, &pkthead);
next = pkthead.rp_next;
if (pkthead.rp_status&RSR_PRX) {
if (next < pageno && next > dp8390info.dpi_pstart) {
/*
* We copy end of packet to avoid break.
*/
phys_copy(dp8390info.dpi_membase+
(dp8390info.dpi_pstart<<8),
dp8390info.dpi_membase+
(dp8390info.dpi_pstop<<8),
(phys_bytes) (next-dp8390info.dpi_pstart)<<8);
}
length = (pkthead.rp_rbcl&0xFF)|(pkthead.rp_rbch<<8);
Curbuff = paddr + sizeof (pkthead);
disabled = 1;
(*bufread)(Curbuff, length-4);
}
pageno = pkthead.rp_next;
if (pageno >= dp8390info.dpi_pstop ||
pageno < dp8390info.dpi_pstart)
printf("page no %x\n", pageno);
/* assert(pageno >= dp8390info.dpi_pstart);
assert(pageno < dp8390info.dpi_pstop);*/
}
}
static
cntintr()
{
register vir_bytes device;
int n;
printf("dp8390: counter overflow\n"); /*DEBUG*/
device = dp8390info.dpi_devaddr;
n = input(device, dp_cntr0);
STADD(ds_fram, n);
n = input(device, dp_cntr1);
STADD(ds_crc, n);
n =input(device, dp_cntr2);
STADD(ds_lost, n);
}
PUBLIC void
dp8390_int()
{
register isr;
register vir_bytes device;
device = dp8390info.dpi_devaddr;
for(isr=input(device, dp_isr); isr&(ISR_OVW|ISR_PRX|ISR_PTX|ISR_CNT);
isr=input(device, dp_isr)) {
if (isr&ISR_OVW) {
printf("OVW, do something\n");
output(device, dp_isr, ISR_OVW); /* ack */
}
if (isr&ISR_PTX) {
dp_xmit_intr();
output(device, dp_isr, ISR_PTX); /* ack */
}
if (isr&ISR_TXE) {
dp_xmit_intr();
output(device, dp_isr, ISR_TXE); /* ack */
}
if (isr&ISR_PRX) {
/*recvintr();*/
got_packet();
output(device, dp_isr, ISR_PRX); /* ack */
}
if (isr&ISR_CNT) {
cntintr();
output(device, dp_isr, ISR_CNT); /* ack */
}
}
}
eth_init(etheraddr, br, bw)
Eth_addr *etheraddr;
int (*br)(), (*bw)();
{
bufread = br;
bufwritten = bw;
epl_init(); /* activate on board memory */
chipinit(etheraddr); /* start ethernet controller chip */
}
eth_write(bufaddr, bufcnt)
phys_bytes bufaddr;
{
int bpageno;
register vir_bytes device;
device = dp8390info.dpi_devaddr;
/* assert(curopacket==0); */
assert(((bufaddr-dp8390info.dpi_membase)&0xFF)==0);
assert(bufcnt >= 60); /* magic Ethernet requirement */
/* assert(bufcnt <= 1514); /* another one */
bpageno = ((bufaddr-dp8390info.dpi_membase)>>8) & 0xFF;
curopacket = bufaddr;
output(device, dp_tpsr, bpageno);
output(device, dp_tbcr1, bufcnt>>8);
output(device, dp_tbcr0, bufcnt&0xFF);
output(device, dp_cr, CR_TXP); /* there it goes */
}
eth_release(bufaddr)
phys_bytes bufaddr;
{
register vir_bytes device;
register phys_bytes paddr;
struct rcvdheader pkthead;
char pageno;
device = dp8390info.dpi_devaddr;
paddr = bufaddr-sizeof(pkthead);
assert(((paddr-dp8390info.dpi_membase)&0xFF)==0);
getheader(paddr, &pkthead);
pageno = pkthead.rp_next;
if (pageno == dp8390info.dpi_pstart)
pageno = dp8390info.dpi_pstop;
if (bufaddr != Curbuff)
panic("eth_release: bad order", NO_NUM);
output(device, dp_bnry, pageno-1);
disabled = 0;
/* recvintr(); */
}
phys_bytes
eth_getbuf()
{
int t_cnt;
register vir_bytes device;
register tsr;
device = dp8390info.dpi_devaddr;
t_cnt = 0;
while (input(device,dp_cr)&CR_TXP) {
if (t_cnt++ > MAX_WAIT)
printf("transmitter frozen\n");
return (phys_bytes)0;
}
#ifndef TRMTINT
#ifdef DPSTAT
tsr = input(device, dp_tsr);
if (tsr&TSR_PTX)
STINC(ds_written); /* It went OK! */
if (tsr&TSR_DFR)
STINC(ds_deferred);
if (tsr&TSR_COL)
STINC(ds_collisions);
if (tsr&TSR_ABT)
STINC(ds_xcollisions);
if (tsr&TSR_CRS) {
printf("Ethernet carrier sense lost\n");
STINC(ds_carlost);
}
if (tsr&TSR_FU) {
printf("Ethernet Fifo Underrun\n");
STINC(ds_fifo);
}
if (tsr&TSR_CDH) {
printf("Ethernet Heartbeat failure\n");
STINC(ds_heartbeat);
}
if (tsr&TSR_OWC) {
printf("Ethernet late collision\n");
STINC(ds_lcol);
}
#endif
#endif
return dp8390info.dpi_tbuf; /* return pointer to xmit buffer */
}
#else NONET
PUBLIC void
dp8390_int()
{
}
#endif NONET
PUBLIC void
eth_stp()
{
/* called from reboot() (klib88.s) to stop the ethernet */
#ifndef NONET
output(dp8390info.dpi_devaddr, dp_cr, CR_STP|CR_DM_ABORT);
#endif
}

View File

@@ -0,0 +1,165 @@
/*
* National Semiconductor DP8390 Network Interface Controller
*/
typedef
union dp8390reg {
struct pg0rd { /* Page 0, for reading ------------- */
char dp_cr; /* Read side of Command Register */
char dp_clda0; /* Current Local Dma Address 0 */
char dp_clda1; /* Current Local Dma Address 1 */
char dp_bnry; /* Boundary Pointer */
char dp_tsr; /* Transmit Status Register */
char dp_ncr; /* Number of Collisions Register */
char dp_fifo; /* Fifo ?? */
char dp_isr; /* Interrupt Status Register */
char dp_crda0; /* Current Remote Dma Address 0 */
char dp_crda1; /* Current Remote Dma Address 1 */
char dp_dum1; /* unused */
char dp_dum2; /* unused */
char dp_rsr; /* Receive Status Register */
char dp_cntr0; /* Tally Counter 0 */
char dp_cntr1; /* Tally Counter 1 */
char dp_cntr2; /* Tally Counter 2 */
} dp_pg0rd;
struct pg0wr { /* Page 0, for writing ------------- */
char dp_cr; /* Write side of Command Register */
char dp_pstart; /* Page Start Register */
char dp_pstop; /* Page Stop Register */
char dp_bnry; /* Boundary Pointer */
char dp_tpsr; /* Transmit Page Start Register */
char dp_tbcr0; /* Transmit Byte Count Register 0 */
char dp_tbcr1; /* Transmit Byte Count Register 1 */
char dp_isr; /* Interrupt Status Register */
char dp_rsar0; /* Remote Start Address Register 0 */
char dp_rsar1; /* Remote Start Address Register 1 */
char dp_rbcr0; /* Remote Byte Count Register 0 */
char dp_rbcr1; /* Remote Byte Count Register 1 */
char dp_rcr; /* Receive Configuration Register */
char dp_tcr; /* Transmit Configuration Register */
char dp_dcr; /* Data Configuration Register */
char dp_imr; /* Interrupt Mask Register */
} dp_pg0wr;
struct pg1rdwr { /* Page 1, read/write -------------- */
char dp_cr; /* Command Register */
char dp_par0; /* Physical Address Register 0 */
char dp_par1; /* Physical Address Register 1 */
char dp_par2; /* Physical Address Register 2 */
char dp_par3; /* Physical Address Register 3 */
char dp_par4; /* Physical Address Register 4 */
char dp_par5; /* Physical Address Register 5 */
char dp_curr; /* Current Page Register */
char dp_mar0; /* Multicast Address Register 0 */
char dp_mar1; /* Multicast Address Register 1 */
char dp_mar2; /* Multicast Address Register 2 */
char dp_mar3; /* Multicast Address Register 3 */
char dp_mar4; /* Multicast Address Register 4 */
char dp_mar5; /* Multicast Address Register 5 */
char dp_mar6; /* Multicast Address Register 6 */
char dp_mar7; /* Multicast Address Register 7 */
} dp_pg1rdwr;
} dp8390;
/* Bits in dp_cr */
#define CR_STP 0x01 /* Stop: software reset */
#define CR_STA 0x02 /* Start: activate NIC */
#define CR_TXP 0x04 /* Transmit Packet */
#define CR_DMA 0x38 /* Mask for DMA control */
# define CR_DM_NOP 0x00 /* DMA: No Operation */
# define CR_DM_RR 0x08 /* DMA: Remote Read */
# define CR_DM_RW 0x10 /* DMA: Remote Write */
# define CR_DM_SP 0x18 /* DMA: Send Packet */
# define CR_DM_ABORT 0x20 /* DMA: Abort Remote DMA Operation */
#define CR_PS 0xC0 /* Mask for Page Select */
# define CR_PS_P0 0x00 /* Register Page 0 */
# define CR_PS_P1 0x40 /* Register Page 1 */
# define CR_PS_T0 0x80 /* Test Mode Register Map ?? */
# define CR_SP_T1 0xC0 /* Test Mode Register Map ?? */
/* Bits in dp_isr */
#define ISR_PRX 0x01 /* Packet Received with no errors */
#define ISR_PTX 0x02 /* Packet Transmitted with no errors */
#define ISR_RXE 0x04 /* Receive Error */
#define ISR_TXE 0x08 /* Transmit Error */
#define ISR_OVW 0x10 /* Overwrite Warning */
#define ISR_CNT 0x20 /* Counter Overflow */
#define ISR_RDC 0x40 /* Remote DMA Complete */
#define ISR_RST 0x80 /* Reset Status */
/* Bits in dp_imr */
#define IMR_PRXE 0x01 /* Packet Received iEnable */
#define IMR_PTXE 0x02 /* Packet Transmitted iEnable */
#define IMR_RXEE 0x04 /* Receive Error iEnable */
#define IMR_TXEE 0x08 /* Transmit Error iEnable */
#define IMR_OVWE 0x10 /* Overwrite Warning iEnable */
#define IMR_CNTE 0x20 /* Counter Overflow iEnable */
#define IMR_RDCE 0x40 /* DMA Complete iEnable */
/* Bits in dp_dcr */
#define DCR_WTS 0x01 /* Word Transfer Select */
# define DCR_BYTEWIDE 0x00 /* WTS: byte wide transfers */
# define DCR_WORDWIDE 0x01 /* WTS: word wide transfers */
#define DCR_BOS 0x02 /* Byte Order Select */
# define DCR_LTLENDIAN 0x00 /* BOS: Little Endian */
# define DCR_BIGENDIAN 0x02 /* BOS: Big Endian */
#define DCR_LAS 0x04 /* Long Address Select */
#define DCR_BMS 0x08 /* Burst Mode Select */
#define DCR_AR 0x10 /* Autoinitialize Remote */
#define DCR_FTS 0x60 /* Fifo Threshold Select */
# define DCR_2BYTES 0x00 /* 2 bytes */
# define DCR_4BYTES 0x40 /* 4 bytes */
# define DCR_8BYTES 0x20 /* 8 bytes */
# define DCR_12BYTES 0x60 /* 12 bytes */
/* Bits in dp_tcr */
#define TCR_CRC 0x01 /* Inhibit CRC */
#define TCR_ELC 0x06 /* Encoded Loopback Control */
# define TCR_NORMAL 0x00 /* ELC: Normal Operation */
# define TCR_INTERNAL 0x02 /* ELC: Internal Loopback */
# define TCR_0EXTERNAL 0x04 /* ELC: External Loopback LPBK=0 */
# define TCR_1EXTERNAL 0x06 /* ELC: External Loopback LPBK=1 */
#define TCR_ATD 0x08 /* Auto Transmit */
#define TCR_OFST 0x10 /* Collision Offset Enable (be nice) */
/* Bits in dp_tsr */
#define TSR_PTX 0x01 /* Packet Transmitted (without error)*/
#define TSR_DFR 0x02 /* Transmit Deferred */
#define TSR_COL 0x04 /* Transmit Collided */
#define TSR_ABT 0x08 /* Transmit Aborted */
#define TSR_CRS 0x10 /* Carrier Sense Lost */
#define TSR_FU 0x20 /* Fifo Underrun */
#define TSR_CDH 0x40 /* CD Heartbeat */
#define TSR_OWC 0x80 /* Out of Window Collision */
/* Bits in tp_rcr */
#define RCR_SEP 0x01 /* Save Errored Packets */
#define RCR_AR 0x02 /* Accept Runt Packets */
#define RCR_AB 0x04 /* Accept Broadcast */
#define RCR_AM 0x08 /* Accept Multicast */
#define RCR_PRO 0x10 /* Physical Promiscuous */
#define RCR_MON 0x20 /* Monitor Mode */
/* Bits in dp_rsr */
#define RSR_PRX 0x01 /* Packet Received Intact */
#define RSR_CRC 0x02 /* CRC Error */
#define RSR_FAE 0x04 /* Frame Alignment Error */
#define RSR_FO 0x08 /* FIFO Overrun */
#define RSR_MPA 0x10 /* Missed Packet */
#define RSR_PHY 0x20 /* Multicast Address Match !! */
#define RSR_DIS 0x40 /* Receiver Disabled */
struct rcvdheader {
char rp_status; /* Copy of rsr */
char rp_next; /* Pointer to next packet */
char rp_rbcl; /* Receive Byte Count Low */
char rp_rbch; /* Receive Byte Count High */
};

View File

@@ -0,0 +1,14 @@
/*
* parameters for driver for
* National Semiconductor DP8390 Network Interface Controller
*/
extern
struct dp8390info {
vir_bytes dpi_devaddr; /* device address */
char dpi_pstart; /* start of recv ring */
char dpi_pstop; /* end of recv ring */
phys_bytes dpi_membase; /* memory address of page 0 */
phys_bytes dpi_tbuf; /* memory address of transmit buffer */
} dp8390info;

View File

@@ -0,0 +1,23 @@
#ifdef DPSTAT
/* statistics from dp8390 */
struct dpstat {
long ds_read; /* packets read */
long ds_written; /* packets written */
long ds_fram; /* Input framing errors */
long ds_crc; /* Input CRC errors */
long ds_lost; /* Packets lost */
long ds_btint; /* Bogus transmit interrupts */
long ds_deferred; /* Deferred packets */
long ds_collisions; /* Packets collided at least once */
long ds_xcollisions; /* Aborts due to excessive collisions */
long ds_carlost; /* Carrier sense lost */
long ds_fifo; /* Fifo underrun */
long ds_heartbeat; /* Heart beat failure */
long ds_lcol; /* Late collisions */
};
#define STINC(x) dpstat.x++
#define STADD(x,y) dpstat.x += y
#else
#define STINC(x) /* nothing */
#define STADD(x,y) /* nothing */
#endif DPSTAT

View File

@@ -0,0 +1,10 @@
/*
* parameters for initialisation of
* Western Digital Ethercard Plus, or WD8003E
*/
extern
struct eplinfo {
vir_bytes epi_devaddr; /* device address */
} eplinfo;

View File

@@ -0,0 +1,24 @@
/* Format of packets on the Ethernet */
#define AMOEBAPROTO 0x8145 /* Official Ethernet protocol number */
#define ALTAMOEBAPROTO 2222 /* Old Amoeba protocol number */
#define ETHERBITS 0x80 /* These addresses on Ethernet */
typedef struct
{
char e[6];
} Eth_addr;
typedef struct
{
Eth_addr f_dstaddr;
Eth_addr f_srcaddr;
unshort f_proto;
struct pktheader f_ah;
} Framehdr;
typedef struct
{
Framehdr ep_fr;
char ep_data[1490];
} Etherpacket;

View File

@@ -0,0 +1,50 @@
#include "kernel.h"
#include "minix/com.h"
#include "dp8390.h"
#include "internet.h"
#include "etherformat.h"
#include "etherplus.h"
#include "dp8390info.h"
#include "eplinfo.h"
#include "assert.h"
/* macros for device I/O */
#define input(devaddr, ep_register) \
in_byte((vir_bytes)&((struct eplusreg *) devaddr)->ep_register)
#define output(devaddr, ep_register, value) \
out_byte((vir_bytes)&((struct eplusreg *) devaddr)->ep_register, value)
epl_init() {
register vir_bytes device;
register sum;
device = eplinfo.epi_devaddr;
assert((dp8390info.dpi_membase&0x81FFF)==0x80000);
sum =
input(device, epl_ea5) +
input(device, epl_ea4) +
input(device, epl_ea3) +
input(device, epl_ea2) +
input(device, epl_ea1) +
input(device, epl_ea0) +
input(device, epl_res2) +
input(device, epl_chksum);
if ((sum&0xFF) != 0xFF)
panic("No ethernet board", NO_NUM);
output(device, epl_ctlstatus, CTL_RESET);
output(device, epl_ctlstatus, CTL_MENABLE|((dp8390info.dpi_membase>>13)&CTL_MEMADDR));
}
etheraddr(eaddr) Eth_addr *eaddr; {
register vir_bytes device;
device = eplinfo.epi_devaddr;
eaddr->e[0] = input(device, epl_ea0);
eaddr->e[1] = input(device, epl_ea1);
eaddr->e[2] = input(device, epl_ea2);
eaddr->e[3] = input(device, epl_ea3);
eaddr->e[4] = input(device, epl_ea4);
eaddr->e[5] = input(device, epl_ea5);
}

View File

@@ -0,0 +1,27 @@
/*
* Western Digital Ethercard Plus, or WD8003E card
*
* This information seems to be guarded like the crown jewels
*/
struct eplusreg {
char epl_ctlstatus; /* Control(write) and status(read) */
char epl_res1[7];
char epl_ea0; /* Most significant eaddr byte */
char epl_ea1;
char epl_ea2;
char epl_ea3;
char epl_ea4;
char epl_ea5; /* Least significant eaddr byte */
char epl_res2;
char epl_chksum; /* sum from epl_ea0 upto here is 0xFF */
dp8390 epl_dp8390; /* NatSemi chip */
};
/* Bits in epl_ctlstatus */
#define CTL_RESET 0x80 /* Software Reset */
#define CTL_MENABLE 0x40 /* Memory Enable */
#define CTL_MEMADDR 0x3F /* Bits SA18-SA13, SA19 implicit 1 */
#define STA_IIJ 0x7 /* Interrupt Indication Jumpers */

View File

@@ -0,0 +1 @@
#define CRASH ((unshort) 0xFF)

View File

@@ -0,0 +1,44 @@
/****************************************************************************/
/* */
/* (c) Copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands */
/* */
/* This product is part of the Amoeba distributed operating system. */
/* */
/* Permission to use, sell, duplicate or disclose this software must be */
/* obtained in writing. Requests for such permissions may be sent to */
/* */
/* */
/* Dr. Andrew S. Tanenbaum */
/* Dept. of Mathematics and Computer Science */
/* Vrije Universiteit */
/* Postbus 7161 */
/* 1007 MC Amsterdam */
/* The Netherlands */
/* */
/****************************************************************************/
#define KERNEL 0
#define USER 1
typedef unshort address;
typedef int func;
#define bufptr vir_bytes
#define NOWHERE ((address) 0)
#define SOMEWHERE ((address) -1)
#define NILVECTOR ((func (*)()) 0)
#ifdef lint
#define ABSPTR(t, c) (use(c), (t) 0)
#else
#define ABSPTR(t, c) ((t) (c))
#endif
#define bit(b) (1 << (b)) /* simulate type 'bit' */
#define lobyte(x) ((unshort) (x) & 0xFF)
#define hibyte(x) ((unshort) (x) >> 8)
#define concat(x, y) ((unshort) (x) << 8 | (unshort) (y) & 0xFF)
#define sizeoftable(t) (sizeof(t) / sizeof((t)[0]))

View File

@@ -0,0 +1,63 @@
/****************************************************************************/
/* */
/* (c) Copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands */
/* */
/* This product is part of the Amoeba distributed operating system. */
/* */
/* Permission to use, sell, duplicate or disclose this software must be */
/* obtained in writing. Requests for such permissions may be sent to */
/* */
/* */
/* Dr. Andrew S. Tanenbaum */
/* Dept. of Mathematics and Computer Science */
/* Vrije Universiteit */
/* Postbus 7161 */
/* 1007 MC Amsterdam */
/* The Netherlands */
/* */
/****************************************************************************/
#define PACKETSIZE 1490 /* network packet size - sizeof(framehdr) */
#define BROADCAST ((address) 0xFF)
#define TYPE 0x0F /* message types */
#define LOCATE 0x01
#define HERE 0x02
#define REQUEST 0x03
#define REPLY 0x04
#define ACK 0x05
#define NAK 0x06
#define ENQUIRY 0x07
#define ALIVE 0x08
#define DEAD 0x09
#define LAST 0x10 /* flags */
#define RETRANS 0x20
struct pktheader {
char ph_dstnode; /* 0: destination node */
char ph_srcnode; /* 1: source node */
char ph_dsttask; /* 2: destination task */
char ph_srctask; /* 3: source task */
char ph_ident; /* 4: transaction identifier */
char ph_seq; /* 5: fragment no. */
unshort ph_size; /* 6: total size of this packet */
char ph_flags; /* 8: some flags (not used) */
char ph_type; /* 9: locate, here, data, ack or nak (!= 0) */
};
#define ph_signal ph_seq
#define NOSEND 0
#define SEND 1
#define DONTKNOW 0
#define LOCAL 1
#define GLOBAL 2
#define siteaddr(x) lobyte(x)
#define tasknum(x) hibyte(x)
#define pktfrom(ph) ((unshort) (ph->ph_srctask<<8 | ph->ph_srcnode & 0xFF))
#define pktto(ph) ((unshort) (ph->ph_dsttask<<8 | ph->ph_dstnode & 0xFF))

View File

@@ -0,0 +1,43 @@
/****************************************************************************/
/* */
/* (c) Copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands */
/* */
/* This product is part of the Amoeba distributed operating system. */
/* */
/* Permission to use, sell, duplicate or disclose this software must be */
/* obtained in writing. Requests for such permissions may be sent to */
/* */
/* */
/* Dr. Andrew S. Tanenbaum */
/* Dept. of Mathematics and Computer Science */
/* Vrije Universiteit */
/* Postbus 7161 */
/* 1007 MC Amsterdam */
/* The Netherlands */
/* */
/****************************************************************************/
struct mpx {
short MX_active; /* is a transaction in progress */
unshort MX_flags; /* flags - see below */
int MX_proc_nr; /* task identifier */
header MX_hdr; /* storage space for header */
} tk_mpx;
#ifdef MPX
#define mx_flags tk_mpx.MX_flags
#define mx_active tk_mpx.MX_active
#define mx_proc_nr tk_mpx.MX_proc_nr
#define mx_hdr tk_mpx.MX_hdr
/* bits in flags: */
#define RUNNABLE bit(0) /* task is runnable */
#define NESTED bit(1) /* nested getreq, trans or putrep */
#define BETWEEN bit(2) /* between getreq and putrep */
#else
#define tk_mpx tk_dummy /* other modules must not touch it */
#endif

View File

@@ -0,0 +1,40 @@
/****************************************************************************/
/* */
/* (c) Copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands */
/* */
/* This product is part of the Amoeba distributed operating system. */
/* */
/* Permission to use, sell, duplicate or disclose this software must be */
/* obtained in writing. Requests for such permissions may be sent to */
/* */
/* */
/* Dr. Andrew S. Tanenbaum */
/* Dept. of Mathematics and Computer Science */
/* Vrije Universiteit */
/* Postbus 7161 */
/* 1007 MC Amsterdam */
/* The Netherlands */
/* */
/****************************************************************************/
struct portcache {
address PE_location;
struct task *PE_link;
} tk_portcache;
#ifdef PORTCACHE
#define pe_location tk_portcache.PE_location
#define pe_link tk_portcache.PE_link
#else
#define tk_portcache tk_dummy /* other modules must not touch it */
#endif
#define NOWAIT 0
#define WAIT 1
#define LOOK 0
#define DELETE 1

View File

@@ -0,0 +1,492 @@
/****************************************************************************/
/* */
/* (c) Copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands */
/* */
/* This product is part of the Amoeba distributed operating system. */
/* */
/* Permission to use, sell, duplicate or disclose this software must be */
/* obtained in writing. Requests for such permissions may be sent to */
/* */
/* */
/* Dr. Andrew S. Tanenbaum */
/* Dept. of Mathematics and Computer Science */
/* Vrije Universiteit */
/* Postbus 7161 */
/* 1007 MC Amsterdam */
/* The Netherlands */
/* */
/****************************************************************************/
#define NDEBUG
#define PORTCACHE
/*
* This module does the port management. It keeps track of the local servers
* doing a ``getreq'' on a port, local clients waiting for a server on some
* port, and interlocal servers addressed by some port. This last category of
* ports may be forgotten, or may be incorrect.
*
* The following routines are defined:
* portinstall(port, where, wait);
* portlookup(port, wait, delete);
* portremove(port, location);
* portquit(port, task);
*
* ``Portinstall'' is called when a port is assumed to be at location
* ``where.'' If ``wait'' is set, the port is local.
* ``Portlookup'' is called to find a port in the cache. If ``wait'' is
* set, the routine will block until the port is found. If ``delete'' is
* set, the port must be removed when it is found.
* ``Portremove'' removes a port from the cache which is thought
* of to be at the specified location.
* When a port doesn't have to be located anymore for some task, ``portquit''
* takes care of that.
*/
#include "kernel.h"
#include "amoeba.h"
#include "global.h"
#include "task.h"
#include "internet.h"
#include "assert.h"
extern struct task task[];
#ifdef STATISTICS
#include "portstat.h"
struct portstat portstat;
#define STINC(x) portstat.x++
#else
#define STINC(x)
#endif
#include "conf.h"
#define LOGHASH 5 /* log sizeof hash table of local ports */
struct porttab {
port p_port; /* the port this entry is about */
unshort p_idle; /* idle timer */
address p_location; /* where is it? (0 = being located) */
address p_asker; /* address of someone interested */
struct porttab *p_nextport; /* port with same hash value */
struct task *p_tasklist; /* list of tasks */
};
#define NILPORTTAB ((struct porttab *) 0)
#define NHASH (1 << LOGHASH)
#define HASHMASK (NHASH - 1)
#define hash(p) (* (unshort *) (p) & HASHMASK)
/* MINIX can't allocate memory in the kernel at run-time
extern unshort nport;
PRIVATE struct porttab *porttab, *lastport, *hashtab[NHASH], *portfree;
*/
PRIVATE struct porttab porttab[NPORTS];
PRIVATE struct porttab *lastport, *hashtab[NHASH], *portfree;
#ifndef NONET
#ifndef NOCLIENT
#define NLOCATE 8 /* max. number of ports to locate */
PRIVATE port loctab[NLOCATE];
PRIVATE unshort loccnt, loctim, locthissweep;
extern unshort minloccnt, maxloccnt;
#endif
#endif
/* Allocate an entry in the hash table at location ``ht.'' */
static struct porttab *allocate(ht, p)
struct porttab **ht;
port *p;
{
register struct porttab *pt;
STINC(pts_alloc);
if ((pt=portfree) == 0) {
STINC(pts_full);
portpurge(); /* total cleanup, not likely to happen */
if ((pt=portfree) == 0)
return 0;
}
portfree = pt->p_nextport;
pt->p_nextport = *ht;
*ht = pt;
pt->p_port = *p;
return pt;
}
/* Install a port in the hash table. If ``wait'' is set, the location will
* be this machine and is certain. If not, the location is somewhere else
* and uncertain.
*/
portinstall(p, where, wait)
register port *p;
address where;
{
register struct porttab **ht, *pt;
register struct task *t;
extern address local;
ht = &hashtab[hash(p)];
for (pt = *ht; pt != NILPORTTAB; pt = pt->p_nextport)
if (PortCmp(&pt->p_port, p)) {
if (pt->p_location == SOMEWHERE) {
compare(pt->p_tasklist, !=, NILTASK);
do {
t = pt->p_tasklist;
t->pe_location = where;
STINC(pts_wakeup);
wakeup((event_t) &t->pe_location);
} while ((pt->p_tasklist = t->pe_link) != NILTASK);
}
#ifndef NOCLIENT
else if (siteaddr(pt->p_location) == local && !wait &&
pt->p_tasklist != 0)
return;
#endif
break;
}
if (pt == NILPORTTAB && (pt = allocate(ht, p)) == NILPORTTAB)
#ifndef NOCLIENT
if (wait)
#endif
panic("portcache full for servers", 0x8000);
#ifndef NOCLIENT
else /* no room left, so forget it */
return;
#endif
pt->p_location = where;
#ifndef NOCLIENT
if (wait) { /* task is going to await a client, so leave it immortal */
#endif
compare(area(where), ==, LOCAL);
t = &task[tasknum(where)];
t->pe_location = where;
t->pe_link = pt->p_tasklist;
pt->p_tasklist = t;
#ifndef NONET
if (pt->p_asker != NOWHERE) {
STINC(pts_here);
hereport(pt->p_asker, p, (unsigned )1);
pt->p_asker = NOWHERE;
}
#endif
#ifndef NOCLIENT
}
#endif
pt->p_idle = 0;
}
#ifndef NONET
#ifndef NOCLIENT
/* Broadcast a locate message
*/
static sendloc(){
register struct porttab *pt;
register unsigned n = 0;
if (locthissweep) {
/* During this clocktick we already sent out a broadcast packet.
* To prevent buggy userprograms from creating a broadcast storm
* we do not send another one, we just prepare for it to be done
*/
STINC(pts_nolocate);
loccnt = maxloccnt;
return;
}
for (pt = porttab; pt < lastport; pt++)
if (pt->p_location == SOMEWHERE) {
loctab[n++] = pt->p_port;
if (n == NLOCATE)
break;
}
if (n) {
locthissweep = 1;
whereport(loctab, n); /* send out the broadcast locate */
} else
loctim = 0; /* No locates necessary anymore */
loccnt = 0;
}
#endif NOCLIENT
#endif NONET
/* Look whether port p is in the portcache. You can specify whether you
* want to wait for the information and whether you want to delete it.
*/
address portlookup(p, wait, del)
register port *p;
{
register struct porttab **ht, *pt;
register struct task *c, *t;
register address location;
STINC(pts_lookup);
ht = &hashtab[hash(p)];
for (pt = *ht; pt != NILPORTTAB; pt = pt->p_nextport)
if (PortCmp(&pt->p_port, p)) { /* found it */
location = pt->p_location;
switch (area(location)) {
case LOCAL: /* local server */
if (pt->p_tasklist == 0)
break;
if (del) { /* remove it */
pt->p_tasklist = pt->p_tasklist->pe_link;
if ((t = pt->p_tasklist) != NILTASK)
pt->p_location = t->pe_location;
}
pt->p_idle = 0;
STINC(pts_flocal);
return(location);
case GLOBAL: /* remote server */
compare(pt->p_tasklist, ==, NILTASK);
pt->p_idle = 0;
STINC(pts_fglobal);
return(location);
case DONTKNOW: /* somebody else wants to know too */
compare(pt->p_tasklist, !=, NILTASK);
break;
default:
assert(0);
}
break;
}
/* The port wasn't in the port cache */
#ifndef NOCLIENT
if (wait) { /* wait for it */
if (pt == NILPORTTAB && (pt = allocate(ht, p)) == NILPORTTAB)
panic("portcache full for clients", 0x8000);
pt->p_location = SOMEWHERE;
c = curtask;
c->pe_link = pt->p_tasklist;
pt->p_tasklist = c;
#ifndef NONET
STINC(pts_locate);
sendloc();
loctim = minloccnt;
#endif
c->pe_location = SOMEWHERE;
if (sleep((event_t) &c->pe_location))
assert(pt->p_tasklist != c);
pt->p_idle = 0;
return(c->pe_location);
}
else
#endif NOCLIENT
return(NOWHERE);
}
/* Port p isn't at location ``location'' anymore */
portremove(p, location)
port *p;
address location;
{
register struct porttab *pt, **ht;
register struct task *t;
for (ht = &hashtab[hash(p)]; (pt= *ht) != NILPORTTAB; ht = &pt->p_nextport)
if (PortCmp(&pt->p_port, p)) {
if (pt->p_location == location) {
if ((t = pt->p_tasklist) != NILTASK) {
compare(area(location), ==, LOCAL);
compare(t->pe_location, ==, location);
if ((pt->p_tasklist = t->pe_link) != NILTASK) {
pt->p_location =
pt->p_tasklist->pe_location;
break;
}
} else {
*ht = pt->p_nextport;
pt->p_location = NOWHERE; /* for dump */
pt->p_nextport = portfree;
portfree = pt;
}
}
else if ((t = pt->p_tasklist) != NILTASK)
while (t->pe_link != NILTASK)
if (t->pe_link->pe_location == location) {
t->pe_link = t->pe_link->pe_link;
break;
}
else
t = t->pe_link;
return;
}
}
#ifndef NOCLIENT
/* Task ``s'' isn't interested anymore */
portquit(p, s)
register port *p;
register struct task *s;
{
register struct porttab *pt, **ht;
register struct task *t;
for (ht = &hashtab[hash(p)]; (pt= *ht) != NILPORTTAB; ht = &pt->p_nextport)
if (PortCmp(&pt->p_port, p)) {
if (pt->p_location != SOMEWHERE)
return;
if ((t = pt->p_tasklist) == s) {
if ((pt->p_tasklist = s->pe_link) == NILTASK) {
*ht = pt->p_nextport;
pt->p_location = NOWHERE; /* for dump */
pt->p_nextport = portfree;
portfree = pt;
}
s->pe_location = NOWHERE;
wakeup((event_t) &s->pe_location);
}
else {
while (t != NILTASK)
if (t->pe_link == s) {
t->pe_link = s->pe_link;
s->pe_location = NOWHERE;
wakeup((event_t) &s->pe_location);
break;
}
else
t = t->pe_link;
}
return;
}
}
#endif NOCLIENT
#ifndef NONET
#define NHERE 8
PRIVATE port heretab[NHERE];
portask(asker, ptab, nports) /* handle locate request */
address asker;
register port *ptab;
unsigned nports;
{
register port *p,*q;
register struct porttab **ht, *pt;
register unsigned nfound;
STINC(pts_portask);
nfound = 0; q = heretab;
for(p=ptab; nports--; p++) {
ht = &hashtab[hash(p)];
for (pt = *ht; pt != NILPORTTAB; pt = pt->p_nextport)
if (PortCmp(&pt->p_port, p)) { /* found it */
if (area(pt->p_location) == LOCAL) {
if (pt->p_tasklist == 0) {
/* just record someone was interested */
pt->p_asker = asker;
break;
}
if (nfound < NHERE) {
*q++ = *p;
nfound++;
}
pt->p_idle = 0;
}
}
}
if (nfound) {
STINC(pts_portyes);
hereport(asker, heretab, nfound);
}
}
#endif
#ifndef NDEBUG
portdump(){
register struct porttab *pt;
register struct task *t;
printf("\n PORT LOCATION IDLE TASKS\n");
for (pt = porttab; pt < lastport; pt++)
if (pt->p_location != NOWHERE) {
prport(&pt->p_port);
printf(" %4x %4d", pt->p_location, pt->p_idle);
for (t = pt->p_tasklist; t != NILTASK; t = t->pe_link)
printf(" {%d, %x}", t - task, t->pe_location);
printf("\n");
}
}
#endif
/* Initialize tables and free list */
portinit(){
register struct porttab *pt;
/* MINIX can't allocate data in the kernel at run-time
extern char *aalloc();
porttab = (struct porttab *) aalloc(nport * sizeof(struct porttab), 0);
lastport = &porttab[nport];
*/
lastport = &porttab[NPORTS];
for (pt = porttab; pt < lastport; pt++) {
pt->p_nextport = portfree;
portfree = pt;
}
}
/* called when freelist was empty, will throw away all mortal ports */
portpurge() {
register struct porttab *pt,**ht,**htp;
for (htp=hashtab; htp< &hashtab[NHASH]; htp++) {
ht = htp;
while ((pt = *ht) != 0) {
if (pt->p_tasklist == 0){
*ht = pt->p_nextport;
pt->p_location = NOWHERE; /* for dump */
pt->p_nextport = portfree;
portfree = pt;
} else
ht = &pt->p_nextport;
}
}
}
#define MAXSWEEP 3000 /* dseconds maximum idle time for port */
#define SWEEPRESOLUTION 100 /* accuracy */
portsweep() {
register struct porttab *pt,**ht,**htp;
static unshort cnt;
#ifndef NOCLIENT
#ifndef NONET
locthissweep = 0;
if (loctim && ++loccnt > loctim) { /* send a locate message */
STINC(pts_relocate);
sendloc();
loctim <<= 1;
if (loctim > maxloccnt)
loctim = maxloccnt;
locthissweep = 0;
}
#endif NONET
#endif
if (++cnt<SWEEPRESOLUTION)
return;
for (htp=hashtab; htp< &hashtab[NHASH]; htp++) {
ht = htp;
while ((pt = *ht) != 0) {
if (pt->p_tasklist == 0 && (pt->p_idle += cnt) > MAXSWEEP) {
*ht = pt->p_nextport;
pt->p_location = NOWHERE; /* for dump */
pt->p_nextport = portfree;
portfree = pt;
STINC(pts_aged);
} else
ht = &pt->p_nextport;
}
}
cnt=0;
}

View File

@@ -0,0 +1,15 @@
struct portstat {
long pts_alloc;
long pts_aged;
long pts_full;
long pts_wakeup;
long pts_here;
long pts_lookup;
long pts_flocal;
long pts_fglobal;
long pts_portask;
long pts_portyes;
long pts_locate;
long pts_nolocate;
long pts_relocate;
};

View File

@@ -0,0 +1,40 @@
/****************************************************************************/
/* */
/* (c) Copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands */
/* */
/* This product is part of the Amoeba distributed operating system. */
/* */
/* Permission to use, sell, duplicate or disclose this software must be */
/* obtained in writing. Requests for such permissions may be sent to */
/* */
/* */
/* Dr. Andrew S. Tanenbaum */
/* Dept. of Mathematics and Computer Science */
/* Vrije Universiteit */
/* Postbus 7161 */
/* 1007 MC Amsterdam */
/* The Netherlands */
/* */
/****************************************************************************/
#ifdef BUFFERED /* HACK */
#define BUFSIZE 100
#define NETBUF ((buffer) -1)
typedef unshort buffer;
#endif
struct task {
#include "mpx.H" /* mpx module */
#include "trans.H" /* trans module */
#include "portcache.H" /* portcache module */
char *tk_aux; /* auxiliary pointer */
/* really a hack to make process task more efficient */
};
extern struct task *curtask, *uppertask;
extern unshort ntask;
#define NILTASK ((struct task *) 0)

View File

@@ -0,0 +1,110 @@
/****************************************************************************/
/* */
/* (c) Copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands */
/* */
/* This product is part of the Amoeba distributed operating system. */
/* */
/* Permission to use, sell, duplicate or disclose this software must be */
/* obtained in writing. Requests for such permissions may be sent to */
/* */
/* */
/* Dr. Andrew S. Tanenbaum */
/* Dept. of Mathematics and Computer Science */
/* Vrije Universiteit */
/* Postbus 7161 */
/* 1007 MC Amsterdam */
/* The Netherlands */
/* */
/****************************************************************************/
struct trans {
char TS_state; /* see below */
char TS_flags; /* several flags - see below */
char TS_clident; /* ident number for client */
char TS_svident; /* ident number for server */
char TS_ident; /* transaction identifier */
char TS_seq; /* fragment sequence number */
char TS_count; /* max. number timer may expire */
char TS_signal; /* signal being sent to the server */
unshort TS_addr; /* network address of this task */
unshort TS_timer; /* timer, decremented every sweep */
unshort TS_cltim; /* client crash timer */
address TS_client; /* if serving: who's the client */
address TS_server; /* if in trans: who's the server */
port TS_portcache; /* this port was used the last time */
header *TS_rhdr; /* saved param in getreq or trans */
header *TS_xhdr; /* saved param in putrep or trans */
bufptr TS_rbuf; /* receiver buffer */
bufptr TS_xbuf; /* transmitter buffer */
unshort TS_rcnt; /* size of rbuf */
unshort TS_xcnt; /* size of xbuf */
unshort TS_offset; /* offset in buffer */
unshort TS_maxloc; /* max. location time in seconds */
long TS_totloc; /* total location time in ticks */
long TS_totsvr; /* total server time in ticks */
#ifdef BUFFERED
address TS_sender; /* task that sent the buffer */
char *TS_savehdr; /* saved header pointer */
buffer TS_buffer; /* buffer */
unshort TS_bufcnt; /* buffer size */
unshort TS_what; /* REQUEST or REPLY */
#endif
} tk_trans;
#ifdef TRANS
#define ts_state tk_trans.TS_state
#define ts_flags tk_trans.TS_flags
#define ts_clident tk_trans.TS_clident
#define ts_svident tk_trans.TS_svident
#define ts_ident tk_trans.TS_ident
#define ts_seq tk_trans.TS_seq
#define ts_timer tk_trans.TS_timer
#define ts_count tk_trans.TS_count
#define ts_signal tk_trans.TS_signal
#define ts_addr tk_trans.TS_addr
#define ts_cltim tk_trans.TS_cltim
#define ts_client tk_trans.TS_client
#define ts_server tk_trans.TS_server
#define ts_portcache tk_trans.TS_portcache
#define ts_rhdr tk_trans.TS_rhdr
#define ts_xhdr tk_trans.TS_xhdr
#define ts_rbuf tk_trans.TS_rbuf
#define ts_xbuf tk_trans.TS_xbuf
#define ts_rcnt tk_trans.TS_rcnt
#define ts_xcnt tk_trans.TS_xcnt
#define ts_offset tk_trans.TS_offset
#define ts_maxloc tk_trans.TS_maxloc
#define ts_totloc tk_trans.TS_totloc
#define ts_totsvr tk_trans.TS_totsvr
#define ts_sender tk_trans.TS_sender
#define ts_savehdr tk_trans.TS_savehdr
#define ts_buffer tk_trans.TS_buffer
#define ts_bufcnt tk_trans.TS_bufcnt
#define ts_what tk_trans.TS_what
/* possible values of ts_state */
#define IDLE 0
#define SENDING 1
#define DONE 2
#define ACKED 3
#define NACKED 4
#define FAILED 5
#define WAITBUF 6
#define RECEIVING 7
#define ABORT 8
#define MEMFAULT 9
/* possible flags in ts_flags */
#define LOCATING bit(0) /* blocked in trans locating a port */
#define PUTREQ bit(1) /* blocked in trans sending a request */
#define GETREQ bit(2) /* blocked in getreq */
#define PUTREP bit(3) /* blocked in putrep */
#define GETREP bit(4) /* blocked in trans getting a reply */
#define SERVING bit(5) /* running between getreq and putrep */
#else
#define tk_trans tk_dummy /* other modules must not touch it */
#endif

View File

@@ -0,0 +1,50 @@
#include "kernel.h"
#include "minix/com.h"
#include "proc.h"
#include "dp8390.h"
#include "assert.h"
#include "dp8390info.h"
#include "eplinfo.h"
struct eplinfo eplinfo = {0x280};
struct dp8390info dp8390info = {0x290, 6, 27, EPLUS_BASE, EPLUS_BASE};
extern vir_bytes eplus_seg;
#if !NONET
getheader(paddr, pkthead)
phys_bytes paddr;
struct rcvdheader *pkthead;
{
vir_bytes offset;
char get_byte();
offset = (paddr - EPLUS_BASE)&0xFFFF;
pkthead->rp_status = get_byte(eplus_seg, offset);
pkthead->rp_next = get_byte(eplus_seg, offset+1);
pkthead->rp_rbcl = get_byte(eplus_seg, offset+2);
pkthead->rp_rbch = get_byte(eplus_seg, offset+3);
}
short
getbint(paddr)
phys_bytes paddr;
{
vir_bytes offset;
short t;
offset = (paddr - EPLUS_BASE)&0xFFFF;
return (((short)get_byte(eplus_seg, offset) & 0xFF)<<8) +
((short)get_byte(eplus_seg, offset+1) & 0xFF);
}
#endif

View File

@@ -0,0 +1,106 @@
i=/usr/include
s=/usr/include/sys
h=/usr/include/minix
l=/usr/lib
m=../../mm
a=$m/mm.h $h/config.h $h/const.h $h/type.h $s/types.h $i/limits.h $i/errno.h \
$m/const.h $m/type.h $m/proto.h $m/glo.h
CFLAGS = -DAM_KERNEL -I../../mm -I. -F
obj = main.s forkexit.s break.s exec.s signal.s getset.s \
alloc.s utility.s table.s putc.s trace.s amoeba.s
mm: Makefile $l/head.s $(obj) $l/libc.a $l/end.s
asld -o mm $l/head.s $(obj) $l/libc.a $l/end.s
clean:
@rm -f $(obj) mm *.bak
alloc.s: $a
$(CC) $(CFLAGS) -c $m/alloc.c
amoeba.s: $a
amoeba.s: $h/com.h
amoeba.s: $i/amoeba.h
break.s: $a
break.s: $i/signal.h
break.s: $m/mproc.h
break.s: $m/param.h
break.s: $m/break.c
$(CC) $(CFLAGS) -c $m/break.c
exec.s: $a
exec.s: $s/stat.h
exec.s: $h/callnr.h
exec.s: $m/mproc.h
exec.s: $m/param.h
exec.s: $m/exec.c
$(CC) $(CFLAGS) -c $m/exec.c
forkexit.s: $a
forkexit.s: $h/callnr.h
forkexit.s: $m/mproc.h
forkexit.s: $m/param.h
forkexit.s: $m/forkexit.c
$(CC) $(CFLAGS) -c $m/forkexit.c
getset.s: $a
getset.s: $h/callnr.h
getset.s: $m/mproc.h
getset.s: $m/param.h
getset.s: $m/getset.c
$(CC) $(CFLAGS) -c $m/getset.c
main.s: $a
main.s: $h/callnr.h
main.s: $h/com.h
main.s: $m/mproc.h
main.s: $m/param.h
main.s: $m/main.c
$(CC) $(CFLAGS) -c $m/main.c
putc.s: $a
putc.s: $h/com.h
putc.s: $m/putc.c
$(CC) $(CFLAGS) -c $m/putc.c
signal.s: $a
signal.s: $s/stat.h
signal.s: $i/signal.h
signal.s: $h/callnr.h
signal.s: $h/com.h
signal.s: $m/mproc.h
signal.s: $m/param.h
signal.s: $m/signal.c
$(CC) $(CFLAGS) -c $m/signal.c
table.s: $a
table.s: $h/callnr.h
table.s: $m/mproc.h
table.s: $m/param.h
table.s: $m/table.c
$(CC) $(CFLAGS) -c $m/table.c
trace.s: $a
trace.s: $i/signal.h
trace.s: $m/mproc.h
trace.s: $m/param.h
trace.s: $m/trace.c
$(CC) $(CFLAGS) -c $m/trace.c
utility.s: $a
utility.s: $s/stat.h
utility.s: $h/callnr.h
utility.s: $h/com.h
utility.s: $m/mproc.h
utility.s: $m/utility.c
$(CC) $(CFLAGS) -c $m/utility.c

View File

@@ -0,0 +1,163 @@
#ifdef AM_KERNEL
/*
** The Amoeba Transaction Layer System Call
**
** Amoeba transactions are implemented as a single system call
** which implements trans(), getreq() and putrep(). timeout() is
** implemented in the user library.
** The job of the transaction layer is to ensure that a user task gets
** only one kernel task. The kernel task is the exclusive domain of
** the user task for the duration of a transaction.
**
** A note on programming style:
** macros names are upper case (all of them except those from andy)
** global variable names start with an upper case letter
** local variables names are lower case
**
** The amoeba transactions use message type 2, just like the device
** drivers. This is for compatibility with the revive code.
*/
#include "mm.h"
#include "minix/com.h"
#include "amoeba.h"
/*
** There are several external global variables which you need to know about
** but due to the hacks everywhere they are declared in an include file.
** who - the task # of the task that sent the request = mm_in.m_source
** mm_in - the message from that task
** mm_out - a message buffer normally used by reply()
** dont_reply - a flag to indicate that no reply should go to sender
**
** do_amoeba returns the error status that will be given to the requesting
** task. The kernel has already done all the data transfers for the task
** so no return message is required.
*/
PUBLIC int
do_amoeba()
{
int ktasknr; /* # of kernel task to perform operation */
int proc_nr; /* # of user task requesting the operation */
int r; /* return status */
int cmd;
/* if it is a revive message from kernel then handle it */
if (mm_in.AM_OP == AM_REVIVE)
return am_revive(mm_in.AM_PROC_NR, mm_in.AM_STATUS, (int)mm_in.AM_FREE_IT);
/*
** check to see if this task already has a kernel task engaged.
** if so then use that one, else find a free kernel task.
*/
if ((ktasknr = alloc_ktask()) >= 0)
return TRYAGAIN; /* no free kernel task, try again? */
proc_nr = who;
mm_in.AM_PROC_NR = proc_nr;
cmd = mm_in.AM_OP;
if ((r = sendrec(ktasknr, &mm_in)) != OK)
panic("do_amoeba: can't send", NO_NUM);
/*
** if necessary suspend. the kernel task will be freed during the revival.
** otherwise we got an immediate answer.
** in that case it was an error or an instant response. probably it
** was an error. if so free the kernel task. if it was not an error
** then don't free the kernel task if it was a getrequest.
*/
if (mm_in.AM_STATUS == SUSPEND)
dont_reply = TRUE;
else
if (mm_in.AM_STATUS < 0 || cmd != AM_GETREQ)
free_ktask(proc_nr);
return mm_in.AM_STATUS;
}
/* task number of task in control of kernel task, 0 if task is free */
PRIVATE struct
{
int proc;
int signalled;
} In_use[AM_NTASKS];
PRIVATE int
alloc_ktask()
{
int i;
int slot = -1;
for (i = 0; i < AM_NTASKS; i++) /* look at all kernel tasks!! */
if (In_use[i].proc == who)
{ /* already has a kernel task */
slot = i;
break;
}
else
if (In_use[i].proc == 0)
slot = i; /* slot i is free, but keep looking */
if (slot < 0) /* no free slot was found */
return 0;
In_use[slot].proc = who;
In_use[slot].signalled = 0;
return AMOEBA_CLASS - slot;
}
PRIVATE int
free_ktask(n)
{
int i;
for (i = 0; i < AM_NTASKS; i++)
if (In_use[i].proc == n)
{
In_use[i].proc = 0;
return;
}
}
PRIVATE int
am_revive(task, status, free_it)
int task;
int status;
int free_it;
{
if (who > 0)
return EPERM;
if (free_it)
free_ktask(task); /* it was not a getreq! */
reply(task, status, 0, (char *) 0); /* revive the task */
dont_reply = TRUE;
return OK;
}
PUBLIC int
am_check_sig(proc, type)
int proc;
int type;
{
/* return 0 if the signal was for a transacting task. otherwise return 1 */
int i;
for (i = 0; i < AM_NTASKS; i++)
if (In_use[i].proc == proc && (!In_use[i].signalled || type == 1))
{
/* mm_out is not being used by anyone right now! */
In_use[i].signalled = 1;
if (type == 1)
{
In_use[i].proc = 0;
mm_out.m_type = AM_TASK_DIED;
}
else
mm_out.m_type = AM_PUTSIG;
mm_out.AM_COUNT = i;
send(AMINT_CLASS, &mm_out);
return 0;
}
return 1;
}
#endif AM_KERNEL

View File

@@ -0,0 +1,33 @@
SHELL = /bin/sh
CFLAGS =
CC = cc
all: from to rsh sherver master
from: from.s
$(CC) -o $@ from.s
to: to.s
$(CC) -o $@ to.s
rsh: rsh.s prot.s
$(CC) -o $@ rsh.s prot.s
chmem =500 $@
sherver: sherver.s prot.s
$(CC) -o $@ sherver.s prot.s
chmem =500 $@
master: master.s
$(CC) -o $@ master.s
chmem =500 $@
sherver.s: sherver.h
rsh.s: sherver.h
clean:
rm -f sherver.s from.s to.s master.s rsh.s prot.s
rm -f sherver from to master rsh

View File

@@ -0,0 +1,29 @@
This directory contains the sources for amoeba based utilities. These are
mainly of interest if you have an ethernet connection. Master and sherver
should not be installed if you do not have an ethernet connection since they
will take up precious memory.
Installation:
1. Type make
2. Copy files as follows:
cp rsh /usr/bin
cp rcp /usr/bin
cp to /usr/bin
cp from /usr/bin
3. Edit /etc/rc and add the lines:
echo "Starting sherver(s)"
/usr/bin/master 1 <uid> <gid> /etc/sherver port
where port is the name that your node is to be known by. It should not be
more than 6 characters long. It can be made up of any characters you like.
Note that the flags <uid> and <gid> are the uid and group id that the
sherver will run under.

View File

@@ -0,0 +1,79 @@
#include <stdio.h>
#include <signal.h>
#include "amoeba.h"
#define BUFSIZE 20480
char * cmd;
catchalarm()
{
fprintf(stderr, "%s: timeout\n", cmd);
exit(1);
}
main(argc, argv)
int argc;
char ** argv;
{
unshort getreq();
unshort putrep();
char * malloc();
int catchalarm();
char * buf;
header hdr;
unshort cnt;
unshort bufsize = BUFSIZE;
unsigned tim = 15 * 60; /* #secs before timeout */
cmd = *argv;
if (argc > 1 && strncmp(argv[1], "-t", 2) == 0)
{
tim = atoi(&argv[1][2]);
argc--;
argv++;
}
if (tim)
signal(SIGALRM, catchalarm);
if (argc != 2 && argc != 3) /* if (!(argc & 2))?? */
{
fprintf(stderr, "Usage: %s [-ttime] [bufsize] port\n", cmd);
exit(-1);
}
if (argc == 3)
bufsize = atoi(argv[2]);
if ((buf = malloc(bufsize * sizeof (char))) == NULL)
{
fprintf(stderr, "%s: out of memory\n", cmd);
exit(-1);
}
strncpy(&hdr.h_port, argv[1], PORTSIZE);
for (;;)
{
if (tim)
alarm(tim);
cnt = getreq(&hdr, buf, bufsize);
if (tim)
alarm(0);
if ((short)cnt < 0)
{
fprintf(stderr, "%s: getreq failed\n", cmd);
exit(-3);
}
hdr.h_status = 0;
if (cnt != 0)
if (write(1, buf, cnt) < 0)
{
perror(cmd);
hdr.h_status = -1;
}
putrep(&hdr, NILBUF, 0);
if (hdr.h_status)
exit(-4);
if (cnt == 0)
exit(0);
}
}

View File

@@ -0,0 +1,78 @@
#include <signal.h>
char console[] = "/dev/console";
run(uid, gid, argv)
char **argv;
{
for (;;)
switch (fork()) {
default:
return;
case 0:
if (setgid(gid) < 0) perror("can't set gid");
if (setuid(uid) < 0) perror("can't set uid");
/*
execvp(*argv, argv);
*/
execv(*argv, argv);
perror("master: exec'ing");
prints("can't execute %s\n", *argv);
/*
kill(getppid(), SIGTERM);
*/
/* If the exec failed, don't try it again immediately.
* Give the kernel a chance to do something else.
*/
sleep (5);
_exit(1);
case -1:
sleep(10);
}
}
main(argc, argv)
char **argv;
{
register n, uid, gid;
/* Minix can't do this
setpgrp(getpid(), getpid());
*/
if (argc < 4) {
prints("Usage: master # uid gid command args ...\n");
return(1);
}
n = atoi(argv[1]);
if (n < 1 || n > 20) {
prints("Bad count.\n");
return(1);
}
signal(SIGHUP, SIG_IGN);
signal(SIGINT, SIG_IGN);
signal(SIGQUIT, SIG_IGN);
/* Put the program into the background. */
switch (fork()) {
case 0:
break;
case -1:
perror(argv[0]);
return 1;
default:
return 0;
}
uid = atoi(argv[2]);
gid = atoi(argv[3]);
/* Start n copies of the program. */
do
run(uid, gid, &argv[4]);
while (--n);
/* Replace each one that dies. */
while (wait((int *) 0) > 0)
run(uid, gid, &argv[4]);
return(0);
}

View File

@@ -0,0 +1,78 @@
#include <stdio.h>
#include <sys/types.h>
#include <pwd.h>
#include <grp.h>
#define isblank(c) ((c) == ' ' || (c) == '\t' || (c) == '\n')
#define MAXTOKEN 16
static char *gettok(fp)
FILE *fp;
{
static char buf[MAXTOKEN + 1];
register char c, *p = buf;
do /* skip blanks */
if ((c = getc(fp)) == EOF)
return(0);
while (isblank(c));
do {
if (c == '#') { /* skip comment */
while ((c = getc(fp)) != EOF)
if (c == '\n') break;
break;
}
*p++ = c;
} while (c != ':' && (c = getc(fp)) != EOF && !isblank(c));
*p++ = 0;
return(buf);
}
static number(p)
char *p;
{
int n;
return sscanf(p, "%d", &n) == 1 ? n : -1;
}
chkprot(chkfil, chkdefault, uid, gid)
char *chkfil;
char *chkdefault;
{
register userchk = 0, n;
register FILE *fp;
register char *p;
register struct passwd *pw;
register struct group *gr;
extern FILE *fopen();
extern struct passwd *getpwuid();
extern struct group *getgrgid();
pw = getpwuid(uid);
endpwent();
gr = getgrgid(gid);
endgrent();
if ((fp = fopen(chkfil, "r")) == NULL && (fp = fopen(chkdefault, "r")) == NULL)
return(-1);
while ((p = gettok(fp)) != 0)
if (strcmp(p, "group:") == 0)
userchk = 0;
else if (strcmp(p, "user:") == 0)
userchk = 1;
else if (userchk) {
if (pw && strcmp(p, pw->pw_name) == 0 ||
uid == number(p)) {
fclose(fp);
return(1);
}
}
else
if (gr && strcmp(p, gr->gr_name) == 0 ||
gid == number(p)) {
fclose(fp);
return(1);
}
return(0);
}

View File

@@ -0,0 +1,76 @@
: Copy a file from any machine to any other machine.
usage="Usage: $0 [machine!]from-file [machine!]to-file"
PATH=/usr/local:/bin:/usr/bin
CDPATH=
case $# in
2) :
;;
*) echo "$usage" 1>&2
exit 1
esac
from=$1 to=$2
case $from in
*!*) IFS="!"
set $from
case $# in
2) from_mach=$1 from_file=$2 IFS=" "
;;
*) echo "$usage" 1>&2
exit 1
esac
;;
*) from_file=$from
esac
case "$from_file" in
"") echo "$usage" 1>&2
exit 1
esac
case $to in
*!*) IFS="!"
set $to
case $# in
2) to_mach=$1 to_file=$2 IFS=" "
;;
*) echo "$usage" 1>&2
exit 1
esac
;;
*) to_file=$to
esac
case "$to_file" in
"") echo "$usage" 1>&2
exit 1
esac
case "$from_mach" in
"$to_mach")
: machines equal
case "$to_mach" in
"") : local
cp "$from_file" "$to_file"
;;
*) : remote
rsh "$to_mach" "cp $from_file $to_file"
;;
esac
;;
*) : machines not equal
case "$to_mach" in
"") : to local
if test -d "$to_file"
then rsh -e "$from_mach" "cat $from_file" >"$to_file/`basename $from_file`"
else rsh -e "$from_mach" "cat $from_file" >"$to_file"
fi
;;
*) : to remote
case "$from_mach" in
"") : from local
rsh -i "$to_mach" "if test -d $to_file; then cat >$to_file/`basename $from_file`; else cat >$to_file; fi" <"$from_file"
;;
*) : from remote
rsh -e "$from_mach" "cat $from_file" | rsh -i "$to_mach" "if test -d $to_file; then cat >$to_file/`basename $from_file`; else cat >$to_file; fi"
;;
esac
;;
esac
;;
esac

View File

@@ -0,0 +1,245 @@
/* rsh [-ei] machine command
*
* -b: run remote process in background
* -e: separate error output
* -i: send input
*/
#include <stdio.h>
#include <signal.h>
#include "amoeba.h"
#include "sherver.h"
char *prog, *mach, buf[BUFFERSIZE];
usage(){
fprintf(stderr, "Usage: %s [-bei] machine command ...\n", prog);
exit(1);
}
panic(s)
char *s;
{
fprintf(stderr, "%s: %s\n", prog, s);
exit(1);
}
char *collect(buf, vec, sep)
char *buf, **vec, sep;
{
register char *p;
while ((p = *vec++) != 0) {
while (*p != 0) {
*buf++ = *p++;
if (buf == &buf[BUFFERSIZE])
panic("environment too large\n");
}
*buf++ = *vec == 0 ? 0 : sep;
}
return(buf);
}
char *setupbuf(argv, flags)
char **argv;
int *flags;
{
register char *p;
extern char **environ, *getenv();
if (*argv == 0) {
if ((p = getenv("SHELL")) == 0)
p = "/bin/sh";
if (strlen(p) > BUFFERSIZE - 10) /* 10 > strlen("exec -i") */
panic("pathname of shell too large");
sprintf(buf, "exec %s -i", p);
p = &buf[strlen(buf) + 1];
*flags |= IFLG;
}
else
p = collect(buf, argv, ' ');
return collect(p, environ, 0);
}
execute(hdr, p, flags)
header *hdr;
char *p;
{
register unshort cnt;
timeout(50);
strncpy(&hdr->h_port, mach, PORTSIZE);
hdr->h_command = EXEC_COMMAND;
hdr->h_size = p - buf;
hdr->h_extra = flags;
cnt = trans(hdr, buf, p - buf, hdr, buf, BUFFERSIZE);
if ((short) cnt < 0) {
fprintf(stderr, "%s: %s not available\n", prog, mach);
return(0);
}
if (hdr->h_status != COMM_DONE) {
if (cnt == 0)
fprintf(stderr, "can't execute command\n");
else
fprintf(stderr, "%.*s\n", cnt, buf);
return(0);
}
return(1);
}
alrm(){
fprintf(stderr, "rsh: getreq timed out\n");
exit(1);
}
commandloop(hdr)
header *hdr;
{
register unshort cnt;
for (;;) {
alarm(12*60*60);
cnt = getreq(hdr, buf, BUFFERSIZE);
alarm(0);
if ((short) cnt < 0) {
fprintf(stderr, "getreq failed\n");
return(-1);
}
switch (hdr->h_command) {
case READ_FD:
if (hdr->h_extra < NFD)
cnt = read(hdr->h_extra, buf, hdr->h_size);
else
fprintf(stderr, "read: bad fd\n");
hdr->h_size = (unshort) cnt;
putrep(hdr, buf, cnt < 0 ? 0 : cnt);
if (cnt == 0)
return(0);
break;
case WRITE_FD:
if (hdr->h_extra < NFD)
if (cnt == 0)
close(hdr->h_extra);
else
write(hdr->h_extra, buf, cnt);
else
fprintf(stderr, "write: bad fd\n");
putrep(hdr, NILBUF, 0);
break;
case EXIT_STATUS:
if (cnt != 0) {
write(2, "Remote message: ", 16);
write(2, buf, cnt);
write(2, "\n", 1);
}
putrep(hdr, NILBUF, 0);
return(hdr->h_extra >> 8);
break;
default:
fprintf(stderr, "unknown command\n");
putrep(hdr, NILBUF, 0);
}
}
}
setupin(hdr)
header *hdr;
{
register pid;
uniqport(&hdr->h_priv.prv_random);
if ((pid = fork()) < 0) {
perror(prog);
exit(-1);
}
if (pid == 0) {
hdr->h_port = hdr->h_priv.prv_random;
_exit(commandloop(hdr)); /* get read commands from sherver */
}
return(pid);
}
main(argc, argv)
char **argv;
{
char *p;
header hdr;
register pid, status;
int flags;
#ifdef sun
put_user_name_in_env();
#endif
prog = *argv++;
if (argc == 1)
usage();
signal(SIGALRM, alrm);
while (*argv != 0 && **argv == '-') {
while (*++*argv)
switch (**argv) {
case 'b': flags |= BFLG; break;
case 'e': flags |= EFLG; break;
case 'i': flags |= IFLG; break;
default: usage();
}
argv++;
}
if ((mach = *argv++) == 0)
usage();
chkperm(mach);
p = setupbuf(argv, &flags); /* get command and environment */
if (flags & IFLG) /* set up input process */
pid = setupin(&hdr);
if (!execute(&hdr, p, flags)) { /* send command to sherver */
if (flags & IFLG)
kill(pid, SIGKILL);
exit(1);
}
if (!(flags & BFLG)) /* get commands from sherver */
status = commandloop(&hdr);
if (flags & IFLG) { /* wait for input process */
close(0); close(1); close(2);
while (wait((int *) 0) != pid)
;
}
exit(status);
}
chkperm(svport)
char *svport;
{
static char chkfil[] = "/etc/XXXXXXXXXXXXXX";
extern char *strchr();
sprintf(strchr(chkfil, 'X'), "rsh:%.14s", svport);
if (chkprot(chkfil, "/etc/rsh:default", geteuid(), getegid()) == 0)
panic("permission denied");
}
char *strchr(s, c)
register char *s;
{
while (*s) {
if (*s == c)
return s;
s++;
}
return 0;
}
#ifdef sun
#include <pwd.h>
put_user_name_in_env()
{
extern struct passwd *getpwuid();
register struct passwd *pw;
static char buf[512];
char host[10];
gethostname(host, sizeof host);
pw = getpwuid(getuid());
sprintf(buf, "UserName=%s@%s", pw ? pw->pw_name : "???", host);
putenv(buf);
}
#endif sun

View File

@@ -0,0 +1,420 @@
#include <stdio.h>
#include <errno.h>
#include <signal.h>
#include "amoeba.h"
#include "sherver.h"
/* isn't minix wonderful */
#undef BUFFERSIZE
#define BUFFERSIZE 8192
#define COMPATIBLE /* with the new rsh */
#define MAXWAIT (4*60*60) /* maximum waiting time in seconds */
#define Secs *10
#define LOCATETIMER 30 Secs
#ifdef DEBUG
char *
portstr(p) port *p; {
static char strbuf[80];
sprintf(strbuf,"%x:%x:%x:%x:%x:%x",
p->_portbytes[0]&0xFF,
p->_portbytes[1]&0xFF,
p->_portbytes[2]&0xFF,
p->_portbytes[3]&0xFF,
p->_portbytes[4]&0xFF,
p->_portbytes[5]&0xFF);
return strbuf;
}
#endif
header hdr;
char *prog, buf[BUFFERSIZE], *envvec[MAXENV], *errstr;
int pidlist[NFD];
extern errno;
static char *sig[] = {
"signal 0",
"hangup",
"interrupt",
"quit",
"illegal instruction",
"trace/BPT trap",
"IOT trap",
"EMT trap",
"floating exception",
"kill",
"bus error",
"memory fault",
"bad system call",
"broken pipe",
"alarm call",
"terminate",
"urgent socket",
"stop (signal)",
"stop",
"continue",
"child exited",
"stop (tty input)",
"stop (tty output)",
"tty input interrupt",
"cputime limit exceeded",
"filesize limit exceeded",
"virtual time alarm",
"profiling timer alarm",
};
panic(s, arg)
char *s;
{
register FILE *f;
FILE * fopen();
#ifdef DEBUG
#define f stderr
#else
if (f = fopen("/dev/tty0", "w")) {
#endif DEBUG
fprintf(f, "%s: ", prog);
fprintf(f, s, arg);
fprintf(f, "\n");
#ifdef DEBUG
#undef f
#else
fclose(f);
}
#endif DEBUG
_exit(1);
}
alrm(){ /* set alarm again to avoid races */
signal(SIGALRM, alrm);
alarm(MAXWAIT);
}
killall(){ /* kill all the created processes */
register n;
for (n = 0; n < NFD; n++)
if (pidlist[n] != 0)
kill(pidlist[n], SIGKILL);
}
trap(){ /* got SIGAMOEBA */
killall();
_exit(0);
}
copyloop(pp, rfd, wfd)
port *pp;
{
register unshort cnt;
register n;
do {
alarm(MAXWAIT);
n = read(rfd, buf, BUFFERSIZE);
alarm(0); alarm(0);
if (n < 0) {
strcpy(buf, errno==EINTR ? "waited too long for input"
: "read error");
killall();
return(1);
}
hdr.h_port = *pp;
hdr.h_command = WRITE_FD;
hdr.h_size = n;
hdr.h_extra = wfd;
cnt = trans(&hdr, buf, (unshort) n, &hdr, NILBUF, 0);
if (cnt != 0)
panic("trans failed (%d iso 0)", (short) cnt);
} while (n != 0);
return(0);
}
setupin(hdr)
header *hdr;
{
int fd, p[2];
register unshort cnt;
port svport;
if (pipe(p) < 0)
errstr = "can't pipe";
else if (p[0] != 0)
errstr = "pipe returned wrong fd";
else if ((pidlist[0] = fork()) < 0)
errstr = "can't fork";
else if (pidlist[0] == 0) {
close(p[0]);
signal(SIGPIPE, SIG_IGN);
#ifdef COMPATIBLE
if (!NullPort(&hdr->h_signature))
svport = hdr->h_signature;
else
#endif
svport = hdr->h_priv.prv_random;
for (;;) {
hdr->h_port = svport;
hdr->h_command = READ_FD;
hdr->h_size = BUFFERSIZE;
hdr->h_extra = 0;
#ifdef DEBUG
fprintf(stderr,"Using read port %s\n",portstr(&hdr->h_port));
#endif
cnt = trans(hdr, NILBUF, 0, hdr, buf, BUFFERSIZE);
if ((short) cnt < 0)
panic("read trans failed (%d)", (short) cnt);
if (cnt == 0)
_exit(0);
if (write(p[1], buf, cnt) != cnt) {
timeout(300);
hdr->h_port = svport;
hdr->h_command = EXIT_STATUS;
hdr->h_extra = 0x100;
if ((cnt = trans(hdr, NILBUF, 0, hdr, NILBUF, 0)) != 0)
panic("trans failed (%d iso 0)", (short) cnt);
_exit(1);
}
}
}
else
close(p[1]);
}
setuperr(){
int errpipe[2];
if (pipe(errpipe) < 0) {
errstr = "can't pipe";
return(-1);
}
if ((pidlist[2] = fork()) < 0) {
close(errpipe[0]);
close(errpipe[1]);
errstr = "can't fork";
return(-1);
}
if (pidlist[2] == 0) {
close(errpipe[1]);
timeout(LOCATETIMER);
_exit(copyloop(&hdr.h_port, errpipe[0], 2));
}
close(errpipe[0]);
return(errpipe[1]);
}
splitup(size){
register char *p = buf, *top = &buf[size], **vec = envvec;
while (p != top) {
if (vec == &envvec[MAXENV]) {
errstr = "too much environment";
return(0);
}
*vec++ = p;
while (*p++ != 0)
if (p == top) {
errstr = "bad format";
return(0);
}
}
*vec = 0;
return(1);
}
runit(outpipe, errout)
int outpipe[2];
{
register fd;
register char *homedir;
extern char **environ, *getenv();
close(1); close(2);
if (hdr.h_extra & BFLG) {
if ((fd = open("/dev/null", 1)) != 1)
panic("open returned wrong fd (%d iso 1)", fd);
else if ((fd = dup(1)) != 2)
panic("dup returned wrong fd (%d iso 2)", fd);
}
else {
close(outpipe[0]); /* outpipe[0] >= 1 */
if ((fd = dup(outpipe[1])) != 1)
panic("dup returned wrong fd (%d iso 1)", fd);
if (hdr.h_extra & EFLG) {
if ((fd = dup(errout)) != 2)
panic("dup returned wrong fd (%d iso 2)", fd);
else
close(errout);
}
else if ((fd = dup(1)) != 2)
panic("dup returned wrong fd (%d iso 2)", fd);
}
for (fd = 3; fd < 20; fd++)
close(fd);
#ifdef LOG
{
#include <fcntl.h>
register int logfd;
logfd = open("/usr/tmp/rsh.log", O_WRONLY|O_APPEND|O_CREAT, 0244);
if (logfd >= 0) {
#include <time.h>
register char *s;
register struct tm *tm;
long t;
char buf[1024]; /* had better be large enough */
static char *months[] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
time(&t);
tm = localtime(&t);
environ = &envvec[1];
s = getenv("UserName");
if (s == 0)
s = getenv("HOME");
if (s == 0)
s = getenv("LOGNAME");
if (s == 0)
s = getenv("USER");
sprintf(buf, "%02d-%s-%02d %02d:%02d:%02d %s\t%s%s\n",
tm->tm_mday, months[tm->tm_mon], tm->tm_year,
tm->tm_hour, tm->tm_min, tm->tm_sec,
s?s:"???", envvec[0],
hdr.h_extra & IFLG ? " (interactive)" : "");
lseek(logfd, 0L, 2);
write(logfd, buf, strlen(buf));
close(logfd);
}
}
#endif
environ = &envvec[1];
if ((homedir = getenv("HOME")) == 0 || chdir(homedir) < 0)
chdir("/");
execl("/bin/sh", "sh", "-c", envvec[0], (char *) 0);
panic("can't execute shell", 0);
}
execomm(size){
int outpipe[2], errout;
if (!splitup(size))
return(-1);
if (!(hdr.h_extra & BFLG)) {
if ((hdr.h_extra & EFLG) && (errout = setuperr()) < 0)
return(-1);
if (pipe(outpipe) < 0) {
if (hdr.h_extra & EFLG)
close(errout);
errstr = "can't pipe";
return(-1);
}
}
if ((pidlist[1] = fork()) < 0) {
if (!(hdr.h_extra & BFLG)) {
if (hdr.h_extra & EFLG)
close(errout);
close(outpipe[0]);
close(outpipe[1]);
}
errstr = "can't fork";
return(-1);
}
if (pidlist[1] == 0)
runit(outpipe, errout);
if (hdr.h_extra & BFLG)
return(0);
if (hdr.h_extra & EFLG)
close(errout);
close(outpipe[1]);
return(outpipe[0]);
}
awaitchild(hdr, status)
header *hdr;
{
register pid, n;
int wstat;
if (status == 0) {
alarm(MAXWAIT);
while ((pid = wait(&wstat)) > 0) {
if (pid == pidlist[1]) {
pidlist[1] = 0;
hdr->h_extra = status;
}
status = wstat;
}
alarm(0); alarm(0);
if (pidlist[1] != 0) {
strcpy(buf, errno == EINTR ? "waited too long"
: "wait error");
killall();
hdr->h_extra = 0x100;
}
else if (status & 0xFF)
if ((status & 0x7F) < sizeof(sig) / sizeof(sig[0]))
strcpy(buf, sig[status & 0x7F]);
else
sprintf(buf, "signal %d", status & 0x7F);
else
buf[0] = 0;
if (status & 0x80)
strcat(buf, " - core dumped");
}
else
hdr->h_extra = status << 8;
timeout(300);
hdr->h_command = EXIT_STATUS;
if ((n = trans(hdr, buf, strlen(buf), hdr, NILBUF, 0)) != 0)
panic("trans failed (%d iso 0)", (short) n);
}
main(argc, argv)
char **argv;
{
register unshort cnt;
register fd;
unshort getreq(), putrep();
prog = argv[0];
if (argc != 2)
panic("usage: sherver machine", 0);
signal(SIGALRM, alrm);
signal(SIGAMOEBA, trap);
strncpy(&hdr.h_port, argv[1], PORTSIZE);
/*cbo*/printf("before first getreq\n");
cnt = getreq(&hdr, buf, BUFFERSIZE);
/*cbo*/printf("after first getreq\n");
if ((short) cnt < 0)
panic("getreq failed (%d)", (short) cnt);
if (hdr.h_size == cnt) {
close(0);
if (hdr.h_extra & IFLG)
setupin(&hdr);
else if (open("/dev/null", 0) != 0)
errstr = "can't open /dev/null";
if (errstr == 0) {
uniqport(&hdr.h_port);
fd = execomm(cnt);
}
}
else
errstr = hdr.h_size > BUFFERSIZE ? "request too large" :
"bad format";
if (errstr == 0) {
hdr.h_status = COMM_DONE;
putrep(&hdr, NILBUF, 0);
if (!(hdr.h_extra & BFLG)) {
timeout(LOCATETIMER);
awaitchild(&hdr, copyloop(&hdr.h_port, fd, 1));
}
}
else {
hdr.h_status = COMM_ERROR;
putrep(&hdr, errstr, strlen(errstr));
}
}

View File

@@ -0,0 +1,20 @@
#define BUFFERSIZE 20480
#define MAXENV 100
#define NFD 3
/* initial command from rsh to sherver */
#define EXEC_COMMAND 1
/* flags in h_extra for EXEC_COMMAND */
#define BFLG 0x01
#define EFLG 0x02
#define IFLG 0x04
/* commands from sherver to rsh (parameter (fd or status) in h_extra) */
#define READ_FD 1
#define WRITE_FD 2
#define EXIT_STATUS 4
/* replies */
#define COMM_DONE 0
#define COMM_ERROR -1

View File

@@ -0,0 +1,50 @@
#include <stdio.h>
#include "amoeba.h"
#define BUFSIZE 20480
main(argc, argv)
char **argv;
{
header hdr;
char *buf, *malloc();
char *cmd = argv[0];
unshort cnt, bufsize = BUFSIZE;
unshort trans();
if (argc > 1 && strncmp(argv[1], "-t", 2) == 0) {
timeout(atoi(&argv[1][2]), 0);
argc--;
argv++;
}
if (argc != 2 && argc != 3) {
fprintf(stderr, "Usage: %s port\n", cmd);
exit(-1);
}
if (argc == 3)
bufsize = atoi(argv[2]);
if ((buf = malloc(bufsize)) == NULL) {
fprintf(stderr, "%s: out of memory\n", cmd);
exit(-1);
}
strncpy(&hdr.h_port, argv[1], PORTSIZE);
for (;;) {
cnt = read(0, buf, bufsize);
if ((short) cnt < 0) {
perror("read");
exit(-3);
}
if (trans(&hdr, buf, cnt, &hdr, NILBUF, 0) != 0) {
fprintf(stderr, "%s: trans failed\n", cmd);
exit(-4);
}
if (hdr.h_status) {
fprintf(stderr, "%s: write failed in from\n", cmd);
exit(-5);
}
if (cnt == 0)
exit(0);
}
}