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,34 @@
# To make 'cp', type: make f=cp
# To make 'ls', type: make f=ls
# To make 'cat', type: make f=cat
# Get the idea?
# To make everything, use:
# mkdir bin
# for i in *.c
# do make f=`basename $i .c`
# done
#
# Furthermore, many commands need a different memory allocation, so chmem must
# be run to change it. See the shell script 'changemem' in tools.
l=/usr/lib
b=../bin
CFLAGS= -F -D_MINIX -D_POSIX_SOURCE
File: $l/libc.a $f.s
@cc -i -o $b/$f $f.s
@chmem =8192 $b/$f >/dev/null
clean:
@rm -f *.s *.bak
@rm -f */*.s
@rm -f */*.bak
all:
@ls *.c >tmp.1
@sed <tmp.1 >tmp.2 '/\.c/s///;/^/s//make f=/'
@rm -rf tmp.1 bin
@mkdir bin
@sh tmp.2
@rm tmp.2

View File

@@ -0,0 +1,280 @@
/* ast - add symbol table. Author: Dick van Veen */
#include <sys/types.h>
#include <fcntl.h>
#include <a.out.h>
#include <stdio.h>
/* Since the a.out file in MINIX does not contain any symbol table,
* we use the symbol table produced with the -s option of asld.
*
* Read symbol table in memory, remove compiler generated labels,
* sort the labels and add it to the a.out file.
*
* When finally there comes a real as and ld, we may also get
* a symbol table in the a.out file, and we can forget this program.
*
*/
/* Ast [flags] [file] [symbolfile]
*
* flags:
* -x do not preserve local symbols
* -X preserve local symbols except for those whose name begin
* with 'I', these are compiler generated.
*
* - when no symbol file is present, symbol.out is assumed.
* - when no file is present, a.out is assumed.
* - when one file name is present it must be the executable file
* - just one flag may be pressent.
*
*/
#define A_OUT "a.out"
#define SYMBOL_FILE "symbol.out" /* contains symbol table */
#define LINE_LENGTH 24
#define WORTH_LESS 1 /* lines contain no symbol */
#define LAST_LINE 2 /* end of file reached */
struct exec header; /* header info of a.out file */
int x_flag; /* flags to ast */
int X_flag;
int o_flag;
char *s_file, *o_file; /* names of files used by ast */
FILE *s_fd, *o_fd; /* file descriptors of those files */
int nr_symbols; /* number of symbols added */
char buffer[LINE_LENGTH]; /* contains line of symbol file */
char io_buf[BUFSIZ]; /* for buffered output on stderr */
unsigned int get_value(); /* forward definition */
main(argc, argv)
int argc;
char **argv;
{
extern FILE *fopen();
argv++;
if (*argv != NULL && **argv == '-') {
*argv += 1;
if (**argv == 'x')
x_flag = 1;
else if (**argv == 'X')
X_flag = 1;
else {
fprintf(stderr, "illegal flag: -%c\n", **argv);
exit(-1);
}
argv++;
}
if (*argv != NULL) {
o_file = *argv;
argv++;
}
if (*argv != NULL) {
s_file = *argv;
argv++;
}
if (*argv != NULL) {
fprintf(stderr, "Usage: ast [-{x,X}] [file] [symbolfile]\n");
exit(-1);
}
if (o_file == NULL) o_file = A_OUT;
o_fd = fopen(o_file, "a");
if (o_fd == NULL) {
fprintf(stderr, "can't open %s\n", o_file);
exit(-1);
}
if (s_file == NULL) s_file = SYMBOL_FILE;
s_fd = fopen(s_file, "r");
if (s_fd == NULL) {
fprintf(stderr, "can't open %s\n", s_file);
exit(-1);
}
setbuf(s_fd, io_buf);
ast(s_fd, o_fd);
exit(0);
}
ast(s_fd, o_fd)
FILE *s_fd, *o_fd;
{
struct nlist symbol;
int line_type;
do_header();
for (;;) {
read_line(s_fd, buffer);
line_type = transform_line(buffer, &symbol);
if (line_type == WORTH_LESS) continue;
if (line_type == LAST_LINE) break;
save_line(o_fd, &symbol);
}
redo_header(o_fd);
}
read_line(fd, buffer)
FILE *fd;
char *buffer;
{
int ch;
char *buf1;
buf1 = buffer;
*buffer = '\n';
ch = fgetc(fd);
while (ch != '\n' && ch != EOF) {
*buffer = ch;
buffer++;
ch = fgetc(fd);
}
if (ch == EOF)
*buffer = '\0';
else
*buffer = '\n';
buffer[1] = '\0';
}
transform_line(buffer, symbol)
char *buffer;
struct nlist *symbol;
{
switch (*buffer) {
case 'a': /* absolute symbol */
symbol->n_sclass = N_ABS;
break;
case 'A': symbol->n_sclass = N_ABS | C_EXT; break;
case 'u': /* undefined symbol */
symbol->n_sclass = N_UNDF;
break;
case 'U':
symbol->n_sclass = N_UNDF | C_EXT;
break;
case 't': /* text symbol */
symbol->n_sclass = N_TEXT;
break;
case 'T':
symbol->n_sclass = N_TEXT | C_EXT;
break;
case 'd':
symbol->n_sclass = N_DATA;
case 'D': /* data symbol */
symbol->n_sclass = N_DATA | C_EXT;
break;
case 'b':
symbol->n_sclass = N_BSS;
case 'B': /* bss symbol */
symbol->n_sclass = N_BSS | C_EXT;
break;
case '\0': /* reached end of file */
return(LAST_LINE);
default: /* one of first two lines */
return(WORTH_LESS);
}
if (buffer[1] != ' ') {
fprintf(stderr, "illegal file format\n");
exit(-1);
}
symbol->n_value = get_value(buffer + 2);
if (buffer[6] != ' ') {
fprintf(stderr, "illegal file format\n");
exit(-1);
}
get_name(buffer + 7, symbol->n_name);
return(0); /* yeah, found a symbol */
}
save_line(fd, symbol)
FILE *fd;
struct nlist *symbol;
{
if (!(symbol->n_sclass & C_EXT)) { /* local symbol */
if (x_flag) return;
if (X_flag && symbol->n_name[0] == 'I') return;
if (X_flag && symbol->n_name[0] == 'L') return;
}
if (fwrite(symbol, sizeof(struct nlist), 1, fd) != 1) {
fprintf(stderr, "can't write %s\n", o_file);
exit(-1);
}
nr_symbols++;
}
unsigned get_value(string)
char *string;
{
unsigned value;
int shift, bits;
value = 0;
for (shift = 0; shift < 16; shift += 4) {
bits = get_bits(*string);
value = (value << 4) | bits;
string++;
}
return(value);
}
get_bits(ch)
char ch;
{
if (ch >= '0' && ch <= '9') return(ch - '0');
if (ch >= 'A' && ch <= 'F') return (ch - 'A' + 10);
if (ch >= 'a' && ch <= 'f') return (ch - 'a' + 10);
fprintf(stderr, "illegal file format\n");
exit(-1);
}
get_name(str1, str2)
register char *str1, *str2;
{
int count;
for (count = 0; count < 8; count++) {
if (*str1 == '\n') break;
*str2++ = *str1++;
}
while (count < 8) {
*str2++ = '\0';
count++;
}
}
do_header()
{
int fd;
fd = open(o_file, O_RDONLY);
if (read(fd, &header, sizeof(struct exec)) != sizeof(struct exec)) {
fprintf(stderr, "%s: no executable file\n", o_file);
exit(-1);
}
if (BADMAG(header)) {
fprintf(stderr, "%s: bad header\n", o_file);
exit(-1);
}
if (header.a_syms != 0L) {
fprintf(stderr, "%s: symbol table is installed\n", o_file);
exit(-1);
}
fseek(o_fd, A_SYMPOS(header), 0);
nr_symbols = 0;
close(fd);
}
redo_header(fd)
FILE *fd;
{
header.a_syms = (long) (nr_symbols * sizeof(struct nlist));
fseek(fd, 0L, 0);
if (fwrite(&header, sizeof(header), 1, fd) != 1) {
fprintf(stderr, "%s: can't write\n", o_file);
exit(-1);
}
}

View File

@@ -0,0 +1,538 @@
/* cc - call the C compiler Author: Erik Baalbergen */
#include <errno.h>
#include <signal.h>
#define SYMBOL_FILE "symbol.out" /* symbol table for prof */
#define MAXARGC 64 /* maximum number of arguments allowed in a list */
#define USTR_SIZE 64 /* maximum length of string variable */
typedef char USTRING[USTR_SIZE];
struct arglist {
int al_argc;
char *al_argv[MAXARGC];
};
/* MINIX paths */
char *PP = "/usr/lib/cpp";
char *CEM = "/usr/lib/cem";
char *OPT = "/usr/lib/opt";
char *CG = "/usr/lib/cg";
char *ASLD = "/usr/bin/asld";
char *AST = "/usr/bin/ast";
char *SHELL = "/bin/sh";
char *LIBDIR = "/usr/lib";
struct arglist LD_HEAD = {1, { "/usr/lib/crtso.s" } };
struct arglist M_LD_HEAD = {1, { "/usr/lib/mrtso.s" } };
struct arglist LD_TAIL = {2, { "/usr/lib/libc.a", "/usr/lib/end.s" } };
char *o_FILE = "a.out"; /* default name for executable file */
#define AST_FLAGS "-X"
#define AST_TAIL "symbol.out"
#define remove(str) (unlink(str), (str)[0] = '\0')
#define cleanup(str) (str && remove(str))
#define init(al) (al)->al_argc = 1
#define library(nm) \
mkstr(alloc((unsigned int)strlen(nm) + strlen(LIBDIR) + 7), \
LIBDIR, "/lib", nm, ".a", 0)
char *ProgCall = 0;
struct arglist SRCFILES;
struct arglist LDFILES;
struct arglist GEN_LDFILES;
struct arglist PP_FLAGS;
struct arglist CEM_FLAGS;
int RET_CODE = 0;
struct arglist OPT_FLAGS;
struct arglist CG_FLAGS;
struct arglist ASLD_FLAGS;
struct arglist DEBUG_FLAGS;
struct arglist CALL_VEC[2];
int o_flag = 0;
int S_flag = 0;
int v_flag = 0;
int F_flag = 0; /* use pipes by default */
int s_flag = 0;
int p_flag = 0; /* profil flag */
char *mkstr();
char *alloc();
USTRING ifile, kfile, sfile, mfile, ofile;
USTRING BASE;
char *tmpdir = "/tmp";
char tmpname[15];
trapcc(sig)
int sig;
{
signal(sig, SIG_IGN);
cleanup(ifile);
cleanup(kfile);
cleanup(sfile);
cleanup(mfile);
cleanup(ofile);
exit(1);
}
main(argc, argv)
char *argv[];
{
register char *f;
char *str;
char **argvec;
int count;
int ext;
register struct arglist *call = &CALL_VEC[0], *call1 = &CALL_VEC[1];
char *file;
char *ldfile = 0;
ProgCall = *argv++;
if (signal(SIGHUP, SIG_IGN) != SIG_IGN) signal(SIGHUP, trapcc);
if (signal(SIGINT, SIG_IGN) != SIG_IGN) signal(SIGINT, trapcc);
if (signal(SIGQUIT, SIG_IGN) != SIG_IGN) signal(SIGQUIT, trapcc);
while (--argc > 0) {
if (*(str = *argv++) != '-') {
append(&SRCFILES, str);
continue;
}
switch (str[1]) {
case 'c':
S_flag = 1;
break;
case 'D':
case 'I':
case 'U':
append(&PP_FLAGS, str);
break;
case 'F':
F_flag = 1;
break;
case 'l':
append(&SRCFILES, library(&str[2]));
break;
case 'o':
o_flag = 1;
if (argc-- >= 0)
o_FILE = *argv++;
break;
case 'O':
append(&CG_FLAGS, "-p4");
break;
case 'S':
S_flag = 1;
break;
case 'v':
v_flag++;
break;
case 'T':
tmpdir = &str[2];
append(&ASLD_FLAGS, str);
/*FALLTHROUGH*/
case 'R':
case 'w':
append(&CEM_FLAGS, str);
break;
case 's':
s_flag = 1;
break;
case 'p':
p_flag = 1;
s_flag = 1;
break;
case 'L':
if (strcmp(&str[1], "LIB") == 0) {
append(&OPT_FLAGS, "-L");
break;
}
/*FALLTHROUGH*/
default: /* -i goes here! */
append(&ASLD_FLAGS, str);
break;
}
}
mktempname(tmpname);
append(&CEM_FLAGS, "-L"); /* disable profiling */
count = SRCFILES.al_argc;
argvec = &(SRCFILES.al_argv[0]);
while (count-- > 0) {
basename(file = *argvec++, BASE);
if (v_flag && SRCFILES.al_argc > 1) {
write(1, file, strlen(file));
write(1, ":\n", 2);
}
ext = extension(file);
if (ext == 'c') { /* .c to .i (if F_flag) or .k */
init(call);
append(call, PP);
concat(call, &PP_FLAGS);
append(call, file);
if (F_flag) { /* to .i */
f = mkstr(ifile, tmpdir, tmpname, ".i", 0);
if (runvec(call, f)) {
file = ifile;
ext = 'i';
}
else {
remove(ifile);
continue;
}
}
else { /* use a pipe; to .k */
init(call1);
append(call1, CEM);
concat(call1, &DEBUG_FLAGS);
concat(call1, &CEM_FLAGS);
append(call1, "-"); /* use stdin */
f = mkstr(kfile, tmpdir, tmpname, ".k", 0);
append(call1, f);
if (runvec2(call, call1)) {
file = kfile;
ext = 'k';
}
else {
remove(kfile);
continue;
}
}
}
if (ext == 'i') { /* .i to .k */
init(call);
append(call, CEM);
concat(call, &DEBUG_FLAGS);
concat(call, &CEM_FLAGS);
append(call, file);
f = mkstr(kfile, tmpdir, tmpname, ".k", 0);
append(call, f);
if (runvec(call, (char *)0)) {
file = kfile;
ext = 'k';
}
else {
remove(kfile);
continue;
}
cleanup(ifile);
}
/* .k to .m */
if (ext == 'k') {
init(call);
append(call, OPT);
concat(call, &OPT_FLAGS);
append(call, file);
f = mkstr(mfile, tmpdir, tmpname, ".m", 0);
if (runvec(call, f) == 0)
continue;
file = mfile;
ext = 'm';
cleanup(kfile);
}
/* .m to .s */
if (ext == 'm') {
ldfile = S_flag ? ofile : alloc(strlen(BASE) + 3);
init(call);
append(call, CG);
concat(call, &CG_FLAGS);
append(call, file);
f = mkstr(ldfile, BASE, ".s", 0);
append(call, f);
if (runvec(call, (char *)0) == 0)
continue;
cleanup(mfile);
file = ldfile;
ext = 's';
}
if (S_flag)
continue;
append(&LDFILES, file);
if (ldfile) {
append(&GEN_LDFILES, ldfile);
ldfile = 0;
}
}
/* *.s to a.out */
if (RET_CODE == 0 && LDFILES.al_argc > 0) {
init(call);
append(call, ASLD);
concat(call, &ASLD_FLAGS);
if (s_flag) append(call, "-s");
append(call, "-o");
append(call, o_FILE);
if (p_flag)
concat(call, &M_LD_HEAD);
else concat(call, &LD_HEAD);
concat(call, &LDFILES);
concat(call, &LD_TAIL);
if (s_flag)
f = SYMBOL_FILE;
else f = (char *) 0;
if (runvec(call, f)) {
register i = GEN_LDFILES.al_argc;
while (i-- > 0)
remove(GEN_LDFILES.al_argv[i]);
}
}
/* add symbol table when p_flag is set */
if (s_flag) {
init(call);
append(call, AST);
append(call, AST_FLAGS);
append(call, o_FILE);
append(call, AST_TAIL);
(void) runvec(call, (char *) 0);
}
return(RET_CODE);
}
#define BUFSIZE (USTR_SIZE * MAXARGC)
char buf[BUFSIZE];
char *bufptr = &buf[0];
char *
alloc(u)
unsigned u;
{
register char *p = bufptr;
if ((bufptr += u) >= &buf[BUFSIZE])
panic("no space\n");
return p;
}
append(al, arg)
struct arglist *al;
char *arg;
{
if (al->al_argc >= MAXARGC)
panic("argument list overflow\n");
al->al_argv[(al->al_argc)++] = arg;
}
concat(al1, al2)
struct arglist *al1, *al2;
{
register i = al2->al_argc;
register char **p = &(al1->al_argv[al1->al_argc]);
register char **q = &(al2->al_argv[0]);
if ((al1->al_argc += i) >= MAXARGC)
panic("argument list overflow\n");
while (i-- > 0)
*p++ = *q++;
}
/*VARARGS1*/
char *
mkstr(dst, arg)
char *dst, *arg;
{
char **vec = (char **) &arg;
register char *p;
register char *q = dst;
while (p = *vec++) {
while (*q++ = *p++);
q--;
}
return dst;
}
basename(str, dst)
char *str;
register char *dst;
{
register char *p1 = str;
register char *p2 = p1;
while (*p1)
if (*p1++ == '/')
p2 = p1;
p1--;
if (*--p1 == '.') {
*p1 = '\0';
while (*dst++ = *p2++);
*p1 = '.';
}
else
while (*dst++ = *p2++);
}
int
extension(fn)
register char *fn;
{
char c;
while (*fn++) ;
fn--;
c = *--fn;
return (*--fn == '.') ? c : 0;
}
runvec(vec, outp)
struct arglist *vec;
char *outp;
{
int pid, fd, status;
if (v_flag) {
pr_vec(vec);
write(2, "\n", 1);
}
if ((pid = fork()) == 0) { /* start up the process */
if (outp) { /* redirect standard output */
close(1);
if ((fd = creat(outp, 0666)) != 1)
panic("cannot create output file\n");
}
ex_vec(vec);
}
if (pid == -1)
panic("no more processes\n");
wait(&status);
return status ? ((RET_CODE = 1), 0) : 1;
}
runvec2(vec0, vec1)
register struct arglist *vec0, *vec1;
{
/* set up 'vec0 | vec1' */
int pid, status1, status2, p[2];
if (v_flag) {
pr_vec(vec0);
write(2, " | ", 3);
pr_vec(vec1);
write(2, "\n", 1);
}
if (pipe(p) == -1)
panic("cannot create pipe\n");
if ((pid = fork()) == 0) {
close(1);
if (dup(p[1]) != 1)
panic("bad dup\n");
close(p[0]);
close(p[1]);
ex_vec(vec0);
}
if (pid == -1)
panic("no more processes\n");
if ((pid = fork()) == 0) {
close(0);
if (dup(p[0]) != 0)
panic("bad dup\n");
close(p[0]);
close(p[1]);
ex_vec(vec1);
}
if (pid == -1)
panic("no more processes\n");
close(p[0]);
close(p[1]);
wait(&status1);
wait(&status2);
return (status1 || status2) ? ((RET_CODE = 1), 0) : 1;
}
/*VARARGS1*/
panic(str, argv)
char *str;
int argv;
{
write(2, str, strlen(str));
exit(1);
}
char *
cindex(s, c)
char *s, c;
{
while (*s)
if (*s++ == c)
return s - 1;
return (char *) 0;
}
pr_vec(vec)
register struct arglist *vec;
{
register char **ap = &vec->al_argv[1];
vec->al_argv[vec->al_argc] = 0;
write(2, *ap, strlen(*ap) );
while (*++ap) {
write(2, " ", 1);
write(2, *ap, strlen(*ap));
}
}
ex_vec(vec)
register struct arglist *vec;
{
extern int errno;
static char *dum_env[1] = (char *) 0;
vec->al_argv[vec->al_argc] = 0;
execve(vec->al_argv[1], &(vec->al_argv[1]), dum_env);
if (errno == ENOEXEC) { /* not an a.out, try it with the SHELL */
vec->al_argv[0] = SHELL;
execv(SHELL, &(vec->al_argv[0]));
}
if (access(vec->al_argv[1], 1) == 0) {
/* File is executable. */
write(2, "Cannot execute ", 15);
write(2, vec->al_argv[1], strlen(vec->al_argv[1]));
write(2, ". Not enough memory.\n", 21);
write(2, "Try cc -F or use chmem to reduce its stack allocation\n",54);
} else {
write(2, vec->al_argv[1], strlen(vec->al_argv[1]));
write(2, " is not executable\n", 19);
}
exit(1);
}
mktempname(nm)
char nm[];
{
register i;
int pid = getpid();
nm[0] = '/'; nm[1] = 'c'; nm[2] = 'e'; nm[3] = 'm';
for (i = 9; i > 3; i--) {
nm[i] = (pid % 10) + '0';
pid /= 10;
}
nm[10] = '\0'; /* null termination */
}

View File

@@ -0,0 +1,271 @@
/* libpack - pack ASCII assembly code */
/* Packs common strings found in PC Minix assembly code into single */
/* byte abbreviations. The abbreviations all have their high bit set. */
/* Do not alter the order of the entries in "table"; asld depends on it.*/
/* External interfaces */
#include <ctype.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
/* Constants */
#define MAXLINE 256 /* maximum input line length */
#define ABBREVS 128 /* number of abbreviations */
#define COMMENT '|' /* comment character */
/* Structures and types */
struct node {
char *string; /* pointer to original string */
size_t length; /* length of original string */
struct node *next; /* next node with same hash value */
};
typedef unsigned short TWOBYTES; /* CHEAT - used to return two bytes */
/* Local interfaces */
static void error_exit(/* int rc, char *msg */);
static void hash_init(/* void */); /* initializes hash table */
static void pack_line(/* char *line */); /* packs an input line */
static TWOBYTES abbreviate_string(/* char *s */); /* abbreviates a string */
/* Macros */
#define HASH(word) ((*(word) + *((word) + 1)) & 0x7f)
#define HIBYTE(n) ((n) >> 8)
#define LOBYTE(n) ((n) & 0xff)
#define MAKETWOBYTES(hi, lo) ((((hi) & 0xff) << 8) | ((lo) & 0xff))
/* Static storage */
static char *table[] = {
"push ax",
"ret",
"mov bp,sp",
"push bp",
"pop bp",
"mov sp,bp",
".text",
"xor ax,ax",
"push 4(bp)",
"pop bx",
"pop si",
"cbw",
"movb al,(bx)",
"pop ax",
"xorb ah,ah",
"mov ax,#1",
"call _callm1",
"add sp,#16",
"mov bx,4(bp)",
"push 6(bp)",
"mov -2(bp),ax",
"I0013:",
"call .cuu",
"mov ax,-2(bp)",
"add 4(bp),#1",
"or ax,ax",
"jmp I0011",
"mov bx,8(bp)",
"push dx",
"mov cx,#2",
"mov bx,#2",
"I0011:",
"I0012:",
"push -2(bp)",
"mov ax,4(bp)",
"mov ax,-4(bp)",
"add sp,#6",
"and ax,#255",
"push bx",
"mov bx,-2(bp)",
"loop 2b",
"jcxz 1f",
".word 4112",
"mov ax,(bx)",
"mov -4(bp),ax",
"jmp I0013",
".data",
"mov bx,6(bp)",
"mov (bx),ax",
"je I0012",
".word 8224",
".bss",
"mov ax,#2",
"call _len",
"call _callx",
".word 28494",
".word 0",
"push -4(bp)",
"movb (bx),al",
"mov bx,ax",
"mov -2(bp),#0",
"I0016:",
".word 514",
".word 257",
"mov ",
"push ",
".word ",
"pop ",
"add ",
"4(bp)",
"-2(bp)",
"(bx)",
".define ",
".globl ",
"movb ",
"xor ",
"jmp ",
"cmp ",
"6(bp)",
"-4(bp)",
"-6(bp)",
"#16",
"_callm1",
"call ",
"8(bp)",
"xorb ",
"and ",
"sub ",
"-8(bp)",
"jne ",
".cuu",
"lea ",
"inc ",
"_M+10",
"#255",
"loop",
"jcxz",
"ax,#",
"bx,#",
"cx,#",
"ax,",
"bx,",
"cx,",
"dx,",
"si,",
"di,",
"bp,",
"ax",
"bx",
"cx",
"dx",
"si",
"di",
"bp",
"sp",
"dec ",
"neg ",
"_execve",
",#0",
NULL
};
/* This table is used to look up strings. */
struct node node[ABBREVS];
struct node *hash[ABBREVS]; /* hash table */
/* Code */
int main(argc, argv)
int argc;
char *argv[];
{
char line[MAXLINE];
switch (argc) {
case 1:
break;
case 2:
if (freopen(argv[1], "r", stdin) == NULL)
error_exit(ENOENT, "libpack: could not open file\n");
break;
default:
error_exit(EINVAL, "Usage: libpack [file]\n");
}
hash_init();
while (fgets(line, MAXLINE, stdin) != NULL) {
pack_line(line);
fputs(line, stdout);
}
exit(0);
}
static void error_exit(rc, msg)
int rc;
char *msg;
{
fputs(msg, stderr);
exit(rc);
}
static void hash_init()
{
int i;
register char **p;
register struct node *np;
for (i = 0, p = table; i < ABBREVS && *p != NULL; i++, p++) {
if (hash[HASH(*p)] == NULL) {
hash[HASH(*p)] = &node[i];
} else {
for (np = hash[HASH(*p)]; np->next != NULL; np = np->next)
;
np->next = &node[i];
}
np = &node[i];
np->string = *p;
np->length = strlen(*p);
np->next = NULL;
}
}
static void pack_line(line)
char *line;
{
register char *ip;
register char *op;
int in_white;
TWOBYTES n;
for (ip = line; *ip != '\0'; ++ip) /* translate tabs */
if (*ip == '\t') *ip = ' ';
op = line;
in_white = 1;
for (ip = line; *ip != '\0'; ++ip) { /* pack strings in line */
if (*ip == COMMENT)
break;
if (isspace(*ip)) {
if (!in_white) {
*op++ = ' ';
in_white = 1;
}
continue;
}
in_white = 0;
n = abbreviate_string(ip);
*op++ = LOBYTE(n);
ip += HIBYTE(n);
}
if (op != line) { /* finish nicely */
if (op[-1] == ' ')
--op;
*op++ = '\n';
}
*op = '\0';
}
static TWOBYTES abbreviate_string(ip)
register char *ip;
{
register struct node *np;
for (np = hash[HASH(ip)]; np != NULL; np = np->next)
if (strncmp(ip, np->string, np->length) == 0)
return MAKETWOBYTES(np->length - 1, 128 + (np - node));
return MAKETWOBYTES(0, *ip);
}

View File

@@ -0,0 +1,169 @@
/* libupack - unpack a packed .s file Author: Andy Tanenbaum */
char *table[] = {
"push ax",
"ret",
"mov bp,sp",
"push bp",
"pop bp",
"mov sp,bp",
".text",
"xor ax,ax",
"push 4(bp)",
"pop bx",
"pop si",
"cbw",
"movb al,(bx)",
"pop ax",
"xorb ah,ah",
"mov ax,#1",
"call _callm1",
"add sp,#16",
"mov bx,4(bp)",
"push 6(bp)",
"mov -2(bp),ax",
"I0013:",
"call .cuu",
"mov ax,-2(bp)",
"add 4(bp),#1",
"or ax,ax",
"jmp I0011",
"mov bx,8(bp)",
"push dx",
"mov cx,#2",
"mov bx,#2",
"I0011:",
"I0012:",
"push -2(bp)",
"mov ax,4(bp)",
"mov ax,-4(bp)",
"add sp,#6",
"and ax,#255",
"push bx",
"mov bx,-2(bp)",
"loop 2b",
"jcxz 1f",
".word 4112",
"mov ax,(bx)",
"mov -4(bp),ax",
"jmp I0013",
".data",
"mov bx,6(bp)",
"mov (bx),ax",
"je I0012",
".word 8224",
".bss",
"mov ax,#2",
"call _len",
"call _callx",
".word 28494",
".word 0",
"push -4(bp)",
"movb (bx),al",
"mov bx,ax",
"mov -2(bp),#0",
"I0016:",
".word 514",
".word 257",
"mov ",
"push ",
".word ",
"pop ",
"add ",
"4(bp)",
"-2(bp)",
"(bx)",
".define ",
".globl ",
"movb ",
"xor ",
"jmp ",
"cmp ",
"6(bp)",
"-4(bp)",
"-6(bp)",
"#16",
"_callm1",
"call ",
"8(bp)",
"xorb ",
"and ",
"sub ",
"-8(bp)",
"jne ",
".cuu",
"lea ",
"inc ",
"_M+10",
"#255",
"loop",
"jcxz",
"ax,#",
"bx,#",
"cx,#",
"ax,",
"bx,",
"cx,",
"dx,",
"si,",
"di,",
"bp,",
"ax",
"bx",
"cx",
"dx",
"si",
"di",
"bp",
"sp",
"dec ",
"neg ",
"_execve",
",#0",
0};
#define IBUFSIZE 10000
#define OBUFSIZE 30000
#define OUTMAX (7*1024)
char input[IBUFSIZE + 1], output[OBUFSIZE + 1];
main()
{
int n, count, bytes, cum;
while (1) {
n = read(0, input, IBUFSIZE);
if (n <= 0) exit(1);
input[n] = 0;
count = unpack88(input, output);
cum = 0;
while (count > 0) {
bytes = (count < OUTMAX ? count : OUTMAX);
n = write(1, output + cum, bytes);
count -= bytes;
cum += bytes;
}
}
}
unpack88(inp, outp)
register char *inp, *outp;
{
register k;
char *p, *orig;
orig = outp;
while (*inp != 0) {
k = *inp & 0377;
if (k < 128) {
*outp++ = *inp++;
} else {
p = table[k - 128];
while (*p != 0) *outp++ = *p++;
*inp++;
}
}
return(outp - orig);
}

View File

@@ -0,0 +1,375 @@
/* lorder - order a library Author: Monty Walls */
/* lorder: find ordering relations for object library
*
* author: Monty Walls
* written: 1/29/88
* Copyright: Copyright (c) 1988 by Monty Walls.
* Not derived from licensed software.
*
* Permission to copy and/or distribute granted under the
* following conditions:
*
* 1). This notice must remain intact.
* 2). The author is not responsible for the consequences of use
* this software, no matter how awful, even if they
* arise from defects in it.
* 3). Altered version must not be represented as being the
* original software.
*
* change log:
* corrected & rewrote scanner to avoid lex. - 2/22/88 - mrw
* oops reversed output filename order. 3/14/88 - mrw
* progname = argv[0] - should be first. 5/25/88 - mbeck
*/
#include <ctype.h>
#include <signal.h>
#include <ar.h>
#include <stdio.h>
#define MAXLINE 256
FILE *lexin;
char *yyfile;
char *tempfile;
char *progname;
char template[] = "lorder.XXXXXX";
struct filelist {
char *name;
struct filelist *next;
};
struct node {
char *name;
char *file;
struct filelist *list;
struct node *left, *right;
};
struct filelist *list;
struct node *tree, *lastnode;
extern char *malloc(), *mktemp();
extern FILE *popen(), *fopen();
extern char *addfile();
extern void user_abort();
main(argc, argv)
int argc;
char **argv;
{
int i;
char cmdstr[MAXLINE];
progname = argv[0];
if (argc > 1) {
signal(SIGINT, user_abort);
for (i = 1; argv[i] && *argv[i]; ++i) {
/* The following code is caused by not enough memory
* on floppy systems.
*
* so instead of ar | libupack ->to us. we use ar
* >tmpfle; libupack <tempfile ->to us */
if (is_liba(argv[i])) {
tempfile = mktemp(template);
sprintf(cmdstr, "ar pv %s >%s", argv[i], tempfile);
system(cmdstr);
sprintf(cmdstr, "libupack <%s", tempfile);
} else {
yyfile = addfile(argv[i]);
sprintf(cmdstr, "libupack <%s", argv[i]);
}
if ((lexin = popen(cmdstr, "r")) != (FILE *) NULL) {
while (yylex() != EOF);
pclose(lexin);
if (tempfile) unlink(tempfile);
} else {
fprintf(stderr, "Error: %s could not open %s\n", progname, argv[i]);
exit(1);
}
}
printtree(tree);
/* Then print list of files for ar also */
for (; list; list = list->next)
fprintf(stdout, "%s %s\n", list->name, list->name);
} else {
fprintf(stderr, "Usage: %s file ....\n", progname);
exit(1);
}
}
void user_abort()
{
unlink(tempfile);
exit(1);
}
char *xalloc(n)
int n;
{
char *p;
if ((p = malloc(n)) == (char *) NULL) {
fprintf(stderr, "Error %s - out of memory\n", progname);
exit(1);
}
return(p);
}
int is_liba(s) /* error handling done later */
char *s;
{
unsigned short key;
FILE *fp;
int ret = 0;
if ((fp = fopen(s, "r")) != (FILE *) NULL) {
fread(&key, sizeof(key), 1, fp);
if (key == ARMAG) ret = 1;
fclose(fp);
}
return(ret);
}
char *strsave(s)
char *s;
{
char *p;
p = xalloc(strlen(s) + 1);
strcpy(p, s);
return(p);
}
char *addfile(s)
char *s;
{
struct filelist *p;
p = (struct filelist *) xalloc(sizeof(struct filelist));
p->name = strsave(s);
if (list)
p->next = list;
else
p->next = NULL;
list = p;
return(p->name);
}
printtree(t)
struct node *t;
{
struct filelist *fp;
if (t) {
if (t->file) {
for (fp = t->list; fp && fp->name; fp = fp->next)
if (t->file != fp->name)
fprintf(stdout, "%s %s\n", fp->name, t->file);
}
printtree(t->right);
printtree(t->left);
}
}
struct node *finddef(s)
char *s;
{
struct node *n;
int cmp;
if (tree) {
lastnode = n = tree;
while (n && n->name) {
lastnode = n;
if (!(cmp = strcmp(s, n->name)))
return(n);
else if (cmp > 0)
n = n->left;
else
n = n->right;
}
}
return((struct node *) NULL);
}
struct node *makedef(s)
char *s;
{
struct node *n;
int cmp;
n = (struct node *) xalloc(sizeof(struct node));
n->name = strsave(s);
n->left = (struct node *) NULL;
n->right = (struct node *) NULL;
if (tree) {
cmp = strcmp(s, lastnode->name);
if (cmp > 0)
lastnode->left = n;
else
lastnode->right = n;
} else
tree = n;
return(n);
}
void dodef(s)
char *s;
{
struct node *n;
if (n = finddef(s)) {
if (n->file != NULL) fprintf(stderr,
"Error %s - %s defined twice in %s and %s\n",
progname, s, n->file, yyfile);
else
n->file = yyfile;
} else {
n = makedef(s);
n->file = yyfile;
n->list = (struct filelist *) NULL;
}
}
void usedef(s)
char *s;
{
struct node *n;
struct filelist *fp, *lastfp;
if (n = finddef(s)) {
/* Scan file list for match */
if (n->list) {
for (fp = n->list; fp; fp = fp->next) {
if (fp->name == yyfile) {
return;
}
lastfp = fp;
}
/* Reached here with no match */
lastfp->next = (struct filelist *) xalloc(sizeof(struct filelist));
lastfp->next->name = yyfile;
lastfp->next->next = (struct filelist *) NULL;
} else {
/* Empty list so far */
n->list = (struct filelist *) xalloc(sizeof(struct filelist));
n->list->name = yyfile;
n->list->next = (struct filelist *) NULL;
}
} else {
n = makedef(s);
n->file = (char *) NULL;
n->list = (struct filelist *) xalloc(sizeof(struct filelist));
n->list->name = yyfile;
n->list->next = (struct filelist *) NULL;
}
}
/* Yylex - scanner for lorder
*
*/
#define MAXNAME 33
#define is_first_char(c) ((c) == '.' || (c) == '_')
#define is_second_char(c) ((c) == '_' || isalpha((c)))
#define is_other_char(c) ((c) == '_' || isalnum((c)))
#define alt_space(c) ((c) == ',' || (c) == '#')
int yylex()
{
int col = 0;
int i = 0;
int is_member = 0;
int in_define = 0;
int lastch = 0;
int was_space = 1;
char s[MAXNAME];
while ((lastch = fgetc(lexin)) != EOF) {
col++; /* increment col */
if (isspace(lastch)) {
EOS: /* eos comes here */
if (i) { /* we have a string */
s[i] = '\0'; /* set eos */
i = 0;
/* If we are in a define use dodef to add
* location of defining member and global to
* symbol table. */
if (in_define) dodef(s);
/* If we are on a 'p -' line for an ar lib
* define this member as the file we are
* using. */
else if (is_member > 0) {
is_member = 0;
yyfile = addfile(s);
}
/* If we have a '.define' mark this line as
* in_define. */
else if (strcmp(s, ".define") == 0)
in_define = 1;
/* Just a reference in the code to a var, so
* add this reference to our symbol table. */
else
usedef(s);
}
/* We are at the eol: reset our counters and switches */
if (lastch == '\n') {
col = 0;
is_member = 0;
in_define = 0;
}
/* Lets do another character */
was_space = 1;
continue;
}
/* Not a space and i == 0 */
if (i == 0) {
/* Are we seeing 'p' in col 1 */
if (lastch == 'p' && col == 1) {
is_member = -1;
}
/* Are we seeing '-' that follows 'p' in col 1 */
else if (lastch == '-' && is_member < 0 && col == 3) {
is_member = 1;
}
/* If we have seen 'p -' now we are reading the name
* or the first character of a global symbol */
else if (is_member > 0 || (is_first_char(lastch) && was_space)) {
s[i++] = lastch;
if (is_member < 0) is_member = 0;
}
was_space = alt_space(lastch);
}
/* Do the second char of a name */
else if (i == 1) {
if (is_member > 0 || is_second_char(lastch)) {
s[i++] = lastch;
} else
is_member = 0;
was_space = alt_space(lastch);
}
/* Do the rest of a symbol or member name */
else if (is_member > 0 || is_other_char(lastch)) {
s[i++] = lastch;
was_space = alt_space(lastch);
} else {
was_space = alt_space(lastch);
goto EOS;
}
}
/* Returns EOF on end of file */
return(lastch);
}

View File

@@ -0,0 +1,140 @@
/* readclock - read the AT real time clock Authors: T. Holm & E. Froese */
/************************************************************************/
/* */
/* readclock.c */
/* */
/* Read the AT real time clock, write the time to */
/* standard output in a form usable by date(1). */
/* If the system is an AT then the time is read */
/* from the built-in clock, and written to standard */
/* output in the form: */
/* */
/* mmddyyhhmmss */
/* */
/* If the system is not an AT then ``-q'' is written */
/* to standard output. This is useful for placement in */
/* the ``/etc/rc'' script: */
/* */
/* /usr/bin/date `/usr/bin/readclock` </dev/tty */
/* */
/************************************************************************/
/* origination 1987-Dec-29 efth */
/************************************************************************/
#define CPU_TYPE_SEGMENT 0xFFFF /* BIOS segment for CPU type */
#define CPU_TYPE_OFFSET 0x000E /* BIOS offset for CPU type */
#define PC_AT 0xFC /* IBM code for PC-AT (0xFFFFE) */
#define PS_386 0xF8 /* IBM code for 386 PS/2's */
#define CLK_ELE 0x70 /* ptr corresponding to element of time to be*/
#define CLK_IO 0x71 /* read or written is written to port clk_ele*/
/* The element can then be read or written by */
/* Reading or writing port clk_io. */
#define YEAR 9 /* Clock register addresses */
#define MONTH 8
#define DAY 7
#define HOUR 4
#define MINUTE 2
#define SECOND 0
#define STATUS 0x0b
#define BCD_TO_DEC(x) ( (x>>4) * 10 + (x & 0x0f) )
struct time {
unsigned year;
unsigned month;
unsigned day;
unsigned hour;
unsigned minute;
unsigned second;
};
main()
{
struct time time1;
struct time time2;
int i;
int cpu_type;
cpu_type = peek(CPU_TYPE_SEGMENT, CPU_TYPE_OFFSET);
if (cpu_type != PS_386 && cpu_type != PC_AT) {
printf("-q\n");
exit(1);
}
for (i = 0; i < 10; i++) {
get_time(&time1);
get_time(&time2);
if (time1.year == time2.year &&
time1.month == time2.month &&
time1.day == time2.day &&
time1.hour == time2.hour &&
time1.minute == time2.minute &&
time1.second == time2.second) {
printf("%02d%02d%02d%02d%02d%02d\n",
time1.month, time1.day, time1.year,
time1.hour, time1.minute, time1.second);
exit(0);
}
}
printf("-q\n");
exit(1);
}
/***********************************************************************/
/* */
/* get_time( time ) */
/* */
/* Update the structure pointed to by time with the current time */
/* as read from the hardware real-time clock of the AT. */
/* If necessary, the time is converted into a binary format before */
/* being stored in the structure. */
/* */
/***********************************************************************/
get_time(t)
struct time *t;
{
t->year = read_register(YEAR);
t->month = read_register(MONTH);
t->day = read_register(DAY);
t->hour = read_register(HOUR);
t->minute = read_register(MINUTE);
t->second = read_register(SECOND);
if ((read_register(STATUS) & 0x04) == 0) {
/* Convert BCD to binary if necessary */
t->year = BCD_TO_DEC(t->year);
t->month = BCD_TO_DEC(t->month);
t->day = BCD_TO_DEC(t->day);
t->hour = BCD_TO_DEC(t->hour);
t->minute = BCD_TO_DEC(t->minute);
t->second = BCD_TO_DEC(t->second);
}
}
read_register(reg_addr)
char reg_addr;
{
int val;
if (port_out(CLK_ELE, reg_addr) < 0 || port_in(CLK_IO, &val) < 0) {
printf("-q\n");
exit(1);
}
return(val);
}

View File

@@ -0,0 +1,312 @@
/* term - terminal simulator Author: Andy Tanenbaum */
/* This program allows the user to turn a MINIX system into a dumb
* terminal to communicate with a remote computer through one of the ttys.
* It forks into two processes. The parent sits in a tight loop copying
* from stdin to the tty. The child sits in a tight loop copying from
* the tty to stdout.
*
* 2 Sept 88 BDE (Bruce D. Evans): Massive changes to make current settings the
* default, allow any file as the "tty", support fancy baud rates and remove
* references to and dependencies on modems and keyboards, so (e.g.)
* a local login on /dev/tty1 can do an external login on /dev/tty2.
*
* 3 Sept 88 BDE: Split parent again to main process copies from stdin to a
* pipe which is copied to the tty. This stops a blocked write to the
* tty from hanging the program.
*
* 11 Oct 88 BDE: Cleaned up baud rates and parity stripping.
*
* Example usage:
* term : baud, bits/char, parity from /dev/tty1
* term 9600 7 even : 9600 baud, 7 bits/char, even parity
* term odd 300 7 : 300 baud, 7 bits/char, odd parity
* term /dev/tty2 : use /dev/tty2 rather than /dev/tty1
* : Any argument starting with "/" is
* : taken as the communication device.
*/
#include <sys/types.h>
#include <minix/config.h>
#include <fcntl.h>
#include <sgtty.h>
#include <signal.h>
#define MAXARGS 3 /* maximum number of uart params */
#define CHUNK 1024 /* how much to read at once */
#define NULL 0
/* Hack some new baud rates for Minix. Minix uses a divide-by-100 encoding. */
#define B200 2
#define B600 6
#define B1800 18
#define B3600 36
#define B7200 72
#define B19200 192
#define EXTA 192
/* We can't handle some standard (slow) V7 speeds and speeds above 25500 since
* since the speed is packed into a char :-(. Trap them with an illegal value.
*/
#define B50 0
#define B75 0
#define B134 0
#define EXTB 0
#define B38400 0
#define B57600 0
#define B115200 0
int commfd; /* open file no. for comm device */
int readpid; /* pid of child reading commfd */
struct sgttyb sgcommfd; /* saved terminal parameters for commfd */
struct sgttyb sgstdin; /* saved terminal parameters for stdin */
int writepid; /* pid of child writing commfd */
#if (MACHINE == ATARI)
char endseq[] = "Ou"; /* sequence to leave simulator */
#else
char endseq[] = "\033[G"; /* sequence to leave simulator */
#endif
/* Keypad '5', and must arrive in 1 piece */
struct param_s {
char *pattern;
int value;
char type;
#define BAD 0
#define BITS 1
#define NOSTRIP 2
#define PARITY 3
#define SPEED 4
}
params[] =
{
"5", BITS5, BITS,
"6", BITS6, BITS,
"7", BITS7, BITS,
"8", BITS8, BITS,
"even", EVENP, PARITY,
"odd", ODDP, PARITY,
"nostrip", 0, NOSTRIP,
"50", B50, SPEED,
"75", B75, SPEED,
"110", B110, SPEED,
"134", B134, SPEED,
"200", B200, SPEED,
"300", B300, SPEED,
"600", B600, SPEED,
"1200", B1200, SPEED,
"1800", B1800, SPEED,
"2400", B2400, SPEED,
"3600", B3600, SPEED,
"4800", B4800, SPEED,
"7200", B7200, SPEED,
"9600", B9600, SPEED,
"19200", B19200, SPEED,
"EXTA", EXTA, SPEED,
"EXTB", EXTB, SPEED,
"38400", B38400, SPEED,
"57600", B57600, SPEED,
"115200", B115200, SPEED,
"", 0, BAD, /* BAD type to end list */
};
unsigned char strip_parity = 1; /* nonzero to strip high bits before output */
int quit(); /* forward declare signal handler */
main(argc, argv)
int argc;
char *argv[];
{
char *commdev = NULL;
int i;
int pipefd[2];
sync();
for (i = 1; i < argc; ++i)
if (argv[i][0] == '/') {
if (commdev != NULL)
error("Too many communication devices", "");
commdev = argv[i];
}
if (commdev == NULL) {
i = MAXARGS + 1;
commdev = "/dev/tty1";
} else
i = MAXARGS + 2;
if (argc > i) error("Usage: term [baudrate] [data_bits] [parity]", "");
commfd = open(commdev, O_RDWR);
if (commfd < 0) error("Can't open ", commdev);
/* Save state of both devices before altering either (may be identical!). */
ioctl(0, TIOCGETP, &sgstdin);
ioctl(commfd, TIOCGETP, &sgcommfd);
set_mode(0, -1, -1, -1, &sgstdin); /* RAW mode on stdin, others
* current */
set_uart(argc, argv);
/* Main body of the terminal simulator. */
signal(SIGINT, quit);
signal(SIGPIPE, quit);
if (pipe(pipefd) < 0) error("Can't create pipe", "");
switch ((writepid = fork())) {
case -1:
error("Can't create process to write to comm device", "");
case 0:
/* Piped stdin to tty */
close(pipefd[1]);
copy(pipefd[0], "piped stdin", commfd, commdev, "");
}
close(pipefd[0]);
switch ((readpid = fork())) {
case -1:
error("Can't create process to read from comm device", "");
case 0:
/* Tty to stdout */
copy(commfd, commdev, 1, "stdout", "");
}
/* Stdin to pipe */
copy(0, "stdin", pipefd[1], "redirect stdin", endseq);
}
set_uart(argc, argv)
int argc;
char *argv[];
{
/* Set up the UART parameters. */
int i, j, bits, nbits, parity, nparities, speed, nspeeds;
char *arg;
register struct param_s *param;
/* Examine all the parameters and check for validity. */
nspeeds = nparities = nbits = 0;
speed = parity = bits = -1; /* -1 means use current value */
for (i = 1; i < argc; ++i) {
if ((arg = argv[i])[0] == '/') continue;
/* Check parameter for legality. */
for (j = 0, param = &params[0];
param->type != BAD && strcmp(arg, param->pattern) != 0;
++j, ++param);
switch (param->type) {
case BAD:
error("Invalid parameter: ", arg);
case BITS:
bits = param->value;
if (++nbits > 1) error("Too many character sizes", "");
break;
case PARITY:
parity = param->value;
if (++nparities > 1) error("Too many parities", "");
break;
case SPEED:
speed = param->value;
if (speed == 0) error("Invalid speed: ", arg);
if (++nspeeds > 1) error("Too many speeds", "");
break;
case NOSTRIP: strip_parity = 0; break;
}
}
set_mode(commfd, speed, parity, bits, &sgcommfd);
}
set_mode(fd, speed, parity, bits, sgsavep)
int speed;
int parity;
int bits;
struct sgttyb *sgsavep;
{
/* Set open file fd to RAW mode with the given other modes. If fd is
* not a tty, this may do nothing but connecting ordinary files as
* ttys may have some use. */
struct sgttyb sgtty;
int tabs;
sgtty = *sgsavep;
tabs = sgtty.sg_flags & XTABS;
if (speed == -1) speed = sgtty.sg_ispeed;
if (parity == -1) parity = sgtty.sg_flags & (EVENP | ODDP);
if (bits == -1)
bits = sgtty.sg_flags & BITS8; /* BITS8 is actually a mask */
sgtty.sg_ispeed = speed;
sgtty.sg_ospeed = speed;
sgtty.sg_flags = RAW | parity | bits | tabs;
ioctl(fd, TIOCSETP, &sgtty);
}
copy(in, inname, out, outname, end)
int in;
char *inname;
int out;
char *outname;
char *end;
{
/* Copy from one open file to another. If the 'end' sequence is not "", and
* precisely matches the input, terminate the copy and various children.
* The end sequence is best provided by keyboard input from one of the
* special keys which always produces chars in a bunch. RAW mode almost
* guarantees exactly one keystroke's worth of input at a time.
*/
static char buf[CHUNK];
char *bufend;
register char *bufp;
int count;
int len;
len = strlen(end);
while (1) {
if ((count = read(in, buf, CHUNK)) <= 0) {
write2sn("Can't read from ", inname);
quit();
}
if (count == len && strncmp(buf, end, count) == 0) quit();
if (strip_parity) for (bufp = buf, bufend = bufp + count;
bufp < bufend; ++bufp)
*bufp &= 0x7F;
if (write(out, buf, count) != count) {
write2sn("Can't write to ", outname);
quit();
}
}
}
error(s1, s2)
char *s1;
char *s2;
{
write2sn(s1, s2);
exit(1);
}
nicequit()
{
exit(0);
}
quit()
{
ioctl(commfd, TIOCSETP, &sgcommfd);
ioctl(0, TIOCSETP, &sgstdin);
signal(SIGINT, nicequit); /* if not caught, sh prints extra newline */
kill(0, SIGINT);
nicequit();
}
write2sn(s1, s2)
{
write(1, s1, strlen(s1));
write(1, s2, strlen(s2));
write(1, "\r\n", 2);
}